这份文档怎样读
源码阅读最容易落入两个陷阱:一是把目录树翻译成中文,知道“文件在哪”却不知道“运行时发生了什么”;二是只摘最漂亮的主链路,忽略缓存失效、异步挂起、显存不足和兼容协议这些真正决定系统行为的分支。
本拆解采用“先建立可运行的心智模型,再逐层追踪证据”的方法。
固定的五层结构
每个主题尽量依次回答:
- 具体问题:例如,为什么同一张图第二次几乎瞬间完成?
- 运行时故事:用一次文生图或一次局部重跑串起对象和状态。
- 源码链路:从入口函数一路追到关键调用,给出固定提交链接。
- 设计取舍:为什么不用简单拓扑排序、全量模型常驻或只缓存叶节点。
- 边界与迁移:哪些是可选能力、错误怎样传播、这套方法能否用于自己的系统。
三种标记
execution.pyL730-844这种卡片表示可直接核对的固定版本源码。POST /prompt → validate_prompt → PromptQueue.put → PromptExecutor.execute_async
上面的等宽块表示调用链或状态变化,不是文件目录。Mermaid 图用于表达对象关系;表格用于对照协议和策略。
名词约定
| 本文用词 | 精确定义 |
|---|---|
| Workflow | 前端编辑、保存的完整画布状态;含坐标、尺寸、连线、分组等 UI 信息 |
| API Prompt | 后端执行协议;以节点 ID 为键,只保留 class_type 与 inputs 等执行信息 |
| 原始节点 | 用户提交的 Prompt 中已经存在的节点 |
| 临时节点 | 执行期间由节点返回的 expand 子图产生的 ephemeral node |
| 输出节点 | 节点协议声明 OUTPUT_NODE / is_output_node,是反向求值的根 |
| 强依赖 | 当前执行必须先得到上游结果的连接 |
| 懒依赖 | 先不纳入拓扑阻塞,直到 check_lazy_status 明确索取 |
| 加载 | 参数驻留在目标执行设备,通常是 GPU |
| 卸载 / offload | 把参数移到 CPU 或采用按模块装载,不等于销毁模型对象 |
有意不做的事
- 不复述 ComfyUI 官方安装教程;这里关注运行时实现。
- 不把每一种模型架构逐个讲完;重点是模型检测、配置分派和公共执行契约。
- 不拆解独立维护的前端源码;只讲本快照中的服务端如何托管前端和约定接口。
- 不把第三方自定义节点的行为归因于核心仓库。
- 不保证后续版本仍保持同一行号;因此所有链接都固定到快照提交。
如何验证本文结论
最短的方法不是相信文字,而是按下面的顺序做一次交叉核对:
1. 在 server.py 找 POST /prompt,确认入队对象的六个字段
2. 在 execution.py 找 PromptExecutor.execute_async,确认从输出节点建立 ExecutionList
3. 在 graph.py 找 stage_node_execution,确认拓扑选择与异步阻塞
4. 在 caching.py 找 CacheKeySetInputSignature,确认签名递归包含上游
5. 在 model_patcher.py 找 load / patch_weight_to_device,确认模型加载与补丁分离
6. 在 samplers.py 找 CFGGuider.sample,确认采样前后模型准备与清理完成这一圈,你已经抓住了 ComfyUI 后端最稳定的骨架。
Last updated on