Skip to Content
Ⅱ · 执行引擎05 · 输入与图验证

05 · 输入与图验证

验证器是外部 JSON 与内部 Python 执行之间的信任边界。它的产物不只是“真/假”,而是:哪些输出可以安全执行、整张请求的顶层错误、以及按节点归组的可解释错误。

为什么不能边执行边检查

一个 Prompt 可能在最后一个节点才暴露类型错。如果前面的 Save、API 或模型节点已经产生副作用,再报告错误就很难回滚。ComfyUI 因此在入队前完成结构和 schema 验证,但不真正加载模型或运行计算。

execution.pyL846-1247递归输入验证与 validate_prompt 汇总。

第一层:Prompt 顶层结构

验证首先面对的是字典键和节点记录,而不是张量。典型失败包括:

  • Prompt 不是预期映射;
  • 某节点缺少 class_type;
  • class_type 不在 NODE_CLASS_MAPPINGS;
  • inputs 缺失或结构不正确;
  • 没有任何可执行的输出节点;
  • partial targets 指向不存在或不合格的节点。

这些属于请求级错误,通常没有必要把任务放入 PromptQueue。

第二层:只验证真正的输出闭包

验证器遍历声明为输出的节点,并递归验证它们的上游。它返回 good_outputs:即便 Prompt 中有多个输出,其中一个分支无效,也能精确记录是哪一组输出失败。

这与“只执行需求闭包”一致:孤立的草稿节点不应阻止另一条完好输出链执行。反过来,一个无效上游会沿依赖使对应输出无效。

第三层:递归与环检测

validate_inputs() 接收两个重要状态:

validated # 已验证节点的 memo,避免重复工作 visiting # 当前 DFS 路径,用于发现回边

当节点已在 visiting 中,说明出现依赖环。代码从第一次出现位置截取路径,加回当前节点,构造类似:

12 (KSampler) -> 18 (SomeNode) -> 12 (KSampler)

然后给环内每个节点写入 dependency_cycle,而不是只责怪最后访问到的一个节点。

静态环在入队前发现;运行时 expand 新增的环则由 ExecutionList 再做防守性检查。

第四层:输入 schema

required 与 optional

节点声明:

{ "required": {"steps": ("INT", {"min": 1, "max": 10000})}, "optional": {"noise_mask": ("MASK",)} }

缺失 required 生成 required_input_missing;缺失 optional 不报错。隐藏输入不依赖客户端提供,由执行阶段注入。

V3 怎样进入同一验证器

V3 节点先把 Schema.inputs 最终化为兼容的输入描述,并记录嵌套/动态输入元数据;自定义验证方法名为 validate_inputs。V1 则调用 INPUT_TYPES(),可选方法名是 VALIDATE_INPUTS。

两种协议最后汇入同一条值、链接与递归验证链,避免维护两套执行语义。

链接输入验证

当值是列表时,协议优先按链接解释。验证器要求:

  1. 恰好两个元素;
  2. 第一个元素指向存在的上游节点;
  3. 第二个元素是有效输出 slot;
  4. 上游 RETURN_TYPES[slot] 能连接到当前输入类型;
  5. 上游节点本身递归通过验证。

错误会包含 received_type、期待的 input config 与 linked_node,让前端能把问题定位到具体插槽。

为什么普通列表值要包装

列表已被链接协议占用。一个 widget 若本来就需要传数组,可包装成:

{ "__value__": [1, 2, 3] }

验证器会解包 __value__,避免把业务数组误判成 [node_id, slot]。V3 typed wrapper 也走类似归一化。

这是协议设计的历史成本:紧凑链接表示很方便,但需要逃生舱表达真正的 list 常量。

常量输入验证

基础类型转换

对于 INT、FLOAT、STRING、BOOLEAN,验证器尝试转换并把归一后的值写回 Prompt。失败产生 invalid_input_type。

这意味着节点执行时通常拿到规范化类型,但要注意 bool("false") 在 Python 中为真一类语言语义;可靠客户端仍应发送正确 JSON 类型,而不是依赖宽松转换。

数值约束

若 input config 声明 min / max,验证器比较范围,分别生成小于最小值或大于最大值的错误。

组合值

当类型声明是可选值列表时,常量必须在列表中。模型文件名下拉框就是典型例子:这既提供 UI 选项,也在提交时防止不存在的名字直接进入 Loader。

自定义验证接管

如果输入名出现在自定义验证函数的参数中,通用范围/组合检查会让位给节点逻辑。节点可以一次看到相关参数,实现跨字段约束。

V1 VALIDATE_INPUTS 与 V3 validate_inputs

自定义验证可返回:

  • True:通过;
  • 字符串:失败原因;
  • 其他不符合约定的值:按协议错误处理;
  • 抛出异常:记录异常类型、消息和 traceback。

验证函数可能是异步的,也参与列表映射。运行时通过函数签名只传它声明需要的输入;若接收 **kwargs,则可接收完整集合。

自定义验证不应做重量级推理或不可逆副作用。POST /prompt 在 aiohttp 事件循环上等待验证结果,慢验证会直接拖慢控制面。

类型系统的强与弱

ComfyUI 类型多是字符串标识,例如 MODEL、CLIP、LATENT、IMAGE。链接验证比较这些声明,也支持协议定义的通配/联合规则。

它能阻止把 IMAGE 直接接到 MODEL,却不能证明:

  • 两个 MODEL 是否来自兼容架构;
  • latent 通道数是否符合目标模型;
  • 文本编码与某个 checkpoint 是否语义匹配;
  • 张量 shape 在运行时分支中一定正确。

因此采样或矩阵乘法仍可能抛 shape mismatch,执行器会添加针对常见 CLIP/Sampler 组合的提示。

错误数据结构

概念上,一个节点错误包含:

{ "type": "return_type_mismatch", "message": "Return type mismatch between linked nodes", "details": "model, received_type(IMAGE) mismatch input_type(MODEL)", "extra_info": { "input_name": "model", "received_type": "IMAGE", "linked_node": ["7", 0] } }

type 适合机器分支,message 适合人读,details 和 extra_info 用于前端标注与调试。把三者分开比只返回一串异常文本更可演进。

一个坏 Prompt 怎样被报告

假设:

  • KSampler 的 steps = 0;
  • model 错接了 IMAGE;
  • 另一个 SaveImage 分支完全正常。

验证器会:

  1. 对 steps 记录 value_smaller_than_min;
  2. 对 model 记录 return_type_mismatch;
  3. 将 KSampler 所在输出从 good_outputs 排除;
  4. 保留另一个可执行输出;
  5. 返回按输出关联的 node_errors。

是否允许部分输出执行取决于最终 validate_prompt 汇总规则与请求目标;客户端不应只看 HTTP status,要读取响应体中的 output/node 级状态。

验证明确不做什么

不做原因 / 后续层
打开 checkpoint 并检查权重太重;由 Loader / comfy.sd 处理
分配 GPU 显存入队前不应改变推理资源
保证输出文件可写到底文件系统状态会变化;执行节点处理
验证运行时 expand 子图子图此时尚不存在;调度器二次防守
保证 API key 有效可能需远端 I/O;API node 执行时处理
隔离恶意 Python 节点节点已在进程内,schema 不是沙箱

节点作者检查表

  1. INPUT_TYPES / Schema 的 required、optional、hidden 是否准确?
  2. 可枚举输入能否用组合列表,让前端与验证共享约束?
  3. 范围能否声明为 min/max/step,而不是埋在执行异常里?
  4. 跨字段约束才使用自定义验证,且保持轻量、确定、无副作用。
  5. 自定义错误返回能否告诉用户“哪一项、收到什么、期待什么”?
  6. V3 嵌套输入是否通过 Schema 表达,而不是手工解析扁平 key?

可迁移的设计方法

  • 在进入 durable / expensive queue 前完成纯结构验证。
  • DFS 同时维护 memo 与当前路径:一个提速,一个找环。
  • 错误采用稳定 code + 人类消息 + 结构化上下文三层。
  • 通用 validator 提供 80% 规则,扩展点只承接跨字段/领域约束。
  • 明确验证边界;schema 通过不等于业务执行必然成功。
Last updated on