Files
6174-comflowy-nodes/flowy/nodes_ideogram.py
T
2024-11-04 16:38:55 +08:00

130 lines
6.5 KiB
Python

import time
import requests
import base64
import io
from PIL import Image
import torch
import numpy as np
import logging
import json
from .types import STRING, INT, API_HOST
from .utils import logger, get_nested_value
from .api_key_manager import load_api_key
logger = logging.getLogger(__name__)
class FlowyIdeogram:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"prompt": ("STRING", {"multiline": True}),
"negative_prompt": ("STRING", {"multiline": True}),
"version": (["ideogram-v2-turbo", "ideogram-v2"],),
"resolution": (["None", "512x1536", "576x1408", "576x1472", "576x1536", "640x1024", "640x1344", "640x1408", "640x1472", "640x1536", "704x1152", "704x1216", "704x1280", "704x1344", "704x1408", "704x1472", "720x1280", "736x1312", "768x1024", "768x1088", "768x1152", "768x1216", "768x1232", "768x1280", "768x1344", "832x960", "832x1024", "832x1088", "832x1152", "832x1216", "832x1248", "864x1152", "896x960", "896x1024", "896x1088", "896x1120", "896x1152", "960x832", "960x896", "960x1024", "960x1088", "1024x640", "1024x768", "1024x832", "1024x896", "1024x960", "1024x1024", "1088x768", "1088x832", "1088x896", "1088x960", "1120x896", "1152x704", "1152x768", "1152x832", "1152x864", "1152x896", "1216x704", "1216x768", "1216x832", "1232x768", "1248x832", "1280x704", "1280x720", "1280x768", "1280x800", "1312x736", "1344x640", "1344x704", "1344x768", "1408x576", "1408x640", "1408x704", "1472x576", "1472x640", "1472x704", "1536x512", "1536x576", "1536x640"],),
"style_type": (["None", "Auto", "Realistic", "Design", "Anime", "Render 3D"],),
"aspect_ratio": (["1:1", "4:3", "3:4", "16:9", "9:16", "3:2", "2:3", "16:10", "10:16", "3:1", "1:3"],),
"magic_prompt_option": (["On", "Off"],),
"seed": ("INT", {"default": 0, "min": 0, "max": 2147483647}),
}
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "generate_image_with_ideogram"
CATEGORY = "Comflowy"
DESCRIPTION = """
Nodes from https://comflowy.com:
- Description: A service to generate images using Ideogram AI.
- How to use:
- Provide a prompt to generate an image.
- Choose resolution, style type, aspect ratio, and magic prompt option.
- Resolution overrides aspect ratio.
- Magic Prompt will interpret your prompt and optimize it to maximize variety and quality of the images generated. You can also use it to write prompts in different languages.
- Make sure to set your API Key using the 'Comflowy Set API Key' node before using this node.
- Output: Returns the generated image.
"""
def generate_image_with_ideogram(self, prompt, negative_prompt, version, resolution, style_type, aspect_ratio, magic_prompt_option, seed):
api_key = load_api_key()
if not api_key:
error_msg = "API Key is not set. Please use the 'Comflowy Set API Key' node to set a global API Key before using this node."
logger.error(error_msg)
raise ValueError(error_msg)
logger.info(f"Starting Ideogram image generation request. prompt: {prompt}, negative_prompt: {negative_prompt}, resolution: {resolution}, style_type: {style_type}, aspect_ratio: {aspect_ratio}, magic_prompt_option: {magic_prompt_option}, seed: {seed}")
try:
response = requests.post(
f"{API_HOST}/api/open/v0/flowy",
headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
json={
"prompt": prompt,
"negative_prompt": negative_prompt,
"version": version,
"resolution": resolution if resolution != "None" else None,
"style_type": style_type if style_type != "None" else None,
"aspect_ratio": aspect_ratio,
"magic_prompt_option": magic_prompt_option,
"seed": seed,
"model_type": "ideogram",
}
)
response.raise_for_status()
result = response.json()
logger.info(f"API request completed. Status code: {response.status_code}")
logger.debug(f"API response content: {json.dumps(result, indent=2)}")
if not result.get('success'):
logger.error(f"API request failed. Response content: {json.dumps(result, indent=2)}")
raise Exception(f"API request failed. Response content: {json.dumps(result, indent=2)}")
output_url = result.get('data', {}).get('output')
if not output_url or not isinstance(output_url, str):
logger.error(f"Complete API response: {json.dumps(result, indent=2)}")
raise Exception(f"Unable to get valid output image URL. API response doesn't have expected data structure. Complete response: {json.dumps(result, indent=2)}")
logger.info(f"Received output URL: {output_url}")
# Verify if URL is accessible
try:
url_check = requests.head(output_url)
url_check.raise_for_status()
except requests.RequestException as e:
logger.error(f"Cannot access output URL: {str(e)}")
raise Exception(f"Cannot access output URL: {str(e)}")
# Add delay to wait for Replicate processing
time.sleep(10)
img_response = requests.get(output_url, stream=True)
img_response.raise_for_status()
# Convert to numpy array
img_np = np.array(img)
# Ensure image has 3 RGB channels
if len(img_np.shape) == 2: # Grayscale image
img_np = np.stack([img_np] * 3, axis=-1)
elif img_np.shape[-1] == 4: # RGBA image
img_np = img_np[:, :, :3]
# Convert to float32 and normalize to 0-1 range
img_np = img_np.astype(np.float32) / 255.0
# Convert to torch tensor, ensure shape is [B,H,W,C]
img_tensor = torch.from_numpy(img_np).unsqueeze(0) # Add batch dimension
logger.info(f"Image processing completed. Output tensor shape: {img_tensor.shape}")
return (img_tensor,)
except Exception as e:
error_msg = f"Error during image generation: {str(e)}"
logger.error(error_msg)
logger.exception("Detailed error information:")
# Return an error marker image, ensure shape is [B,H,W,C]
error_image = torch.zeros((1, 100, 400, 3), dtype=torch.float32)
return (error_image,)