Skip to content

[Modular]improve loop block#14159

Open
yiyixuxu wants to merge 6 commits into
mainfrom
refactor-iterative-loop-blocks
Open

[Modular]improve loop block#14159
yiyixuxu wants to merge 6 commits into
mainfrom
refactor-iterative-loop-blocks

Conversation

@yiyixuxu

@yiyixuxu yiyixuxu commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

This PR adds an improved IterativePipelineblocks intended to replace LoopSequentialPipelineBlocks:

so that it can be nested and composed freely -> you can nest a IterativePipelineblocks inside another to created a nested loop (autoregressive chunk loop)

I refactored flux2 denoise loop as as example on how to use them

…tate scopes

Adds a loop composite whose sub-blocks are ordinary state blocks, so loops
can nest and compose freely (e.g. an autoregressive chunk loop containing a
timestep denoise loop). Loop variables like the current timestep are provided
through a loop-local scope on PipelineState (`loop_scope()` / `set_local`):
they resolve sub-blocks' declared inputs while the loop runs and are
discarded when it exits, so they never surface as pipeline inputs. Sub-blocks
declare everything they consume; declared outputs persist as usual.

The loop block declares its own surface symmetrically to
LoopSequentialPipelineBlocks: loop_inputs, loop_locals (names it provides via
the scope), loop_intermediate_outputs, loop_expected_components/configs.
Subclasses hand-write `__call__` around `loop_step()`, same idiom as leaf
blocks around `get_block_state`.

Ports the flux2 denoise loops (flux2, klein, klein-base) as the reference
example, moves `progress_bar` to the ModularPipelineBlocks base, and treats
the new class as a leaf in workflow traversal like LoopSequential. Adds
structure/execution/nesting tests modeled on the helios chunk-loop use case.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added size/L PR with diff > 200 LOC tests modular-pipelines and removed size/L PR with diff > 200 LOC labels Jul 10, 2026
@HuggingFaceDocBuilderDev

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

yiyixuxu and others added 5 commits July 10, 2026 16:06
Loop variables (i, t, k, ...) now ride the call signature: leaf sub-blocks
of an IterativePipelineBlocks accept them after (components, state), the
loop declares their names in `loop_variables`, and `loop_step` validates
every leaf's signature against it before the first iteration. Assembled
sub-blocks (nested loops, sequential/conditional groups) are called with
the regular (components, state) interface and pass their own loop
variables to their own sub-blocks.

This removes the PipelineState scope machinery entirely — PipelineState
and get/set_block_state are unchanged from main — and loop sub-blocks keep
the familiar LoopSequentialPipelineBlocks authoring style, now with full
composability.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Remove the composite exemption in loop_step: every sub-block of an
IterativePipelineBlocks — including a nested loop — must accept the loop
variables after (components, state), validated before the first iteration.
A nested loop accepts the outer variables in its hand-written __call__
(ignoring or forwarding them) and passes its own loop_variables to its own
sub-blocks. Plain Sequential/Conditional groups are not supported as loop
sub-blocks (flatten instead).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The abstract __call__ placeholder now accepts **kwargs and the docstring
shows the nested case: a loop nested inside another accepts the outer
loop's variables in its hand-written __call__.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ModularPipelineBlocks now defines an abstract __call__ raising a clear
NotImplementedError. Loop steps get their own base class,
ModularLoopPipelineBlocks, whose only difference is the __call__ contract
(accepts the enclosing loop's variables after (components, state)).
IterativePipelineBlocks validates at construction that every sub-block is
a ModularLoopPipelineBlocks or a nested IterativePipelineBlocks, in
addition to the signature validation before the first iteration.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Remove loop_inputs / loop_intermediate_outputs / loop_expected_components /
loop_expected_configs from IterativePipelineBlocks — when the loop logic in
__call__ consumes inputs or components beyond what sub-blocks declare, the
subclass overrides the aggregated inputs / expected_components properties
directly (see Flux2DenoiseLoopWrapper).

Sub-block validation (type + loop-variable signature) now runs at
construction (__init__ and from_blocks_dict) instead of lazily in
loop_step.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added the size/L PR with diff > 200 LOC label Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants