From 2f2d9b6b3efe9309cd15a37c159f513e78a07c74 Mon Sep 17 00:00:00 2001 From: TiyaAnlite Date: Sat, 11 Oct 2025 20:12:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- base.py | 35 ++++++++++++++++++++++++++++++++--- nodes.py | 40 ++++++++++++++++++++++++++++++++++++---- register.py | 2 ++ 3 files changed, 70 insertions(+), 7 deletions(-) diff --git a/base.py b/base.py index 9b02102..ab25c14 100644 --- a/base.py +++ b/base.py @@ -36,6 +36,10 @@ class BaseImageNode: URL_EDIT = "https://api-model.onethingai.com/v1/images/edits" RETURN_TYPES = ("IMAGE",) + @classmethod + def IS_CHANGED(cls, **kwargs): + return float("NaN") + @classmethod def INPUT_TYPES(cls): cls.BASE_INPUT["required"]["model"] = (cls.SUPPORTED_MODELS, {}) @@ -72,6 +76,7 @@ class BaseImageNode: # write buffer buffered = io.BytesIO() image_to_encode.save(buffered, format="PNG") + buffered.seek(0) return buffered @staticmethod @@ -87,7 +92,7 @@ class BaseImageNode: # Process images if len(result["data"]) == 0: raise ValueError("no image result") - if "b64_json" not in result["data"][0]: + if "b64_json" not in result["data"][0] or not result["data"][0]["b64_json"]: raise ValueError("no b64 json in result") image_bytes = base64.b64decode(result["data"][0]["b64_json"]) image = Image.open(io.BytesIO(image_bytes)) @@ -117,6 +122,23 @@ class BaseImageNode: "size": image_size } + # filter + input_types = self.INPUT_TYPES() + for key, settings in input_types["required"].items(): + if len(settings) > 1 and "enabled" in settings[1] and model not in settings[1]["enabled"]: + if key in kwargs: + del kwargs[key] + print(f"filtered input: {key} at models: {model}") + for key, settings in input_types["optional"].items(): + if len(settings) > 1 and "enabled" in settings[1] and model not in settings[1]["enabled"]: + if key == "reference_image": + reference_image = None + print("reference_image off") + continue + if key in kwargs: + del kwargs[key] + print(f"filtered input: {key} at models: {model}") + extra_params = {} if extra: @@ -125,8 +147,13 @@ class BaseImageNode: except json.decoder.JSONDecodeError: raise ValueError("extra not a json string") + payload, timeout, extra_params, reference_image, kwargs = self.post_input(payload, timeout, extra_params, reference_image, **kwargs) + return self.generate(client, headers, payload, timeout, extra_params, reference_image, **kwargs) + def post_input(self, payload: dict, timeout: int, extra_params: dict, reference_image=None, **kwargs) -> tuple[dict, int, dict, list, dict]: + return payload, timeout, extra_params, reference_image, kwargs + def generate(self, client: requests.Session, headers: dict[str, str], payload: dict, timeout: int, extra_params: dict, reference_image=None, **kwargs): # Implement it @@ -138,6 +165,7 @@ class OpenAICompatibleNode(BaseImageNode): def generate(self, client, headers, payload, timeout, extra_params, reference_image=None, **kwargs): payload.update(kwargs) payload.update(extra_params) + payload["n"] = 1 try: if reference_image is None: # generate mode, use json api @@ -146,7 +174,8 @@ class OpenAICompatibleNode(BaseImageNode): self.URL_GENERATIONS, headers=headers, json=payload, - timeout=timeout + timeout=timeout, + verify=False ) return self.read_image_result(response) @@ -154,7 +183,7 @@ class OpenAICompatibleNode(BaseImageNode): # edit mode, use form api # headers["Content-Type"] = "multipart/form-data" img = self.read_reference_image(reference_image) - files = {"image[]": img} + files = {"image": img} response = client.post( self.URL_EDIT, headers=headers, diff --git a/nodes.py b/nodes.py index 3af3b81..87b96b3 100644 --- a/nodes.py +++ b/nodes.py @@ -9,18 +9,42 @@ class WanxiangImage(OpenAICompatibleNode): "wanx2.1-t2i-plus", "wanx2.1-t2i-turbo", "wanx2.0-t2i-turbo", - "flux-dev", ] + EXTEND_INPUT = { + "optional": { + "reference_image": ("IMAGE", {"enabled": []}) + } + } + +class FluxImage(OpenAICompatibleNode): + SUPPORTED_MODELS = [ + "flux-dev" + ] + EXTEND_INPUT = { + "optional": { + "reference_image": ("IMAGE", {"enabled": []}) + } + } class HunyuanImage(OpenAICompatibleNode): SUPPORTED_MODELS = [ "hunyuan-image" ] + EXTEND_INPUT = { + "optional": { + "reference_image": ("IMAGE", {"enabled": []}) + } + } class OpenAIImage(OpenAICompatibleNode): SUPPORTED_MODELS = [ "gpt-image-1" ] + EXTEND_INPUT = { + "required": { + "quality": (["low", "medium", "high"], {"default": "medium"}), + } + } class SeedreamImage(VolcengineNode): SUPPORTED_MODELS = [ @@ -30,10 +54,18 @@ class SeedreamImage(VolcengineNode): ] EXTEND_INPUT = { "required": { - "seed": ("INT", {"default": "-1", "min": -1, "max": 2147483647}), + "seed": ("INT", {"default": "-1", "min": -1, "max": 2147483647, "enabled": ["doubao-seedream-3-0-t2i-250415", "doubao-seededit-3-0-i2i-250628"]}), "watermark": ("BOOLEAN", {"default": True}), }, "optional": { - "guidance_scale": ("FLOAT", {"min": 1, "max": 10}) + "reference_image": ("IMAGE", {"enabled": ["doubao-seedream-4-0-250828", "doubao-seededit-3-0-i2i-250628"]}), + "guidance_scale": ("FLOAT", {"min": 1, "max": 10, "enabled": ["doubao-seedream-3-0-t2i-250415", "doubao-seededit-3-0-i2i-250628"]}) } - } \ No newline at end of file + } + + def post_input(self, payload: dict, timeout: int, extra_params: dict, reference_image=None, **kwargs): + if payload["model"] == "doubao-seededit-3-0-i2i-250628": + payload["size"] = "adaptive" + if reference_image is None: + raise ValueError("doubao-seededit-3-0-i2i-250628需要参数:reference_image") + return payload, timeout, extra_params, reference_image, kwargs \ No newline at end of file diff --git a/register.py b/register.py index 51c6436..ebc3284 100644 --- a/register.py +++ b/register.py @@ -6,6 +6,7 @@ NODE_CLASS_MAPPINGS = { "OneThingAILoader": OneThingAILoader, "OnethingAIImageGemini":GeminiImage, "OnethingAIImageWanxiang":WanxiangImage, + "OnethingAIFlux":FluxImage, "OnethingAIImageHunyuan":HunyuanImage, "OnethingAIImageOpenAI":OpenAIImage, "OnethingAIImageSeedream": SeedreamImage @@ -16,6 +17,7 @@ NODE_DISPLAY_NAME_MAPPINGS = { "OneThingAILoader": "OneThingAI Image Generator", "OnethingAIImageGemini": "OneThingAI Gemini Image", "OnethingAIImageWanxiang": "OneThingAI Wanxiang Image", + "OnethingAIFlux": "OneThingAI Flux Image", "OnethingAIImageHunyuan": "OneThingAI Hunyuan Image", "OnethingAIImageOpenAI": "OneThingAI OpenAI Image", "OnethingAIImageSeedream": "OneThingAI Seedream Image"