Skip to content

Commit 4ecbf1f

Browse files
authored
Merge branch 'main' into main
2 parents 544420e + a1acc51 commit 4ecbf1f

496 files changed

Lines changed: 10314 additions & 1127 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.ai/models.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ Linked from `AGENTS.md`, `skills/model-integration/SKILL.md`, and `review-rules.
1515
* When adding a new transformer (or reviewing one), skim `src/diffusers/models/transformers/transformer_flux.py`, `src/diffusers/models/transformers/transformer_flux2.py`, `src/diffusers/models/transformers/transformer_qwenimage.py`, and `src/diffusers/models/transformers/transformer_wan.py` first to establish the pattern. Most conventions (mixin set, file structure, naming, gradient-checkpointing implementation, `_no_split_modules` settings, etc.) are easiest to internalize by comparison rather than from a fixed list.
1616
* **Loading goes through `from_pretrained` / `from_single_file`.** Weights and configs load through the standard paths — never fetched or imported out-of-band at runtime. Don't override or add a custom `from_pretrained`, and don't load weights manually (`load_file(...)`, `hf_hub_download(...)`, or `sys.path.insert(...)` to import a reference repo). For an original-format single checkpoint, add `from_single_file` support (mixin + weight-mapping).
1717

18+
## Single-file model layout
19+
20+
A model follows the **single-file policy**: its full implementation lives in one `transformer_<name>.py` (or `unet_<name>.py`) — attention (the `Attention` class and its processor), transformer blocks, RoPE, and any model-specific layers should all be in that file.
21+
22+
For shared building blocks, either:
23+
- **import** a common layer from `normalization.py`, `attention.py`, or `embeddings.py`, or
24+
- **`# Copied from`** a class in another model and rename (`# Copied from ...transformer_other.OtherBlock with Other->This`), so `make fix-copies` keeps the copies in sync.
25+
1826
## Attention pattern
1927

2028
Attention must follow the diffusers pattern: both the `Attention` class and its processor are defined in the model file. The processor's `__call__` handles the actual compute and must use `dispatch_attention_fn` rather than calling `F.scaled_dot_product_attention` directly. The attention class inherits `AttentionModuleMixin` and declares `_default_processor_cls` and `_available_processors`.
@@ -62,7 +70,7 @@ class MyModelAttention(nn.Module, AttentionModuleMixin):
6270
What you pass as `attn_mask=` to `dispatch_attention_fn` determines which backends work:
6371

6472
- **No mask needed → pass `None`, not an all-zero tensor.** A dense 4D additive float mask of all `0.0` does no math but still hard-raises on `flash` / `_flash_3` / `_sage` (see `attention_dispatch.py:2328, 2544, 3266`). Only materialize a mask when it carries information. This is the Flux / Flux2 / Wan pattern: no mask, works on every backend, relies on the model having been trained tolerating consistent padding.
65-
- **Padding mask → bool `(B, L)` or `(B, 1, 1, L)`.** Only pass when the batch actually contains different-length sequences (i.e. there is real padding). If all sequences are the same length, set the mask to `None` — many backends (flash, sage, aiter) raise `ValueError` on any non-None mask, and even SDPA-based backends pay unnecessary overhead processing a no-op mask. See `pipeline_qwenimage.py` `encode_prompt` for the pattern: `if mask.all(): mask = None`. When a mask is needed, use bool format — it stays compatible with the `*_varlen` kernels via `_normalize_attn_mask` (`attention_dispatch.py:639`), which reduces bool masks to `cu_seqlens`. Dense additive-float masks *cannot* be reduced this way and so lose the varlen path.
73+
- **Padding mask → bool `(B, L)` or `(B, 1, 1, L)`.** Only pass when the batch actually contains padding. If all sequences are the same length and padded to max length, set the mask to `None` — many backends (flash, sage, aiter) raise `ValueError` on any non-None mask, and even SDPA-based backends pay unnecessary overhead processing a no-op mask. See `pipeline_qwenimage.py` `encode_prompt` for the pattern: `if mask.all(): mask = None`. Some models are also trained without a mask — pass `None` for these even when padding is present (SD, Flux etc). When a mask is needed, use bool format — it stays compatible with the `*_varlen` kernels via `_normalize_attn_mask` (`attention_dispatch.py:639`), which reduces bool masks to `cu_seqlens`. Dense additive-float masks *cannot* be reduced this way and so lose the varlen path.
6674
- **Other mask types (structural, BlockMask, etc.)** — if the model requires a different mask pattern, figure out how to support as many backends as possible (e.g. use `window_size` kwarg for sliding window on flash, `BlockMask` for Flex) and document which backends are supported for that model.
6775
- **Don't declare `attention_mask` (or `encoder_hidden_states_mask`) in the forward signature if you ignore it.** "For API stability with other transformers" is not a reason; readers assume a declared param is honored, and downstream pipelines will pass padding masks that silently get dropped. Some existing models in the repo carry unused mask params for historical reasons — e.g. `QwenDoubleStreamAttnProcessor2_0.__call__` declares `encoder_hidden_states_mask` but never reads it (the joint mask is routed through `attention_mask` instead), and the block-level forward in `transformer_qwenimage.py` declares it but always receives `None`. This is a legacy behavior and should not be replicated in new models.
6876

.ai/pipelines.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,7 @@ src/diffusers/pipelines/<model>/
7676
6. **Be deliberate about methods on the pipeline.** `__call__` is the user's mental model. The methods on the class are how they navigate it. Diffusers convention (flux, sdxl, wan, qwenimage) is a flat class body of public lifecycle methods (`__init__`, `check_inputs`, `encode_prompt`, `prepare_latents`, `__call__`). Two principles, not strict rules — use judgment:
7777
- **If a method is called from `__call__`, and it's a step in the pipeline lifecycle, make it public.** Each call from `__call__` should correspond to a step a user can identify: either a standard one (`encode_prompt`, `prepare_latents`, `set_timesteps`, …) or a pipeline-specific one (`prepare_src_latents`, `prepare_reference_audio_latents`, …). Don't gate these behind a `_`; they're part of the pipeline's API surface alongside their standard siblings.
7878
- **If a method is only used by another method, make it private (`_foo`) or lift it to a module-level function — and keep the count down.** Before adding one, see if the logic can be absorbed into its caller. Unless you expect the helper to be reused by another method (or another task pipeline), absorbing is usually the better call — especially when the body is small. Avoid a pipeline class littered with private helpers that bury the lifecycle..
79+
80+
7. **Don't modify the state of a registered component on the fly.** From inside `__call__` or other helper methods, don't change the state of `self.text_encoder` / `self.transformer` / `self.vae` — no in-place `.to(dtype/device)`, no setting attributes/buffers or swapping submodules. Components are shared and routinely reused across pipelines, so a per-call mutation may silently change another pipeline's outputs. You should pass a component that's already in the right state, and document that expectation explicitly. Only when that's genuinely inconvenient and you must change state for the duration of a call — e.g. swapping in an attention processor — save the original first and restore it before returning, so the component is left exactly as you found it. The PAG pipelines are the reference for this: `pipeline_pag_sd.py` snapshots `original_attn_proc = self.unet.attn_processors`, installs the PAG processors for the denoising loop, then calls `self.unet.set_attn_processor(original_attn_proc)` at the end of `__call__`.
81+
82+
8. **Don't reimplement `DiffusionPipeline`.** A pipeline subclass adds only *pipeline-specific* steps (`__call__`, `check_inputs`, `encode_prompt`, `prepare_latents`, …). Device placement, offloading, and component loading/registration already live on the base class — don't add your own; use what's there.

.github/workflows/build_documentation.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,13 @@ permissions:
1717

1818
jobs:
1919
build:
20-
uses: huggingface/doc-builder/.github/workflows/build_main_documentation.yml@2430c1ec91d04667414e2fa31ecfc36c153ea391 # main
20+
uses: huggingface/doc-builder/.github/workflows/build_main_documentation.yml@e60a538eea9817ab312196d0d233604b01697265 # main
2121
with:
2222
commit_sha: ${{ github.sha }}
2323
install_libgl1: true
2424
package: diffusers
2525
notebook_folder: diffusers_doc
2626
languages: en ko zh ja pt
27-
custom_container: diffusers/diffusers-doc-builder
2827
pre_command: uv pip uninstall transformers huggingface_hub && UV_PRERELEASE=allow uv pip install -U transformers@git+https://github.com/huggingface/transformers.git
2928
secrets:
3029
token: ${{ secrets.HUGGINGFACE_PUSH }}

.github/workflows/build_pr_documentation.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,11 @@ jobs:
4242
4343
build:
4444
needs: check-links
45-
uses: huggingface/doc-builder/.github/workflows/build_pr_documentation.yml@90b4ee2c10b81b5c1a6367c4e6fc9e2fb510a7e3 # main
45+
uses: huggingface/doc-builder/.github/workflows/build_pr_documentation.yml@e60a538eea9817ab312196d0d233604b01697265 # main
4646
with:
4747
commit_sha: ${{ github.event.pull_request.head.sha }}
4848
pr_number: ${{ github.event.number }}
4949
install_libgl1: true
5050
package: diffusers
5151
languages: en ko zh ja pt
52-
custom_container: diffusers/diffusers-doc-builder
5352
pre_command: uv pip uninstall transformers huggingface_hub && UV_PRERELEASE=allow uv pip install -U transformers@git+https://github.com/huggingface/transformers.git

.github/workflows/claude_review.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ jobs:
8484
git clone --local --bare . /tmp/local-origin.git
8585
git config url."file:///tmp/local-origin.git".insteadOf "$(git remote get-url origin)"
8686
87-
- uses: anthropics/claude-code-action@2ff1acb3ee319fa302837dad6e17c2f36c0d98ea # v1
87+
- uses: anthropics/claude-code-action@80b31826338489861333dc17217865dfe8085cdc # v1.0.155
8888
env:
8989
CLAUDE_SYSTEM_PROMPT: |
9090
You are a strict code reviewer for the diffusers library (huggingface/diffusers).

docker/diffusers-pytorch-cuda/Dockerfile

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,6 @@ RUN uv pip install --no-cache-dir \
4040
torchaudio==2.10.0 \
4141
--index-url https://download.pytorch.org/whl/cu129
4242

43-
# Install compatible versions of numba/llvmlite for Python 3.10+
44-
RUN uv pip install --no-cache-dir \
45-
"llvmlite>=0.40.0" \
46-
"numba>=0.57.0"
47-
4843
RUN uv pip install --no-cache-dir "git+https://github.com/huggingface/diffusers.git@main#egg=diffusers[test]"
4944

5045
# Extra dependencies

docs/source/en/_toctree.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,8 @@
355355
title: Ideogram4Transformer2DModel
356356
- local: api/models/transformer_joyimage
357357
title: JoyImageEditTransformer3DModel
358+
- local: api/models/krea2_transformer2d
359+
title: Krea2Transformer2DModel
358360
- local: api/models/latte_transformer3d
359361
title: LatteTransformer3DModel
360362
- local: api/models/longcat_image_transformer2d
@@ -563,6 +565,8 @@
563565
title: Kandinsky 5.0 Image
564566
- local: api/pipelines/kolors
565567
title: Kolors
568+
- local: api/pipelines/krea2
569+
title: Krea 2
566570
- local: api/pipelines/latent_consistency_models
567571
title: Latent Consistency Models
568572
- local: api/pipelines/latent_diffusion
@@ -643,6 +647,8 @@
643647
title: Z-Image
644648
title: Image
645649
- sections:
650+
- local: api/pipelines/diffusion_gemma
651+
title: DiffusionGemma
646652
- local: api/pipelines/llada2
647653
title: LLaDA2
648654
title: Text
@@ -712,6 +718,8 @@
712718
title: DDPMScheduler
713719
- local: api/schedulers/deis
714720
title: DEISMultistepScheduler
721+
- local: api/schedulers/discrete_ddim
722+
title: DiscreteDDIMScheduler
715723
- local: api/schedulers/multistep_dpm_solver_inverse
716724
title: DPMSolverMultistepInverse
717725
- local: api/schedulers/multistep_dpm_solver
@@ -724,6 +732,8 @@
724732
title: EDMDPMSolverMultistepScheduler
725733
- local: api/schedulers/edm_euler
726734
title: EDMEulerScheduler
735+
- local: api/schedulers/entropy_bound
736+
title: EntropyBoundScheduler
727737
- local: api/schedulers/euler_ancestral
728738
title: EulerAncestralDiscreteScheduler
729739
- local: api/schedulers/euler

docs/source/en/api/loaders/lora.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ LoRA is a fast and lightweight training method that inserts and trains a signifi
148148

149149
[[autodoc]] loaders.lora_pipeline.Ideogram4LoraLoaderMixin
150150

151+
## Krea2LoraLoaderMixin
152+
153+
[[autodoc]] loaders.lora_pipeline.Krea2LoraLoaderMixin
154+
151155
## LoraBaseMixin
152156

153157
[[autodoc]] loaders.lora_base.LoraBaseMixin
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!--Copyright 2026 Krea AI and The HuggingFace Team. All rights reserved.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
4+
the License. You may obtain a copy of the License at
5+
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
8+
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
9+
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
10+
specific language governing permissions and limitations under the License.
11+
-->
12+
13+
# Krea2Transformer2DModel
14+
15+
The single-stream MMDiT flow-matching transformer used by [Krea 2](https://github.com/krea-ai/krea-2).
16+
17+
## Krea2Transformer2DModel
18+
19+
[[autodoc]] Krea2Transformer2DModel

0 commit comments

Comments
 (0)