* 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>
113 lines
3.7 KiB
Python
113 lines
3.7 KiB
Python
from .modelverse_api.utils import imageurl2tensor
|
|
from .modelverse_api.client import ModelverseClient
|
|
from .modelverse_api.requests.step1x_edit import Step1xEdit
|
|
import torch
|
|
from comfy.comfy_types.node_typing import IO
|
|
|
|
|
|
class Step1xEditNode:
|
|
"""
|
|
Step1X Edit Node
|
|
|
|
This node uses Modelverse's Step1X Edit API to transform photos with simple instructions.
|
|
"""
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"client": ("MODELVERSE_API_CLIENT",),
|
|
"prompt": (IO.STRING, {"multiline": True, "default": "", "tooltip": "The prompt to guide the image edit."}),
|
|
"negative_prompt": (IO.STRING, {"multiline": True, "default": "", "tooltip": "The negative prompt to use."}),
|
|
"image": (IO.IMAGE, {"default": None, "tooltip": "The image to be edited."}),
|
|
"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"
|
|
}),
|
|
"num_inference_steps": (IO.INT, {
|
|
"default": 30,
|
|
"min": 1,
|
|
"max": 50,
|
|
"step": 1,
|
|
"display": "number",
|
|
"tooltip": "Number of inference steps (1 to 50)"
|
|
}),
|
|
"guidance_scale": (IO.FLOAT, {
|
|
"default": 4.0,
|
|
"min": 0.0,
|
|
"max": 20.0,
|
|
"step": 0.1,
|
|
"display": "number",
|
|
"tooltip": "The CFG scale (0.0 to 20.0)"
|
|
}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = (IO.IMAGE, )
|
|
RETURN_NAMES = ("image", )
|
|
|
|
CATEGORY = "UCLOUD_MODELVERSE"
|
|
FUNCTION = "execute"
|
|
|
|
async def execute(self,
|
|
client,
|
|
prompt,
|
|
image,
|
|
negative_prompt,
|
|
num_requests=1,
|
|
seed=-1,
|
|
num_inference_steps=30,
|
|
guidance_scale=4.0):
|
|
|
|
if prompt is None or prompt == "":
|
|
raise ValueError("Prompt is required")
|
|
|
|
if image is None:
|
|
raise ValueError("Input image is required")
|
|
print("INFO:", "Running Step1X-Edit.")
|
|
|
|
client = ModelverseClient(client["api_key"])
|
|
|
|
tasks = [client.async_send_request(Step1xEdit(
|
|
prompt=prompt,
|
|
image=image,
|
|
negative_prompt=negative_prompt,
|
|
guidance_scale=guidance_scale,
|
|
num_inference_steps=num_inference_steps,
|
|
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 Step1xEditNode": Step1xEditNode
|
|
}
|
|
|
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
"Modelverse Step1xEditNode": "Modelverse Step1X Edit"
|
|
}
|