丁同亚的博客

夺朱非正色

导航

comfyui原理

ComfyUI 原理笔记

基于ai对话学习整理


一、整体架构

文本输入 → CLIP编码 → 文本向量 → UNet去噪 → VAE解码 → 图像输出

ComfyUI 是一个基于节点工作流的 AI 图像生成工具,核心原理基于 Stable Diffusion(稳定扩散) 技术。

什么是工作流?

核心认知:工作流 = 数据流

所谓"流",就是数据在节点之间流动的过程。

本质:

节点A → 节点B → 节点C → 节点D

数据从A流出,经过B、C,最终到达D

类比水管:

水源 → 水管 → 水龙头
模型 → 节点连线 → 输出

水流过管道 = 数据流过节点

流动的数据类型:

数据类型 说明
MODEL UNet模型权重
CLIP 文本编码器
VAE 图像编解码器
CONDITIONING 条件向量
LATENT 潜空间数据
IMAGE 图像数据
MASK 蒙版数据

工作流 = 节点 + 连线 + 数据类型

组成 作用
节点 处理站(加工数据)
连线 管道(传输数据)
数据 流水(被加工的对象)

工作流特点:

  • 单向流动:数据从输出端流向输入端
  • 类型匹配:连线两端数据类型必须匹配
  • 可分支:一个输出可以连多个输入

二、核心概念

1. 扩散(Diffusion)

正向扩散(加噪):向图像逐步添加噪声,直至变成纯噪声

原图 → +噪声 → +噪声 → ... → 纯噪声

反向扩散(去噪):从纯噪声逐步去除噪声,恢复出图像

纯噪声 → -预测噪声 → -预测噪声 → ... → 清晰图像

本质:AI 通过海量训练学会"什么样的像素组合是合理的",去噪过程就是"把不合理的噪声变成合理"。

2. 噪声(Noise)

  • 随机生成的像素数据,表现为画面上的杂色/颗粒感
  • 是扩散模型的"燃料与起点"
  • 纯噪声 = 完全随机的像素值

3. 潜空间(Latent Space)

  • 图像的"压缩版",通过 VAE 编解码器转换
  • 512×512 像素 → 64×64 潜空间(信息减少 64 倍)
  • 保留了"语义特征",丢弃了"像素细节"
  • 在潜空间操作更高效,是 AI 进行"思考"的地方
图像 → VAE Encode → 潜空间 → 处理 → VAE Decode → 图像

4. VAE(变分自编码器)

组件 功能
编码器 将图像压缩为潜空间表示
解码器 将潜空间还原为图像

5. CLIP

CLIP = Contrastive Language-Image Pre-training(对比语言-图像预训练)

  • 把文字和图像都转换成向量
  • 相似的内容,向量也相似
  • 建立文字和图像之间的"语义桥梁"
文字 "猫" → Token [猫] → CLIP → 向量
图像 "猫" → CLIP → 向量 → 与文字向量相似

6. Token(词元)

  • 文字拆分的最小单位
  • "一只可爱的猫" → [一只] [可爱] [的] [猫] → 4个token
  • CLIP 把 token 转换成向量

7. UNet(核心神经网络)

UNet = 扩散模型的大脑,负责预测噪声

输入:当前潜空间 + 条件向量
        ↓
UNet处理
        ↓
输出:预测噪声

结构特点:

  • 编码器:压缩图像信息(逐步降维)
  • 解码器:还原图像信息(逐步升维)
  • 跳跃连接:保留细节,防止信息丢失
输入 → 编码器 → 解码器 → 输出
         ↓
      跳跃连接(保留细节)

模型组成:

大模型(Checkpoint文件)
    │
    ├── UNet ← 核心部分,负责预测噪声(占80-90%体积)
    ├── CLIP ← 文本编码
    └── VAE  ← 图像编解码

类比:

大模型 = 一辆车
UNet     = 发动机(核心动力)
CLIP     = 方向盘(控制方向)
VAE      = 变速箱(转换输出)

架构 vs 权重:

架构(UNet/Transformer)= 骨架/框架(先天设计)
权重 = 知识/技能(后天学习)

训练过程:空架构 + 大量图片训练 → 调整权重 → 学会生成图像

UNet vs Transformer:

架构 原理 特点
UNet 卷积神经网络(CNN) 局部感受野,效率高
Transformer 注意力机制 全局感受野,理解力强
UNet:看局部拼图,一块一块理解
Transformer:看全局,同时理解所有部分的关系

早期SD使用UNet,新一代模型(DiT、Sora、Flux)开始使用Transformer。


三、采样控制

1. CFG(无分类器引导)

让 AI 更听提示词的话

  • 无 CFG:生成图像可能偏离提示词
  • 有 CFG:生成的图像更符合提示词描述
  • 常用值:7-12

原理详解

核心公式:

输出 = 无条件输出 + CFG系数 × (条件输出 - 无条件输出)

双路前向传播:

噪声latent z ──┬── 文本embedding → 预测 ε_cond
               │
               └── 空embedding   → 预测 ε_uncond

数学表达:
$$ \epsilon_{guided} = \epsilon_{uncond} + w \cdot (\epsilon_{cond} - \epsilon_{uncond}) $$

关键点:

  • 两者都是噪声预测,不是完整图像
  • 叠加发生在噪声层面,而非像素层面
  • 无条件输出代表模型对"一般图像分布"的默认理解
  • 条件与无条件之差,即文本带来的"特殊偏好"

通俗理解:

  • CFG值如同"听话程度"
  • 值高 → 严格遵循提示词(可能过于饱和)
  • 值低 → 自由发挥(更随机多样)

2. 采样器(Sampler)

控制去噪的具体算法

核心作用:
每步去噪时,"预测噪声怎么用"的策略

核心公式:

当前图像 - 预测噪声 × 步长 = 下一步图像

采样器就是控制这个减法的具体算法:

  • 减多少:步长(step size)
  • 怎么减:直接减、随机减、分步减
  • 何时停:到第几步退出

本质: "每步砍多少噪声、怎么砍" 的策略

完整去噪流程:

原始噪声 → UNet预测噪声 × 步长 → 采样器计算 → 下一步图像
                                                      ↓
                                              循环 N 次
                                                      ↓
                                             最终清晰图像

步长 vs 步数:

概念 含义 常见值
步长 每步擦掉多少噪点 0.1 ~ 1.0
步数 总共擦多少次 20 ~ 50
总去噪量 ≈ 步长 × 步数 ≈ 1(理论上)
采样器 原理 特点
euler 最简欧拉法,每步直接减去预测噪声 快速简单,质量一般
euler_a 欧拉祖先采样,加入随机性 细节丰富,艺术感强
dpm_2 2阶DPM求解器,精度更高 质量高,速度适中
dpm++_2m 多步DPM优化版 快速且高质量
lcm 潜在一致性模型 极速(4-8步)
ddim 确定性路径,可控性强 适合图生图

3. 调度器(Scheduler)

控制每步"步长多大"的策略

比喻:

从北京去上海(1000公里)

normal:每步走50公里 → 走20步 → 到达
karras:前10步走100公里(快)→ 后10步走50公里(慢)→ 到达
exponential:指数衰减 → 前期很快 → 后期很慢

为什么需要调度器:

  • 前期:图像还很模糊,可以大胆迈步
  • 后期:图像逐渐清晰,步子要小一点,不然容易走过头
调度器 步长变化 特点
normal 固定 均衡
karras 前大后小 前期快,后期精细,细节更好
exponential 指数衰减 平滑过渡
simple 线性 简单粗暴

4. 条件控制(Conditioning)

告诉AI生成什么、不生成什么

正面条件(Positive):

"一只可爱的猫" → 告诉AI:我要这个

负面条件(Negative):

"模糊、变形、低质量" → 告诉AI:我不要这个

条件如何生效:

文本 → CLIP编码 → 文本向量
                      ↓
噪声 → UNet → 结合条件向量 → 预测噪声

UNet在预测噪声时,会参考条件向量,让噪声"往想要的方向走"。

多种条件控制方式:

方式 编码方式 注入位置 作用
Prompt CLIP → 向量 UNet text encoder 文字描述
Negative Prompt CLIP → 向量 UNet text encoder 排除不需要的元素
ControlNet 专用模型 → 特征图 UNet各层 空间控制(构图/姿势/边缘)
IP-Adapter 图像编码器 → 特征 UNet 风格/内容参考
LoRA 修改模型权重 改变UNet本身 注入特定风格/角色

本质区别:

  • 提示词/ControlNet/IP-Adapter = 外部引导(加条件)
  • LoRA = 模型微调(改模型本身)

四、视频生成

1. 核心原理

视频生成与图片生成的核心区别:

图片 视频
单帧输出 多帧连续输出
2D潜空间 3D潜空间(空间+时间)
一次去噪 逐帧去噪+帧间一致性

视频潜空间:

图片潜空间:  [B, C, H, W]
视频潜空间:  [B, C, T, H, W]

B = 批次
C = 通道数
T = 时间维度(帧数)
H = 高度
W = 宽度

2. 主流方案

方案一:SVD(Stable Video Diffusion)- 图像→视频

输入图像 → SVD Encoder → 潜空间 → SVD UNet → 视频潜空间 → SVD Decoder → 帧序列

方案二:AnimateDiff - 文字→视频

文本 → CLIP → 向量 → AnimateDiff UNet → 视频潜空间 → VAE Decode → 帧序列

方案三:Frame by Frame - 逐帧生成

第1帧 → 生成 → 结果1 → 第2帧以结果1为参考 → 结果2 → ...

3. 帧间一致性

问题: 每帧独立生成会导致角色/背景跳变

解决方案:

方法 原理
ControlNet 用上一帧作为ControlNet输入
IP-Adapter 用上一帧作为风格参考
潜空间混合 在潜空间层面混合相邻帧
Motion模块 专门学习运动规律

4. 视频节点详解

输入节点:

Load Video → 加载视频文件 → 输出:帧序列 + 帧率 + 尺寸
Video Info → 获取视频信息 → 输出:帧数、分辨率、时长

处理节点:

Split Frames → 将视频拆分为单帧
Merge Frames → 将帧序列合并为视频
Frame Interpolation → 帧插值(增加帧率)

采样节点:

KSampler (Video) → 视频采样器
参数:frames(帧数), motion_bucket_id(运动幅度), fps(帧率)

输出节点:

Video Combine → 合成视频文件
参数:fps(帧率), crf(压缩质量), format(输出格式)

5. 关键参数

motion_bucket_id(运动幅度):

值范围:1-255
低值(1-50)→ 微小运动
中值(50-150)→ 正常运动
高值(150-255)→ 剧烈运动

fps(帧率):

8 FPS → 卡顿感(动画风格)
24 FPS → 电影感
30 FPS → 流畅
60 FPS → 超流畅

6. 完整工作流示例

图像转视频(SVD):

Load Image → SVD Image Encode → SVD Conditioning → KSampler SVD → SVD Decode → Video Combine

文字转视频(AnimateDiff):

Load Checkpoint → Load AnimateDiff Model → CLIP Text Encode → Empty Latent Video → KSampler → VAE Decode → Video Combine

7. 显存优化

显存 ≈ 帧数 × 分辨率 × 模型大小
方法 原理
分块生成 每次只生成部分帧
潜空间压缩 使用更小的潜空间
模型卸载 用完即卸载
量化 INT8/FP16

8. 常见问题

问题 原因 解决方案
闪烁 帧间不一致 使用ControlNet/IP-Adapter
静止不动 motion_bucket_id太低 提高运动幅度
变形 帧间差异太大 降低augmentation_level
显存不足 帧数太多 减少帧数或分块生成

五、ComfyUI 节点类型

类别 节点 功能
加载器 Load Checkpoint 加载模型
条件 CLIP Text Encode 文本编码
采样 KSampler 控制去噪
潜空间 VAE Encode/Decode 编解码
图像 Load/Save/Preview Image 图像操作
蒙版 Convert to Mask 蒙版处理

五、工作流程

┌─────────────────────────────────────────────────────┐
│  1. Load Checkpoint(加载模型)                      │
│           ↓                                         │
│  2. CLIP Text Encode(文本编码)                     │
│           ↓                                         │
│  3. Empty Latent Image(创建噪声起点)               │
│           ↓                                         │
│  4. KSampler(多步去噪)                             │
│           ↓                                         │
│  5. VAE Decode(潜空间转图像)                       │
│           ↓                                         │
│  6. Save Image(保存结果)                           │
└─────────────────────────────────────────────────────┘

六、优势特点

  • 节点式工作流:可视化拼接,灵活定制
  • 内存优化:1GB 显存可运行,支持模型卸载
  • 智能缓存:仅重新执行变更的部分
  • 离线运行:不强制联网
  • 高度扩展:支持自定义节点

七、源码架构

1. 目录结构

ComfyUI/
├── main.py              # 入口文件
├── server.py            # 服务器(Web UI)
├── execution.py         # 工作流执行引擎
├── nodes.py             # 内置节点定义
├── comfy/               # 核心模块
│   ├── model_management.py   # 模型管理
│   ├── samplers.py           # 采样器实现
│   ├── clip_model.py         # CLIP模型
│   └── unet.py               # UNet实现
├── custom_nodes/        # 自定义节点
└── web/                 # 前端界面

2. 核心模块

入口与服务器:

main.py → 初始化、加载节点、启动服务
server.py → POST /prompt(执行工作流)、WebSocket(实时通信)

工作流执行引擎:

class PromptExecutor:
    def execute(self, prompt, workflow):
        # 1. 解析工作流JSON
        # 2. 构建执行图(DAG)
        # 3. 拓扑排序
        # 4. 逐节点执行
        # 5. 缓存中间结果

3. 节点系统

节点定义:

class KSampler:
    @classmethod
    def INPUT_TYPES(cls):
        return {"required": {"model": ("MODEL",), "steps": ("INT",), ...}}
    
    RETURN_TYPES = ("LATENT",)
    FUNCTION = "sample"
    CATEGORY = "sampling"
    
    def sample(self, model, steps, ...):
        return (latent,)

节点元信息:

属性 说明
INPUT_TYPES 输入参数定义
RETURN_TYPES 输出类型
FUNCTION 执行方法名
CATEGORY 节点分类

4. 数据类型系统

TYPE_MAP = {
    "MODEL": Model,
    "CLIP": ClipModel,
    "VAE": VAE,
    "LATENT": Dict[str, torch.Tensor],
    "IMAGE": torch.Tensor,
    "CONDITIONING": List[Tuple],
    "MASK": torch.Tensor,
}

5. 执行流程

前端拖拽节点 → JSON发送到后端 → 解析构建DAG → 拓扑排序
    → 逐节点执行(检查缓存→加载模型→执行→缓存输出)→ 推送结果到前端

6. 智能缓存机制

def get_cache_key(node_id, inputs):
    return hash((node_id, tuple(sorted(inputs.items()))))

缓存命中: 相同节点 + 相同输入 → 直接返回缓存 → 跳过执行

7. 自定义节点机制

def load_custom_nodes():
    for folder in custom_nodes_folders:
        module = import_module(file)
        NODE_CLASS_MAPPINGS.update(module.NODE_CLASS_MAPPINGS)

自定义节点模板:

class MyCustomNode:
    @classmethod
    def INPUT_TYPES(cls):
        return {"required": {...}}
    RETURN_TYPES = ("IMAGE",)
    FUNCTION = "execute"
    def execute(self, ...):
        return (result,)

NODE_CLASS_MAPPINGS = {"MyCustomNode": MyCustomNode}

8. 关键设计模式

模式 应用
工厂模式 节点创建
策略模式 采样器切换
观察者模式 WebSocket通知
缓存模式 中间结果缓存
DAG调度 工作流执行

八、关键术语表

术语 中文 说明
Diffusion 扩散 先加噪后去噪的过程
Noise 噪声 随机像素数据
Latent Space 潜空间 图像的压缩表示
VAE 变分自编码器 潜空间编解码器
CLIP 对比学习模型 文字-图像语义桥梁
Token 词元 文字的最小单位
UNet UNet网络 预测噪声的神经网络
CFG 无分类器引导 提示词引导强度
Sampler 采样器 去噪算法
Scheduler 调度器 噪声调度策略

整理于 2026年4月3日

posted on 2026-04-03 16:51  丁同亚的博客  阅读(233)  评论(0)    收藏  举报