Skip to content

Commit 614828a

Browse files
committed
Merge remote-tracking branch 'upstream/main' into sefi-image-diffusers
2 parents 7cf9396 + 8a29f31 commit 614828a

683 files changed

Lines changed: 21399 additions & 20732 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/AGENTS.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,17 @@ Strive to write code as simple and explicit as possible.
3030
- **Models** — see [models.md](models.md) for model conventions, attention pattern, implementation rules, dependencies, and gotchas. For adding or converting a model, use the [model-integration](./skills/model-integration/SKILL.md) skill.
3131
- **Pipelines** — see [pipelines.md](pipelines.md) for pipeline conventions, patterns, and gotchas.
3232
- **Modular pipelines** — see [modular.md](modular.md) for modular pipeline conventions, patterns, and gotchas.
33+
- **Tests** — see [testing.md](testing.md) for test conventions: required test layers, tester mixins, and dummy-component rules.
3334

3435
## Skills
3536

3637
Task-specific guides live in `.ai/skills/` and are loaded on demand by AI agents. Available skills include:
3738

3839
- [model-integration](./skills/model-integration/SKILL.md) (adding/converting pipelines)
40+
- [custom-blocks](./skills/custom-blocks/SKILL.md) (packaging a `ModularPipelineBlocks` subclass for the Hub)
41+
- [diffusers-cli](./skills/diffusers-cli/SKILL.md) (running pipelines, inspecting schemas, and using the Diffusers CLI)
3942
- [self-review](./skills/self-review/SKILL.md) (pre-PR self-review against the project rules)
4043

4144
## Self-review before a PR
4245

43-
Before opening a PR, run self-review against [review-rules.md](review-rules.md). The [self-review skill](skills/self-review/SKILL.md) runs this as the same pass the `@claude` CI reviewer uses.
46+
Before opening a PR, run self-review against [review-rules.md](review-rules.md). The [self-review skill](skills/self-review/SKILL.md) runs this as the same pass the `@claude` CI reviewer uses. Share the final report on the PR (description or comment) — see the skill for details.

.ai/models.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Linked from `AGENTS.md`, `skills/model-integration/SKILL.md`, and `review-rules.
66
## Coding style
77

88
- All layer calls should be visible directly in `forward` — avoid helper functions that hide `nn.Module` calls.
9+
- Prefer descriptive variable names over short ones. For example, prefer spelling out `query` over `q`.
910
- Avoid graph breaks for `torch.compile` compatibility — do not insert NumPy operations in forward implementations and any other patterns that can break `torch.compile` compatibility with `fullgraph=True`.
1011
- No new mandatory dependency without discussion (e.g. `einops`). Optional deps guarded with `is_X_available()` and a dummy in `utils/dummy_*.py`.
1112

@@ -182,4 +183,8 @@ Boolean gate. If `False` (default), calling that method raises `ValueError`. All
182183
```
183184
See `transformer_flux.py`, `transformer_flux2.py`, `transformer_wan.py`, `unet_2d_condition.py`, and `pipeline_pixart_alpha.py` for reference usages. Never leave an unconditional `torch.float64` in the model.
184185

185-
6. **Using `torch.empty`.** - Do not use `torch.empty` to initialize parameters. Use `torch.zeros` or `torch.ones`, instead.
186+
6. **Using `torch.empty`.** - Do not use `torch.empty` to initialize parameters. Use `torch.zeros` or `torch.ones`, instead.
187+
188+
7. **Tensor contiguity.** - Non-contiguous tensors can degrade performance. Therefore, try to maintain contiguity
189+
of the tensors whenever possible. A non-contiguous tensor is usually produced because of the operations. A common
190+
example is a `flatten()` followed by a `transpose()`. This sequence is known to produce non-contiguous layouts. So, prefer calling `contiguous()` on the output tensor to maintain performance.

.ai/modular.md

Lines changed: 96 additions & 3 deletions
Large diffs are not rendered by default.

.ai/pipelines.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,11 @@ src/diffusers/pipelines/<model>/
8080
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__`.
8181

8282
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.
83+
84+
9. **Build `callback_kwargs` with a loop, never a dict comprehension.** `{k: locals()[k] for k in callback_on_step_end_tensor_inputs}` always raises `KeyError`: inside a comprehension, `locals()` is the comprehension's own scope, not `__call__`'s. Use the standard form (see `pipeline_stable_diffusion.py`):
85+
```python
86+
callback_kwargs = {}
87+
for k in callback_on_step_end_tensor_inputs:
88+
callback_kwargs[k] = locals()[k]
89+
```
90+
The bug is invisible until someone actually passes `callback_on_step_end` — the `PipelineTesterMixin` callback tests are what catch it.

.ai/review-rules.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Before reviewing, read and apply the guidelines in:
77
- [models.md](models.md) — model conventions, attention pattern, implementation rules, dependencies, gotchas
88
- [pipelines.md](pipelines.md) — pipeline conventions, coding style, gotchas
99
- [modular.md](modular.md) — modular pipeline conventions, patterns, common mistakes
10+
- [testing.md](testing.md) — test conventions: required test layers, tester mixins, dummy-component rules. When a PR adds or changes tests, check them against this guide.
1011
- [skills/model-integration/pitfalls.md](skills/model-integration/pitfalls.md) — known pitfalls causing numerical discrepancies between the reference implementation and the diffusers port (dtype mismatches, config assumptions, etc.)
1112

1213
## Common mistakes
@@ -20,7 +21,7 @@ Common mistakes are covered in the common-mistakes / gotcha sections in [AGENTS.
2021
A PR can leave existing docs stale or surface a pattern worth recording. Scan the docs related to what the PR touches and flag updates as a **suggestions / additional info** section (not blocking):
2122

2223
- **Usage docs.** New or changed public behavior — a new pipeline/model, a new argument, changed defaults, a renamed API — should have matching updates in `docs/`, docstrings, and examples. Flag any that now describe outdated behavior or that are missing for the new surface.
23-
- **Agent docs.** If the review turns up a rule, pattern, or common gotcha that isn't written down yet — especially one the author got wrong or that you had to reason out — propose adding it to the relevant agent guide ([AGENTS.md](AGENTS.md), [models.md](models.md), [pipelines.md](pipelines.md), [modular.md](modular.md), a skill, or this file) so the next contributor/agent gets it for free instead of repeating the mistake.
24+
- **Agent docs.** If the review turns up a rule, pattern, or common gotcha that isn't written down yet — especially one the author got wrong or that you had to reason out — propose adding it to the relevant agent guide ([AGENTS.md](AGENTS.md), [models.md](models.md), [pipelines.md](pipelines.md), [modular.md](modular.md), a skill, or this file) so the next contributor/agent gets it for free instead of repeating the mistake. Human review comments on the PR are a good source for these: if a human reviewer pointed something out and your review missed it, that usually indicates a doc gap — figure out what's missing and propose the addition.
2425

2526
## Dead code analysis (new models)
2627

.ai/skills/custom-blocks/SKILL.md

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
---
2+
name: custom-blocks
3+
description: >
4+
Use when the user has written (or wants to write) a `ModularPipelineBlocks`
5+
subclass in a local Python file and needs to package it into a Hub-uploadable
6+
directory. Covers the workflow from a single `block.py` file to a published
7+
custom-block repo that consumers can load via
8+
`ModularPipeline.from_pretrained(<repo>, trust_remote_code=True)`.
9+
---
10+
11+
## What this skill is for
12+
13+
A `ModularPipelineBlocks` subclass is a unit of pipeline logic — input/output spec plus a `__call__` — that
14+
slots into diffusers' modular pipeline composition. Once you have one defined locally, you almost always want to
15+
publish it as a small Hub repo so others can `from_pretrained` it. `diffusers-cli custom_blocks` automates the
16+
packaging step: it parses your Python file, instantiates the chosen block class, and writes a
17+
`save_pretrained`-style directory in your cwd that's ready to push to the Hub.
18+
19+
Use this skill when:
20+
21+
- The user is writing a custom modular block and asks "how do I publish this?" or "package this for the Hub".
22+
- The user has a `block.py` (or similar) file with one or more `ModularPipelineBlocks` subclasses.
23+
- You're scaffolding a new modular pipeline repo and need the on-disk layout that `ModularPipelineBlocks.from_pretrained`
24+
expects.
25+
26+
Don't use this skill for: running an existing modular pipeline (`diffusers-cli run`), introspecting one
27+
(`diffusers-cli schema`), or writing the block class itself — this skill packages an *already-written* block.
28+
29+
## The end-to-end workflow
30+
31+
```
32+
[you: write block.py] → diffusers-cli custom_blocks → [packaged dir in cwd]
33+
34+
hf upload <repo> .
35+
36+
consumers: ModularPipeline.from_pretrained(<repo>, trust_remote_code=True)
37+
diffusers-cli schema --model <repo> --trust-remote-code
38+
diffusers-cli run --model <repo> --trust-remote-code ...
39+
```
40+
41+
The skill covers the middle box. The bookends (writing the block and uploading) are out of scope.
42+
43+
## Command surface
44+
45+
```bash
46+
diffusers-cli custom_blocks [--block_module_name <file.py>] [--block_class_name <ClassName>]
47+
```
48+
49+
### Flags
50+
51+
- `--block_module_name <file>` — Python file containing the block class. Defaults to `block.py` in the cwd.
52+
- `--block_class_name <name>` — Which class in the file to package. Optional: if omitted, the CLI parses the
53+
file with `ast`, finds every class that inherits from `ModularPipelineBlocks`, and uses the first one (with
54+
an info log naming the others). Specify explicitly when the file defines more than one block and you want a
55+
specific one.
56+
57+
### What it does
58+
59+
1. **AST scan**: parses `<file>` without executing it, walks top-level `ClassDef` nodes, and collects every
60+
class whose `bases` include `ModularPipelineBlocks`.
61+
2. **Pick a class**: uses `--block_class_name` if given, else the first found. Errors with the list of available
62+
classes if your name doesn't match.
63+
3. **Load and save**: imports the file via `importlib.util.spec_from_file_location` (this does execute the
64+
module — make sure your block.py is something you trust to run), instantiates the chosen class with no
65+
constructor args, and calls `.save_pretrained(os.getcwd())`.
66+
67+
The result is a Hub-uploadable directory laid out the way `ModularPipelineBlocks.from_pretrained` expects:
68+
your block source, an `auto_map` in the config so consumers know to load it with `trust_remote_code=True`,
69+
and any artifacts `save_pretrained` writes for that block class.
70+
71+
## End-to-end example
72+
73+
Given a `block.py` like:
74+
75+
```python
76+
from diffusers.modular_pipelines import ModularPipelineBlocks, InputParam, OutputParam
77+
78+
class MyDenoiseBlock(ModularPipelineBlocks):
79+
model_name = "my-denoise"
80+
81+
@property
82+
def inputs(self):
83+
return [
84+
InputParam("latents", type_hint="torch.Tensor", required=True, description="Noisy latents."),
85+
InputParam("guidance_scale", type_hint="float", default=7.5),
86+
]
87+
88+
@property
89+
def intermediate_outputs(self):
90+
return [OutputParam("latents", type_hint="torch.Tensor")]
91+
92+
def __call__(self, components, state):
93+
# ... denoising logic ...
94+
return components, state
95+
```
96+
97+
Package it:
98+
99+
```bash
100+
diffusers-cli custom_blocks --block_module_name block.py
101+
```
102+
103+
Output in cwd:
104+
105+
```
106+
./
107+
├── block.py
108+
├── modular_config.json # contains auto_map → MyDenoiseBlock
109+
└── (any state files MyDenoiseBlock.save_pretrained writes)
110+
```
111+
112+
Upload to the Hub:
113+
114+
```bash
115+
hf upload my-user/my-denoise-block .
116+
```
117+
118+
Consumers can now use it:
119+
120+
```python
121+
from diffusers import ModularPipeline
122+
pipe = ModularPipeline.from_pretrained("my-user/my-denoise-block", trust_remote_code=True)
123+
```
124+
125+
Or via CLI:
126+
127+
```bash
128+
diffusers-cli schema --model my-user/my-denoise-block --trust-remote-code
129+
diffusers-cli run --model my-user/my-denoise-block --trust-remote-code \
130+
--pipeline-kwargs '{"latents": "...", "guidance_scale": 7.5}'
131+
```
132+
133+
## Common errors
134+
135+
- **`Could not parse '<file>': SyntaxError`** — the file isn't valid Python. Fix the syntax; the AST step runs
136+
before any execution.
137+
- **`block_class_name could not be retrieved. Available classes from <file>: [ClassA, ClassB]`** — your
138+
`--block_class_name` doesn't match any `ModularPipelineBlocks` subclass found. Pick from the list shown.
139+
- **No classes found**: silent — the command will try to use the first entry in an empty list and raise
140+
`IndexError`. If you hit that, double-check your class actually inherits from `ModularPipelineBlocks`
141+
(the AST scan looks for that literal base-class name; aliased imports like `from diffusers import ...
142+
as MPB` won't be picked up).
143+
- **Block requires constructor args**: the command calls `<ClassName>()` with no args. If your block needs
144+
`__init__` parameters, refactor to take them from `state`/`components` at `__call__` time instead, or
145+
hardcode defaults in `__init__`.
146+
147+
## Verifying the install
148+
149+
If `diffusers-cli` isn't on PATH, see the install verification section of
150+
[`../diffusers-cli/SKILL.md`](../diffusers-cli/SKILL.md#verifying-the-cli-is-installed).
151+
152+
## Related
153+
154+
- [`diffusers-cli` skill](../diffusers-cli/SKILL.md) — once your block is uploaded, `schema`/`run`
155+
let you call it from the terminal without writing Python.
156+
- diffusers' [modular pipelines docs](../../../docs/source/en/modular_diffusers) — for writing the block
157+
class itself.

.ai/skills/diffusers-cli/SKILL.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
name: diffusers-cli
3+
description: >
4+
Use when the user wants to run a diffusers pipeline from a terminal (one-off
5+
generation, batch jobs, smoke-testing a new model), run on HF Sandbox
6+
hardware via `--remote`, introspect a pipeline's input schema before
7+
calling it, or attach a LoRA at inference time. Prefer this over writing
8+
ad-hoc Python scripts for generation tasks.
9+
---
10+
11+
## Overview
12+
13+
`diffusers-cli` is the shipped CLI in `src/diffusers/commands/`. Subcommands relevant to agentic use:
14+
15+
| Command | Purpose |
16+
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
17+
| `run` | Run any `DiffusionPipeline` or `ModularPipeline`. Forwards `--pipeline-kwargs` verbatim, saves output by detecting its runtime type, optionally runs on HF Jobs via `--remote`. |
18+
| `schema` | Print the input schema for a pipeline repo (kwarg names, types, defaults, descriptions). **No weights downloaded** — only the small index file. |
19+
| `custom_blocks` | Package a local `ModularPipelineBlocks` subclass for the Hub. |
20+
| `env` | Print versions of diffusers + torch + transformers + accelerate + safetensors + CUDA + GPU info. Use when investigating environment issues, dtype/precision support, or building bug reports. |
21+
22+
## When to read which file
23+
24+
Most agentic work goes through `run`. Read the matching reference file before constructing a command:
25+
26+
- **[`run.md`](run.md)** — full reference for `diffusers-cli run`. Covers `--pipeline-kwargs`
27+
semantics and the shell-quoting gotcha, LoRA via `--lora`, optimization flags (`--dtype`, `--cpu-offload`,
28+
`--attention-backend`, `--vae-tiling/slicing`), output handling and `--push-to` bucket uploads, the full
29+
`--remote` HF Jobs flow (image, container command, log streaming, timing payload, artifact download), and
30+
context parallel (`--context-parallel`) for both local-torchrun and `--remote` paths.
31+
32+
The other commands are small enough that `diffusers-cli <command> --help` is the canonical reference:
33+
34+
```bash
35+
diffusers-cli schema --help
36+
diffusers-cli custom_blocks --help
37+
diffusers-cli env --help
38+
```
39+
40+
## When NOT to use this skill
41+
42+
- Multi-stage workflows where you need intermediate tensor manipulation between pipelines → write Python.
43+
- Training or fine-tuning → CLI only covers inference.
44+
- Anything requiring `quantization_config` or other low-level loader knobs not exposed by the CLI flags → write
45+
Python. (`device_map` is exposed as `--device-map`; see [run.md](run.md#optimization-flags).)
46+
47+
## Verifying the CLI is installed
48+
49+
The console entry point is registered in `pyproject.toml` (`diffusers-cli =
50+
"diffusers.commands.diffusers_cli:main"`). If `diffusers-cli` is not on PATH after `pip install -e .`, reinstall
51+
with `pip install -e . --force-reinstall --no-deps` and check `which diffusers-cli`. If the installed binary is
52+
missing recent features (e.g. you see `unrecognized arguments: --lora`), reinstall.
53+
54+
## Output formats
55+
56+
`--format {auto, human, agent, json}` (top-level flag, must appear before the subcommand):
57+
58+
- **`human`** — plain-text indented output for terminals (default when not running under an agent harness). No ANSI color.
59+
- **`agent`** — TSV tables and `key=value` lines. Auto-selected when an agent env var is present
60+
(`CLAUDECODE`, `CLAUDE_CODE`, `CODEX_SANDBOX`, `CURSOR_AI`, `AIDER_AI_CONTEXT`, `GH_COPILOT_AGENT`,
61+
`AI_AGENT`). Token-cheap for LLM agents to read.
62+
- **`json`** — compact JSON. Use for programmatic parsing (scripts, services) where type fidelity and nested
63+
structures matter.
64+
65+
`stdout` carries data; `stderr` carries hints/warnings/progress — parseable output is never polluted.
66+
67+
Rule of thumb: `--format json` for scripts that will `json.loads()` the output, otherwise leave it on
68+
auto-detect (`agent` for LLMs, `human` for terminals).

0 commit comments

Comments
 (0)