[u] 新增节点:toggle,修改知衣节点

This commit is contained in:
tangguancheng
2026-04-29 14:05:09 +08:00
parent 65268e9959
commit 2627f37078
6 changed files with 104 additions and 10 deletions
+1 -1
View File
@@ -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"}
+3
View File
@@ -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)",
}
+65
View File
@@ -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)",
}
+11 -2
View File
@@ -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"]
+12 -1
View File
@@ -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"]