8000 The Modular Diffusers by yiyixuxu · Pull Request #9672 · huggingface/diffusers · GitHub
[go: up one dir, main page]

Skip to content

The Modular Diffusers #9672

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 188 commits into from
Jul 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
188 commits
Select commit Hold shift + click to select a range
33f85fa
add
yiyixuxu Oct 14, 2024
52a7f1c
add dataflow info for each block in builder _repr_
yiyixuxu Oct 16, 2024
e8d0980
add img2img support - output does not match with non-modular pipeline…
yiyixuxu Oct 16, 2024
ad3f9a2
update img2img, result match
yiyixuxu Oct 17, 2024
ddea157
add from_pipe + run_blocks
yiyixuxu Oct 17, 2024
af9572d
controlnet
yiyixuxu Oct 19, 2024
2b6dcbf
fix controlnet
yiyixuxu Oct 20, 2024
70272b1
combine controlnetstep into contronetdesnoisestep
yiyixuxu Oct 20, 2024
46ec174
refactor guider, remove prepareguidance step to be combinedd into den…
yiyixuxu Oct 23, 2024
f1b3036
update pag guider - draft
yiyixuxu Oct 23, 2024
540d303
refactor guider
yiyixuxu Oct 26, 2024
6742f16
up
yiyixuxu Oct 27, 2024
005195c
add
yiyixuxu Oct 27, 2024
024a9f5
fix so that run_blocks can work with inputs in the state
yiyixuxu Oct 27, 2024
37e8dc7
remove img2img blocksgit status consolidate text2img and img2img
yiyixuxu Oct 27, 2024
8b811fe
refactor, from_pretrained, from_pipe, remove_blocks, replace_blocks
yiyixuxu Oct 30, 2024
c70a285
style
yiyixuxu Oct 30, 2024
ffc2992
add autostep (not complete)
yiyixuxu Nov 16, 2024
ace53e2
update/refactor
yiyixuxu Dec 10, 2024
a8df0f1
Modular APG (#10173)
hlky Dec 10, 2024
e50d614
only add model as expected_component when the model need to run for t…
yiyixuxu Dec 11, 2024
bc3d1c9
add model_cpu_offload_seq + _exlude_from_cpu_offload
yiyixuxu Dec 13, 2024
2b3cd2d
update
yiyixuxu Dec 14, 2024
b305c77
add offload support!
yiyixuxu Dec 14, 2024
0b90051
add vae encoder node
yiyixuxu Dec 19, 2024
806e8e6
Merge branch 'main' into modular-diffusers
yiyixuxu Dec 29, 2024
4fa85c7
add model_manager and global offloading method
yiyixuxu Dec 31, 2024
72d9a81
components manager
yiyixuxu Dec 31, 2024
10d4a77
style
yiyixuxu Dec 31, 2024
27dde51
add output arg to run_blocks
yiyixuxu Dec 31, 2024
8c02572
add memory_reserve_margin arg to auto offload
yiyixuxu Dec 31, 2024
a09ca7f
refactors: block __init__ no longer accept args. remove update_state…
yiyixuxu Jan 1, 2025
ed59f90
modular pipeline builder -> ModularPipeline
yiyixuxu Jan 1, 2025
72c5bf0
add a from_block class method to modular pipeline
yiyixuxu Jan 1, 2025
6c93626
remove run_blocks, just use __call__
yiyixuxu Jan 1, 2025
1d63306
make it work with lora
yiyixuxu Jan 3, 2025
2e0f5c8
start to add inpaint
yiyixuxu Jan 3, 2025
c12a05b
update to to not assume pipeline has hf_device_map
yiyixuxu Jan 3, 2025
54f410d
add inpaint
yiyixuxu Jan 6, 2025
6985906
controlnet input & remove the MultiPipelineBlocks class
yiyixuxu Jan 7, 2025
db94ca8
add controlnet inpaint + more refactor
yiyixuxu Jan 7, 2025
e973de6
fix contro;net inpaint preprocess
yiyixuxu Jan 8, 2025
7a34832
[modular] Stable Diffusion XL ControlNet Union (#10509)
hlky Jan 9, 2025
2220af6
refactor
yiyixuxu Jan 11, 2025
fb78f4f
Merge branch 'modular-diffusers' of github.com:huggingface/diffusers …
yiyixuxu Jan 11, 2025
0966663
adjust print
yiyixuxu Jan 11, 2025
7f897a9
fix
yiyixuxu Jan 12, 2025
a6804de
add controlnet union to auto & fix for pag
yiyixuxu Jan 12, 2025
7007f72
InputParam, OutputParam, get_auto_doc
yiyixuxu Jan 16, 2025
a226920
get_block_state make it less verbose
yiyixuxu Jan 17, 2025
77b5fa5
make it work with lora has both text_encoder & unet
yiyixuxu Jan 18, 2025
6e2fe26
fix more for lora
yiyixuxu Jan 18, 2025
68a5185
refactor more, ipadapter node, lora node
yiyixuxu Jan 20, 2025
d046cf7 8000
block state + fix for num_images_per_prompt > 1 for denoise/controlne…
yiyixuxu Jan 22, 2025
71df158
Update src/diffusers/pipelines/stable_diffusion_xl/pipeline_stable_di…
yiyixuxu Jan 22, 2025
b3fb418
Merge branch 'modular-diffusers' of github.com:huggingface/diffusers …
yiyixuxu Jan 22, 2025
00cae4e
docstring doc doc doc
yiyixuxu Jan 23, 2025
ccb35ac
Merge branch 'main' into modular-diffusers
yiyixuxu Jan 23, 2025
00a3bc9
fix
yiyixuxu Jan 23, 2025
4bed3e3
up up
yiyixuxu Jan 26, 2025
c7020df
add model_info
yiyixuxu Jan 27, 2025
2c3e4ea
fix
yiyixuxu Jan 29, 2025
e5089d7
update
yiyixuxu Jan 31, 2025
8ddb20b
up
yiyixuxu Feb 1, 2025
cff0fd6
more refactor
yiyixuxu Feb 1, 2025
485f8d1
more refactor
yiyixuxu Feb 1, 2025
addaad0
more more more refactor
yiyixuxu Feb 3, 2025
12650e1
up
yiyixuxu Feb 4, 2025
96795af
Merge branch 'main' into modular-diffusers
yiyixuxu Apr 8, 2025
6a509ba
Merge branch 'main' into modular-diffusers
yiyixuxu May 1, 2025
a8e853b
[modular diffusers] more refactor (#11235)
yiyixuxu Jun 20, 2025
7ad01a6
rename modular_pipeline_block_mappings.py to modular_block_mapping
yiyixuxu Jun 20, 2025
5a8c1b5
add block mappings to modular_diffusers.stable_diffusion_xl.__init__
yiyixuxu Jun 20, 2025
8913d59
add to method to modular loader, copied from DiffusionPipeline, not t…
yiyixuxu Jun 20, 2025
45392cc
update the description of StableDiffusionXLDenoiseLoopWrapper
yiyixuxu Jun 20, 2025
9e58856
add __repr__ method for InsertableOrderedDict
yiyixuxu Jun 21, 2025
04c16d0
update
yiyixuxu Jun 21, 2025
083479c
ordereddict -> insertableOrderedDict; make sure loader to method works
yiyixuxu Jun 21, 2025
4751d45
shorten loop subblock name
yiyixuxu Jun 22, 2025
d12531d
lora: only remove hooks that we add back
yiyixuxu Jun 22, 2025
19545fd
update components manager __repr__
yiyixuxu Jun 22, 2025
78d2454
fix
yiyixuxu Jun 23, 2025
085ade0
add doc (developer guide)
yiyixuxu Jun 23, 2025
42c06e9
update doc
yiyixuxu Jun 23, 2025
1ae591e
update code format
yiyixuxu Jun 23, 2025
bb40443
up
yiyixuxu Jun 23, 2025
7c78fb1
add a overview doc page
yiyixuxu Jun 24, 2025
48e4ff5
update overview
yiyixuxu Jun 24, 2025
e49413d
update doc
yiyixuxu Jun 25, 2025
ffbaa89
move save_pretrained to the correct place
yiyixuxu Jun 25, 2025
cdaaa40
update ComponentSpec.from_component, only update config if it is crea…
yiyixuxu Jun 25, 2025
1c9f0a8
ujpdate toctree
yiyixuxu Jun 25, 2025
174628e
Merge branch 'main' into modular-diffusers
yiyixuxu Jun 25, 2025
c0327e4
update init
yiyixuxu Jun 25, 2025
5917d70
remove lora related changes
yiyixuxu Jun 25, 2025
8c038f0
Update src/diffusers/loaders/lora_base.py
yiyixuxu Jun 25, 2025
cb328d3
Apply suggestions from code review
yiyixuxu Jun 25, 2025
7d2a633
style
yiyixuxu Jun 25, 2025
74b908b
style
yiyixuxu Jun 25, 2025
9530245
correct code format
yiyixuxu Jun 25, 2025
c437ae7
copies
yiyixuxu Jun 25, 2025
f3453f0
copy
yiyixuxu Jun 25, 2025
a82e211
style
yiyixuxu Jun 25, 2025
a33206d
fix
yiyixuxu Jun 25, 2025
75e6238
revert changes in pipelines.stable_diffusion_xl folder, can seperate …
yiyixuxu Jun 25, 2025
129d658
oops, fix
yiyixuxu Jun 25, 2025
da4242d
use diffusers ModelHook, raise a import error for accelerate inside e…
yiyixuxu Jun 26, 2025
ab6d634
style
yiyixuxu Jun 26, 2025
7492e33
fix
yiyixuxu Jun 26, 2025
b92cda2
move quicktour to first page
yiyixuxu Jun 26, 2025
61772f0
updatee a comment
yiyixuxu Jun 26, 2025
9abac85
remove mapping file, move to preeset.py
yiyixuxu Jun 26, 2025
84f4b27
modular_pipeline_presets.py -> modular_blocks_presets.py
yiyixuxu Jun 26, 2025
449f299
move all the sequential pipelines & auto pipelines to the blocks_pres…
yiyixuxu Jun 26, 2025
7608d2e
style
yiyixuxu Jun 26, 2025
f63d62e
intermediates_inputs -> intermediate_inputs; component_manager -> com…
yiyixuxu Jun 27, 2025
655512e
components manager: change get -> search_models; add get_ids, get_com…
yiyixuxu Jun 28, 2025
885a596
blocks -> sub_blocks; will not by default load all; add load_default…
yiyixuxu Jun 28, 2025
b543bcc
docstring blocks -> sub_blocks
yiyixuxu Jun 28, 2025
75540f4
more blocks -> sub_blocks
yiyixuxu Jun 28, 2025
93760b1
InsertableOrderedDict -> InsertableDict
yiyixuxu Jun 28, 2025
9aaec5b
up
yiyixuxu Jun 28, 2025
58dbe0c
finimsh the quickstart!
yiyixuxu Jun 28, 2025
49ea4d1
style
yiyixuxu Jun 28, 2025
92b6b43
add some visuals
yiyixuxu Jun 28, 2025
8c680bc
up
yiyixuxu Jun 28, 2025
fedaa00
Merge branch 'main' into modular-diffusers
yiyixuxu Jun 29, 2025
fdd2bed
2024 -> 2025; fix a circular import
yiyixuxu Jun 29, 2025
3a3441c
start the write your own pipeline block tutorial
yiyixuxu Jun 30, 2025
9fae382
Apply suggestions from code review
yiyixuxu Jun 30, 2025
b43e703
Update docs/source/en/modular_diffusers/write_own_pipeline_block.md
yiyixuxu Jun 30, 2025
c75b88f
up
yiyixuxu Jun 30, 2025
285f877
make InsertableDict importable from modular_pipelines
yiyixuxu Jun 30, 2025
f09b1cc
start the section on sequential pipelines
yiyixuxu Jun 30, 2025
c5849ba
more
yiyixuxu Jun 30, 2025
363737e
add loop sequential blocks
yiyixuxu Jun 30, 2025
bbd9340
up
yiyixuxu Jun 30, 2025
0138e17
remove the get_exeuction_blocks rec from AutoPipelineBlocks repr
yiyixuxu Jun 30, 2025
db4b54c
finish the autopipelines section!
yiyixuxu Jun 30, 2025
abf28d5
update
yiyixuxu Jun 30, 2025
4b12a60
Merge branch 'main' into modular-diffusers
yiyixuxu Jun 30, 2025
f27fbce
more attemp to fix circular import
yiyixuxu Jun 30, 2025
98ea5c9
Merge branch 'modular-diffusers' of github.com:huggingface/diffusers …
yiyixuxu Jun 30, 2025
b5db8aa
developer_guide -> end-to-end guide
yiyixuxu Jul 1, 2025
4543d21
rename quick start- it is really not quick
yiyixuxu Jul 1, 2025
1987c07
update docstree
yiyixuxu Jul 1, 2025
2e20241
up up
yiyixuxu Jul 1, 2025
13fe248
add modularpipelineblocks to be pushtohub mixin
yiyixuxu Jul 1, 2025
8cb5b08
up upup
yiyixuxu Jul 1, 2025
3e46c86
fix links in the doc
yiyixuxu Jul 1, 2025
13c51bb
Modular PAG Guider (#11860)
a-r-r-o-w Jul 4, 2025
b750c69
Modular Guider ConfigMixin (#11862)
a-r-r-o-w Jul 5, 2025
284f827
Modular custom config object serialization (#11868)
a-r-r-o-w Jul 5, 2025
2c66fb3
Apply suggestions from code review
yiyixuxu Jul 6, 2025
63e94cb
resolve conflicnt
yiyixuxu Jul 6, 2025
4f8b6f5
style + copy
yiyixuxu Jul 6, 2025
23de59e
add sub_blocks for pipelineBlock
yiyixuxu Jul 6, 2025
7cea9a3
add a guider section on doc
yiyixuxu Jul 7, 2025
0a4819a
add sub_folder to save_pretrained() for config mixin
yiyixuxu Jul 7, 2025
229c4b3
add from_pretrained/save_pretrained for guider
yiyixuxu Jul 7, 2025
179d6d9
add subfolder to push_to_hub
yiyixuxu Jul 7, 2025
5af003a
update from_componeenet, update_component
yiyixuxu Jul 7, 2025
0fcdd69
style
yiyixuxu Jul 7, 2025
ceeb3c1
fix
yiyixuxu Jul 7, 2025
0fcce2a
Merge branch 'main' into modular-diffusers
yiyixuxu Jul 7, 2025
6521f59
make sure modularpipeline from_pretrained works without modular_model…
yiyixuxu Jul 7, 2025
e0083b2
Merge branch 'modular-diffusers' of github.com:huggingface/diffusers …
yiyixuxu Jul 7, 2025
863c7df
components manager: use shorter ID, display id instead of name
yiyixuxu Jul 8, 2025
a2da000
add a guide on components manager
yiyixuxu Jul 8, 2025
be5e10a
Copied-from implementation of PAG-guider (#11882)
a-r-r-o-w Jul 8, 2025
04171c7
Merge branch 'modular-diffusers' of github.com:huggingface/diffusers …
yiyixuxu Jul 8, 2025
e6ffde2
Apply suggestions from code review
yiyixuxu Jul 8, 2025
5f3ebef
update remove duplicated config for pag, and remove the description o…
yiyixuxu Jul 8, 2025
59abd95
add link to components manager doc
yiyixuxu Jul 8, 2025
f95c320
addreess more review comments
yiyixuxu Jul 8, 2025
79166dc
Merge branch 'main' into modular-diffusers
yiyixuxu Jul 8, 2025
cb9dca5
add experimental marks to all modular docs
yiyixuxu Jul 8, 2025
d27b654
add more docstrings + experimental marks
yiyixuxu Jul 8, 2025
595581d
style
yiyixuxu Jul 8, 2025
73c5fe8
Merge branch 'modular-diffusers' of github.com:huggingface/diffusers …
yiyixuxu Jul 8, 2025
de7cdf6
Merge modular diffusers with main (#11893)
a-r-r-o-w Jul 9, 2025
a935bea
big doc updategit status!
yiyixuxu Jul 9, 2025
2b006a2
Merge branch 'modular-diffusers' of github.com:huggingface/diffusers …
yiyixuxu Jul 9, 2025
9106f9c
Merge branch 'main' into modular-diffusers
a-r-r-o-w Jul 9, 2025
cf0f8e5
Merge branch 'main' into modular-diffusers
a-r-r-o-w Jul 9, 2025
2104bef
update more modular pipeline doc
yiyixuxu Jul 9, 2025
65ba892
update doc
yiyixuxu Jul 9, 2025
01300a3
up
yiyixuxu Jul 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions docs/source/en/_toctree.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,26 @@
- local: hybrid_inference/api_reference
title: API Reference
title: Hybrid Inference
- sections:
- local: modular_diffusers/overview
title: Overview
- local: modular_diffusers/modular_pipeline
title: Modular Pipeline
- local: modular_diffusers/components_manager
title: Components Manager
- local: modular_diffusers/modular_diffusers_states
title: Modular Diffusers States
- local: modular_diffusers/pipeline_block
title: Pipeline Block
- local: modular_diffusers/sequential_pipeline_blocks
title: Sequential Pipeline Blocks
- local: modular_diffusers/loop_sequential_pipeline_blocks
title: Loop Sequential Pipeline Blocks
- local: modular_diffusers/auto_pipeline_blocks
title: Auto Pipeline Blocks
- local: modular_diffusers/end_to_end_guide
title: End-to-End Example
title: Modular Diffusers
- sections:
- local: using-diffusers/consisid
title: ConsisID
Expand Down
316 changes: 316 additions & 0 deletions docs/source/en/modular_diffusers/auto_pipeline_blocks.md
1241
Original file line number Diff line number Diff line change
@@ -0,0 +1,316 @@
<!--Copyright 2025 The HuggingFace Team. All rights 10000 reserved.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
-->

# AutoPipelineBlocks

<Tip warning={true}>

🧪 **Experimental Feature**: Modular Diffusers is an experimental feature we are actively developing. The API may be subject to breaking changes.

</Tip>

`AutoPipelineBlocks` is a subclass of `ModularPipelineBlocks`. It is a multi-block that automatically selects which sub-blocks to run based on the inputs provided at runtime, creating conditional workflows that adapt to different scenarios. The main purpose is convenience and portability - for developers, you can package everything into one workflow, making it easier to share and use.

In this tutorial, we will show you how to create an `AutoPipelineBlocks` and learn more about how the conditional selection works.

<Tip>

Other types of multi-blocks include [SequentialPipelineBlocks](sequential_pipeline_blocks.md) (for linear workflows) and [LoopSequentialPipelineBlocks](loop_sequential_pipeline_blocks.md) (for iterative workflows). For information on creating individual blocks, see the [PipelineBlock guide](pipeline_block.md).

Additionally, like all `ModularPipelineBlocks`, `AutoPipelineBlocks` are definitions/specifications, not runnable pipelines. You need to convert them into a `ModularPipeline` to actually execute them. For information on creating and running pipelines, see the [Modular Pipeline guide](modular_pipeline.md).

</Tip>

For example, you might want to support text-to-image and image-to-image tasks. Instead of creating two separate pipelines, you can create an `AutoPipelineBlocks` that automatically chooses the workflow based on whether an `image` input is provided.

Let's see an example. We'll use the helper function from the [PipelineBlock guide](./pipeline_block.md) to create our blocks:

**Helper Function**

```py
from diffusers.modular_pipelines import PipelineBlock, InputParam, OutputParam
import torch

def make_block(inputs=[], intermediate_inputs=[], intermediate_outputs=[], block_fn=None, description=None):
class TestBlock(PipelineBlock):
model_name = "test"

@property
def inputs(self):
return inputs

@property
def intermediate_inputs(self):
return intermediate_inputs

@property
def intermediate_outputs(self):
return intermediate_outputs

@property
def description(self):
return description if description is not None else ""

def __call__(self, components, state):
block_state = self.get_block_state(state)
if block_fn is not None:
block_state = block_fn(block_state, state)
self.set_block_state(state, block_state)
return components, state

return TestBlock
```

Now let's create a dummy `AutoPipelineBlocks` that includes dummy text-to-image, image-to-image, and inpaint pipelines.


```py
from diffusers.modular_pipelines import AutoPipelineBlocks

# These are dummy blocks and we only focus on "inputs" for our purpose
inputs = [InputParam(name="prompt")]
# block_fn prints out which workflow is running so we can see the execution order at runtime
block_fn = lambda x, y: print("running the text-to-image workflow")
block_t2i_cls = make_block(inputs=inputs, block_fn=block_fn, description="I'm a text-to-image workflow!")

inputs = [InputParam(name="prompt"), InputParam(name="image")]
block_fn = lambda x, y: print("running the image-to-image workflow")
block_i2i_cls = make_block(inputs=inputs, block_fn=block_fn, description="I'm a image-to-image workflow!")

inputs = [InputParam(name="prompt"), InputParam(name="image"), InputParam(name="mask")]
block_fn = lambda x, y: print("running the inpaint workflow")
block_inpaint_cls = make_block(inputs=inputs, block_fn=block_fn, description="I'm a inpaint workflow!")

class AutoImageBlocks(AutoPipelineBlocks):
# List of sub-block classes to choose from
block_classes = [block_inpaint_cls, block_i2i_cls, block_t2i_cls]
# Names for each block in the same order
block_names = ["inpaint", "img2img", "text2img"]
# Trigger inputs that determine which block to run
# - "mask" triggers inpaint workflow
# - "image" triggers img2img workflow (but only if mask is not provided)
# - if none of above, runs the text2img workflow (default)
block_trigger_inputs = ["mask", "image", None]
# Description is extremely important for AutoPipelineBlocks
@property
def description(self):
return (
"Pipeline generates images given different types of conditions!\n"
+ "This is an auto pipeline block that works for text2img, img2img and inpainting tasks.\n"
+ " - inpaint workflow is run when `mask` is provided.\n"
+ " - img2img workflow is run when `image` is provided (but only when `mask` is not provided).\n"
+ " - text2img workflow is run when neither `image` nor `mask` is provided.\n"
)

# Create the blocks
auto_blocks = AutoImageBlocks()
# convert to pipeline
auto_pipeline = auto_blocks.init_pipeline()
```

Now we have created an `AutoPipelineBlocks` that contains 3 sub-blocks. Notice the warning message at the top - this automatically appears in every `ModularPipelineBlocks` that contains `AutoPipelineBlocks` to remind end users that dynamic block selection happens at runtime.

```py
AutoImageBlocks(
Class: AutoPipelineBlocks

====================================================================================================
This pipeline contains blocks that are selected at runtime based on inputs.
Trigger Inputs: ['mask', 'image']
====================================================================================================


Description: Pipeline generates images given different types of conditions!
This is an auto pipeline block that works for text2img, img2img and inpainting tasks.
- inpaint workflow is run when `mask` is provided.
- img2img workflow is run when `image` is provided (but only when `mask` is not provided).
- text2img workflow is run when neither `image` nor `mask` is provided.



Sub-Blocks:
• inpaint [trigger: mask] (TestBlock)
Description: I'm a inpaint workflow!

• img2img [trigger: image] (TestBlock)
Description: I'm a image-to-image workflow!

• text2img [default] (TestBlock)
Description: I'm a text-to-image workflow!

)
```

Check out the documentation with `print(auto_pipeline.doc)`:

```py
>>> print(auto_pipeline.doc)
class AutoImageBlocks

Pipeline generates images given different types of conditions!
This is an auto pipeline block that works for text2img, img2img and inpainting tasks.
- inpaint workflow is run when `mask` is provided.
- img2img workflow is run when `image` is provided (but only when `mask` is not provided).
- text2img workflow is run when neither `image` nor `mask` is provided.

Inputs:

prompt (`None`, *optional*):

image (`None`, *optional*):

mask (`None`, *optional*):
```

There is a fundamental trade-off of AutoPipelineBlocks: it trades clarity for convenience. While it is really easy for packaging multiple workflows, it can become confusing without proper documentation. e.g. if we just throw a pipeline at you and tell you that it contains 3 sub-blocks and takes 3 inputs `prompt`, `image` and `mask`, and ask you to run an image-to-image workflow: if you don't have any prior knowledge on how these pipelines work, you would be pretty clueless, right?

This pipeline we just made though, has a docstring that shows all available inputs and workflows and explains how to use each with different inputs. So it's really helpful for users. For example, it's clear that you need to pass `image` to run img2img. This is why the description field is absolutely critical for AutoPipelineBlocks. We highly recommend you to explain the conditional logic very well for each `AutoPipelineBlocks` you would make. We also recommend to always test individual pipelines first before packaging them into AutoPipelineBlocks.

Let's run this auto pipeline with different inputs to see if the conditional logic works as described. Remember that we have added `print` in each `PipelineBlock`'s `__call__` method to print out its workflow name, so it should be easy to tell which one is running:

```py
>>> _ = auto_pipeline(image="image", mask="mask")
running the inpaint workflow
>>> _ = auto_pipeline(image="image")
running the image-to-image workflow
>>> _ = auto_pipeline(prompt="prompt")
running the text-to-image workflow
>>> _ = auto_pipeline(image="prompt", mask="mask")
running the inpaint workflow
```

However, even with documentation, it can become very confusing when AutoPipelineBlocks are combined with other blocks. The complexity grows quickly when you have nested AutoPipelineBlocks or use them as sub-blocks in larger pipelines.

Let's make another `AutoPipelineBlocks` - this one only contains one block, and it does not include `None` in its `block_trigger_inputs` (which corresponds to the default block to run when none of the trigger inputs are provided). This means this block will be skipped if the trigger input (`ip_adapter_image`) is not provided at runtime.

```py
from diffusers.modular_pipelines import SequentialPipelineBlocks, InsertableDict
inputs = [InputParam(name="ip_adapter_image")]
block_fn = lambda x, y: print("running the ip-adapter workflow")
block_ipa_cls = make_block(inputs=inputs, block_fn=block_fn, description="I'm a IP-adapter workflow!")

class AutoIPAdapter(AutoPipelineBlocks):
block_classes = [block_ipa_cls]
block_names = ["ip-adapter"]
block_trigger_inputs = ["ip_adapter_image"]
@property
def description(self):
return "Run IP Adapter step if `ip_adapter_image` is provided."
```

Now let's combine these 2 auto blocks together into a `SequentialPipelineBlocks`:

```py
auto_ipa_blocks = AutoIPAdapter()
blocks_dict = InsertableDict()
blocks_dict["ip-adapter"] = auto_ipa_blocks
blocks_dict["image-generation"] = auto_blocks
all_blocks = SequentialPipelineBlocks.from_blocks_dict(blocks_dict)
pipeline = all_blocks.init_pipeline()
```

Let's take a look: now things get more confusing. In this particular example, you could still try to explain the conditional logic in the `description` field here - there are only 4 possible execution paths so it's doable. However, since this is a `SequentialPipelineBlocks` that could contain many more blocks, the complexity can quickly get out of hand as the number of blocks increases.

```py
>>> all_blocks
SequentialPipelineBlocks(
Class: ModularPipelineBlocks

====================================================================================================
This pipeline contains blocks that are selected at runtime based on inputs.
Trigger Inputs: ['image', 'mask', 'ip_adapter_image']
Use `get_execution_blocks()` with input names to see selected blocks (e.g. `get_execution_blocks('image')`).
====================================================================================================


Description:


Sub-Blocks:
[0] ip-adapter (AutoIPAdapter)
Description: Run IP Adapter step if `ip_adapter_image` is provided.


[1] image-generation (AutoImageBlocks)
Description: Pipeline generates images given different types of conditions!
This is an auto pipeline block that works for text2img, img2img and inpainting tasks.
- inpaint workflow is run when `mask` is provided.
- img2img workflow is run when `image` is provided (but only when `mask` is not provided).
- text2img workflow is run when neither `image` nor `mask` is provided.


)

```

This is when the `get_execution_blocks()` method comes in handy - it basically extracts a `SequentialPipelineBlocks` that only contains the blocks that are actually run based on your inputs.

Let's try some examples:

`mask`: we expect it to skip the first ip-adapter since `ip_adapter_image` is not provided, and then run the inpaint for the second block.

```py
>>> all_blocks.get_execution_blocks('mask')
SequentialPipelineBlocks(
Class: ModularPipelineBlocks

Description:


Sub-Blocks:
[0] image-generation (TestBlock)
Description: I'm a inpaint workflow!

)
```

Let's also actually run the pipeline to confirm:

```py
>>> _ = pipeline(mask="mask")
skipping auto block: AutoIPAdapter
running the inpaint workflow
```

Try a few more:

```py
print(f"inputs: ip_adapter_image:")
blocks_select = all_blocks.get_execution_blocks('ip_adapter_image')
print(f"expected_execution_blocks: {blocks_select}")
print(f"actual execution blocks:")
_ = pipeline(ip_adapter_image="ip_adapter_image", prompt="prompt")
# expect to see ip-adapter + text2img

print(f"inputs: image:")
blocks_select = all_blocks.get_execution_blocks('image')
print(f"expected_execution_blocks: {blocks_select}")
print(f"actual execution blocks:")
_ = pipeline(image="image", prompt="prompt")
# expect to see img2img

print(f"inputs: prompt:")
blocks_select = all_blocks.get_execution_blocks('prompt')
print(f"expected_execution_blocks: {blocks_select}")
print(f"actual execution blocks:")
_ = pipeline(prompt="prompt")
# expect to see text2img (prompt is not a trigger input so fallback to default)

print(f"inputs: mask + ip_adapter_image:")
blocks_select = all_blocks.get_execution_blocks('mask','ip_adapter_image')
print(f"expected_execution_blocks: {blocks_select}")
print(f"actual execution blocks:")
_ = pipeline(mask="mask", ip_adapter_image="ip_adapter_image")
# expect to see ip-adapter + inpaint
```

In summary, `AutoPipelineBlocks` is a good tool for packaging multiple workflows into a single, convenient interface and it can greatly simplify the user experience. However, always provide clear descriptions explaining the conditional logic, test individual pipelines first before combining them, and use `get_execution_blocks()` to understand runtime behavior in complex compositions.
Loading
Loading
0