Descripción general
El esquema V3 de ComfyUI introduce una forma más organizada de definir nodos, y las futuras extensiones de las funciones de los nodos solo se agregarán al esquema V3. Puedes usar esta guía para migrar tus nodos V1 existentes al nuevo esquema V3.Conceptos básicos
El esquema V3 se mantiene en la nueva API versionada de Comfy, lo que significa que las futuras revisiones del esquema serán compatibles hacia atrás.comfy_api.latest apuntará a la última API numerada que aún está en desarrollo; la versión anterior a latest es la que se puede considerar «estable». La versión v0_0_2 es la versión actual (y la primera) de la API, así que se le harán más cambios sin previo aviso. Cuando se considere estable, se creará una nueva versión v0_0_3 para que latest apunte a ella.
Arquitectura V1 frente a V3
Los cambios más importantes del esquema V3 son:- Las entradas y salidas se definen con objetos en lugar de un diccionario.
- El método de ejecución queda fijado con el nombre ‘execute’ y es un método de clase.
- La función
def comfy_entrypoint(), que devuelve un objeto ComfyExtension, define los nodos expuestos en lugar de NODE_CLASS_MAPPINGS/NODE_DISPLAY_NAME_MAPPINGS - Los objetos nodo no exponen ‘state’:
def __init__(self)no tendrá efecto sobre lo que se expone en las funciones del nodo, ya que todas son métodos de clase. La clase del nodo también se sanea antes de ejecutarse.
V1 (heredado)
V3 (moderno)
Pasos de migración
Pasar de V1 a V3 debería ser sencillo en la mayoría de los casos y es simplemente un cambio de sintaxis.Paso 1: Cambiar la clase base
Todos los nodos del esquema V3 deben heredar deComfyNode. Se permiten varias capas de herencia siempre que en la parte superior de la cadena haya un padre ComfyNode.
V1:
Paso 2: Convertir INPUT_TYPES en define_schema
Las propiedades del nodo, como el id del nodo, el nombre visible, la categoría, etc., que antes se asignaban en distintos lugares del código (diccionarios y propiedades de clase), ahora se mantienen juntas mediante la claseSchema.
Se espera que la función define_schema(cls) devuelva un objeto Schema, de forma muy parecida a como funcionaba INPUT_TYPES(s) en V1.
Los tipos de entrada y salida principales compatibles se guardan y documentan en comfy_api/{version} dentro de _io.py, que por defecto usa el espacio de nombres io. Como ahora las entradas y salidas se definen con clases en lugar de diccionarios o cadenas, los tipos personalizados se admiten definiendo tu propia clase o usando la función auxiliar Custom de io.
Los tipos personalizados se explican en una sección más abajo.
Una clase de tipo tiene las siguientes propiedades:
class Inputpara las entradas (por ejemplo,Model.Input(...)).class Outputpara las salidas (por ejemplo,Model.Output(...)). Ten en cuenta que no todos los tipos admiten ser salida.Typepara obtener la anotación de tipo del tipo (por ejemplo,Model.Type). Ten en cuenta que algunas anotaciones son soloany, lo que puede cambiar en el futuro. Estas anotaciones no se aplican y solo sirven como documentación útil.
Paso 3: Actualizar el método de ejecución
Todas las funciones de ejecución en V3 se llamanexecute y son métodos de clase.
V1:
Paso 4: Convertir las propiedades del nodo
Aquí tienes algunos ejemplos de nombres de propiedades; consulta el código fuente encomfy_api.latest._io para más detalles.
Paso 5: Gestionar los métodos especiales
Se admiten los mismos métodos especiales que en V1, pero en minúsculas o con nombres completamente nuevos para que sean más claros. Su uso sigue siendo el mismo.Validación (V1 → V3)
La función de validación de entradas se renombró avalidate_inputs.
V1:
Evaluación diferida (V1 → V3)
La funcióncheck_lazy_status pasa a ser un método de clase y por lo demás no cambia.
V1:
Control de caché (V1 → V3)
La funcionalidad del control de caché sigue siendo la misma que en V1, pero el nombre original era muy engañoso respecto a cómo operaba. La funciónIS_CHANGED de V1 indica a la ejecución que no vuelva a ejecutar el nodo si el valor devuelto es IGUAL al de la última vez que se ejecutó el nodo.
Por eso la función IS_CHANGED se renombró a fingerprint_inputs. Uno de los errores más comunes de los desarrolladores era pensar que, si devolvías True, el nodo se volvería a ejecutar siempre. Como True se devolvería siempre, tenía el efecto contrario: hacer que el nodo se ejecutara una sola vez y reutilizara los valores en caché.
Un ejemplo del uso de esta función es el nodo LoadImage. Devuelve el hash del archivo seleccionado, de modo que, si el archivo cambia, el nodo se ve obligado a volver a ejecutarse.
V1:
Paso 6: Crear la extensión y el punto de entrada
En lugar de definir diccionarios que vinculan el id del nodo con la clase y el nombre visible, ahora hay una claseComfyExtension y una función comfy_entrypoint que se debe definir.
En el futuro se podrán agregar más funciones a ComfyExtension para registrar más cosas además de nodos mediante get_node_list.
comfy_entrypoint puede ser async o no, pero get_node_list debe definirse como async.
V1:
Referencia de tipos de entrada
Ya se explicó en el paso 2, pero aquí tienes algunas comparaciones de tipos entre V1 y V3. Consultacomfy_api.latest._io para ver las declaraciones completas de los tipos.
Tipos básicos
control_after_generate
Las entradas Int y Combo admiten un parámetrocontrol_after_generate que agrega un widget de control para cambiar el valor automáticamente después de cada generación. En V1 era un simple bool; en V3 puedes usar la enumeración io.ControlAfterGenerate para un control explícito. Pasar True equivale a io.ControlAfterGenerate.randomize.
Tipos de ComfyUI
Combo (desplegables y listas de selección)
Los tipos Combo en V3 requieren una definición explícita de clase. V1:Referencia de Schema
La dataclassSchema define todas las propiedades de un nodo V3. Aquí tienes una referencia completa de todos los campos disponibles:
Parámetros comunes de entrada
Todos los tipos de entrada comparten estos parámetros base:
Las entradas de widget (Int, Float, String, Boolean, Combo) además admiten:
Funciones avanzadas
Entradas ocultas
Las entradas ocultas dan acceso al contexto de ejecución, como los metadatos del prompt, el ID del nodo y otros valores internos. No son visibles en la UI. En V1, las entradas ocultas se declaraban con una clave"hidden" en INPUT_TYPES. En V3 se declaran con el parámetro hidden del Schema y sus valores se consultan con cls.hidden.
V1:
Algunos valores ocultos se agregan automáticamente según los indicadores del Schema. Los nodos de salida (
is_output_node=True) reciben automáticamente prompt y extra_pnginfo. Los nodos de API (is_api_node=True) reciben automáticamente los tokens de autenticación.Ayudantes de UI
V3 incluye ayudantes de UI en el móduloui para gestionar patrones comunes, como la vista previa y el guardado de archivos. Se pasan a io.NodeOutput con el parámetro ui.
Ayudantes de vista previa
Los ayudantes de vista previa guardan archivos temporales y devuelven datos de UI para mostrarlos dentro del nodo.Ayudantes de guardado
Los ayudantes de guardado ofrecen métodos para guardar archivos en el directorio de salida con una incrustación correcta de metadatos. Normalmente se usan en los nodos de salida.Devolver diccionarios de UI sin procesar
Si necesitas devolver datos de UI que no tienen un ayudante, puedes pasar un diccionario directamente:Nodos de salida
Para los nodos que producen efectos secundarios (como guardar archivos). Igual que en V1, marcar un nodo como salida muestra un botón de reproducciónrun en la ventana contextual del nodo, lo que permite ejecutar el gráfico parcialmente.
Tipos personalizados
Crea tipos de entrada y salida personalizados con una definición de clase o con la función auxiliarCustom.
Entradas MultiType
MultiType permite que una entrada acepte más de un tipo. Es útil cuando un nodo puede operar sobre distintos tipos de datos a través de la misma ranura de entrada.
Si el primer argumento (id) es una instancia de una clase Input en lugar de una cadena, esa entrada se usa para crear un widget con sus valores sobrescritos. En caso contrario, la entrada es solo de socket.
MatchType (coincidencia de tipos genérica)
MatchType crea entradas y salidas vinculadas por tipo. Cuando un usuario conecta un tipo específico a una entrada MatchType, todas las demás entradas y salidas que comparten la misma plantilla se restringen automáticamente a ese tipo. Así funcionan los nodos como Switch y Create List con cualquier tipo.
Entradas dinámicas
V3 incorpora tipos de entrada dinámicos que cambian las entradas disponibles según la interacción del usuario. No hay equivalente en V1 para estas funciones.Autogrow
Autogrow crea un número variable de entradas que crecen automáticamente a medida que el usuario conecta más. Hay dos tipos de plantilla:
TemplatePrefix genera entradas con un prefijo numerado (por ejemplo, image0, image1, image2…):
DynamicCombo
DynamicCombo crea un desplegable que muestra u oculta distintas entradas según la opción seleccionada. Es útil para nodos en los que distintos modos requieren parámetros diferentes.
Ejecución asíncrona
V3 admite métodosexecute asíncronos. Es útil para nodos que realizan operaciones de E/S, llamadas a API u otro trabajo asíncrono. Basta con declarar execute como async:
Servicios de ejecución de la API de Comfy
La claseComfyAPI da acceso a los servicios de ejecución de ComfyUI, como el informe de progreso y el registro de reemplazo de nodos. Impórtala y crea una instancia:
Informe de progreso
Informa del progreso de la ejecución desde el métodoexecute de un nodo. La barra de progreso se muestra en la interfaz de ComfyUI. Esto reemplaza el patrón de V1 que usaba comfy.utils.PROGRESS_BAR_HOOK.
set_progress acepta una imagen PIL, un tensor ImageInput o None en el parámetro preview_image. Cuando se llama desde execute, el node_id se determina automáticamente a partir del contexto de ejecución.Reemplazo de nodos
El reemplazo de nodos permite asignar nodos antiguos u obsoletos a nodos nuevos, de modo que los flujos de trabajo existentes se actualicen automáticamente. Registra los reemplazos conComfyAPI en el método on_load de tu extensión.
old_widget_ids es importante: el JSON del flujo de trabajo guarda los valores de los widgets por índice de posición, no por nombre. Esta lista asigna esos índices de posición a los IDs de entrada para que el sistema de reemplazo pueda identificar correctamente los valores de los widgets durante la migración.
Para los nodos que usan entradas dinámicas (como Autogrow), usa rutas con punto en el mapeo:
Ciclo de vida de la extensión
La claseComfyExtension admite ganchos de ciclo de vida además de get_node_list:
NodeOutput
La claseNodeOutput es el valor de retorno estandarizado de execute. Admite varios patrones: