Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
ebd06f9
[Modular] loader related (#13025)
yiyixuxu Feb 3, 2026
6d4fc6b
[Modular] mellon doc etc (#13051)
yiyixuxu Feb 3, 2026
1b8fc6c
[modular] change the template modular pipeline card (#13072)
sayakpaul Feb 4, 2026
430c557
Add support for Magcache (#12744)
AlanPonnachan Feb 4, 2026
90818e8
[docs] Fix syntax error in quantization configuration (#13076)
sayakpaul Feb 4, 2026
03af690
docs: improve docstring scheduling_dpmsolver_multistep_inverse.py (#1…
delmalih Feb 4, 2026
9fe0a9c
[core] make flux hidden states contiguous (#13068)
sayakpaul Feb 5, 2026
a3dcd98
[core] make qwen hidden states contiguous to make torchao happy. (#13…
sayakpaul Feb 5, 2026
99e2cff
Feature/zimage inpaint pipeline (#13006)
CalamitousFelicitousness Feb 5, 2026
ca79f8c
GGUF fix for unquantized types when using unquantize kernels (#12498)
dxqb Feb 6, 2026
44b8201
docs: improve docstring scheduling_dpmsolver_multistep_inverse.py (#1…
delmalih Feb 6, 2026
10dc589
[modular]simplify components manager doc (#13088)
yiyixuxu Feb 6, 2026
09dca38
ZImageControlNet cfg (#13080)
hlky Feb 7, 2026
fd705bd
[Modular] refactor Wan: modular pipelines by task etc (#13063)
yiyixuxu Feb 7, 2026
44f4dc0
[Modular] guard `ModularPipeline.blocks` attribute (#13014)
yiyixuxu Feb 9, 2026
baaa8d0
LTX 2 Improve `encode_video` by Accepting More Input Types (#13057)
dg845 Feb 9, 2026
8933686
Z image lora training (#13056)
linoytsaban Feb 9, 2026
20efb79
[modular] add modular tests for Z-Image and Wan (#13078)
sayakpaul Feb 9, 2026
94a44e4
initial conversion script
miguelmartin75 Jan 9, 2026
3eec046
cosmos control net block
miguelmartin75 Jan 10, 2026
e181679
CosmosAttention
miguelmartin75 Jan 15, 2026
d46e6cb
base model conversion
miguelmartin75 Jan 15, 2026
8cbb7a0
wip
miguelmartin75 Jan 16, 2026
e526bac
pipeline updates
miguelmartin75 Jan 17, 2026
7fef44a
convert controlnet
miguelmartin75 Jan 20, 2026
6b93134
pipeline: working without controls
miguelmartin75 Jan 20, 2026
8548861
wip
miguelmartin75 Jan 20, 2026
a41df6f
debugging
miguelmartin75 Jan 21, 2026
17cb688
Almost working
miguelmartin75 Jan 22, 2026
d089d7d
temp
miguelmartin75 Jan 22, 2026
ec92d7f
control working
miguelmartin75 Jan 22, 2026
67cb736
cleanup + detail on neg_encoder_hidden_states
miguelmartin75 Jan 23, 2026
0a88230
convert edge
miguelmartin75 Jan 23, 2026
f501bb6
pos emb for control latents
miguelmartin75 Jan 24, 2026
0d457f1
convert all chkpts
miguelmartin75 Jan 26, 2026
bfa83e2
resolve TODOs
miguelmartin75 Jan 27, 2026
5ae1a05
remove prints
miguelmartin75 Jan 27, 2026
f1ce209
Docs
miguelmartin75 Jan 27, 2026
57388b7
add siglip image reference encoder
miguelmartin75 Jan 27, 2026
cee7324
Add unit tests
miguelmartin75 Jan 30, 2026
2f9ce6a
controlnet: add duplicate layers
miguelmartin75 Jan 31, 2026
bc31b30
Additional tests
miguelmartin75 Jan 31, 2026
e8fbac2
skip less
miguelmartin75 Jan 31, 2026
a55fb3c
skip less
miguelmartin75 Jan 31, 2026
0811456
remove image_ref
miguelmartin75 Feb 2, 2026
276a6b3
minor
miguelmartin75 Feb 2, 2026
1d912ec
docs
miguelmartin75 Feb 2, 2026
c0699dc
remove skipped test in transfer
miguelmartin75 Feb 2, 2026
2b4cecf
Don't crash process
miguelmartin75 Feb 2, 2026
1f66428
formatting
miguelmartin75 Feb 2, 2026
6fdb677
revert some changes
miguelmartin75 Feb 2, 2026
30a0866
remove skipped test
miguelmartin75 Feb 2, 2026
7d1525c
make style
miguelmartin75 Feb 2, 2026
4b38767
Address comment + fix example
miguelmartin75 Feb 6, 2026
4bbedfb
CosmosAttnProcessor2_0 revert + CosmosAttnProcessor2_5 changes
miguelmartin75 Feb 11, 2026
d4e7e6c
make style
miguelmartin75 Feb 12, 2026
0460203
make fix-copies
miguelmartin75 Feb 12, 2026
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
2 changes: 2 additions & 0 deletions docs/source/en/_toctree.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@
title: Guiders
- local: modular_diffusers/custom_blocks
title: Building Custom Blocks
- local: modular_diffusers/mellon
title: Using Custom Blocks with Mellon
title: Modular Diffusers
- isExpanded: false
sections:
Expand Down
4 changes: 0 additions & 4 deletions docs/source/en/api/pipelines/ltx2.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,6 @@ video, audio = pipe(
output_type="np",
return_dict=False,
)
video = (video * 255).round().astype("uint8")
video = torch.from_numpy(video)

encode_video(
video[0],
Expand Down Expand Up @@ -185,8 +183,6 @@ video, audio = pipe(
output_type="np",
return_dict=False,
)
video = (video * 255).round().astype("uint8")
video = torch.from_numpy(video)

encode_video(
video[0],
Expand Down
41 changes: 41 additions & 0 deletions docs/source/en/api/pipelines/z_image.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,41 @@ image = pipe(
image.save("zimage_img2img.png")
```

## Inpainting

Use [`ZImageInpaintPipeline`] to inpaint specific regions of an image based on a text prompt and mask.

```python
import torch
import numpy as np
from PIL import Image
from diffusers import ZImageInpaintPipeline
from diffusers.utils import load_image

pipe = ZImageInpaintPipeline.from_pretrained("Tongyi-MAI/Z-Image-Turbo", torch_dtype=torch.bfloat16)
pipe.to("cuda")

url = "https://raw.githubusercontent.com/CompVis/stable-diffusion/main/assets/stable-samples/img2img/sketch-mountains-input.jpg"
init_image = load_image(url).resize((1024, 1024))

# Create a mask (white = inpaint, black = preserve)
mask = np.zeros((1024, 1024), dtype=np.uint8)
mask[256:768, 256:768] = 255 # Inpaint center region
mask_image = Image.fromarray(mask)

prompt = "A beautiful lake with mountains in the background"
image = pipe(
prompt,
image=init_image,
mask_image=mask_image,
strength=1.0,
num_inference_steps=9,
guidance_scale=0.0,
generator=torch.Generator("cuda").manual_seed(42),
).images[0]
image.save("zimage_inpaint.png")
```

## ZImagePipeline

[[autodoc]] ZImagePipeline
Expand All @@ -64,3 +99,9 @@ image.save("zimage_img2img.png")
[[autodoc]] ZImageImg2ImgPipeline
- all
- __call__

## ZImageInpaintPipeline

[[autodoc]] ZImageInpaintPipeline
- all
- __call__
178 changes: 42 additions & 136 deletions docs/source/en/modular_diffusers/components_manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,179 +12,85 @@ specific language governing permissions and limitations under the License.

# ComponentsManager

The [`ComponentsManager`] is a model registry and management system for Modular Diffusers. It adds and tracks models, stores useful metadata (model size, device placement, adapters), prevents duplicate model instances, and supports offloading.
The [`ComponentsManager`] is a model registry and management system for Modular Diffusers. It adds and tracks models, stores useful metadata (model size, device placement, adapters), and supports offloading.

This guide will show you how to use [`ComponentsManager`] to manage components and device memory.

## Add a component
## Connect to a pipeline

The [`ComponentsManager`] should be created alongside a [`ModularPipeline`] in either [`~ModularPipeline.from_pretrained`] or [`~ModularPipelineBlocks.init_pipeline`].
Create a [`ComponentsManager`] and pass it to a [`ModularPipeline`] with either [`~ModularPipeline.from_pretrained`] or [`~ModularPipelineBlocks.init_pipeline`].

> [!TIP]
> The `collection` parameter is optional but makes it easier to organize and manage components.

<hfoptions id="create">
<hfoption id="from_pretrained">

```py
from diffusers import ModularPipeline, ComponentsManager
import torch

comp = ComponentsManager()
pipe = ModularPipeline.from_pretrained("YiYiXu/modular-demo-auto", components_manager=comp, collection="test1")
manager = ComponentsManager()
pipe = ModularPipeline.from_pretrained("Tongyi-MAI/Z-Image-Turbo", components_manager=manager)
pipe.load_components(torch_dtype=torch.bfloat16)
```

</hfoption>
<hfoption id="init_pipeline">

```py
from diffusers import ComponentsManager
from diffusers.modular_pipelines import SequentialPipelineBlocks
from diffusers.modular_pipelines.stable_diffusion_xl import TEXT2IMAGE_BLOCKS

t2i_blocks = SequentialPipelineBlocks.from_blocks_dict(TEXT2IMAGE_BLOCKS)

modular_repo_id = "YiYiXu/modular-loader-t2i-0704"
components = ComponentsManager()
t2i_pipeline = t2i_blocks.init_pipeline(modular_repo_id, components_manager=components)
from diffusers import ModularPipelineBlocks, ComponentsManager
import torch
manager = ComponentsManager()
blocks = ModularPipelineBlocks.from_pretrained("diffusers/Florence2-image-Annotator", trust_remote_code=True)
pipe= blocks.init_pipeline(components_manager=manager)
pipe.load_components(torch_dtype=torch.bfloat16)
```

</hfoption>
</hfoptions>

Components are only loaded and registered when using [`~ModularPipeline.load_components`] or [`~ModularPipeline.load_components`]. The example below uses [`~ModularPipeline.load_components`] to create a second pipeline that reuses all the components from the first one, and assigns it to a different collection

```py
pipe.load_components()
pipe2 = ModularPipeline.from_pretrained("YiYiXu/modular-demo-auto", components_manager=comp, collection="test2")
```

Use the [`~ModularPipeline.null_component_names`] property to identify any components that need to be loaded, retrieve them with [`~ComponentsManager.get_components_by_names`], and then call [`~ModularPipeline.update_components`] to add the missing components.

```py
pipe2.null_component_names
['text_encoder', 'text_encoder_2', 'tokenizer', 'tokenizer_2', 'image_encoder', 'unet', 'vae', 'scheduler', 'controlnet']

comp_dict = comp.get_components_by_names(names=pipe2.null_component_names)
pipe2.update_components(**comp_dict)
```

To add individual components, use the [`~ComponentsManager.add`] method. This registers a component with a unique id.

```py
from diffusers import AutoModel

text_encoder = AutoModel.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0", subfolder="text_encoder")
component_id = comp.add("text_encoder", text_encoder)
comp
```

Use [`~ComponentsManager.remove`] to remove a component using their id.

```py
comp.remove("text_encoder_139917733042864")
```

## Retrieve a component

The [`ComponentsManager`] provides several methods to retrieve registered components.

### get_one

The [`~ComponentsManager.get_one`] method returns a single component and supports pattern matching for the `name` parameter. If multiple components match, [`~ComponentsManager.get_one`] returns an error.

| Pattern | Example | Description |
|-------------|----------------------------------|-------------------------------------------|
| exact | `comp.get_one(name="unet")` | exact name match |
| wildcard | `comp.get_one(name="unet*")` | names starting with "unet" |
| exclusion | `comp.get_one(name="!unet")` | exclude components named "unet" |
| or | `comp.get_one(name="unet&#124;vae")` | name is "unet" or "vae" |

[`~ComponentsManager.get_one`] also filters components by the `collection` argument or `load_id` argument.

```py
comp.get_one(name="unet", collection="sdxl")
```

### get_components_by_names

The [`~ComponentsManager.get_components_by_names`] method accepts a list of names and returns a dictionary mapping names to components. This is especially useful with [`ModularPipeline`] since they provide lists of required component names and the returned dictionary can be passed directly to [`~ModularPipeline.update_components`].

```py
component_dict = comp.get_components_by_names(names=["text_encoder", "unet", "vae"])
{"text_encoder": component1, "unet": component2, "vae": component3}
```

## Duplicate detection

It is recommended to load model components with [`ComponentSpec`] to assign components with a unique id that encodes their loading parameters. This allows [`ComponentsManager`] to automatically detect and prevent duplicate model instances even when different objects represent the same underlying checkpoint.

```py
from diffusers import ComponentSpec, ComponentsManager
from transformers import CLIPTextModel

comp = ComponentsManager()

# Create ComponentSpec for the first text encoder
spec = ComponentSpec(name="text_encoder", repo="stabilityai/stable-diffusion-xl-base-1.0", subfolder="text_encoder", type_hint=AutoModel)
# Create ComponentSpec for a duplicate text encoder (it is same checkpoint, from the same repo/subfolder)
spec_duplicated = ComponentSpec(name="text_encoder_duplicated", repo="stabilityai/stable-diffusion-xl-base-1.0", subfolder="text_encoder", type_hint=CLIPTextModel)

# Load and add both components - the manager will detect they're the same model
comp.add("text_encoder", spec.load())
comp.add("text_encoder_duplicated", spec_duplicated.load())
```

This returns a warning with instructions for removing the duplicate.
Components loaded by the pipeline are automatically registered in the manager. You can inspect them right away.

```py
ComponentsManager: adding component 'text_encoder_duplicated_139917580682672', but it has duplicate load_id 'stabilityai/stable-diffusion-xl-base-1.0|text_encoder|null|null' with existing components: text_encoder_139918506246832. To remove a duplicate, call `components_manager.remove('<component_id>')`.
'text_encoder_duplicated_139917580682672'
```

You could also add a component without using [`ComponentSpec`] and duplicate detection still works in most cases even if you're adding the same component under a different name.

However, [`ComponentManager`] can't detect duplicates when you load the same component into different objects. In this case, you should load a model with [`ComponentSpec`].

```py
text_encoder_2 = AutoModel.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0", subfolder="text_encoder")
comp.add("text_encoder", text_encoder_2)
'text_encoder_139917732983664'
```
## Inspect components

## Collections
Print the [`ComponentsManager`] to see all registered components, including their class, device placement, dtype, memory size, and load ID.

Collections are labels assigned to components for better organization and management. Add a component to a collection with the `collection` argument in [`~ComponentsManager.add`].

Only one component per name is allowed in each collection. Adding a second component with the same name automatically removes the first component.
The output below corresponds to the `from_pretrained` example above.

```py
from diffusers import ComponentSpec, ComponentsManager

comp = ComponentsManager()
# Create ComponentSpec for the first UNet
spec = ComponentSpec(name="unet", repo="stabilityai/stable-diffusion-xl-base-1.0", subfolder="unet", type_hint=AutoModel)
# Create ComponentSpec for a different UNet
spec2 = ComponentSpec(name="unet", repo="RunDiffusion/Juggernaut-XL-v9", subfolder="unet", type_hint=AutoModel, variant="fp16")

# Add both UNets to the same collection - the second one will replace the first
comp.add("unet", spec.load(), collection="sdxl")
comp.add("unet", spec2.load(), collection="sdxl")
Components:
=============================================================================================================================
Models:
-----------------------------------------------------------------------------------------------------------------------------
Name_ID | Class | Device: act(exec) | Dtype | Size (GB) | Load ID
-----------------------------------------------------------------------------------------------------------------------------
text_encoder_140458257514752 | Qwen3Model | cpu | torch.bfloat16 | 7.49 | Tongyi-MAI/Z-Image-Turbo|text_encoder|null|null
vae_140458257515376 | AutoencoderKL | cpu | torch.bfloat16 | 0.16 | Tongyi-MAI/Z-Image-Turbo|vae|null|null
transformer_140458257515616 | ZImageTransformer2DModel | cpu | torch.bfloat16 | 11.46 | Tongyi-MAI/Z-Image-Turbo|transformer|null|null
-----------------------------------------------------------------------------------------------------------------------------

Other Components:
-----------------------------------------------------------------------------------------------------------------------------
ID | Class | Collection
-----------------------------------------------------------------------------------------------------------------------------
scheduler_140461023555264 | FlowMatchEulerDiscreteScheduler | N/A
tokenizer_140458256346432 | Qwen2Tokenizer | N/A
-----------------------------------------------------------------------------------------------------------------------------
```

This makes it convenient to work with node-based systems because you can:

- Mark all models as loaded from one node with the `collection` label.
- Automatically replace models when new checkpoints are loaded under the same name.
- Batch delete all models in a collection when a node is removed.
The table shows models (with device, dtype, and memory info) separately from other components like schedulers and tokenizers. If any models have LoRA adapters, IP-Adapters, or quantization applied, that information is displayed in an additional section at the bottom.

## Offloading

The [`~ComponentsManager.enable_auto_cpu_offload`] method is a global offloading strategy that works across all models regardless of which pipeline is using them. Once enabled, you don't need to worry about device placement if you add or remove components.

```py
comp.enable_auto_cpu_offload(device="cuda")
manager.enable_auto_cpu_offload(device="cuda")
```

All models begin on the CPU and [`ComponentsManager`] moves them to the appropriate device right before they're needed, and moves other models back to the CPU when GPU memory is low.

You can set your own rules for which models to offload first.
Call [`~ComponentsManager.disable_auto_cpu_offload`] to disable offloading.

```py
manager.disable_auto_cpu_offload()
```
Loading
Loading