ComfyUI开发指南 -- 插件开发(上)

19 人赞同了该文章

上次说过了怎么将comfyUI作为微服务接口,编写web程序去封装调用,今天接着讲如何在comfyUI里开发自定义节点,从而扩充comfyUI的能力。


首先,我们去到comfyUI的custom_nodes 子文件夹下 ,可以看到一个 example_node.py 的示例文件,我们就先用它来讲解。文件默认是注释掉的状态,我们需要把后缀改成py 才能让它在comfyUI中启用。


抛开里面的英文注释,我们先直观快速观察一下代码内容,开头是新建了一个python 类 然后是构造方法 ,类方法 ,一些类属性配置 。然后是一个看上去像节点逻辑的函数。最后是像节点映射关系一样的字典。

class Example:
    def __init__(self):
        pass
    
    @classmethod
    def INPUT_TYPES(s):
        return {
            "required": {
                "image": ("IMAGE",),
                "int_field": ("INT", {
                    "default": 0, #默认值
                    "min": 0, #最小值
                    "max": 4096, #最大值
                    "step": 64, #滑动步长
                    "display": "number" # 组件外观: 数值  "number" 或  滑动条 "slider"
                }),
                "float_field": ("FLOAT", {
                    "default": 1.0,
                    "min": 0.0,
                    "max": 10.0,
                    "step": 0.01,
                    "round": 0.001, #表示舍入精度的值将默认设置为步长值。可以设置为 False 以禁用舍入。
                    "display": "number"}),
                "print_to_screen": (["enable", "disable"],),
                "string_field": ("STRING", {
                    "multiline": False, #如果您希望该字段看起来像 ClipTextEncode 节点上的字段显示(即只显示一行字符串,多余部分会在 UI上隐藏 ,只有在用户编辑时才会全部显示) 则为 True
                    "default": "Hello World!"
                }),
            },
        }

    RETURN_TYPES = ("IMAGE",)
    #RETURN_NAMES = ("image_output_name",)

    FUNCTION = "test"

    #OUTPUT_NODE = False

    CATEGORY = "Example"

    def test(self, image, string_field, int_field, float_field, print_to_screen):
        if print_to_screen == "enable":
            print(f"""Your input contains:
                string_field aka input text: {string_field}
                int_field: {int_field}
                float_field: {float_field}
            """)
        #对图像进行一些处理,在本例中只是将其反转
        image = 1.0 - image
        return (image,)

   
    #@classmethod
    #def IS_CHANGED(s, image, string_field, int_field, float_field, print_to_screen):
    #    return ""

# Set the web directory, any .js file in that directory will be loaded by the frontend as a frontend extension
# WEB_DIRECTORY = "./somejs"

# A dictionary that contains all nodes you want to export with their names
# 一个包含所有你想要导出的节点和它们对应的名称的字典, 名称需要全局唯一
# NOTE: names should be globally unique 
NODE_CLASS_MAPPINGS = {
    "Example": Example
}

# A dictionary that contains the friendly/humanly readable titles for the nodes
#  一个包含所有节点最终呈现给用户的名称和系统存储的名称对应关系的字典
NODE_DISPLAY_NAME_MAPPINGS = {
    "Example": "Example Node"
}


然后我们再去comfy中直观感受一下这个节点的功能和在UI方面的长相

节点接受一个图片,输出一个图片,中间有些参数,效果是反转图像色彩。


当print to screen为enable ,控制台会打印我们的参数配置


代码和功能上都大致过一遍后,我们来深入地探索一下节点是怎么实现这么一个功能的。


INPUT_TYPES
首先是节点的入参,是在 INPUT_TYPES 方法中一一声明的, 会返回一个包含所有输入字段配置的字典
字段首先分成三类 必须,隐藏,可选 。每个节点必须拥有必选的属性。 像例子中 int_field、 float_field、print_to_screen 、string_field 四个都是required 也就是必填项。
然后是字段类型,具体而言可以是以下字段类型: "MODEL", "VAE", "CLIP", "CONDITIONING", "LATENT", "IMAGE", "INT", "STRING", "FLOAT".其中 "INT", "STRING" 和"FLOAT" 是节点字段的一些特殊值 ( 因为和SD模型本身没有直接联系)例子中正好包含这三个特殊类型,以及一个图像输入
然后根据不同类型的字段有不同的配置参数,最大最小值,步长,文本是否多行显示......


RETURN_TYPES
其次是返回值的声明,与INPUT_TYPES 对应 RETURN_TYPES . 指定节点返回的字段类型


FUNCTION
然后是节点的逻辑,就是节点都干了些什么,怎么干的
其实都是 FUNCTION 对应的函数来实现的
需要 FUNCTION 类属性来指定函数名, 然后再实现这个函数
这里test 函数是实现了图像色彩反转的功能,参数就是 刚才input type里声明的那些,加上个self 指针指向自己
最后将输出结果返回 (反转完的图像)


最后是两个字典
一个包含所有你想要导出的节点和它们对应的类名称, 名称需要全局唯一。
一个包含所有节点最终呈现给用户的名称和系统存储的名称对应关系。



总结一下

如果我们要实现一个ComfyUI节点,我们需要编写一个节点类 然后设计好 入参 返回 功能用到的逻辑代码 ,最后按上面介绍的一些约定规则开发实现。


下半部分将带大家手把手开发一个插件对接dify (大语言模型运维平台) ,让我们用LLM来优化翻译我们的提示词