Files
ucloud-comfyui-plugin/py/flux_kontext_max.py
T
jasonandjason.mei 681f6ebc5f support text generation
* add gitignore

* add video api

* fix: export to video

* fix

* fix

* fix

* fix

* fix

* add i2v

* fix

* fix

* add openai

* fix: add base url

* change default models

* fix: add base url

* add v1

* fix models

* fix models

* fix models

* fix models

* fix models

* fix bug

* fix

* try to fix

* use IO.STRING test

* image fix

* add chat content

* add files

* fix optional

* fix file read

* fix file read

* change name

* add get models

* add unused apikey

* change model sort

* fix IMAGE_LIST

* fix: change to image

* add model cache

* remove json_object

* change max_tokens to 65536

* change max_tokens to 6000

---------

Co-authored-by: jason.mei <jason.mei@ucloud.cn>
2025-09-15 15:31:26 +08:00

124 lines
4.2 KiB
Python

from .modelverse_api.utils import imageurl2tensor
from .modelverse_api.client import ModelverseClient
from .modelverse_api.requests.flux_kontext_max import FluxKontextMax, FluxKontextMaxMulti
import torch
from comfy.comfy_types.node_typing import IO
class FluxKontextMaxNode:
"""
Flux Image Generator Node (Kontext Max)
This node uses Modelverse's Flux model to generate high-quality images.
There are two modes available:
single image as input: single-image editing mode;
multiple images as input: multi-image editing mode;
"""
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"client": ("MODELVERSE_API_CLIENT",),
"prompt": (IO.STRING, {"multiline": True, "default": "", "tooltip": "Text description of the image to generate"}),
"images": ("IMAGE_LIST", {
"tooltip": "The image(s) to edit from. If not included, use text-to-image mode.",
"forceInput": False,
"default": None
}),
"num_requests": (IO.INT, {
"default": 1,
"min": 1,
"max": 10,
"step": 1,
"display": "number",
"tooltip": "Number of request to make (1 to 10)"
}),
"seed": (IO.INT, {
"default": -1,
"min": -1,
"max": 0xffffffffffffffff,
"control_after_generate": True,
"tooltip": "Random seed for reproducible results. -1 for random seed"
}),
"guidance_scale": (IO.FLOAT, {
"default": 2.5,
"min": 0.0,
"max": 10.0,
"step": 0.1,
"display": "number",
"tooltip": "Guidance scale for generation (0.0 to 10.0)"
}),
},
}
RETURN_TYPES = ("IMAGE", )
RETURN_NAMES = ("image",)
CATEGORY = "UCLOUD_MODELVERSE"
FUNCTION = "execute"
async def execute(self,
client,
prompt,
images,
num_requests=1,
seed=-1,
guidance_scale=3.5):
if prompt is None or prompt == "":
raise ValueError("Prompt is required")
if images is None:
raise ValueError("Input image(s) is required")
mode = "single"
if isinstance(images, list):
print("INFO:", "Running Flux Kontext Max multi-image edit mode.")
print(
"INFO:", f"{len(images)} image included for the multi-image edit.")
mode = "multi"
else:
print("INFO:", "Running Flux Kontext Max single-image edit mode.")
client = ModelverseClient(client["api_key"])
if mode == "multi":
tasks = [client.async_send_request(FluxKontextMaxMulti(
prompt=prompt,
images=images,
guidance_scale=guidance_scale,
seed=seed+i,
))
for i in range(num_requests)]
else:
tasks = [client.async_send_request(FluxKontextMax(
prompt=prompt,
image=images,
guidance_scale=guidance_scale,
seed=seed+i,
))
for i in range(num_requests)]
image_urls = await client.run_tasks(tasks)
output_images_list = []
for image_url in image_urls:
if not image_url:
print(
"WARN:", "No image URLs in the generated result in current request. Skipping...")
output_images = imageurl2tensor(image_url)
output_images_list.append(output_images)
print(
"INFO:", f"{len(output_images_list)}/{num_requests} request made successfully.")
return (torch.cat(output_images_list, dim=0),)
NODE_CLASS_MAPPINGS = {
"Modelverse FluxKontextMaxNode": FluxKontextMaxNode
}
NODE_DISPLAY_NAME_MAPPINGS = {
"Modelverse FluxKontextMaxNode": "Modelverse Flux Kontext Max"
}