diff --git a/nodes/fibo_edit_structured_instruction_node.py b/nodes/fibo_edit_structured_instruction_node.py index fe65dc1..2caf901 100644 --- a/nodes/fibo_edit_structured_instruction_node.py +++ b/nodes/fibo_edit_structured_instruction_node.py @@ -1,11 +1,9 @@ import requests -import torch - from .common import ( deserialize_and_get_comfy_key, image_to_base64, + normalize_images_input, poll_status_until_completed, - preprocess_image, ) @@ -19,7 +17,7 @@ class FIBOEditStructuredInstructionNode: return { "required": { "api_token": ("STRING", {"default": "BRIA_API_TOKEN"}), - "image": ("IMAGE",), + "images": ("IMAGE",), "instruction": ("STRING",), }, } @@ -33,53 +31,46 @@ class FIBOEditStructuredInstructionNode: if api_token.strip() == "" or api_token.strip() == "BRIA_API_TOKEN": raise Exception("Please insert a valid API token.") - def _build_payload(self, image, instruction): - # Process image - if isinstance(image, torch.Tensor): - processed_image = preprocess_image(image) - else: - processed_image = image - + def _build_payload(self, processed_image, instruction): payload = { "instruction": instruction, "images": [image_to_base64(processed_image)], } - return payload - def execute(self, api_token, image, instruction): + def execute(self, api_token, images, instruction): self._validate_token(api_token) - payload = self._build_payload(image, instruction) api_token = deserialize_and_get_comfy_key(api_token) - headers = {"Content-Type": "application/json", "api_token": api_token} + # Normalize input to list of PIL images + images = normalize_images_input(images) - try: - response = requests.post(self.api_url, json=payload, headers=headers) + batch_results = [] - if response.status_code in (200, 202): - print( - f"Initial request successful to {self.api_url}, polling for completion..." - ) + for idx, pil_image in enumerate(images): + try: + payload = self._build_payload(pil_image, instruction) + headers = {"Content-Type": "application/json", "api_token": api_token} + + response = requests.post(self.api_url, json=payload, headers=headers) + + if response.status_code not in (200, 202): + raise Exception(f"API request failed with status {response.status_code}: {response.text}") + + print(f"Initial request successful for image {idx}, polling for completion...") response_dict = response.json() status_url = response_dict.get("status_url") - request_id = response_dict.get("request_id") - if not status_url: raise Exception("No status_url returned from API") - print(f"Request ID: {request_id}, Status URL: {status_url}") - final_response = poll_status_until_completed(status_url, api_token) - result = final_response.get("result", {}) structured_instruction = result.get("structured_instruction", "") + batch_results.append(structured_instruction) - return (structured_instruction,) + except Exception as e: + print(f"[FIBOEditStructuredInstructionNode] Skipping image {idx} due to error: {e}") + batch_results.append("") - raise Exception( - f"Error: API request failed with status code {response.status_code} {response.text}" - ) - - except Exception as e: - raise Exception(f"{e}") \ No newline at end of file + combined_instructions = "\n---\n".join(batch_results) + return (combined_instructions,) \ No newline at end of file diff --git a/workflows/Fibo_edit_workflow.json b/workflows/Fibo_edit_workflow.json index a6208dd..be1829a 100644 --- a/workflows/Fibo_edit_workflow.json +++ b/workflows/Fibo_edit_workflow.json @@ -1,48 +1,9 @@ { "id": "3eb93704-25f0-4511-b147-cf0403c5d060", "revision": 0, - "last_node_id": 8, - "last_link_id": 9, + "last_node_id": 10, + "last_link_id": 11, "nodes": [ - { - "id": 2, - "type": "LoadImage", - "pos": [ - -245.09060668945312, - 882.640869140625 - ], - "size": [ - 274.080078125, - 314 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 4, - 6, - 8 - ] - }, - { - "name": "MASK", - "type": "MASK", - "links": null - } - ], - "properties": { - "Node name for S&R": "LoadImage" - }, - "widgets_values": [ - "0a9d91e579872d653daf3243df4598f0 (2).png", - "image" - ] - }, { "id": 7, "type": "PreviewImage", @@ -130,7 +91,7 @@ "widget": { "name": "structured_instruction" }, - "link": 7 + "link": 11 } ], "outputs": [ @@ -142,7 +103,7 @@ ] }, { - "name": "structured_prompt", + "name": "structured_instruction", "type": "STRING", "links": null }, @@ -166,44 +127,6 @@ "randomize" ] }, - { - "id": 5, - "type": "FIBOEditStructuredInstructionNode", - "pos": [ - -122.1817626953125, - 435.91400146484375 - ], - "size": [ - 314.6372985839844, - 82 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 6 - } - ], - "outputs": [ - { - "name": "structured_instruction", - "type": "STRING", - "links": [ - 7 - ] - } - ], - "properties": { - "Node name for S&R": "FIBOEditStructuredInstructionNode" - }, - "widgets_values": [ - "", - "change the lamp to a coffee mug" - ] - }, { "id": 4, "type": "FIBOEditNode", @@ -240,7 +163,7 @@ ] }, { - "name": "structured_prompt", + "name": "structured_instruction", "type": "STRING", "links": null }, @@ -263,6 +186,83 @@ 55, "randomize" ] + }, + { + "id": 2, + "type": "LoadImage", + "pos": [ + -245.09060668945312, + 882.640869140625 + ], + "size": [ + 274.080078125, + 314 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 4, + 8, + 10 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "0a9d91e579872d653daf3243df4598f0 (2).png", + "image" + ] + }, + { + "id": 10, + "type": "FIBOEditStructuredInstructionNode", + "pos": [ + -139.52833557128906, + 410.5189208984375 + ], + "size": [ + 314.6372985839844, + 82 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 10 + } + ], + "outputs": [ + { + "name": "structured_instruction", + "type": "STRING", + "links": [ + 11 + ] + } + ], + "properties": { + "Node name for S&R": "FIBOEditStructuredInstructionNode" + }, + "widgets_values": [ + "BRIA_API_TOKEN", + "" + ] } ], "links": [ @@ -282,22 +282,6 @@ 0, "IMAGE" ], - [ - 6, - 2, - 0, - 5, - 0, - "IMAGE" - ], - [ - 7, - 5, - 0, - 8, - 2, - "STRING" - ], [ 8, 2, @@ -313,6 +297,22 @@ 7, 0, "IMAGE" + ], + [ + 10, + 2, + 0, + 10, + 0, + "IMAGE" + ], + [ + 11, + 10, + 0, + 8, + 2, + "STRING" ] ], "groups": [], @@ -321,8 +321,8 @@ "ds": { "scale": 0.7522123482651067, "offset": [ - 958.445911560887, - -236.63172581276325 + 684.0553164416729, + -258.9658284524182 ] }, "frontendVersion": "1.25.11"