[u] 新增节点:toggle,修改知衣节点
This commit is contained in:
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "Comfyui_Fd_Nodes"
|
||||
version = "36.0.0" # 999开头的版本是debug版
|
||||
version = "37.0.0" # 999开头的版本是debug版
|
||||
description = "Custom nodes for fd project"
|
||||
authors = [
|
||||
{name = "xuyucai", email = "986327386@qq.com"}
|
||||
|
||||
@@ -50,6 +50,7 @@ from .prompt_nodes import EcommercePromptGenerator, PromptListSelector
|
||||
from .zhiyi_text_node import ZhiYiTextGenNode
|
||||
from .zhiyi_image_text_node import ZhiYiImageTextNode
|
||||
from .zhiyi_image_to_image_node import ZhiYiImageToImageNode
|
||||
from .toggle import NodeToggleByID
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -1152,6 +1153,7 @@ NODE_CLASS_MAPPINGS = {
|
||||
"ZhiYiImageTextNode": ZhiYiImageTextNode,
|
||||
"ZhiYiImageToImageNode": ZhiYiImageToImageNode,
|
||||
"ZhiYiTextGenNode": ZhiYiTextGenNode,
|
||||
"NodeToggleByID": NodeToggleByID,
|
||||
}
|
||||
|
||||
# A dictionary that contains the friendly/humanly readable titles for the nodes
|
||||
@@ -1170,4 +1172,5 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"ZhiYiImageTextNode": "知衣-图生文",
|
||||
"ZhiYiImageToImageNode": "知衣-图生图",
|
||||
"ZhiYiTextGenNode": "知衣-文生文",
|
||||
"NodeToggleByID": "节点开关 (按ID)",
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
class NodeToggleByID:
|
||||
"""
|
||||
根据节点 ID 标签批量开启或关闭工作流中的节点。
|
||||
node_switch: 0=关闭目标节点,1=开启目标节点
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"node_switch": ("INT", {
|
||||
"default": 1,
|
||||
"min": 0,
|
||||
"max": 1,
|
||||
"step": 1,
|
||||
"display": "number",
|
||||
}),
|
||||
"node_ids": ("STRING", {
|
||||
"default": "",
|
||||
"multiline": False,
|
||||
"placeholder": "节点ID列表,由前端动态管理",
|
||||
}),
|
||||
},
|
||||
"hidden": {
|
||||
"prompt": "PROMPT",
|
||||
"unique_id": "UNIQUE_ID",
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("status",)
|
||||
FUNCTION = "toggle_nodes"
|
||||
CATEGORY = "utils/node_control"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def toggle_nodes(self, node_switch, node_ids, prompt=None, unique_id=None):
|
||||
ids = [nid.strip() for nid in node_ids.split(",") if nid.strip()]
|
||||
|
||||
if not ids:
|
||||
return ("未指定任何节点 ID",)
|
||||
|
||||
enable = node_switch == 1
|
||||
action = "开启" if enable else "关闭"
|
||||
|
||||
if not prompt:
|
||||
return (f"将对 {len(ids)} 个节点执行{action}操作",)
|
||||
|
||||
status_parts = []
|
||||
for node_id in ids:
|
||||
if node_id in prompt:
|
||||
class_type = prompt[node_id].get("class_type", "未知")
|
||||
status_parts.append(f"节点 {node_id} ({class_type}): {action}")
|
||||
else:
|
||||
status_parts.append(f"节点 {node_id}: 未找到")
|
||||
|
||||
return ("\n".join(status_parts),)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"NodeToggleByID": NodeToggleByID,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"NodeToggleByID": "节点开关 (按ID)",
|
||||
}
|
||||
@@ -21,6 +21,13 @@ class ZhiYiImageTextNode:
|
||||
}),
|
||||
},
|
||||
"optional": {
|
||||
"node_switch": ("INT", {
|
||||
"default": 0,
|
||||
"min": 0,
|
||||
"max": 1,
|
||||
"step": 1,
|
||||
"display": "number",
|
||||
}),
|
||||
"system_prompt": ("STRING", {
|
||||
"default": "",
|
||||
"multiline": True,
|
||||
@@ -47,15 +54,17 @@ class ZhiYiImageTextNode:
|
||||
OUTPUT_NODE = False
|
||||
|
||||
def _image_tensor_to_base64(self, image_tensor):
|
||||
# ComfyUI IMAGE: shape (B, H, W, C), float32, 0~1
|
||||
arr = (image_tensor[0].numpy() * 255).clip(0, 255).astype(np.uint8)
|
||||
pil_img = Image.fromarray(arr)
|
||||
buf = io.BytesIO()
|
||||
pil_img.save(buf, format="PNG")
|
||||
return base64.b64encode(buf.getvalue()).decode("utf-8")
|
||||
|
||||
def generate(self, image, prompt,
|
||||
def generate(self, image, prompt, node_switch=1,
|
||||
system_prompt="", temperature=0.7, max_tokens=2048):
|
||||
if node_switch == 1:
|
||||
return ("",)
|
||||
|
||||
cfg = load_config()
|
||||
base_url = cfg["base_url"]
|
||||
api_key = cfg["api_key"]
|
||||
|
||||
@@ -48,6 +48,13 @@ class ZhiYiImageToImageNode:
|
||||
}),
|
||||
},
|
||||
"optional": {
|
||||
"node_switch": ("INT", {
|
||||
"default": 0,
|
||||
"min": 0,
|
||||
"max": 1,
|
||||
"step": 1,
|
||||
"display": "number",
|
||||
}),
|
||||
"image_2": ("IMAGE",),
|
||||
"image_3": ("IMAGE",),
|
||||
"image_4": ("IMAGE",),
|
||||
@@ -89,28 +96,23 @@ class ZhiYiImageToImageNode:
|
||||
raise RuntimeError("内容被过滤 (content_filter),请修改提示词或输入图片后重试")
|
||||
msg = choice["message"]
|
||||
|
||||
# 格式1: message.images[0].image_url.url
|
||||
if "images" in msg and msg["images"]:
|
||||
return msg["images"][0]["image_url"]["url"]
|
||||
|
||||
# 格式2: message.content 列表中含 image_url 类型
|
||||
content = msg.get("content", [])
|
||||
if isinstance(content, list):
|
||||
for part in content:
|
||||
if isinstance(part, dict):
|
||||
if part.get("type") == "image_url":
|
||||
return part["image_url"]["url"]
|
||||
# 格式3: type=image, 直接含 base64
|
||||
if part.get("type") == "image":
|
||||
return part.get("url") or part.get("data", "")
|
||||
|
||||
# 格式4: content 直接是 base64 字符串
|
||||
if isinstance(content, str) and len(content) > 100:
|
||||
return content
|
||||
|
||||
raise KeyError(f"无法从响应中提取图片,响应结构: {list(msg.keys())}")
|
||||
|
||||
# gemini image-preview 系列不支持 seed 参数
|
||||
MODELS_NO_SEED = {"gemini-3-pro-image-preview", "gemini-3.1-flash-image-preview"}
|
||||
|
||||
def _single_request(self, url, api_key, messages, model, aspect_ratio, image_size, seed):
|
||||
@@ -142,9 +144,13 @@ class ZhiYiImageToImageNode:
|
||||
return self._base64_to_tensor(out_data_url)
|
||||
|
||||
def generate(self, image_1, prompt, model, aspect_ratio, image_size,
|
||||
batch_size=1, seed_mode="随机种子", seed=0,
|
||||
batch_size=1, seed_mode="随机种子", seed=0, node_switch=1,
|
||||
image_2=None, image_3=None, image_4=None,
|
||||
image_5=None, image_6=None, system_prompt=""):
|
||||
if node_switch == 1:
|
||||
# 返回原图和 seed=0,保持输出类型一致
|
||||
return (image_1, 0)
|
||||
|
||||
cfg = load_config()
|
||||
base_url = cfg["base_url"]
|
||||
api_key = cfg["api_key"]
|
||||
|
||||
@@ -16,6 +16,13 @@ class ZhiYiTextGenNode:
|
||||
}),
|
||||
},
|
||||
"optional": {
|
||||
"node_switch": ("INT", {
|
||||
"default": 0,
|
||||
"min": 0,
|
||||
"max": 1,
|
||||
"step": 1,
|
||||
"display": "number",
|
||||
}),
|
||||
"system_prompt": ("STRING", {
|
||||
"default": "",
|
||||
"multiline": True,
|
||||
@@ -41,7 +48,11 @@ class ZhiYiTextGenNode:
|
||||
CATEGORY = "知衣/文生文"
|
||||
OUTPUT_NODE = False
|
||||
|
||||
def generate(self, prompt, system_prompt="", temperature=0.7, max_tokens=2048):
|
||||
def generate(self, prompt, node_switch=1,
|
||||
system_prompt="", temperature=0.7, max_tokens=2048):
|
||||
if node_switch == 1:
|
||||
return ("",)
|
||||
|
||||
cfg = load_config()
|
||||
base_url = cfg["base_url"]
|
||||
api_key = cfg["api_key"]
|
||||
|
||||
Reference in New Issue
Block a user