Article

模型工作流 ComfyUI

更新于:2026-07-20

ComfyUI 完全指南

第一章:ComfyUI 基础入门

1.1 什么是 ComfyUI?

概念名称说明注意事项
ComfyUI一个基于节点的工作流图形界面工具,用于构建和执行 Stable Diffusion 等生成式 AI 模型的推理流程。不是传统 GUI 图像生成器,而是可视化编程环境。
节点(Node)工作流中的基本功能单元,每个节点封装特定操作(如加载模型、生成图像、调整参数等)。节点之间通过数据端口连接,形成执行图。
工作流(Workflow)由多个节点及其连接关系构成的完整推理流程,可保存为 JSON 文件。工作流具有确定性,相同输入 + 相同节点配置 = 相同输出。
非破坏性编辑所有操作均可随时修改、重连、替换,不影响原始模型或数据。鼓励实验性搭建,无需担心”覆盖”结果。
开源与可扩展性ComfyUI 完全开源(MIT 许可),支持社区开发的自定义节点插件。插件质量参差不齐,需注意来源安全性。

1.2 安装与启动 ComfyUI

步骤名称操作细节注意事项
克隆官方仓库在终端执行:git clone https://github.com/comfyanonymous/ComfyUI.git需预先安装 Git;建议使用稳定分支(main)。
安装 Python 依赖进入 ComfyUI 目录后执行:pip install -r requirements.txt推荐使用 Python 3.10 或 3.11;避免系统全局 pip。
下载模型文件将 Stable Diffusion 模型(如 .ckpt.safetensors)放入 models/checkpoints/ 目录模型需用户自行提供,不可直接分发。
启动 ComfyUI 服务在终端执行:python main.py默认监听 http://127.0.0.1:8188;首次启动会自动下载部分依赖(如 torch)。
配置启动参数(可选)例如:python main.py --listen 0.0.0.0 --port 8080--listen 0.0.0.0 允许局域网访问;注意防火墙设置。
使用虚拟环境(推荐)创建并激活虚拟环境后再安装依赖,例如:python -m venv comfy_env && source comfy_env/bin/activate(Linux/macOS)Windows 用户使用 comfy_env\Scripts\activate

1.3 界面概览与基本操作

操作名称操作细节注意事项
添加节点右键画布空白处 → 选择节点类别(如 Loaders、Samplers)→ 点击具体节点类型也可通过快捷键 Ctrl+Space(Windows/Linux)或 Cmd+Space(macOS)打开搜索菜单。
移动画布按住空格键 + 鼠标左键拖动类似 Photoshop 导航方式。
连接节点端口从一个节点的输出端口(右侧圆点)拖拽到另一个节点的输入端口(左侧圆点)仅当数据类型兼容时才能连接(如 IMAGE → IMAGE)。
断开连接点击已连接的连线中间的小圆点,或拖拽连线末端离开端口无法直接删除单根连线,需通过断开操作。
执行工作流点击顶部工具栏的 “Queue Prompt” 按钮必须存在至少一个 “KSampler” 或等效执行节点,且输入完整。
查看生成结果结果自动显示在 “Preview Image” 节点或 “Save Image” 节点输出区域若无预览节点,需手动添加。
删除节点选中节点后按 Delete支持多选(框选或 Shift+点击)。
保存工作流点击顶部 “Save” 按钮(软盘图标),保存为 .json 文件仅保存节点结构与参数,不包含模型或图像数据。
加载工作流点击顶部 “Load” 按钮(文件夹图标),选择已保存的 .json 文件若缺少对应模型或自定义节点,可能报错或显示缺失节点。
自动布局(Auto Arrange)右键画布 → 选择 “Auto Arrange”有助于整理复杂工作流,但可能不完全符合用户逻辑顺序。

第二章:工作流(Workflow)构建基础

2.1 节点(Node)类型与功能分类

节点类别说明典型节点示例注意事项
加载器类(Loaders)用于加载模型、VAE、Lora、文本编码器等资源Load Checkpoint, Load VAE, Load Lora模型路径需正确;部分节点自动缓存以提升性能。
采样器类(Samplers)执行扩散过程的核心推理节点,控制生成质量与步数KSampler, KSampler Advanced必须连接正/负提示词和潜在空间输入;Advanced 版支持更细粒度控制。
编码/解码类将图像转为潜在表示(Encode)或将潜在表示还原为图像(Decode)CLIP Text Encode, VAEEncode, VAEDecodeCLIP 编码器输出 conditioning,非图像数据。
图像处理类对生成图像进行后处理,如缩放、裁剪、遮罩合成等Image Scale, Image Crop, MaskComposite输入必须是 IMAGE 类型;部分节点支持批处理。
条件控制类提供 ControlNet、T2I-Adapter、IP-Adapter 等高级控制信号ControlNet Apply, IPAdapter Apply需先加载对应 ControlNet 模型;图像尺寸需匹配主图。
实用工具类包括常量、数学运算、列表操作、调试输出等辅助功能Primitive, Math, Preview Image, Show TextPrimitive 节点可作为参数占位符;Preview 不影响流程执行。
自定义节点由社区或用户开发的扩展节点,功能多样Impact Pack, WAS Node Suite 等需手动安装插件;版本兼容性需注意。

2.2 连接节点:数据流与执行顺序

概念/操作名称说明示例/细节注意事项
数据端口(Port)节点左侧为输入端口,右侧为输出端口;每个端口有明确数据类型(如 IMAGE、LATENT、CONDITIONING)CLIP Text Encode 输出 CONDITIONING → KSampler 的 positive 输入类型不匹配时无法连接,系统会提示错误。
执行依赖关系ComfyUI 按数据依赖自动推导执行顺序,无需手动指定流程先执行 Load Checkpoint,再执行 KSampler无输入依赖的节点不会被执行。
多输入合并某些节点支持多个同类型输入(如多个 Lora 叠加)Load Lora → Model Merge(需通过特定节点实现叠加)并非所有节点支持多输入;需使用 ModelMerge 或 Apply Lora 链式调用。
分支与复用一个输出端口可连接到多个输入端口(广播)一个 KSampler 输出 IMAGE 可同时连到 Save Image 和 Image Scale数据会被复制,不影响原始值。
循环与递归限制ComfyUI 不支持显式循环结构;工作流为有向无环图(DAG)无法将节点输出直接或间接连回自身输入若需迭代效果,需借助外部脚本或多次执行。
惰性求值机制仅执行生成最终输出所必需的节点路径若删除 Save Image 节点且无其他输出,整个流程可能不执行调试时建议保留 Preview Image 或 Save Image 节点。

2.3 保存、加载与分享工作流

操作名称操作细节示例/用途注意事项
保存为 JSON点击顶部工具栏 “Save” 按钮(软盘图标),文件扩展名为 .jsonworkflow_v1.json仅包含节点配置、连接关系和参数,不含模型、图像或自定义节点代码。
加载 JSON 工作流点击 “Load” 按钮(文件夹图标),选择本地 .json 文件可恢复之前构建的复杂流程若缺少对应模型或插件节点,会显示红色”缺失节点”占位符。
导出带资源的工作流(非官方)使用第三方插件(如 ComfyUI-Manager)打包模型引用信息生成附带 model_info.json 的压缩包官方不支持自动打包模型,需手动管理依赖。
分享工作流.json 文件上传至社区平台(如 OpenArt、Civitai、GitHub Gist)供他人复现相同生成效果建议在描述中注明所需模型名称、版本及插件依赖。
工作流版本兼容性ComfyUI 更新可能导致旧工作流节点参数变化或废弃新版中某些节点重命名(如 “KSampler” → 保留但内部逻辑优化)建议定期备份工作流;重大更新前测试兼容性。
清理未连接节点右键画布 → “Clean Unconnected Nodes”移除调试残留或废弃节点,使工作流更清晰不影响已连接的有效流程。
工作流注释与分组使用 “Note” 节点添加文字说明;或使用 “Reroute” 整理连线在复杂流程中标注模块功能(如 “Face Refinement Section”)Note 节点不影响执行;Reroute 可减少连线交叉。

第三章:常用内置节点详解

3.1 加载器节点(Loaders)

方法名称语法(输入参数 → 输出)用途代码示例(节点配置片段)注意事项
Load Checkpoint输入:ckpt_name(str);输出:MODEL, CLIP, VAE加载完整 Stable Diffusion 模型"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": "realisticVisionV60B1_v60B1VAE.safetensors"}模型需位于 models/checkpoints/;首次加载较慢,后续缓存加速。
Load VAE输入:vae_name(str);输出:VAE单独加载 VAE 解码器"class_type": "VAELoader", "inputs": {"vae_name": "vae-ft-mse-840000-ema-pruned.safetensors"}可替换 checkpoint 自带的 VAE 以改善细节或修复色偏。
Load Lora输入:lora_name(str), strength_model(float), strength_clip(float);输出:MODEL, CLIP加载并应用 LoRA 微调权重"class_type": "LoraLoader", "inputs": {"lora_name": "add_detail.safetensors", "strength_model": 1.0, "strength_clip": 1.0}需先连接基础模型;多个 LoRA 需链式加载。
Load Textual Inversion输入:embedding_name(str);输出:CLIP加载嵌入向量(如 .pt/.bin)用于提示词扩展"class_type": "TextualInversionLoader", "inputs": {"embedding_name": "badhandv4.pt"}嵌入文件需放在 models/embeddings/;仅影响 CLIP 编码。
Load ControlNet Model输入:control_net_name(str);输出:CONTROL_NET加载 ControlNet 权重"class_type": "ControlNetLoader", "inputs": {"control_net_name": "control_canny-fp16.safetensors"}必须与 Apply ControlNet 节点配合使用。
Load Upscale Model输入:model_name(str);输出:UPSCALE_MODEL加载 ESRGAN/SwinIR 等超分模型"class_type": "UpscaleModelLoader", "inputs": {"model_name": "RealESRGAN_x4plus.pth"}用于 Image Upscale (Model) 节点。

3.2 模型推理节点(Models & Samplers)

方法名称语法(输入参数 → 输出)用途代码示例(节点配置片段)注意事项
KSampler输入:model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image;输出:LATENT标准扩散采样器"class_type": "KSampler", "inputs": {"seed": 12345, "steps": 20, "cfg": 7.0, "sampler_name": "dpmpp_2m", "scheduler": "karras", ...}最常用采样节点;latent_image 通常来自 Empty Latent Image。
KSampler Advanced输入:同上 + add_noise, start_at_step, end_at_step, return_with_leftover_noise;输出:LATENT高级采样器,支持分段采样与噪声控制"class_type": "KSamplerAdvanced", "inputs": {"add_noise": true, "start_at_step": 0, "end_at_step": 15, "return_with_leftover_noise": false}适用于 img2img、inpainting 或多阶段生成。
CLIP Text Encode输入:text(str), clip;输出:CONDITIONING将文本提示编码为条件向量"class_type": "CLIPTextEncode", "inputs": {"text": "a portrait of a cat wearing sunglasses", "clip": ["4", 1]}正负提示需分别编码后传入 KSampler。
Empty Latent Image输入:width(int), height(int), batch_size(int);输出:LATENT创建空白潜在空间张量"class_type": "EmptyLatentImage", "inputs": {"width": 512, "height": 768, "batch_size": 1}尺寸需匹配模型训练分辨率(通常 512 或 768)。
VAEEncode输入:pixels(IMAGE), vae;输出:LATENT将图像编码为潜在表示(用于 img2img)"class_type": "VAEEncode", "inputs": {"pixels": ["5", 0], "vae": ["2", 2]}图像需先经 Load Image 加载。
VAEDecode输入:samples(LATENT), vae;输出:IMAGE将潜在表示解码为 RGB 图像"class_type": "VAEDecode", "inputs": {"samples": ["3", 0], "vae": ["2", 2]}所有生成流程最终需此节点输出可视图像。

3.3 图像处理与后处理节点(Image Processing)

方法名称语法(输入参数 → 输出)用途代码示例(节点配置片段)注意事项
Load Image输入:image(str);输出:IMAGE, MASK从本地加载图像及透明通道遮罩"class_type": "LoadImage", "inputs": {"image": "input.png"}支持 PNG/JPG;MASK 仅当图像含 Alpha 通道时有效。
Save Image输入:images(IMAGE), filename_prefix(str);输出:—保存图像到 output 目录"class_type": "SaveImage", "inputs": {"filename_prefix": "my_output"}自动编号命名;路径不可自定义(除非修改源码)。
Preview Image输入:images(IMAGE);输出:—在 UI 中实时预览结果"class_type": "PreviewImage", "inputs": {"images": ["6", 0]}仅用于调试,不影响执行逻辑。
Image Scale输入:image(IMAGE), upscale_method(str), width(int), height(int), crop(str);输出:IMAGE调整图像尺寸"class_type": "ImageScale", "inputs": {"upscale_method": "lanczos", "width": 1024, "height": 1024, "crop": "center"}crop 可选 “disabled”, “center”, “top”, “bottom” 等。
Image Crop输入:image(IMAGE), width(int), height(int), x(int), y(int);输出:IMAGE裁剪指定区域"class_type": "ImageCrop", "inputs": {"width": 256, "height": 256, "x": 100, "y": 100}坐标原点在左上角;超出边界会报错。
MaskComposite输入:destination(IMAGE), source(IMAGE), mask(MASK), x(int), y(int), operation(str);输出:IMAGE将源图按遮罩合成到目标图"class_type": "MaskComposite", "inputs": {"operation": "add", "x": 0, "y": 0}operation 可为 “add”, “subtract”, “multiply” 等。
Image Blend输入:image1(IMAGE), image2(IMAGE), blend_factor(float);输出:IMAGE线性混合两张图像"class_type": "ImageBlend", "inputs": {"blend_factor": 0.5}两图尺寸必须一致。

3.4 条件与控制节点(Conditioning & Control)

方法名称语法(输入参数 → 输出)用途代码示例(节点配置片段)注意事项
ControlNet Apply输入:conditioning(CONDITIONING), control_net(CONTROL_NET), image(IMAGE), strength(float);输出:CONDITIONING应用 ControlNet 控制信号"class_type": "ControlNetApply", "inputs": {"strength": 0.8, "image": ["7", 0], "control_net": ["8", 0], "conditioning": ["9", 0]}image 尺寸应与生成图一致;strength 控制影响力。
IPAdapter Apply输入:ipadapter(IPADAPTER), model(MODEL), image(IMAGE), weight(float);输出:MODEL应用 IP-Adapter 图像提示"class_type": "IPAdapterApply", "inputs": {"weight": 0.6, "image": ["10", 0]}需先加载 IPAdapter 模型;支持多图输入(部分实现)。
Conditioning Combine输入:conditioning_1(CONDITIONING), conditioning_2(CONDITIONING);输出:CONDITIONING合并两个条件向量(如正提示+ControlNet)"class_type": "ConditioningCombine", "inputs": {"conditioning_1": ["11", 0], "conditioning_2": ["12", 0]}顺序可能影响结果;通常 ControlNet 条件后合并。
Conditioning Set Area输入:conditioning(CONDITIONING), width(int), height(int), x(int), y(int), strength(float);输出:CONDITIONING限制提示词作用区域"class_type": "ConditioningSetArea", "inputs": {"width": 256, "height": 256, "x": 100, "y": 100, "strength": 1.0}用于局部重绘或焦点控制。
T2I-Adapter Apply输入:conditioning, adapter(T2I_ADAPTER), image(IMAGE), weight(float);输出:CONDITIONING应用 T2I-Adapter(如深度图、姿态)"class_type": "T2IAdapterApply", "inputs": {"weight": 0.7, "image": ["13", 0]}需预处理输入图为对应特征图(如 Canny 边缘)。
GLIGEN Apply输入:conditioning, gligen_model, text(str), boxes(list);输出:CONDITIONING在指定框内生成特定对象(GLIGEN)"class_type": "GLIGENApply", "inputs": {"text": "a red apple", "boxes": [[0.2, 0.3, 0.4, 0.5]]}boxes 为归一化坐标 [x1, y1, x2, y2]

第四章:自定义节点开发

4.1 自定义节点结构与注册机制

方法/概念名称语法/说明用途代码示例注意事项
节点类定义继承 comfy.nodes.PreviewImage 或直接定义函数,使用 @classmethod 装饰器创建自定义功能逻辑见下方代码必须定义 INPUT_TYPES, RETURN_TYPES, FUNCTION, CATEGORY 四个类属性。
节点注册将节点类放入 __init__.py 或通过 NODE_CLASS_MAPPINGS 显式注册使 ComfyUI 能识别并加载节点NODE_CLASS_MAPPINGS = {"MyCustomNode": MyCustomNode}NODE_DISPLAY_NAME_MAPPINGS = {"MyCustomNode": "My Custom Node"}文件需放在 custom_nodes/your_plugin/ 目录下;重启 ComfyUI 生效。
插件目录结构custom_nodes/<插件名>/__init__.py标准化自定义节点组织方式custom_nodes/my_custom_node/ 下包含 __init__.pynodes.py避免直接修改 ComfyUI 核心代码;便于版本管理和分享。
动态加载机制ComfyUI 启动时自动扫描 custom_nodes/ 下所有子目录并导入 __init__.py无需手动配置即可加载社区插件插件若含语法错误会导致整个目录加载失败,建议独立测试。
节点显示名称映射使用 NODE_DISPLAY_NAME_MAPPINGS 定义 UI 中显示的友好名称提升用户界面可读性NODE_DISPLAY_NAME_MAPPINGS = {"MyCustomNode": "Uppercase Text Converter"}显示名可包含空格和特殊字符,不影响内部调用。

节点类定义代码示例:

class MyCustomNode:
    @classmethod
    def INPUT_TYPES(cls):
        return {"required": {"text": ("STRING", {"default": "hello"})}}

    RETURN_TYPES = ("STRING",)
    FUNCTION = "execute"
    CATEGORY = "custom/utils"

    def execute(self, text):
        return (text.upper(),)

4.2 输入输出定义与类型系统

方法/概念名称语法/说明用途代码示例注意事项
INPUT_TYPES 结构返回字典,含 "required" 和可选 "optional" 键,值为参数名到类型+配置的映射定义节点输入接口见下方代码支持类型包括:INT, FLOAT, STRING, BOOLEAN, IMAGE, LATENT, MODEL, CLIP, VAE, CONDITIONING, MASK 等。
RETURN_TYPES类属性,元组形式列出输出数据类型声明节点输出的数据类型RETURN_TYPES = ("IMAGE", "MASK")输出顺序必须与 execute 函数返回值一致。
RETURN_NAMES(可选)类属性,为每个输出指定 UI 显示名称提高工作流可读性RETURN_NAMES = ("processed_image", "alpha_mask")若未定义,默认使用 output_0, output_1
类型兼容规则只有相同或兼容类型才能连接(如 IMAGE → IMAGE保证数据流类型安全自定义类型需通过全局类型系统注册(不推荐初学者使用)。
默认值与约束INPUT_TYPES 中通过字典设置 default/min/max/step控制参数范围与初始值"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff})STRING 类型支持多行:{"default": "", "multiline": True}
多选/下拉菜单使用元组列表作为类型定义提供预设选项"mode": (["resize", "crop", "pad"], {"default": "resize"})用户只能从列表中选择,不可输入其他值。

INPUT_TYPES 完整示例:

@classmethod
def INPUT_TYPES(cls):
    return {
        "required": {
            "value": ("INT", {"default": 10, "min": 1, "max": 100})
        },
        "optional": {
            "multiplier": ("FLOAT", {"default": 1.0})
        }
    }

4.3 调试与日志输出方法

方法/操作名称语法/说明用途代码示例注意事项
print() 输出execute 方法中使用标准 Python print临时调试变量值def execute(self, text): print(f"[DEBUG] Input text: {text}"); return (text,)输出显示在启动 ComfyUI 的终端中;生产环境应移除。
logging 模块使用 Python 内置 logging 记录结构化日志更规范的日志管理import logging; logger = logging.getLogger(__name__); logger.info("Processing value: %s", x)需配置日志级别;默认 INFO 及以上会显示。
异常抛出raise ValueError 或其他异常提示用户输入错误if value <= 0: raise ValueError("Value must be positive")ComfyUI 会捕获异常并在 UI 中显示红色错误提示。
Preview Image 调试在自定义节点中返回 IMAGE 并连接 Preview Image 节点可视化中间结果RETURN_TYPES = ("IMAGE",);图像需为 [B, H, W, C] 格式,C=3,值范围 [0,1]注意数据格式。
临时保存中间结果使用 tempfile 或固定路径写入文件持久化调试数据with open("/tmp/debug_output.txt", "w") as f: f.write(str(data))注意路径跨平台兼容性;避免写入 ComfyUI 核心目录。
使用 comfy.utils调用 ComfyUI 内部工具函数(如 common_upscale复用已有图像处理逻辑from comfy.utils import common_upscale; upscaled = common_upscale(image, 1024, 1024, "lanczos", "center")需了解内部 API,可能随版本变动。

第五章:高级功能与扩展

5.1 批处理与循环节点

方法/概念名称语法/说明用途示例注意事项
Image Batch输入多个 IMAGE,自动合并为 batch 维度将多张图像打包成单个批次输入模型使用节点 “ImageBatch”:连接 image1, image2 → 自动输出 [B=2, H, W, C] 张量所有输入图像尺寸必须一致;否则报错。
Batch to Image List将 BATCH 图像拆分为图像列表便于对每张图单独后处理节点 “ImageListToImageBatch” 的逆操作;配合 “For Loop” 类插件使用官方 ComfyUI 无原生循环,需依赖插件(如 WAS Suite 或 Impact Pack)。
Primitive 节点 + 批提示使用 STRING 或 INT 的 Primitive 节点作为提示词/种子占位符实现参数批量替换创建 Primitive (STRING) → 连接到 CLIP Text Encode;保存工作流后,通过脚本修改 JSON 中的值实现批量生成需外部脚本驱动;非 UI 内置批处理。
Seed++ 节点(社区插件)自动生成递增种子序列快速生成多组随机结果安装 Impact Pack 后使用 “Seed++” 节点,设置起始 seed 和 count依赖第三方插件;非官方内置功能。
For Loop 模拟(WAS Suite)利用 “Math” + “Conditioning” + “Reroute” 构建有限迭代逻辑在无真正循环支持下模拟重复操作WAS Node Suite 提供 “While Loop” 和 “Index” 节点性能开销大;仅适用于轻量级重复任务。
批量保存命名Save Image 节点自动按序编号(00001_, 00002_…)区分同一批次中不同输出filename_prefix 设为 "batch_run" → 输出 batch_run_00001_.png, batch_run_00002_.png无法自定义命名规则(除非修改源码或使用插件)。

5.2 外部 API 集成与脚本调用

方法/操作名称语法/说明用途示例注意事项
启用 REST API启动 ComfyUI 时添加 --listen--port 参数允许外部程序通过 HTTP 请求触发工作流python main.py --listen 0.0.0.0 --port 8188默认仅本地访问;开放网络需注意安全。
API:获取队列状态GET /queue查询当前任务队列curl http://localhost:8188/queue返回 pending/running 任务列表。
API:执行工作流POST /prompt;Body: {"prompt": {...}, "extra_data": {}, "client_id": "..."}以编程方式提交完整工作流 JSON使用 Python requests:resp = requests.post("http://localhost:8188/prompt", json={"prompt": workflow_dict})workflow_dict 需与 .json 文件结构一致;需处理节点 ID 映射。
获取输出图像监听 WebSocket 或轮询 /history获取生成结果的文件名通过 client_id 关联请求与响应;从 /history/{prompt_id} 获取 output_images 字段推荐使用 WebSocket 实时监听(官方提供示例 client.py)。
调用外部脚本(Exec Node)使用 WAS Suite 的 “Text File Write” 或 “Python Script” 节点在工作流中执行系统命令或 Python 脚本”PythonScriptNode” 输入 code 字符串存在安全风险;默认禁用,需手动启用 exec 权限。
触发 Webhook在工作流末尾添加 HTTP 请求节点(需插件)生成完成后通知其他服务安装 ComfyUI-Advanced-ControlNet 或自定义节点,发送 POST 到 Slack/Discord webhook需处理网络异常和重试逻辑。
参数化工作流模板编写脚本动态替换 JSON 中的字段(如 prompt、seed)实现大规模自动化生成data["3"]["inputs"]["text"] = "a photo of " + subject节点 ID(如 “3”)可能随编辑变化,建议使用标签或注释辅助定位。

5.3 插件管理与社区资源

方法/操作名称语法/说明用途示例注意事项
ComfyUI-Manager 插件安装后提供 UI 界面管理插件一键安装/更新/卸载社区节点cd custom_nodes && git clone https://github.com/ltdrdata/ComfyUI-Manager.git需联网;部分插件依赖特定 Python 包。
插件依赖自动安装Manager 支持读取插件的 requirements.txt 并自动 pip install简化环境配置插件目录含 requirements.txt若系统无权限,需手动运行 pip install -r
社区资源平台Civitai、OpenArt、GitHub、Comfy-Org 官方仓库获取模型、工作流、节点插件Civitai 搜索 “ComfyUI workflow” → 下载 .json注意许可证(License)和兼容性(SD1.5 vs SDXL)。
插件冲突排查临时移除 custom_nodes/ 下插件目录测试定位导致崩溃或错误的插件mv ComfyUI-Impact-Pack /tmp/建议一次只启用一个新插件进行测试。
节点文档与示例大多数插件在 GitHub README 中提供节点图和参数说明快速上手复杂插件Impact Pack README 包含人脸检测、细节增强等完整工作流截图优先阅读官方文档,避免误用。
贡献与反馈在插件仓库提 Issue 或 PR报告 Bug 或贡献代码GitHub → Issues → 描述问题 + 附工作流 JSON + 错误日志提供可复现步骤将极大提升修复效率。

第六章:性能优化与部署

6.1 显存管理与模型卸载策略

方法/操作名称语法/说明用途示例注意事项
启用模型自动卸载extra_model_paths.yaml 或启动参数中配置减少显存占用,避免 OOM启动命令:python main.py --disable-smart-memory(注:默认已启用智能内存管理)ComfyUI 默认启用”按需加载+空闲卸载”;禁用后可能提升速度但增加显存压力。
手动触发模型清理使用内置节点 “FreeU” 或 “Model Sampling” 中的 unload 选项(部分插件支持)主动释放不再使用的模型Impact Pack 提供 “Unload Model” 节点,连接至工作流末尾官方节点无直接 unload 接口;依赖社区插件实现。
模型共享机制多个工作流共用同一 CLIP/VAE/MODEL 实例避免重复加载相同模型将 KSampler 和 CLIP Text Encode 连接到同一个 CheckpointLoader 节点输出若修改模型路径,所有引用将同步更新。
使用低精度推理(FP16)加载模型时自动使用半精度(若硬件支持)降低显存消耗,提升推理速度大多数 Checkpoint 模型在 RTX 显卡上默认以 FP16 加载;无需额外设置部分老模型或自定义 LoRA 可能出现数值不稳定。
显存监控工具通过 nvidia-smi 或集成日志观察显存变化诊断瓶颈终端运行:watch -n 1 nvidia-smiComfyUI 本身不提供显存面板;可结合第三方监控插件(如 ComfyUI-Manager 的状态栏)。
分块处理大图(Tiled VAE)启用 Tiled VAE 解码/编码支持超分辨率图像生成而不爆显存安装插件 ComfyUI-TiledDiffusion,使用 “Tiled VAE Decode” 节点替代标准 VAE Decode会略微降低图像连贯性;适用于 >2K 分辨率任务。

6.2 工作流加速技巧

方法/操作名称语法/说明用途示例注意事项
缓存中间结果(Cache Node)使用 “Cache” 节点(如 WAS Suite 提供)保存昂贵计算结果避免重复执行相同子流程将 ControlNet 预处理结果接入 Cache 节点 → 后续迭代直接读取缓存缓存基于输入哈希;输入不变则跳过计算。
禁用预览图生成在 Save Image 节点取消勾选 “Preview” 或移除 Preview Image 节点减少 CPU 图像解码开销删除工作流中所有 Preview Image 节点;或设置环境变量:COMFYUI_PREVIEW=0(部分版本支持)对批量生成场景提速明显。
使用更高效的采样器选择 DPM++ 2M Karras、UniPC 等快速收敛采样器在较少步数下获得高质量结果KSampler 节点:sampler_name = "dpmpp_2m_karras", steps = 20不同采样器对步数敏感度不同;建议测试对比。
并行工作流执行通过 API 同时提交多个独立 prompt利用 GPU 空闲周期提升吞吐多线程脚本并发调用 /prompt 接口(需确保 batch size 合理)GPU 利用率高时可能互相阻塞;建议监控队列长度。
优化图像尺寸输入图像尽量为 64 的倍数(如 512x768)避免内部 padding 带来的计算浪费使用 “Image Scale” 节点将输入统一缩放到 512x768 或 1024x1024SD1.5 最佳尺寸为 512;SDXL 为 1024。
预加载常用模型启动时自动加载高频模型(通过脚本或 Manager 插件)减少首次生成延迟使用 ComfyUI-Manager 的 “Model Auto Load” 功能,配置常驻模型列表会增加启动时间和初始显存占用。

6.3 Docker 部署与远程访问

方法/操作名称语法/说明用途示例注意事项
官方 Docker 镜像构建基于 GitHub 提供的 Dockerfile 构建快速容器化部署git clone https://github.com/comfyanonymous/ComfyUI.git; cd ComfyUI; docker build -t comfyui .需提前安装 NVIDIA Container Toolkit。
启用 GPU 支持运行容器时添加 --gpus all 参数使容器内程序可调用宿主机 GPUdocker run --gpus all -p 8188:8188 -v ./models:/ComfyUI/models comfyui确保宿主机已安装 nvidia-docker2。
持久化模型与工作流通过 -v 挂载宿主机目录到容器内保留模型、自定义节点和工作流-v /host/models:/ComfyUI/models -v /host/custom_nodes:/ComfyUI/custom_nodes -v /host/input:/ComfyUI/input路径需与容器内一致;注意文件权限。
远程 Web 访问绑定 0.0.0.0 并开放端口允许局域网或其他设备访问docker run -p 8188:8188 ... 并在启动命令中加 --listen 0.0.0.0生产环境建议加反向代理(Nginx)和身份验证。
环境变量配置通过 -e 设置 COMFYUI_ARGS 等变量动态调整启动参数docker run -e COMFYUI_ARGS="--listen 0.0.0.0 --port 8188 --disable-smart-memory" ...部分镜像需自定义 entrypoint 支持。
HTTPS 与认证(高级)结合 Nginx + Let’s Encrypt 或 Basic Auth安全远程访问在宿主机部署 Nginx:location / { auth_basic "Restricted"; proxy_pass http://localhost:8188; }ComfyUI 本身无用户系统;安全依赖外部层。

ComfyUI 自定义插件开发教程

第一章:ComfyUI 基础与插件机制概览

1.1 ComfyUI 核心架构简介

概念名称说明注意事项
节点(Node)ComfyUI 的基本功能单元,每个节点封装特定操作(如加载模型、生成图像等),通过输入/输出端口连接形成工作流。节点必须继承自特定基类并注册到节点系统中才能被 UI 识别。
工作流(Workflow)由多个节点及其连接关系构成的有向无环图(DAG),描述图像生成的完整流程。工作流以 JSON 格式保存,可通过前端导出/导入。
执行器(Executor)负责解析工作流图并按依赖顺序调度节点执行的后端组件。执行顺序由拓扑排序决定,不支持循环依赖。
服务端(Server)基于 Python 的 HTTP/WebSocket 服务,提供 API 接口、静态资源和 WebSocket 实时通信。默认使用 aiohttp 框架,监听 8188 端口。
前端(Frontend)基于 HTML/JavaScript 的图形化界面,用于构建和运行工作流。前端与后端通过 WebSocket 同步节点状态和执行结果。

1.2 插件系统工作原理

概念名称说明注意事项
插件自动发现机制ComfyUI 启动时会扫描 custom_nodes 目录下所有子目录,若包含 __init__.py 或符合特定命名规则,则尝试加载为插件。插件目录名不能以 _ 开头,否则会被跳过。
节点注册机制插件通过定义函数并使用 @classmethod 或直接在模块顶层调用注册方法(如 NODE_CLASS_MAPPINGS)向系统注册节点类。必须同时提供 NODE_CLASS_MAPPINGSNODE_DISPLAY_NAME_MAPPINGS(可选但推荐)。
模块隔离每个插件作为独立 Python 模块加载,避免全局命名冲突。插件内部应避免修改全局状态或 monkey-patch 核心模块。
动态重载支持在开发模式下,可通过重启服务或使用热重载工具(如 watchdog)实现插件代码更新后自动生效。Colab 环境通常需手动重启内核以加载新插件。
依赖管理插件可自带 requirements.txt,用户需手动安装依赖;部分启动脚本(如 main.py --install-deps)可自动处理。不建议在插件中硬编码 pip 安装命令,应引导用户显式安装依赖。

1.3 插件目录结构规范

组成部分说明注意事项
custom_nodes/your_plugin_name/插件根目录,名称应具有唯一性和描述性(如 ComfyUI-ExamplePlugin)。目录名将影响模块导入路径,避免使用空格或特殊字符。
__init__.py插件入口文件,必须包含 NODE_CLASS_MAPPINGS 字典,用于注册节点类。若缺失此文件,ComfyUI 将忽略该目录。
nodes.py(或其他模块文件)实际定义节点类的 Python 文件,可按功能拆分为多个模块。节点类需继承 object,无需特定父类,但需实现标准接口(如 INPUT_TYPES, RETURN_TYPES 等)。
requirements.txt列出插件依赖的第三方 Python 包(如 torchvision, opencv-python)。用户需自行运行 pip install -r requirements.txt,ComfyUI 不自动安装。
__pycache__/.gitignore缓存目录或版本控制忽略文件,不影响功能。建议在 .gitignore 中排除 __pycache__.ipynb_checkpoints 等临时文件。
web/(可选)存放自定义前端资源(如 JS、CSS),用于扩展 UI 控件。需配合后端路由注册,普通插件通常不需要。
LICENSE / README.md开源许可证和使用说明,提升插件可用性与合规性。社区分发时强烈建议包含。

第二章:本地与 Colab 环境搭建

2.1 本地 ComfyUI 安装与运行

步骤名称操作细节注意事项
克隆官方仓库在终端执行:git clone https://github.com/comfyanonymous/ComfyUI.git建议使用稳定分支(如 master),避免直接使用开发中 commit。
安装 Python 依赖进入目录后运行:pip install -r requirements.txt需 Python ≥ 3.9;建议在虚拟环境(venv 或 conda)中操作。
安装 PyTorch根据 CUDA 版本从 PyTorch 官网安装对应版本,例如:pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121不要使用 requirements.txt 中的 CPU 版本(若需 GPU 支持)。
启动服务执行:python main.py默认监听 127.0.0.1:8188,如需局域网访问加参数 --listen 0.0.0.0
访问 WebUI在浏览器打开:http://127.0.0.1:8188若启用 --listen,可从其他设备访问本机 IP。
安装自定义插件将插件目录放入 ComfyUI/custom_nodes/ 下,重启服务生效插件目录需含 __init__.py,否则不会被加载。

2.2 在 Google Colab 中部署 ComfyUI

步骤名称操作细节注意事项
创建新 Colab 笔记本在 Google Drive 中新建 .ipynb 文件,选择 GPU 运行时(Runtime → Change runtime type → GPU)免费版 Colab 有运行时长限制(通常 ≤ 12 小时)。
克隆 ComfyUI 仓库执行:!git clone https://github.com/comfyanonymous/ComfyUI.git使用 ! 表示 shell 命令,在 Colab cell 中运行。
安装依赖执行:%cd ComfyUI!pip install -r requirements.txtColab 已预装 PyTorch,通常无需重新安装,但需确认版本兼容性。
启动 ComfyUI 服务执行:!python main.py --listen 0.0.0.0 --port 8188必须加 --listen 0.0.0.0 才能通过隧道访问。
建立公网隧道使用 ngrok:先 !pip install pyngrok,再 from pyngrok import ngrok; ngrok.set_auth_token("YOUR_TOKEN"); public_url = ngrok.connect(8188)ngrok 需注册账号获取免费 token;也可用 Cloudflare Tunnel 替代。
获取访问链接打印 public_url 并在新标签页打开首次加载可能较慢,因需下载模型或初始化资源。

2.3 持久化插件开发环境配置(Colab)

步骤名称操作细节注意事项
挂载 Google Drive执行:from google.colab import drive; drive.mount('/content/drive')插件代码建议存于 Drive 以避免会话丢失。
软链接插件目录将 Drive 中的插件目录链接到 ComfyUI:!ln -s /content/drive/MyDrive/comfy_plugins /content/ComfyUI/custom_nodes/my_plugin使用符号链接(symlink)便于实时同步代码修改。
自动安装插件依赖在启动前运行:!pip install -r /content/drive/MyDrive/comfy_plugins/requirements.txt避免每次重启都手动安装依赖。
保存启动脚本将完整启动流程写入 .py.sh 文件并存于 Drive,例如 start_comfy.py可封装 ngrok 启动、路径设置等逻辑,提高复用性。
使用 Colab Notebook 单元格组织流程分别创建”挂载”、“克隆”、“链接插件”、“启动服务”等单元格便于调试和按需重跑部分步骤。
备份工作流 JSON将常用工作流导出为 .json 并保存至 Drive防止 Colab 会话结束后丢失工作流配置。

第三章:自定义节点开发基础

3.1 节点类的基本结构

方法/属性名称语法用途代码示例注意事项
类定义class MyNode:定义一个自定义节点类,无需继承特定父类class ImageProcessor:类名应具有描述性,避免与内置节点冲突
@classmethod 或模块级字典NODE_CLASS_MAPPINGS = {"MyNode": MyNode}将节点类注册到 ComfyUI 系统中NODE_CLASS_MAPPINGS = {"ImageProcessor": ImageProcessor}必须在插件的 __init__.py 或顶层模块中定义
NODE_DISPLAY_NAME_MAPPINGSNODE_DISPLAY_NAME_MAPPINGS = {"MyNode": "My Custom Node"}为节点指定在 UI 中显示的友好名称NODE_DISPLAY_NAME_MAPPINGS = {"ImageProcessor": "Image Enhancer"}可选,但推荐提供以提升用户体验
FUNCTION 类属性FUNCTION = "process"指定节点执行时调用的实例方法名FUNCTION = "enhance_image"默认为 "execute",若使用其他名称需显式声明
CATEGORY 类属性CATEGORY = "image/postprocessing"定义节点在 UI 菜单中的分类路径CATEGORY = "my_plugins/image"使用斜杠分隔层级,便于组织
RETURN_TYPESRETURN_TYPES = ("IMAGE",)声明节点输出的数据类型(用于类型检查和连接验证)RETURN_TYPES = ("IMAGE", "MASK")必须为元组,即使只有一个输出
RETURN_NAMES(可选)RETURN_NAMES = ("enhanced_image", "alpha_mask")为输出端口指定 UI 显示名称RETURN_NAMES = ("output_img",)若未提供,则使用默认名称如 "output 0"

3.2 输入输出定义方法

方法/属性名称语法用途代码示例注意事项
INPUT_TYPES 类方法@classmethod def INPUT_TYPES(cls): return {...}定义节点的所有输入参数及其类型、默认值和 UI 控件见下方示例必须为类方法,返回嵌套字典
输入类型:"STRING""prompt": ("STRING", {"default": "hello"})接收文本字符串输入"text": ("STRING", {"multiline": True})支持 multiline, dynamicPrompts 等选项
输入类型:"INT" / "FLOAT""steps": ("INT", {"default": 20, "min": 1, "max": 100})接收整数或浮点数,可设范围"scale": ("FLOAT", {"default": 7.5, "min": 0.0, "max": 20.0})step 参数可控制滑块步长
输入类型:"BOOLEAN""use_gpu": ("BOOLEAN", {"default": True})布尔开关"flip": ("BOOLEAN", {"default": False})UI 显示为复选框
输入类型:数据类(如 "IMAGE""image": ("IMAGE",)接收来自其他节点的数据流(如图像张量)"latent": ("LATENT",)类型名必须大写,且与输出类型匹配
动态输入("required" vs "optional"INPUT_TYPES 中分组定义区分必填与可选输入{"required": {...}, "optional": {"mask": ("MASK",)}}optional 字段在 UI 中可折叠,缺失时传入 None
自定义下拉菜单"mode": (["fast", "quality"], {"default": "fast"})提供枚举选项"scheduler": (["euler", "ddim"],)第一个元素是选项列表,必须为 list 或 tuple

INPUT_TYPES 完整代码示例:

@classmethod
def INPUT_TYPES(cls):
    return {
        "required": {
            "text": ("STRING", {"multiline": True}),
            "strength": ("FLOAT", {"default": 0.8, "min": 0.0, "max": 1.0})
        },
        "optional": {
            "image": ("IMAGE",)
        }
    }

3.3 执行逻辑与数据流控制

方法/属性名称语法用途代码示例注意事项
执行方法(由 FUNCTION 指定)def process(self, text, strength, image=None): ...实现节点核心逻辑,接收输入并返回输出def enhance(self, image, factor=1.0): return (enhanced_img,)参数名必须与 INPUT_TYPES 中键名一致
返回值格式return (output1, output2, ...)返回元组,顺序对应 RETURN_TYPESreturn (processed_image, mask_tensor)必须为元组,即使只有一个输出也要加逗号
张量数据格式(IMAGE)torch.Tensor,shape: (B, H, W, C)ComfyUI 图像标准格式(B=批量, C=通道=3 或 4)img = torch.clamp(img, 0, 1)像素值通常为 [0, 1] 浮点数,非 [0,255]
错误处理使用 raise ValueError("message")抛出异常将中断工作流并在 UI 显示错误if image is None: raise ValueError("Image input required")避免静默失败,应提供明确错误信息
日志输出print()logging调试时输出信息到控制台print(f"Processing image of shape {image.shape}")Colab 中可在运行单元格下方查看输出
无副作用原则不修改输入张量,返回新对象保证工作流可重入与并行安全output = input_tensor.clone()直接修改输入可能导致上游节点状态污染

第四章:高级节点功能实现

4.1 动态输入/输出端口

方法/属性名称语法用途代码示例注意事项
RETURN_TYPES 动态设置在执行方法内动态返回类型允许根据条件改变输出类型或数量return ("STRING", "IMAGE") if condition else ("STRING",)必须确保逻辑清晰且可预测,避免混乱的连接
RETURN_NAMES 动态设置(可选)同样可以在执行方法内动态返回名称根据实际输出情况调整显示名称return ("processed_text", "modified_image") if condition else ("original_text",)提高用户理解度,但需与 RETURN_TYPES 对应
INPUT_TYPES 动态配置通过类变量或执行时逻辑修改支持基于上下文变化的输入端口使用类变量控制 INPUT_TYPES 或在运行时修改可能影响节点复用性,谨慎使用
条件输入定义可选或条件性输入提供更灵活的节点接口设计"optional_input": ("FLOAT", {"default": 0.5, "optional": True})确保 UI 能够正确处理并展示这些输入

示例代码:

def process(self, text, optional_input=None):
    # 根据某些条件决定是否需要使用 optional_input
    if optional_input is not None:
        processed = f"{text} with {optional_input}"
        return (processed,)
    else:
        return (text,)

4.2 自定义 UI 控件集成

方法/属性名称语法用途代码示例注意事项
INPUT_TYPES 中添加自定义控件"custom_widget": ("CUSTOM_WIDGET", {...})在节点 UI 中集成特殊控件如滑块、下拉菜单等"quality": ("INT", {"widget": "slider", "min": 1, "max": 10})需要框架支持特定控件,否则可能无效
注册自定义控件在插件初始化阶段注册自定义控件类型扩展 ComfyUI 以支持更多类型的 UI 组件NODE_CUSTOM_WIDGETS = {"MyNode": {"custom_slider": {"type": "slider", "min": 0, "max": 1}}}必须确保控件逻辑正确实现,并遵循框架规范
获取自定义控件值在执行方法中正常接收参数使用自定义控件获取用户输入def execute(self, custom_slider_value): ...自定义控件值如同普通参数一样传递和使用

示例代码:

@classmethod
def INPUT_TYPES(cls):
    return {
        "required": {
            "image_quality": ("INT", {"widget": "slider", "min": 1, "max": 10})
        }
    }

def execute(self, image_quality):
    print(f"Processing image at quality level: {image_quality}")
    ...

4.3 异步与多线程处理

方法/属性名称语法用途代码示例注意事项
异步函数定义使用 async def 定义异步执行方法实现非阻塞操作,提高效率async def async_process(self, input_data): await asyncio.sleep(1); return result需要框架支持异步调用,且注意异常处理
多线程执行使用 Python threading 模块或第三方库并行处理数据,加速计算密集型任务from threading import Thread; thread = Thread(target=compute_heavy_task); thread.start()小心管理共享资源,避免死锁和竞争条件
回调机制设计回调函数或使用事件监听器在任务完成后通知其他组件或更新 UIon_complete=lambda result: print("Task done!")保证回调逻辑简洁可靠,防止内存泄漏

示例代码(简化版异步):

import asyncio

class AsyncProcessor:
    async def async_execute(self, data):
        await asyncio.sleep(2)  # 模拟耗时操作
        return f"Processed {data}"

# 在主程序或框架适配层中调用
async def main():
    processor = AsyncProcessor()
    result = await processor.async_execute("example")
    print(result)

第五章:模型与资源加载机制

5.1 加载自定义模型(LoRA、Checkpoint 等)

方法/属性名称语法用途代码示例注意事项
folder_paths.get_folder_paths("checkpoints")folder_paths.get_folder_paths("checkpoints")获取 ComfyUI 配置的 checkpoint 模型目录列表ckpt_dirs = folder_paths.get_folder_paths("checkpoints")返回的是列表,可能包含多个路径(如主目录 + extra_model_paths
folder_paths.get_filename_list("loras")folder_paths.get_filename_list("loras")获取指定类型模型的可用文件名列表(不含路径)lora_names = folder_paths.get_filename_list("loras")支持类型包括 "checkpoints", "loras", "vae", "clip", "unet"
load_checkpoint_guess_config()load_checkpoint_guess_config(ckpt_path)自动推断并加载 Stable Diffusion checkpoint 模型model, clip, vae = load_checkpoint_guess_config(ckpt_path)来自 comfy.sd 模块,适用于 .safetensors.ckpt
LoraLoader.load_lora()LoraLoader().load_lora(model, clip, lora_path, strength_model, strength_clip)应用 LoRA 权重到模型和 CLIPmodel_lora, clip_lora = LoraLoader().load_lora(model, clip, lora_path, 1.0, 1.0)需先加载基础模型,再叠加 LoRA
自定义模型加载节点继承标准节点模式,调用上述 API在插件中封装模型加载逻辑供用户使用见下方完整示例必须处理路径合法性、文件存在性检查

完整节点示例(简化):

import folder_paths
from comfy.sd import load_checkpoint_guess_config

class CustomCheckpointLoader:
    @classmethod
    def INPUT_TYPES(cls):
        return {"required": {"ckpt_name": (folder_paths.get_filename_list("checkpoints"),)}}

    RETURN_TYPES = ("MODEL", "CLIP", "VAE")
    FUNCTION = "load"
    CATEGORY = "custom/loaders"

    def load(self, ckpt_name):
        ckpt_path = folder_paths.get_full_path("checkpoints", ckpt_name)
        model, clip, vae = load_checkpoint_guess_config(ckpt_path)
        return (model, clip, vae)

5.2 资源路径管理与缓存策略

概念/方法名称说明用途代码示例注意事项
folder_paths.add_model_folder_path(type_name, path)向指定模型类型注册额外搜索路径扩展模型加载范围(如挂载 Google Drive 目录)folder_paths.add_model_folder_path("loras", "/content/drive/MyDrive/lora")需在 ComfyUI 启动早期调用(如插件 __init__.py 中)
folder_paths.get_full_path(type_name, filename)根据类型和文件名拼接完整绝对路径安全获取模型文件路径,避免硬编码full_path = folder_paths.get_full_path("vae", "vae-ft-mse-840000-ema-pruned.safetensors")若文件不存在于任何注册路径,返回 None
模型缓存机制(ComfyUI 内部)自动缓存已加载的模型(基于路径哈希)避免重复加载相同模型,节省显存和时间无需用户干预,由 ModelPatcher 等内部类管理缓存键为文件路径,重命名文件会视为新模型
手动清除缓存使用 delgc.collect() 释放模型对象在 Colab 等内存受限环境中主动回收资源del model; torch.cuda.empty_cache()显式删除变量后调用 PyTorch 清理 GPU 缓存
extra_model_paths.yaml配置文件,用于全局添加模型搜索路径无需修改代码即可扩展模型目录见下方示例重启服务后生效,适用于多插件共享路径

extra_model_paths.yaml 示例片段:

my_models:
  base_path: /content/drive/MyDrive/AI_Models
  checkpoints: models/Stable-diffusion
  loras: models/Lora

5.3 兼容 WebUI 模型格式

概念/方法名称说明用途代码示例注意事项
WebUI Checkpoint 格式.ckpt.safetensors 文件,包含 UNet、VAE、CLIP 权重ComfyUI 原生支持此类格式,可直接加载与 5.1 中 load_checkpoint_guess_config 兼容不需要转换,但需注意部分 WebUI 特有变体(如 Inpainting 模型)可能缺少 VAE
WebUI LoRA 格式单一 .safetensors 文件,含 lora_unet_*lora_te_*ComfyUI 的 LoraLoader 完全兼容可直接通过 LoraLoader 节点加载确保 LoRA 名称不包含非法字符(如空格、中文)
嵌入(Embeddings / Textual Inversion)存放于 embeddings/ 目录的 .pt.bin 文件ComfyUI 通过 CLIPLoader 自动识别并加载用户在文本提示中使用 <embedding_name> 即可文件名即为关键词,不支持子目录(除非手动注册路径)
VAE 模型兼容性WebUI 的 vae-ft-mse-*.safetensors 可直接用于 ComfyUI替换默认 VAE 以改善图像质量通过 VAELoader 节点加载若 checkpoint 已内嵌 VAE,需显式替换才生效
模型元数据缺失处理WebUI 模型通常无配置文件(如 config.jsonComfyUI 通过权重结构自动推断模型类型load_checkpoint_guess_config 内部实现猜测逻辑极少数非标模型可能加载失败,需手动指定配置

第六章:插件打包与分发

6.1 插件元数据配置(__init__.pypyproject.toml

配置项/文件语法/结构用途示例注意事项
__init__.py 中的 NODE_CLASS_MAPPINGS字典,键为节点标识符,值为类对象向 ComfyUI 注册所有自定义节点NODE_CLASS_MAPPINGS = {"MyNode": MyNodeClass}必须存在,否则插件不会被识别
NODE_DISPLAY_NAME_MAPPINGS字典,键同上,值为 UI 显示名提供用户友好的节点名称NODE_DISPLAY_NAME_MAPPINGS = {"MyNode": "My Custom Processor"}可选,但强烈推荐
__init__.py 中的 __all__(可选)列表,指定公开接口控制 from plugin import * 的行为__all__ = ["MyNodeClass"]非必需,主要用于代码规范
pyproject.toml(标准格式)使用 TOML 语法描述项目元数据支持现代 Python 构建工具(如 pip install -e .见下方完整示例若仅用于 ComfyUI,非强制,但利于分发
pyproject.toml[project] 区块定义名称、版本、依赖等声明插件基本信息和运行依赖name = "comfyui-myplugin"dependencies = ["opencv-python"]名称建议以 comfyui- 开头,便于识别
pyproject.toml[tool.comfy](社区约定)自定义扩展字段(非官方但常用)标注插件类别、作者、兼容性等[tool.comfy]display_name = "My Plugin"author = "Alice"目前无官方 schema,但部分管理器(如 ComfyUI-Manager)会读取

pyproject.toml 完整示例:

[build-system]
requires = ["setuptools >= 61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "comfyui-image-enhancer"
version = "1.0.0"
description = "A ComfyUI plugin for image post-processing"
dependencies = [
    "opencv-python>=4.5.0",
    "numpy"
]

[tool.comfy]
display_name = "Image Enhancer"
author = "Your Name"
category = "postprocessing"

6.2 GitHub 发布与自动更新机制

操作/机制名称操作细节用途示例注意事项
创建 GitHub 仓库在 GitHub 上新建仓库,命名如 ComfyUI-MyPlugin托管插件源码,便于协作与分发仓库 URL: https://github.com/yourname/ComfyUI-MyPlugin建议遵循 ComfyUI-<PluginName> 命名惯例
添加 Release 版本使用 GitHub Releases 发布带版本号的 ZIP 包用户可通过版本号稳定安装Tag: v1.0.0,附带源码 ZIP确保包含 __init__.py 和必要资源
支持 git clone 安装用户执行 git clone <url> custom_nodes/xxx最常用安装方式,支持热更新git clone https://github.com/.../ComfyUI-MyPlugin插件目录名不影响功能,但影响导入路径
实现自动更新检测(通过 ComfyUI-Manager)在插件根目录添加 .gitinstall.json兼容第三方插件管理器的更新检查无需额外代码,只要是从 Git 安装即可用户需安装 ComfyUI-Manager
install.json(可选)JSON 文件,声明依赖和启动脚本供 ComfyUI-Manager 自动安装依赖{"pip": ["opencv-python"], "git": []}放在插件根目录,非官方但广泛支持
使用 GitHub Actions(可选)编写 CI 脚本进行基本测试确保主分支代码可运行触发 pytest 或语法检查对简单插件非必需,但提升专业性

install.json 示例:

{
  "pip": ["opencv-python", "scikit-image"],
  "git": []
}

6.3 社区插件注册与兼容性测试

机制/操作名称说明用途示例/操作注意事项
提交至 ComfyUI-Manager 插件列表在其 GitHub 仓库提交 PR 更新 custom-node-list.json让用户能在 UI 中一键安装你的插件Fork ComfyUI-Manager,修改列表文件需提供有效仓库 URL 和分类
兼容性标签(如 comfyui_version在文档或 pyproject.toml 中声明支持的 ComfyUI 版本范围避免用户在不兼容版本中使用"compatible_comfyui": ">=0.3.0"目前无强制校验,靠社区自律
基础兼容性测试在本地或 Colab 中验证:1) 能加载;2) 节点可连接;3) 能出图确保插件在主流环境中正常工作使用默认 SD1.5 checkpoint 测试全流程至少测试 CPU + GPU(如有)两种模式
避免全局副作用不修改 sys.path、不 monkey-patch 核心模块防止与其他插件冲突使用局部导入,不执行顶层副作用代码插件应”即插即用”,卸载后无残留影响
提供 example_workflow.json附带一个可运行的工作流示例降低用户上手门槛存放于插件根目录或 examples/ 子目录工作流应仅依赖公开模型或提供下载链接
遵循开源许可证在仓库中包含 LICENSE 文件明确使用和分发条款MIT、Apache-2.0 等宽松许可证更受欢迎无 LICENSE 默认保留所有权利,不利于传播

第七章:Colab 环境下的插件调试技巧

7.1 实时日志查看与错误追踪

方法/操作名称操作细节用途示例注意事项
使用 print() 输出调试信息在节点执行方法中插入 print() 语句查看变量值、执行路径、中间结果print(f"Input shape: {image.shape}")Colab 单元格输出区域会实时显示,但需确保服务在前台运行
捕获异常并打印完整 traceback使用 try...except + traceback.format_exc()获取详细的错误堆栈,便于定位问题import traceback; try: result = risky_operation() except Exception as e: print("Error:", traceback.format_exc())避免仅打印 str(e),会丢失上下文
将日志重定向到文件启动 ComfyUI 前设置日志文件持久化记录,便于回溯分析`python main.py —listen 0.0.0.0 2>&1tee comfy.log`
监控 GPU 显存使用在单元格中定期运行 !nvidia-smi检查是否因显存泄漏导致崩溃在独立单元格中执行 !nvidia-smiColab 免费版 GPU 显存有限(通常 ≤ 15GB),需谨慎管理
使用 logging 模块(可选)配置 Python logging 输出到控制台结构化日志,支持多级别(DEBUG/INFO/ERRORimport logging; logging.basicConfig(level=logging.DEBUG); logging.debug("Node started")在 Colab 中效果与 print() 类似,但更规范

7.2 使用 ngrok / Cloudflare Tunnel 暴露 WebUI

工具/操作名称操作细节用途示例注意事项
使用 ngrok(推荐)1. 安装 pyngrok;2. 设置 auth token;3. 调用 ngrok.connect(8188)将本地端口映射为公网 HTTPS 链接!pip install pyngrok; from pyngrok import ngrok; ngrok.set_auth_token("YOUR_TOKEN"); public_url = ngrok.connect(8188); print(public_url)必须注册 ngrok 账号获取免费 token;链接每次会话不同
使用 Cloudflare Tunnel(替代方案)1. 安装 cloudflared;2. 运行 cloudflared tunnel --url http://localhost:8188无需账号的隧道方案,更稳定!wget ... cloudflared-linux-amd64 -O cloudflared; !chmod +x cloudflared; !./cloudflared tunnel --url http://localhost:8188输出中查找 https://*.trycloudflare.com 链接;首次运行需确认
后台运行 ComfyUI + 隧道使用 &nohup 同时启动服务和隧道避免阻塞 Colab 单元格!python main.py --listen 0.0.0.0 &; !./cloudflared tunnel ... &推荐先启动 ComfyUI,再启动隧道,避免端口未就绪
自动提取并打印隧道 URL解析 cloudflared 输出中的 URL 行方便用户直接点击访问使用 subprocess 和正则匹配 trycloudflare.com URL需处理子进程流,避免死锁;ngrok 可直接通过 API 获取
隧道稳定性提示避免长时间空闲,定期交互防止 Colab 自动断开或隧道超时每 5 分钟在 UI 中点击一次或发送 WebSocket 心跳免费隧道通常有连接数或带宽限制

7.3 断点调试与变量监控(结合 VS Code + Colab)

方法/工具名称操作细节用途示例注意事项
使用 debugpy 远程调试1. 在 Colab 安装 debugpy;2. 启动调试服务器;3. VS Code 连接在 VS Code 中设置断点、单步执行、查看变量!pip install debugpy; import debugpy; debugpy.listen(("0.0.0.0", 5678)); print("Waiting for debugger attach..."); debugpy.wait_for_client()必须配合 ngrok/Cloudflare 将 5678 端口暴露出去
配置 VS Code launch.json添加远程 attach 配置连接到 Colab 中的 Python 进程{"name": "Attach to Colab", "type": "python", "request": "attach", "connect": {"host": "YOUR_NGROK_URL", "port": 5678}, "pathMappings": [{"localRoot": "${workspaceFolder}", "remoteRoot": "/content"}]}remoteRoot 通常为 /content;host 填 ngrok 的 TCP 隧道地址(如 0.tcp.ngrok.io
创建 ngrok TCP 隧道(用于 debugpy)ngrok tcp 5678暴露调试端口(非 HTTP)在新单元格运行:!ngrok tcp 5678;从输出中获取 0.tcp.ngrok.io:XXXXXHTTP 隧道无法用于 debugpy,必须用 tcp 类型
在节点代码中插入 debugpy.breakpoint()触发断点暂停精确控制调试入口点def execute(self, image): debugpy.breakpoint(); return (image * 0.5,)仅在已连接调试器时生效,否则继续执行
替代方案:使用 pdb + 日志在无 IDE 时快速检查状态简易命令行调试import pdb; pdb.set_trace()在 Colab 中会阻塞输出,需在单元格下方交互输入命令(如 n, p var),体验较差

💡 提示:由于 Colab 会话不可持久,建议将调试代码封装在函数中,并通过条件开关(如 if DEBUG:)控制是否启用 debugpy,避免影响正常运行。

第八章:常见问题与性能优化

8.1 内存泄漏检测与规避

方法/操作名称语法/说明用途代码示例注意事项
显式删除张量变量使用 del 释放不再需要的 PyTorch 张量防止 Python 引用计数阻止内存回收del output_tensor; torch.cuda.empty_cache()仅删除变量名,不立即释放 GPU 内存,需配合 empty_cache()
调用 torch.cuda.empty_cache()清理 PyTorch 缓存的未使用显存块回收碎片化显存,缓解 OOMtorch.cuda.empty_cache()不会释放正在使用的张量,仅清理缓存池
使用上下文管理器隔离计算在函数内局部作用域执行 heavy 操作确保中间变量在函数退出时自动销毁def process(): temp = torch.randn(1000, 1000).cuda(); return temp.mean()避免在类实例中长期持有大张量引用
监控对象引用(gc 模块)使用 gc.get_referrers(obj) 查看谁引用了对象定位意外持有的引用链import gc; refs = gc.get_referrers(my_tensor); print(len(refs))仅用于调试,生产环境应避免;输出较难解读
避免全局缓存字典不在模块顶层存储模型/张量到 dict防止插件间或多次运行累积内存❌ 错误:CACHE = {};✅ 正确:使用局部变量或弱引用若必须缓存,考虑 weakref.WeakValueDictionary

8.2 GPU 显存管理最佳实践

方法/操作名称语法/说明用途代码示例注意事项
使用 .to(device) 显式控制设备将张量移至 GPU 或 CPU避免隐式复制导致显存浪费image = image.to("cuda") if use_gpu else image.to("cpu")默认设备可能不是 "cuda",建议显式指定
启用 torch.inference_mode()上下文管理器,禁用梯度计算和部分历史记录减少显存占用并加速推理with torch.inference_mode(): output = model(input)替代旧版 torch.no_grad(),更高效
分批处理(Batching)将大任务拆分为小 batch 依次处理控制峰值显存,避免 OOMfor i in range(0, total, batch_size): batch = data[i:i+batch_size]; process(batch)需权衡吞吐量与显存,batch_size 过小会降低效率
使用半精度(FP16)调用 .half()autocast减少显存占用约 50%,提升速度with torch.autocast("cuda"): output = model(input.half())并非所有模型都支持 FP16,可能影响数值稳定性
及时释放中间结果不保留不必要的中间张量降低显存峰值x1 = f(x); x2 = g(x1); return x2;✅ return g(f(x))复杂逻辑可手动 del x1 后调用 empty_cache()

8.3 节点执行效率分析工具

工具/方法名称语法/说明用途代码示例注意事项
time.time() 简单计时记录执行前后时间戳快速测量节点整体耗时import time; start = time.time(); result = heavy_function(); print("Time:", time.time() - start)精度较低,适用于粗略评估
torch.cuda.Event(GPU 计时)使用 CUDA 事件精确测量 GPU 执行时间排除 CPU 调度开销,专注 GPU 性能start = torch.cuda.Event(enable_timing=True); end = torch.cuda.Event(enable_timing=True); start.record(); output = model(input); end.record(); torch.cuda.synchronize(); print(start.elapsed_time(end))必须调用 synchronize() 等待 GPU 完成
cProfile + pstatsPython 内置性能分析器定位 CPU 瓶颈函数import cProfile, pstats; pr = cProfile.Profile(); pr.enable(); node.execute(...); pr.disable(); pstats.Stats(pr).sort_stats('cumulative').print_stats(10)对 GPU 操作无效,仅分析 Python 层
nvprof / nsight(高级)NVIDIA 命令行性能分析工具深入分析 CUDA kernel 效率!nvprof --print-gpu-trace python test_node.pyColab 中可能受限;需安装 CUDA 工具包
日志标记关键阶段在节点中插入阶段日志手动划分耗时区间print("[DEBUG] Preprocess done"); print("[DEBUG] Model forward done")无需额外依赖,适合快速排查慢环节

第九章:情绪可控的 index-TTS2 语音大模型插件开发

9.1 index-TTS2 模型加载与推理接口封装

方法/组件名称语法/说明用途代码示例注意事项
模型初始化(TTSModel 类)使用官方 TTSModel 封装加载 checkpoint 和 config统一管理模型实例,避免重复加载from tts_model import TTSModel; tts = TTSModel(model_path="models/index-tts2", device="cuda")首次加载较慢;建议在插件全局或单例中缓存实例
支持的情绪标签(Emotion Tags)字符串列表,如 "happy", "sad", "angry", "neutral"控制语音情感风格emotion = "happy"实际支持的情绪需参考模型训练数据,非任意字符串都有效
推理接口 tts.synthesize()synthesize(text, emotion=None, language="en", speed=1.0)核心语音合成方法audio, sr = tts.synthesize("Hello!", emotion="excited", language="en")返回 (numpy.ndarray, int),音频为 float32,范围 [-1, 1]
设备自动检测自动选择 "cuda"(若可用)或 "cpu"提升兼容性device = "cuda" if torch.cuda.is_available() else "cpu"Colab 环境通常有 GPU,但需显式启用
模型路径管理使用 folder_paths.get_full_path("tts_models", filename)兼容 ComfyUI 资源路径体系model_dir = folder_paths.get_full_path("tts_models", "index-tts2")需提前将模型放入 ComfyUI/models/tts_models/ 或通过 extra_model_paths.yaml 注册

💡 提示:index-TTS2 通常包含 config.jsonmodel.pthvocoder/ 子目录,需完整放置。

9.2 情绪与语音参数的 UI 配置节点设计

输入参数名称类型/控件说明示例值注意事项
text("STRING", {"multiline": True})待合成的文本内容"I'm so happy to see you!"支持多行输入,便于长文本
emotion(["neutral", "happy", "sad", "angry", "excited"],)情绪风格选择下拉菜单"happy"选项应与模型实际支持的情绪对齐
language(["en", "zh", "ja", "ko"],)语言选择(若模型支持多语)"zh"index-TTS2 支持中英日韩,需确认模型版本
speed("FLOAT", {"default": 1.0, "min": 0.5, "max": 2.0, "step": 0.1})语速控制(0.5~2.0 倍)1.2过快或过慢可能影响自然度
seed("INT", {"default": -1, "min": -1, "max": 1e9})随机种子(-1 表示随机)-142用于复现相同语音效果(若模型支持)
output_format(["wav", "mp3"],)输出音频格式(可选)"wav"插件内部可调用 scipypydub 转换

节点输出定义:

  • RETURN_TYPES = ("AUDIO", "INT")
  • RETURN_NAMES = ("audio_waveform", "sample_rate")
  • 音频以 (N,) shape 的 NumPy 数组输出,符合 ComfyUI 音频生态惯例(未来可与其他音频节点串联)

9.3 音频输出与持久化(WAV/MP3 导出)

功能/方法名称语法/说明用途代码示例注意事项
保存为 WAV 文件使用 scipy.io.wavfile.write()无损保存合成语音from scipy.io.wavfile import write; write("/content/output.wav", sr, (audio * 32767).astype(np.int16))需将 float32 [-1,1] 转为 int16 [-32768, 32767]
保存为 MP3(可选)使用 pydub.AudioSegment.export()压缩格式,节省空间from pydub import AudioSegment; seg = AudioSegment(audio.tobytes(), frame_rate=sr, sample_width=4, channels=1); seg.export("out.mp3", format="mp3")需安装 pydub 和 ffmpeg;Colab 默认有 ffmpeg
在 Colab 中下载文件使用 files.download()方便用户获取结果from google.colab import files; files.download("output.wav")仅限 Colab 环境
返回音频供后续节点使用直接返回 (audio, sr) 元组支持工作流内音频链式处理(如加混响、变速)return (audio, sr)为未来扩展(如音频编辑插件)预留接口
错误处理:文本为空检查输入并抛出友好错误防止空文本导致崩溃if not text.strip(): raise ValueError("Text input is empty!")提升用户体验

完整节点骨架示例(简化版):

import torch
import numpy as np
from tts_model import TTSModel  # 假设已封装
import folder_paths

class IndexTTS2Node:
    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "text": ("STRING", {"multiline": True}),
                "emotion": (["neutral", "happy", "sad", "angry", "excited"],),
                "language": (["en", "zh", "ja", "ko"],),
                "speed": ("FLOAT", {"default": 1.0, "min": 0.5, "max": 2.0}),
            }
        }

    RETURN_TYPES = ("AUDIO", "INT")
    RETURN_NAMES = ("audio", "sample_rate")
    FUNCTION = "synthesize"
    CATEGORY = "audio/tts"

    def synthesize(self, text, emotion, language, speed):
        if not text.strip():
            raise ValueError("Input text is empty!")
        
        model_path = folder_paths.get_full_path("tts_models", "index-tts2")
        tts = TTSModel(model_path, device="cuda" if torch.cuda.is_available() else "cpu")
        audio, sr = tts.synthesize(text, emotion=emotion, language=language, speed=speed)
        return (audio, sr)