那么你想制作一个自定义节点吗?您在网上查找并发现资源非常稀少或令人生畏?我喜欢 ComfyUI,但必须说的是:尽管已有几个月的历史,但它围绕自定义节点的文档非常糟糕。人们甚至可以说“撒旦层”。
原文网址:https://www.reddit.com/r/comfyui/comments/18wp6oj/tutorial_create_a_custom_node_in_5_minutes/
教程专区:https://heehel.com/category/ai-tutorial
AI工具专区:https://heehel.com/category/ai-soft
AIGC专区:https://heehel.com/category/aigc
- 你可以找到一个50分钟长的视频(虽然不完整但非常好),作为初学者,你真的不希望它那么长。
- 你可能会发现不完整的指南让您感到困惑,而不是提供帮助。
- 你可能会偶然发现自定义节点指南……用于完全不同的软件 x)。
- 你会发现有人告诉你“只要研究代码”,这确实是一个完全的初学者最不想听到的事情,特别是如果他们对 Python 不太了解的话^^'。
不过别担心。你只需要等待其他人代替你受苦并愿意分享他们的经历。对你来说幸运的是,这就是我的情况。这意味着我必须为你受苦!
我在此发誓,5分钟内,您将拥有一个准备就绪的自定义节点。
作者:u/LJRE_
创建脚本
让我们立即开始,进入自定义节点文件夹。在此处创建一个新的文本文件(目前不在新文件夹中)。为其指定.py 扩展名和任何您想要的名称(但要避免空格和特殊字符)。然后打开它。
任何文本编辑器都可以,但我推荐Notepad++,因为它可以理解代码语法。
打开你的文件,它是空白的。我们将编写代码以使自定义节点出现在 Comfy!
...但首先,我们必须了解我们如何进行:
……对此:
让我们分解一下什么是节点:
- 节点(盒子本身)。
- 一个名字(实际上是四个名字,但我们稍后会看到)
- 变量或小部件。
- 输入点。
- 输出点。
在Python代码中,节点被定义为一个类。类名必须始终以大写字母开头,并且始终是单个单词。它看起来像这样:
将所有代码复制粘贴到空白文件中。然后保存并打开ComfyUI。
双击工作流程中的空白区域,然后输入“Node”。您应该在列表中看到 myNode!选择它。恭喜,您制作了第一个自定义节点!
……但就目前而言,这并不是很有趣。让我们添加一些小部件!
创建小部件
变量或小部件在“required”行之后定义。事情是这样的:
"text": ("STRING", {"default":"嘿嘿!"}),
复制粘贴该行,然后在代码中在其前面添加16个空格。它必须位于与“required”一词相关的括号之间。保存,然后重新启动 ComfyUI。
如果您的节点变成红色并且软件抛出错误,则说明您没有添加足够的空间,或者没有在所需区域中复制该行。
否则,您的自定义节点将变成这样:
我将小部件称为“变量”,因为您可以手动更改它们。单击小部件,您可以更改文本。
创建输入
现在假设我们想要一个“真实的”输入,我的意思是使一个点出现的输入。超级简单!输入点与小部件完全相同(因为小部件实际上也是输入,但让我们将它们作为单独的东西保存在我们的脑海中!)。
你只需要写“forceInput”:True而不是默认值。
在代码中的“必需”部分中,复制粘贴上一行(包括其前面的空格!)。然后更改名称(例如从“text”更改为“text2”)并删除所有“默认部分”。而是写上面的粗体文本。
你的线路变成这样:
"text2": ("STRING", {"forceInput": True}),
这两个词让 Comfy 明白它是一个点输入而不是一个小部件。让我们检查一下它是否有效!重启舒服。您会看到您的节点已更改...
…… 但它并没有按预期工作^^'。从今天开始,如果您的自定义节点已经在您的工作流程中,则在更改其输入/小部件/输出时,其行为是不可预测的。
目前就是这样。我在该教程中展示了这一点,因为了解这条规则对您来说很重要:每当您处理自定义节点时,请始终在每次测试之前将其从工作流程中删除。
回到我们的例子。删除 ComfyUI 中的自定义节点。之前我们通过双击来搜索它,但现在我们不这样做。如果我们想在上下文菜单中找到它怎么办?我们开工吧!
但我们去哪里寻找它呢?为了了解,请阅读代码。查找 CATEGORY 行。
知道了?如果您找到了它,您会注意到我们的示例位于“image/mynode2”类别中。
在 ComfyUI 中,右键单击工作流程,然后单击图像。您会找到我们的自定义类别,mynode2!单击它,您就可以在此处找到我们的小节点。
选择它。
我们现在已经拿到了。自定义节点有一个名为 text2(或任何您所称的名称)的输入点。
现在,如果我们不想只使用文本怎么办?我们将其保存到以后,但现在,再次阅读我们的代码,您会注意到输入/小部件有一个类型,在本例中为:STRING。您将其转换为 INT,然后将该输入/小部件转换为整数。
现在您知道如何提供输入了!显然,下一步是学习如何处理输出。
创建输出
这些是在类的 RETURN_TYPES 和 RETURN_LINES 行中定义的。是的,只需要这两行!
在您的代码中,用以下内容填充 RETURN_TYPES 括号:
“STRING”、“INT”、“FLOAT”、“LATENT”
您刚刚定义了四个输出,我想您可以猜出它们的类型!如果你想玩得开心,你可以添加更多。有两条规则永远不要忘记:
- 1. 始终以大写字母书写类型!
- 2. 确保使用正确的类型!
你注意到了吗?一个输出到另一个输出的撇号并不相同。没有这方面的规定,所以不用担心。这些符号是可以互换的。
您还可以将每个输出的名称更改为您想要的任何名称。在 RETURN_LINES 行中,用以下内容填充括号:
“TxtO”、“IntO”、“FloatO”、“潜在输出。真的很酷,对吧?”
现在您必须小心该行中的名称数量与您定义的输出类型的数量相匹配。知道了?好的。
在 ComfyUI 中,删除自定义节点并重新启动软件。放回自定义节点。
耶!输出出现!请注意,它们已经有了匹配的颜色。潜在输出是粉红色的;如果您尝试放置调节或图像输出,它们将已经是橙色和蓝色。同样,无色输出已经要求兼容的节点。
您现在可以尝试:将字符串输出附加到与文本相关的节点或尝试使用潜在输出。
命名节点
我们快到了!现在我们来看看代码的最后一部分:类映射和名称映射。
第一行是类映射,您可以在类和节点名称之间创建一对。
NODE_CLASS_MAPPINGS = {
“我的第一个节点”:MyNode
}
第一个值是您希望在软件中显示的名称,因此它可以是任何内容,只需确保它位于撇号之间。第二个必须是代码中定义的类的名称。
如果您有多个自定义节点,则每个节点都必须在此处有一行,您可以在其中定义要在软件中显示的名称并将其与类的名称配对。
我不确定第二行(名称映射)的作用。你甚至可以让它为空,运行程序时不会出错。我会让更有知识的人给我们解释一下^^'。
最后的问题
现在,还有最后一个问题。目前,我们的自定义节点位于自定义节点的默认文件夹中。如果你想把它放在自己的文件夹中怎么办?我们来试试吧。
创建一个新文件夹,将脚本文件拖入其中。如果您现在重新启动 ComfyUI,则会出现错误。
为什么?
因为程序需要一个初始化文件才能明白必须使用该文件夹中的脚本。
为什么?
因为……因为 x)。(因为Python是狗屎,但我们却被它困住了,所以我们不得不忍受它,因为它基本上无处不在.)
我们现在就这样做吧。在您的自定义节点文件夹中,创建一个新的文本文件并将其命名为:
__init__.py
打开它,然后复制粘贴以下代码:
从 .myfirstnode 导入 MyNode
NODE_CLASS_MAPPINGS = { "MyNode": MyNode }
NODE_DISPLAY_NAME_MAPPINGS = { "FirstNode": "我的第一个节点" }
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']
--
这里有一些规则需要理解:
在第一行中,点后面的单词必须是您的脚本名称。
在第一行导入 后,您必须拥有在 python 脚本中定义的所有类的列表,以逗号分隔。
如果您有多个脚本,则必须多次编写该行,每个脚本一次。
相反,对于其他线路,您只需要一根线路。
节点类映射行必须包含您在脚本中定义的所有类映射。只需复制粘贴它们并用逗号分隔即可。
显示名称映射的工作原理类似。
这两行在 init 文件中是必需的。请注意,它们会覆盖原始脚本中定义的任何内容。因此,一旦您的自定义节点位于其自己的文件夹中,您就必须在 init 文件中定义节点/类名称对。
你永远不应该触碰“所有线”。
结论
就是这样!有了这个,你可以在 ComfyUI 中创建任何东西!当然,我们所做的一切都只是骨架。
然后,还有肉!您可以使用代码使该节点执行您想要的任何操作。绝对每个 Python 函数都可以工作!通过 Python,您甚至可以使用其他语言,例如 javascript(对于视觉内容至关重要)。
但这是你必须自己学习的东西。编程是一种语言;因此,它极其多样化,你永远无法真正 100% 了解它。但就像真正的语言一样,您可以立即从简单的东西开始并逐步学习!
不过我会给出一些关于 Python 的规则:
空间很重要!
永远不要使用制表符来缩进你的行。使用多个空格。在 Notepad++ 中,每个缩进键入空格四次。切勿使用选项卡。我花了今年的第一天尝试修复一个实际上完美的代码,除了我对选项卡的使用之外!
这些是纯 Python 规则。但 ComfyUI 也有自己的一套规则。通过本指南,我们回顾了其中的很多内容,但还有其他一些内容:
如果您想创建自定义节点 PACK,则不需要多个脚本。重要的是每个自定义节点都有一个类。
一类具有输入、输出和至少一个函数。在我们的代码中可以看到:
功能=“测试”
此行表示自定义节点应用此脚本中定义的名为“test”的函数。
为了让您的自定义节点真正执行某些操作,您需要确保此行中调用的函数实际上执行您想做的任何操作。
例如,如果它是两个输入的总和,则必须由它调用总和。
函数=“mysum”
def sum(自身, a,b)
c=a+b
返回c
此代码示例将不起作用,因为该函数不是为此自定义节点调用的函数。但是,您可以创建一个“mysum”函数,最终调用 sum(a,b) 函数。
3. 我认为函数必须始终将“self”作为其第一个参数。我不知道为什么,也不知道它是 Comfy 特有的还是 Python 的一般规则。不管怎样,每当你定义一个函数时,永远不要忘记 self 参数!
我仅仅触及了表面,但通过个人经验,你会走得更远!我现在将向您推荐本指南:
https://github.com/chrisgoringe/Comfy-Custom-Node-How-To/wiki
它不完整,所以一开始会让人感到害怕,但它包含许多有关 ComfyUI 编码的有用信息。毕竟它是由制作自己的自定义节点的人编写的!
我还将分享一个自定义节点“模板”:
百度网盘链接:https://pan.baidu.com/s/1gB9zUWlxKjvka4gQpQDygQ?pwd=ykel
提取码:ykel 解压密码:heehel
这就是我们在本教程中处理的自定义节点(进行了一些细微的调整)。每当您想从头开始时,只需将其提取到 custom_nodes 文件夹中,它就可以从 get-go 开始工作。那么你只需要修改脚本即可!
最后,这里有一些练习供您训练。重写我们刚刚创建的自定义节点并用它解决这些问题。
- 将小部件转换为输入点。
- 添加三个输出:图像、条件、模型。
3)
以下是自定义节点的代码:
class NodeKO: def __init__(self): pass @classmethod def INPUT_TYPES(s): return { "required": { "text": ("STRING", {"default":"Hey Hey!"}), "text2": ("STRING", {"forceInput" True}), }, } RETURN_TYPES = ("STRING","INT", "FLOAT", 'LATENT', "CONDITIONING", "IMAGE", "MODEL") RETURN_NAMES = ("TxtO", "IntO", "FloatO", "Latent output. Really cool, huh?", "A condition" , "Our image." , "Mo mo modell!!!") FUNCTION = "test" #OUTPUT_NODE = False CATEGORY = "nodeKO" def test(self): return () # A dictionary that contains all nodes you want to export with their names # NOTE: names should be globally unique NODE_CLASS_MAPPINGS = { "My KO Node": MyNode } # A dictionary that contains the friendly/humanly readable titles for the nodes NODE_DISPLAY_NAME_MAPPINGS = { "FirstNode": "My First Node" }
--
重写它以使其工作。提示:有三个错误需要修复。
玩得开心,我希望这可以帮助一些有创意的人^^。
https://heehel.com/aigc/comfyui-lora-training-node.html
https://heehel.com/aigc/comfyui-community-platform.html