简单示例
下面是“反转图片节点”的代码,概述了自定义节点开发中的关键概念。主要属性
每个自定义节点都是一个 Python 类,具有以下关键属性:INPUT_TYPES
顾名思义,INPUT_TYPES 定义了节点的输入。该方法返回一个 dict,必须包含 required 键,也可以包含 optional 和/或 hidden 键。required 和 optional 输入的唯一区别在于,optional 输入可以不连接。关于
hidden 输入的更多信息,参见 隐藏输入。
每个键的值又是一个 dict,其中的键值对指定输入的名称和类型。类型由一个 tuple 定义,第一个元素是数据类型,第二个元素是包含附加参数的 dict。
这里我们只有一个必需输入,名为 image_in,类型为 IMAGE,没有额外参数。
注意,与接下来几个属性不同,INPUT_TYPES 是一个 @classmethod。这样做的目的是让下拉小部件中的选项(比如要加载的 checkpoint 名称)可以在运行时由 Comfy 动态计算。我们稍后会详细介绍这一点。
RETURN_TYPES
一个由str 组成的 tuple,定义了节点返回的数据类型。如果节点没有输出,也必须提供 RETURN_TYPES = ()。
如果你只有一个输出,记得加上逗号:
RETURN_TYPES = ("IMAGE",)。这是 Python 创建元组所必需的。RETURN_NAMES
用于标记输出的名称。此项为可选;如果省略,名称将直接使用RETURN_TYPES 的小写形式。
CATEGORY
节点在 ComfyUI 添加节点 菜单中的分类。可以用路径指定子菜单,例如examples/trivial。
FUNCTION
节点执行时应调用的 Python 函数名。 该函数以命名参数的方式被调用。所有required(和 hidden)输入都会包含在内;optional 输入只有在连接时才会包含,因此你应在函数定义中为它们提供默认值(或用 **kwargs 捕获)。
该函数返回一个与 RETURN_TYPES 对应的元组。即使没有返回内容,也必须返回元组(return ())。同样,如果只有一个输出,记得加上逗号 return (image_out,)!
执行控制扩展
Comfy 的一个很棒的特性是它会缓存输出,并且只会执行那些结果可能与上次运行不同的节点。这可以极大地加快许多工作流的速度。 本质上,这通过识别哪些节点会产生输出(比如 Image Preview 和 Save Image 节点,这些节点总是会被执行),然后反向追踪哪些节点提供了自上次运行以来可能已更改的数据。 自定义节点有两个可选特性可以协助这一过程。OUTPUT_NODE
默认情况下,节点不会被视为输出节点。设置OUTPUT_NODE = True 可以指定该节点为输出节点。
IS_CHANGED
默认情况下,如果节点的任何输入或小部件发生变化,Comfy 会认为该节点已更改。这通常是正确的,但在某些情况下你可能需要重写此行为,例如节点使用了随机数(且未指定种子——此时最好提供一个种子输入,以便用户可以控制可复现性并避免不必要的执行)、加载了可能已在外部更改的输入,或有时会忽略某些输入(因此不需要仅因这些输入变化而执行)。注意,IS_CHANGED 的返回值不应为
bool 类型。IS_CHANGED 接收与主函数(由 FUNCTION 指定)相同的参数,并可以返回任意 Python 对象。该对象会与上次运行时返回的对象进行比较,如果 is_changed != is_changed_old,则认为节点已更改(相关代码在 execution.py 中)。
由于 True == True,如果节点返回 True 表示已更改,实际上会被认为未更改!如果不是为了兼容现有节点,这一行为本可以在 Comfy 代码中修正。
如果你希望节点始终被认为已更改(不推荐,因为这会阻止 Comfy 优化执行流程),可以 return float("NaN")。这会返回一个 NaN,它与任何值都不相等,甚至与另一个 NaN 也不相等。
一个实际检查变化的好例子是内置的 LoadImage 节点的代码,它会加载图片并返回哈希值:
其他属性
还有三个属性可以用来修改 Comfy 对节点的默认处理方式。INPUT_IS_LIST, OUTPUT_IS_LIST
用于控制数据的顺序处理,详见后文。VALIDATE_INPUTS
如果定义了类方法VALIDATE_INPUTS,则在工作流开始执行前会被调用。VALIDATE_INPUTS 如果输入有效应返回 True,否则返回一个描述错误的字符串(这会阻止执行)。
常量校验
注意,
VALIDATE_INPUTS 只会接收到在工作流中定义为常量的输入。任何来自其他节点的输入都不会在 VALIDATE_INPUTS 中可用。VALIDATE_INPUTS 只会收到其签名中请求的输入(即 inspect.getfullargspec(obj_class.VALIDATE_INPUTS).args 返回的参数)。通过这种方式接收的输入不会经过默认校验规则。例如,在下面的代码片段中,前端会使用 foo 输入指定的 min 和 max,但后端不会强制校验。
**kwargs,则会收到所有可用输入,并且所有这些输入都将跳过校验,就像显式指定一样。
类型校验
如果VALIDATE_INPUTS 方法接收一个名为 input_types 的参数,则会传入一个字典,键为每个连接到其他节点输出的输入名,值为该输出的类型。
当存在此参数时,所有输入类型的默认校验都会被跳过。下面是一个利用前端允许指定多种类型的例子: