ComfyUI añade bucles nativos: Start Loop y End Loop
El núcleo de ComfyUI ahora ejecuta bucles de forma nativa. Combina Start Loop con End Loop para iterar un grafo por recuento, rango de índices o lista, con valores transportados.
utilities/looping.
Cómo se dibuja un bucle
No hay ningún contenedor de bucle que configurar. Un bucle es un par de nodos, y el cuerpo es todo lo que queda entre ellos: cualquier cosa conectada desde Start Loop hasta End Loop se ejecuta una vez por iteración.
La estructura del bucle se comprueba durante la validación normal del prompt, por lo que un bucle mal formado falla antes de que comience la ejecución. Cada Start Loop debe emparejarse de forma inequívoca con exactamente un End Loop, los ámbitos anidados deben mantenerse coherentes y una rama de bucle no puede escapar de su End Loop. Start Loop y End Loop se declaran como límites de bucle en su esquema de nodo, que es lo que lee la comprobación de emparejamiento.
En el momento de la ejecución, el cuerpo original se inhibe y cada iteración se proyecta como nuevos nodos de grafo en cola, incluida la primera. Las iteraciones siguen siendo trabajo ordinario del scheduler, en lugar de ser gestionadas por un intérprete de bucle separado, y el progreso de la iteración se informa en el nodo como Iteration n / total.
Tres formas de contar iteraciones
La entrada mode de Start Loop determina cómo se produce el contador de iteraciones, y solo se muestran las entradas del modo seleccionado.
| Modo | Itera sobre | Entradas propias |
|---|---|---|
simple | Un número fijo de repeticiones | num_iterations (por defecto 4) |
For | Un rango de índices numérico | start_iteration_index (por defecto 0), max_iteration (por defecto 4, exclusivo), step (por defecto 1) |
List | Una pasada por cada elemento de una lista conectada | list |
step es al menos 1 y un valor de 0 genera un error. Si el recuento de iteraciones calculado es cero, el cuerpo del bucle no se ejecuta y is_last se informa como verdadero.
Qué devuelve Start Loop
| Salida | Significado |
|---|---|
iteration_index | Índice de la iteración actual |
is_first | Verdadero en la primera iteración |
is_last | Verdadero en la última iteración |
list_item | El elemento actual en modo List, vacío en los demás modos |
current_iteration_value | El valor transportado por el bucle para esta iteración |
is_first es el gancho habitual para una primera pasada distinta, por ejemplo sembrar un bucle de vídeo desde un fotograma fuente en lugar del último fotograma de la ventana anterior.
El caso mínimo: un Start Loop, un pequeño cuerpo de generación, un End Loop. El passthrough de Guardar Imagen está conectado a una entrada de terminación para que siga ejecutándose una vez por iteración.
Cerrar el bucle
End Loop cierra el ámbito y decide qué sale de él.
| Entrada | Rol |
|---|---|
output_value | El valor devuelto después de que finalice el bucle |
next_iteration_value | Se envía de vuelta a Start Loop como current_iteration_value para la siguiente iteración |
accumulate | Cuando está habilitado, se devuelve el output_value de cada iteración en lugar de solo el de la última |
entradas de termination | Entradas de crecimiento dinámico para vistas previas, guardadores y otros efectos secundarios que deben ejecutarse en cada iteración. Sus valores no se devuelven |
End Loop tiene un único socket de salida cuyo tipo sigue a output_value. Con accumulate habilitado, los valores salen como una lista normal de ComfyUI, concatenados en el orden de iteración.
Las entradas de termination son la solución a una sorpresa habitual: un nodo Vista previa de imagen o Guardar Imagen colocado dentro del cuerpo solo se activaría en la iteración final, porque los cuerpos proyectados anteriores se reemplazan. Conectar el passthrough de ese nodo a una entrada de terminación lo mantiene ejecutándose una vez por iteración y lo mantiene dentro del límite del bucle.
Con accumulate activado, las cuatro generaciones vuelven como una sola lista. Vista previa de imagen se termina para que cada iteración sea visible a medida que se completa.
Variar el trabajo en cada iteración
Como iteration_index es una salida entera normal, puede impulsar cualquier cosa aguas abajo: resolución, número de pasos, variantes de prompt o una rampa de fuerza de LoRA.
El modo For alimentando iteration_index hacia la resolución, con resultados de distintos tamaños acumulados al final.
Transportar estado entre iteraciones
initial_iteration_value siembra el valor transportado en la primera iteración, y el next_iteration_value de cada iteración se convierte en el current_iteration_value de la siguiente. Eso es todo el canal de estado, y hay exactamente uno por cada par de Start Loop y End Loop.
Para transportar más de una cosa, ponlas en una lista. El nodo existente Create List ahora acepta entradas heterogéneas, por lo que un valor transportado puede contener estado mixto, como una imagen y el prompt de texto que la produjo. Dos nodos de la categoría utilities dan soporte a este patrón:
- Create List: construye el valor transportado a partir de entradas mixtas.
- Get Item From List: nuevo en la misma versión. Toma una lista y un índice y devuelve ese elemento como un valor normal, de modo que los componentes del estado transportado se pueden desempaquetar dentro de la siguiente iteración.
Generación con Z-Image y descripción con visión-lenguaje pasadas de un lado a otro a través de un único valor transportado de imagen y texto.
Anidamiento y caché
parent_iteration en Start Loop es una entrada forzada: conecta el iteration_index del bucle externo para anidar un bucle dentro de otro. El anidamiento es explícito en lugar de inferido, y cada Start Loop sigue necesitando exactamente un End Loop.
cache_iterations en Start Loop es avanzado y está desactivado por defecto. Cuando se habilita, los nodos de iteración proyectados pueden reutilizar resultados en caché de ejecuciones anteriores. El propio nodo End Loop es un nodo ejecutado ordinario, por lo que su salida final se almacena en caché con normalidad en cualquier caso.
Un bucle externo en modo List sobre prompts, con el bucle de generación anidado dentro de él mediante parent_iteration.
Ejemplos de vídeo y latent
El mecanismo se creó pensando en la extensión de vídeo, donde cada ventana depende de la anterior. Dos ejemplos publicados muestran el patrón directamente.
Un bucle de vídeo de último fotograma a primer fotograma: la imagen fuente siembra initial_iteration_value, el fotograma final de cada ventana generada se convierte en el primer fotograma de la siguiente ventana, y los lotes de fotogramas se acumulan y se reagrupan en un solo clip.
Un latent transportado directamente por el bucle con accumulate desactivado, de modo que solo se devuelve el latent final, además de un conmutador lazy para el manejo de la primera iteración y una fuerza de LoRA que cambia gradualmente a medida que avanza el muestreo.
El punto de partida más simple, un bucle de generación de cuatro iteraciones sin estado transportado, es un único par de Start Loop y End Loop:
Dónde viven los nodos
Start Loop y End Loop son nodos del núcleo en la categoría utilities/looping y se incluyen con el propio ComfyUI, por lo que no se necesita ningún paquete de nodos. Create List y Get Item From List se encuentran en utilities. El comportamiento de bucle está documentado en las páginas oficiales de nodos integrados de Start Loop y End Loop.
Los flujos de trabajo existentes no se ven afectados: los bucles son opcionales, y un grafo sin par de Start Loop y End Loop se pone en cola exactamente igual que antes.
Comentarios
Inicia sesión con GitHub para unirte a la conversación.