From d1f43ef98b5c933b34aed80772274bc629bb1117 Mon Sep 17 00:00:00 2001 From: lining3 Date: Wed, 9 Jul 2025 16:35:59 +0800 Subject: [PATCH] first commit --- README.md | Bin 0 -> 2392 bytes __init__.py | 3 ++ onethingai.py | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 README.md create mode 100644 __init__.py create mode 100644 onethingai.py diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a62241df65d09093efc947d24b4a3e958b81257f GIT binary patch literal 2392 zcmai$T~Cui5QXR3#Q(5?3o)^R2*z-SCJIrID8zV$ZRuBROKnS_e_lP$Ot;&&Einze zZ+B6sYvP~6I4)Smd?v38nv zXA_$`LXve@B%$5fcmwuSsCC&V$DRtUBRf`F!bx_ob!;AE@yxAy;#=3rmhAWs-$3cf z?@+79b|KC$7hJcENI%F9Uw5*`ACc6w{;`4qYViOoV$51>RwsB3=JEHJuu*p?pJP4y z733r}@dJPGvBTSr9oj3~w}<&N>GZAE_ifJ(?5)=G+w(;PXX4nGUC%~(u17G^8u=jZ z-?AlovalmhHT~^b!Fs3to}<y*wcBt)ZBk;xW)_j)BT0^F#4K-QAULzn*t{sDski>YLnM zaELgvuKTWQRsB*`J$Y(*l*|cgZs?i}#jB@pa4wk3+KjY6k~(C8%8a}wbupDl^!M}3 zmFkU}sPc>IxDrOphs-SZus=KWSQ1G$&176W!HJdLSff&d%no@aN zYZEo*Y0-Ig0#TD&I+-gBudnA7&6FtplPjC&NHNn<n#okXvZJc4#9+y~c~3YaMGW6x~v&m`-%?6NlWe4gZy74Cq#VkA$| zkJSku_fKJPCPaMo-Tya#V?xFG$UvFPOgyaH@(~jg)*a`6Af%Xr1^rxB19etR&){D2 zMm;Ax(K)JqTo5Doac}LZ#tzr8FNInrJ2Bv`^f3x8Tf`KI8-RI6 zHwFIT{I1Hk6}1>0pAlmM;f)F^H~fY2f}Wry@1=*zom77RfXQ!y>g3t+-xHsgZb`H# KF_im>^Zx*Zoq!$y literal 0 HcmV?d00001 diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..0836072 --- /dev/null +++ b/__init__.py @@ -0,0 +1,3 @@ +from .onethingai import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS + +__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS'] \ No newline at end of file diff --git a/onethingai.py b/onethingai.py new file mode 100644 index 0000000..73bbfed --- /dev/null +++ b/onethingai.py @@ -0,0 +1,122 @@ +import requests +from requests.adapters import HTTPAdapter +from urllib3.util.retry import Retry +import json +from PIL import Image +import io +import base64 +import numpy as np +import torch + +class OneThingAILoader: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "api_key": ("STRING", {"default": "", "multiline": False}), + "prompt": ("STRING", {"default": "", "multiline": True}), + "model": ("STRING", {"default": "gpt4o"}), + "num_images": ("INT", {"default": 1, "min": 1, "max": 10}), + "width": ("INT", {"default": 1024, "min": 512, "max": 2048, "step": 64}), + "height": ("INT", {"default": 1024, "min": 512, "max": 2048, "step": 64}), + "retries": ("INT", {"default": 3, "min": 0, "max": 5}), + "timeout": ("INT", {"default": 20, "min": 5, "max": 100}), + }, + } + + RETURN_TYPES = ("IMAGE", ) + FUNCTION = "generate" + CATEGORY = "image generation" + + def generate(self, api_key, prompt, model="gpt4o", num_images=1, width=1024, height=1024, retries=3, timeout=8): + # API endpoint + url = "https://api-model.onethingai.com/v1/images/generations" + + # Setup retry strategy + retry_strategy = Retry( + total=retries, + backoff_factor=1, + status_forcelist=[429, 500, 502, 503, 504], + ) + + # Create session with retry strategy + session = requests.Session() + adapter = HTTPAdapter(max_retries=retry_strategy) + session.mount("https://", adapter) + + # Request headers + headers = { + "Authorization": f"Bearer {api_key}", + "Content-Type": "application/json" + } + + # Request payload + payload = { + "model": model, + "prompt": prompt, + "n": num_images, + "size": f"{width}x{height}", + } + + try: + # Make API request with timeout + response = session.post( + url, + headers=headers, + json=payload, + timeout=timeout + ) + response.raise_for_status() + + # Parse response + result = response.json() + + if "data" not in result: + raise ValueError(f"Unexpected API response: {result}") + + # Process images + images = [] + for img_data in result["data"]: + if "b64_json" in img_data: + # Decode base64 image + image_bytes = base64.b64decode(img_data["b64_json"]) + image = Image.open(io.BytesIO(image_bytes)) + + # Convert to RGB if necessary + if image.mode != "RGB": + image = image.convert("RGB") + + # Convert to numpy array + image_array = np.array(image) + images.append(image_array) + + # Stack images if multiple were generated + if len(images) > 1: + final_image = np.stack(images) + else: + final_image = images[0] + + # Convert numpy array to torch tensor + final_image = torch.from_numpy(final_image).float()/255.0 + final_image = final_image.unsqueeze(0) + + return (final_image,) + + except requests.exceptions.RequestException as e: + raise RuntimeError(f"API request failed: {str(e)}") + except json.JSONDecodeError: + raise RuntimeError("Failed to parse API response") + except Exception as e: + raise RuntimeError(f"Error generating images: {str(e)}") + finally: + session.close() + +# Register the node class +NODE_CLASS_MAPPINGS = { + "OneThingAILoader": OneThingAILoader +} + +# Add descriptions +NODE_DISPLAY_NAME_MAPPINGS = { + "OneThingAILoader": "OneThingAI Image Generator" +} \ No newline at end of file