Skip to content

Commit b57ffdf

Browse files
authored
Merge branch 'main' into modular-index-tests
2 parents 9e87e3d + 680076f commit b57ffdf

File tree

2 files changed

+78
-5
lines changed

2 files changed

+78
-5
lines changed

docs/source/en/api/modular_diffusers/pipeline_blocks.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,8 @@
1414

1515
## AutoPipelineBlocks
1616

17-
[[autodoc]] diffusers.modular_pipelines.modular_pipeline.AutoPipelineBlocks
17+
[[autodoc]] diffusers.modular_pipelines.modular_pipeline.AutoPipelineBlocks
18+
19+
## ConditionalPipelineBlocks
20+
21+
[[autodoc]] diffusers.modular_pipelines.modular_pipeline.ConditionalPipelineBlocks

docs/source/en/modular_diffusers/auto_pipeline_blocks.md

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,16 @@ from diffusers.modular_pipelines import AutoPipelineBlocks
121121

122122
class AutoImageBlocks(AutoPipelineBlocks):
123123
# List of sub-block classes to choose from
124-
block_classes = [block_inpaint_cls, block_i2i_cls, block_t2i_cls]
124+
block_classes = [InpaintBlock, ImageToImageBlock, TextToImageBlock]
125125
# Names for each block in the same order
126126
block_names = ["inpaint", "img2img", "text2img"]
127127
# Trigger inputs that determine which block to run
128128
# - "mask" triggers inpaint workflow
129129
# - "image" triggers img2img workflow (but only if mask is not provided)
130130
# - if none of above, runs the text2img workflow (default)
131131
block_trigger_inputs = ["mask", "image", None]
132-
# Description is extremely important for AutoPipelineBlocks
133132

133+
@property
134134
def description(self):
135135
return (
136136
"Pipeline generates images given different types of conditions!\n"
@@ -141,7 +141,7 @@ class AutoImageBlocks(AutoPipelineBlocks):
141141
)
142142
```
143143

144-
It is **very** important to include a `description` to avoid any confusion over how to run a block and what inputs are required. While [`~modular_pipelines.AutoPipelineBlocks`] are convenient, it's conditional logic may be difficult to figure out if it isn't properly explained.
144+
It is **very** important to include a `description` to avoid any confusion over how to run a block and what inputs are required. While [`~modular_pipelines.AutoPipelineBlocks`] are convenient, its conditional logic may be difficult to figure out if it isn't properly explained.
145145

146146
Create an instance of `AutoImageBlocks`.
147147

@@ -152,5 +152,74 @@ auto_blocks = AutoImageBlocks()
152152
For more complex compositions, such as nested [`~modular_pipelines.AutoPipelineBlocks`] blocks when they're used as sub-blocks in larger pipelines, use the [`~modular_pipelines.SequentialPipelineBlocks.get_execution_blocks`] method to extract the a block that is actually run based on your input.
153153

154154
```py
155-
auto_blocks.get_execution_blocks("mask")
155+
auto_blocks.get_execution_blocks(mask=True)
156+
```
157+
158+
## ConditionalPipelineBlocks
159+
160+
[`~modular_pipelines.AutoPipelineBlocks`] is a special case of [`~modular_pipelines.ConditionalPipelineBlocks`]. While [`~modular_pipelines.AutoPipelineBlocks`] selects blocks based on whether a trigger input is provided or not, [`~modular_pipelines.ConditionalPipelineBlocks`] is able to select a block based on custom selection logic provided in the `select_block` method.
161+
162+
Here is the same example written using [`~modular_pipelines.ConditionalPipelineBlocks`] directly:
163+
164+
```py
165+
from diffusers.modular_pipelines import ConditionalPipelineBlocks
166+
167+
class AutoImageBlocks(ConditionalPipelineBlocks):
168+
block_classes = [InpaintBlock, ImageToImageBlock, TextToImageBlock]
169+
block_names = ["inpaint", "img2img", "text2img"]
170+
block_trigger_inputs = ["mask", "image"]
171+
default_block_name = "text2img"
172+
173+
@property
174+
def description(self):
175+
return (
176+
"Pipeline generates images given different types of conditions!\n"
177+
+ "This is an auto pipeline block that works for text2img, img2img and inpainting tasks.\n"
178+
+ " - inpaint workflow is run when `mask` is provided.\n"
179+
+ " - img2img workflow is run when `image` is provided (but only when `mask` is not provided).\n"
180+
+ " - text2img workflow is run when neither `image` nor `mask` is provided.\n"
181+
)
182+
183+
def select_block(self, mask=None, image=None) -> str | None:
184+
if mask is not None:
185+
return "inpaint"
186+
if image is not None:
187+
return "img2img"
188+
return None # falls back to default_block_name ("text2img")
189+
```
190+
191+
The inputs listed in `block_trigger_inputs` are passed as keyword arguments to `select_block()`. When `select_block` returns `None`, it falls back to `default_block_name`. If `default_block_name` is also `None`, the entire conditional block is skipped — this is useful for optional processing steps that should only run when specific inputs are provided.
192+
193+
## Workflows
194+
195+
Pipelines that contain conditional blocks ([`~modular_pipelines.AutoPipelineBlocks`] or [`~modular_pipelines.ConditionalPipelineBlocks]`) can support multiple workflows — for example, our SDXL modular pipeline supports a dozen workflows all in one pipeline. But this also means it can be confusing for users to know what workflows are supported and how to run them. For pipeline builders, it's useful to be able to extract only the blocks relevant to a specific workflow.
196+
197+
We recommend defining a `_workflow_map` to give each workflow a name and explicitly list the inputs it requires.
198+
199+
```py
200+
from diffusers.modular_pipelines import SequentialPipelineBlocks
201+
202+
class MyPipelineBlocks(SequentialPipelineBlocks):
203+
block_classes = [TextEncoderBlock, AutoImageBlocks, DecodeBlock]
204+
block_names = ["text_encoder", "auto_image", "decode"]
205+
206+
_workflow_map = {
207+
"text2image": {"prompt": True},
208+
"image2image": {"image": True, "prompt": True},
209+
"inpaint": {"mask": True, "image": True, "prompt": True},
210+
}
211+
```
212+
213+
All of our built-in modular pipelines come with pre-defined workflows. The `available_workflows` property lists all supported workflows:
214+
215+
```py
216+
pipeline_blocks = MyPipelineBlocks()
217+
pipeline_blocks.available_workflows
218+
# ['text2image', 'image2image', 'inpaint']
219+
```
220+
221+
Retrieve a specific workflow with `get_workflow` to inspect and debug a specific block that executes the workflow.
222+
223+
```py
224+
pipeline_blocks.get_workflow("inpaint")
156225
```

0 commit comments

Comments
 (0)