隐藏输入

除了在客户端创建对应输入或小部件的 required(必需)和 optional(可选)输入外,还有三种 hidden(隐藏)输入选项,允许自定义节点从服务器请求特定信息。

这些选项通过在 INPUT_TYPESdict 中返回 hidden 字段来访问,其签名为 dict[str,str],可包含 PROMPTEXTRA_PNGINFOUNIQUE_ID 中的一个或多个。

@classmethod
def INPUT_TYPES(s):
    return {
        "required": {...},
        "optional": {...},
        "hidden": {
            "unique_id": "UNIQUE_ID",
            "prompt": "PROMPT", 
            "extra_pnginfo": "EXTRA_PNGINFO",
        }
    }

UNIQUE_ID

UNIQUE_ID 是节点的唯一标识符,与客户端节点的 id 属性相同。它通常用于客户端与服务器的通信(参见 消息)。

PROMPT

PROMPT 是客户端发送到服务器的完整提示(prompt)。详见 prompt 对象

EXTRA_PNGINFO

EXTRA_PNGINFO 是一个字典,会被复制到任何保存的 .png 文件的元数据中。自定义节点可以将额外信息存储在该字典中用于保存(或作为与下游节点通信的一种方式)。

注意:如果 Comfy 启动时使用了 disable_metadata 选项,这些数据将不会被保存。

DYNPROMPT

DYNPROMPTcomfy_execution.graph.DynamicPrompt 的一个实例。它与 PROMPT 不同,DYNPROMPT 可能会在执行过程中因 节点扩展 而发生变化。

DYNPROMPT 仅应在高级场景下使用(如在自定义节点中实现循环)。

灵活输入

自定义数据类型

如果你希望在自定义节点之间传递数据,定义自定义数据类型会很有帮助。这几乎只需要为数据类型选择一个唯一的大写字符串名称,例如 CHEESE

然后你可以在节点的 INPUT_TYPESRETURN_TYPES 中使用 CHEESE,Comfy 客户端只允许 CHEESE 输出连接到 CHEESE 输入。CHEESE 可以是任意 Python 对象。

需要注意的一点是,由于 Comfy 客户端并不了解 CHEESE,你需要(除非为 CHEESE 定义了自定义小部件,这属于进阶话题)强制它作为输入而不是小部件。这可以通过输入选项字典中的 forceInput 选项实现:

@classmethod
def INPUT_TYPES(s):
    return {
        "required": { "my_cheese": ("CHEESE", {"forceInput":True}) }
    }

通配输入

@classmethod
def INPUT_TYPES(s):
    return {
        "required": { "anything": ("*",{})},
    }

@classmethod
def VALIDATE_INPUTS(s, input_types):
    return True

前端允许使用 * 表示该输入可以连接到任意来源。由于后端并未正式支持此功能,你可以通过在 VALIDATE_INPUTS 函数中接受名为 input_types 的参数来跳过类型校验。(详见 VALIDATE_INPUTS 了解更多信息。) 节点需要自行处理传入的数据。

动态创建的输入

如果输入是在客户端动态创建的,则无法在 Python 源码中定义。为了访问这些数据,我们需要一个 optional 字典,允许 Comfy 传递任意名称的数据。由于 Comfy 服务器

class ContainsAnyDict(dict):
    def __contains__(self, key):
        return True
...

@classmethod
def INPUT_TYPES(s):
    return {
        "required": {},
        "optional": ContainsAnyDict()
    }
...

def main_method(self, **kwargs):
    # 动态创建的输入数据会在 kwargs 字典中

感谢 rgthree 提供的这个 Python 小技巧!