如何将训练模型接入ComfyUI?完整加载流程演示

在AI生成技术日益渗透内容创作的今天,一个常见的挑战浮出水面:如何在保持操作便捷的同时,实现对图像生成过程的精细控制?许多用户从Stable Diffusion WebUI起步,很快便遇到瓶颈——当需要叠加多个ControlNet、动态调度提示词或调试中间潜变量时,传统界面显得捉襟见肘。正是在这种需求驱动下,ComfyUI 脱颖而出。

它不像普通工具那样把模型封装成“黑盒”,而是反其道而行之,将整个推理流程拆解为可编辑的节点图。你可以像搭积木一样构建自己的生成流水线,每一个组件都清晰可见、随时可调。这种“无代码但高自由度”的设计,让它迅速成为研究团队和产品开发者的首选平台。


要真正用好ComfyUI,第一步就是理解它是如何加载并组织模型的。这不仅仅是把文件扔进目录那么简单——背后是一套精密的模块化解耦机制。

核心在于 Load Checkpoint 这个节点。当你选择一个模型(比如微调后的 my_anime_style.safetensors),它并不会一次性把所有权重塞进显存。相反,系统会智能地将模型三大组件分离:

  • UNet:负责去噪扩散过程
  • CLIP:将文本提示词编码为语义向量
  • VAE:将潜空间特征解码为最终图像

这种分离式加载是ComfyUI高效运行的关键。更重要的是,默认采用“懒加载”策略——只有当下游节点明确请求某个组件时,才会将其送入GPU。这意味着你可以在同一工作流中切换多个大模型,而不会立刻耗尽显存。

我们来看底层实现逻辑。尽管ComfyUI以图形界面示人,其本质是一个高度结构化的Python应用。关键代码位于 nodes.py 中的 CheckpointLoaderSimple 类:

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

    RETURN_TYPES = ("MODEL", "CLIP", "VAE")
    FUNCTION = "load_checkpoint"

    def load_checkpoint(self, ckpt_name, output_vae=True, output_clip=True):
        ckpt_path = folder_paths.get_full_path("checkpoints", ckpt_name)
        sd = utils.load_torch_file(ckpt_path, safe_load=True)

        model = self.convert_to_model(sd)
        clip = self.convert_to_clip(sd) if output_clip else None
        vae = self.convert_to_vae(sd) if output_vae else None

        return (model, clip, vae)

这段代码看似简单,实则蕴含工程智慧。首先,通过 safe_load=True 确保只允许加载 .safetensors 格式的安全张量,避免恶意代码注入风险;其次,返回三个独立对象,使得后续节点可以按需引用特定组件,比如你可以只为采样器换新UNet,而继续使用原始CLIP编码器。

这也解释了为什么有时候你的提示词“不起作用”——很可能是因为忘记连接 clip 输出端口。图形界面上的一根连线,实际上决定了文本信息能否进入推理链路。


当然,真实项目中很少只用基础模型。LoRA、ControlNet、T2I-Adapter等扩展模块已成为标配。面对这些多样化训练成果,ComfyUI提供了一套优雅的插件化解决方案:自定义节点机制。

这套机制开放且规范。开发者只需遵循接口约定,就能注册新功能节点。例如加载LoRA的典型实现如下:

class LoraLoader:
    def __init__(self):
        self.loaded_lora = None

    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "model": ("MODEL", ),
                "lora_name": (folder_paths.get_filename_list("loras"), ),
                "strength_model": ("FLOAT", {"default": 1.0, "min": -2.0, "max": 2.0, "step": 0.01}),
                "strength_clip": ("FLOAT", {"default": 1.0, "min": -2.0, "max": 2.0, "step": 0.01}),
            }
        }

    RETURN_TYPES = ("MODEL", "CLIP")
    FUNCTION = "load_lora"
    CATEGORY = "loaders"

    def load_lora(self, model, lora_name, strength_model, strength_clip):
        lora_path = folder_paths.get_full_path("loras", lora_name)
        lora = utils.load_torch_file(lora_path, safe_load=True)

        new_modelpatcher = model.clone()
        if strength_model != 0:
            m, _ = lora_model_helper.load_lora_for_models(model, None, lora, strength_model, 0)
            new_modelpatcher = m

        new_clip = None
        if strength_clip != 0:
            _, c = lora_model_helper.load_lora_for_models(None, model.get("clip"), lora, 0, strength_clip)
            new_clip = c

        return (new_modelpatcher, new_clip)

这个节点的设计充分体现了现代AI工具链的灵活性。它接收原始模型作为输入,动态注入LoRA权重,并支持分别调节UNet与CLIP分支的融合强度。更巧妙的是,使用 clone() 方法确保原模型不受影响,符合函数式编程原则,便于构建可复用的工作流分支。

实践中我发现,很多初学者容易忽略缓存机制的重要性。频繁加载相同LoRA不仅拖慢速度,还可能导致显存碎片化。建议在实际部署时加入轻量级缓存层,尤其是对于那些被多条路径共享的基础适配器。


现在让我们回到最实际的问题:如何把你自己训练好的模型跑起来?

假设你刚刚完成一次基于SD 1.5的风格微调,得到了名为 my_anime_style.safetensors 的模型文件。以下是完整的接入流程。

第一步:放置模型文件

将模型放入正确目录:

comfyui/
 └── models/
     └── checkpoints/
         └── my_anime_style.safetensors

注意,不是随便放哪里都可以。ComfyUI依赖预设路径扫描机制自动发现可用模型。如果你的文件没出现在下拉列表里,第一反应应该是检查路径是否正确,以及扩展名是否为 .ckpt.safetensors

第二步:启动环境

运行 run.batpython main.py,浏览器打开 http://127.0.0.1:8188。等待后端初始化完成,你会看到干净的节点画布。

第三步:搭建基础工作流

  1. 加载主模型
    搜索并添加 Load Checkpoint 节点,在 ckpt_name 中选择你的 my_anime_style.safetensors。此时节点已准备好输出 model, clip, vae 三个端口。

  2. 处理文本输入
    添加两个 CLIP Text Encode 节点,分别用于正向和负向提示词。务必把 Load Checkpointclip 输出连接过去,否则文本无法编码。

  3. 配置采样流程
    添加 KSampler,连接以下输入:
    - model ← 主模型输出
    - positive ← 正向文本编码结果
    - negative ← 负向文本编码结果
    - 设置步数为20,采样器为Euler a,随机种子留空以启用随机模式

  4. 解码与保存
    接上 VAE Decode 将潜变量转为像素图像,再连到 Save Image 节点指定输出位置。

  5. 设定图像尺寸
    可通过 Empty Latent Image 节点预设分辨率(如512x512),并将生成的latent传给 KSampler

最终连接关系如下:

[Load Checkpoint: my_anime_style] 
          │
     ┌────┴────┐
     ▼         ▼
[Text Encode +]  [Text Encode -]
     │         │
     └────┬────┘
          ▼
      [KSampler]
          ▼
     [VAE Decode]
          ▼
     [Save Image]

点击右上角 “Queue Prompt”,观察日志输出。若一切正常,几秒后你就能在 output/ 目录看到生成结果。


但在真实使用中,总会遇到各种“意外”。这里总结几个高频问题及应对思路:

  • 模型不显示?
    首先确认文件确实在 models/checkpoints/ 下。其次注意某些打包脚本可能更改扩展名为 .bin.pt,这类文件不会被识别。推荐始终使用 .safetensors 格式,既安全又高效。

  • 图像模糊不清?
    很可能是VAE不匹配。有些微调模型移除了内置VAE,导致默认解码器产生色偏或细节丢失。解决方法是在 Load Checkpoint 中勾选 output_vae,或单独加载专用VAE节点。

  • 显存爆炸?
    常见于同时加载多个大模型或重复实例。建议关闭不必要的预览节点,利用ComfyUI的延迟执行特性分批运行。也可以考虑使用 Model Merge 节点提前整合权重,减少运行时负担。

  • 效果不如预期?
    别急着怀疑模型质量,先检查工作流逻辑。我曾见过因少连一根线而导致CLIP未更新的情况。图形界面虽然直观,但也容易因视觉疲劳漏掉关键连接。


从工程角度看,掌握ComfyUI不仅是学会用几个节点,更是建立起一种新的AI开发思维模式。

比如,我习惯将常用子流程(如“提示词编码+条件注入”)保存为子图模板,下次直接拖拽复用;对于不同训练阶段的模型,我会用 _v1, _pruned, _merged 等后缀命名,避免混淆;每次重要实验前都会导出 .json 工作流备份,防止配置丢失。

更重要的是,这种节点式架构天然适合自动化。你可以将整个流程导出为API服务,嵌入到网页、APP甚至工业设计软件中。某动画工作室就曾基于ComfyUI搭建内部角色生成系统,美术师只需上传草图,后台自动执行包含ControlNet线稿提取、LoRA风格迁移、多轮精修的复杂流程,极大提升了生产效率。


回过头看,ComfyUI的价值远不止于“可视化操作”。它代表了一种AI生成的工程化范式转变:从试错式交互转向可复现、可调试、可扩展的系统构建。

无论你是研究人员想验证新算法,开发者要打造品牌专属生成器,还是创意人探索视觉边界,这套工具都能提供坚实支撑。它的学习曲线或许陡峭,但一旦掌握,你会发现——原来AI创作不仅可以“做什么”,还能“怎么做”。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐