节点扩展
通常,当一个节点执行时,该执行函数会立即返回该节点的输出结果。“节点扩展”是一种相对高级的技术,允许节点返回一个应该在其位置替代的节点子图。这项技术使得自定义节点能够实现循环。
简单示例一个简单示例
首先,这是一个节点扩展的简单示例:
我们强烈建议在创建子图时使用GraphBuilder
类。这不是强制性的,但它可以防止你犯许多简单的错误。
def load_and_merge_checkpoints(self, checkpoint_path1, checkpoint_path2, ratio):
from comfy_execution.graph_utils import GraphBuilder # Usually at the top of the file
graph = GraphBuilder()
checkpoint_node1 = graph.node("CheckpointLoaderSimple", checkpoint_path=checkpoint_path1)
checkpoint_node2 = graph.node("CheckpointLoaderSimple", checkpoint_path=checkpoint_path2)
merge_model_node = graph.node("ModelMergeSimple", model1=checkpoint_node1.out(0), model2=checkpoint_node2.out(0), ratio=ratio)
merge_clip_node = graph.node("ClipMergeSimple", clip1=checkpoint_node1.out(1), clip2=checkpoint_node2.out(1), ratio=ratio)
return {
# Returning (MODEL, CLIP, VAE) outputs
"result": (merge_model_node.out(0), merge_clip_node.out(0), checkpoint_node1.out(2)),
"expand": graph.finalize(),
}
虽然这个节点之前可以通过手动调用ComfyUI内部实现,但使用扩展意味着每个子节点将被单独缓存(因此如果你更改model2
,你不需要重新加载model1
)。
需求
为了执行节点扩展,一个节点必须返回一个包含以下键的字典:
result
:节点输出的元组。这可能包括最终值(类似于从正常节点返回的内容)和节点输出。expand
:要执行扩展的最终图。如果您不使用GraphBuilder
,请参阅下文。
如果不使用GraphBuilder的附加要求
expand
键期望的格式与ComfyUI API格式相同。以下要求由GraphBuilder
处理,但如果你选择不使用它,则必须手动处理:
- 节点ID必须在整个图中是唯一的。(这包括由于使用列表而导致同一节点多次执行之间。)
- 节点ID必须在多次执行图中(包括由于缓存导致的部分执行)之间是确定性和一致的。
即使你不想使用GraphBuilder
来实际构建图(例如,因为你正在从文件中加载图的原始json),你也可以使用GraphBuilder.alloc_prefix()
函数来生成前缀,并使用comfy.graph_utils.add_graph_prefix
来修复现有图以满足这些要求。
高效子图缓存 Efficient Subgraph Caching
虽然你可以将非字面量输入传递给子图内的节点(如torch张量),但这可能会妨碍子图内的缓存。当可能时,你应该传递子图对象的链接而不是节点本身。(你可以在输入的附加参数中将输入声明为rawLink
,以轻松完成此操作。)