Skip to content

[docs] update philosophy.md (finally)#13808

Open
yiyixuxu wants to merge 1 commit into
mainfrom
philosophy-refresh
Open

[docs] update philosophy.md (finally)#13808
yiyixuxu wants to merge 1 commit into
mainfrom
philosophy-refresh

Conversation

@yiyixuxu
Copy link
Copy Markdown
Collaborator

@yiyixuxu yiyixuxu commented May 26, 2026

in this PR, I

  1. removed stuff that's no longer true in our philosophy file, mostly single-file related
  2. add a mention on modular pipelines

Update the framing to match how Diffusers actually works now: models
follow the single-file policy (with UNet/older transformers as legacy
exceptions, not the model), add a Modular Pipelines section parallel to
standard Pipelines, and slim Pipelines/Models bullets to remove stale
guidance (per-task pipeline subclassing, generic-class checkpoint
adaptation, dead links to deprecated repos).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@github-actions github-actions Bot added documentation Improvements or additions to documentation size/S PR with diff < 50 LOC labels May 26, 2026
@yiyixuxu yiyixuxu requested review from DN6, dg845, sayakpaul and stevhliu May 26, 2026 05:59
@HuggingFaceDocBuilderDev
Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

### Pipelines

Pipelines are designed to be easy to use (therefore do not follow [*Simple over easy*](#simple-over-easy) 100%), are not feature complete, and should loosely be seen as examples of how to use [models](#models) and [schedulers](#schedulers) for inference.
Pipelines are intended **only** for inference. Pipelines are designed to be easy to use (therefore do not follow [*Simple over easy*](#simple-over-easy) 100%) — they should be readable, self-explanatory, easy to tweak, and loosely seen as examples of how to use [models](#models) and [schedulers](#schedulers). Pipelines are not feature complete, to build feature-complete user interfaces on top of Diffusers, consider using [Modular Diffusers](../modular_diffusers/overview).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Pipelines are intended **only** for inference. Pipelines are designed to be easy to use (therefore do not follow [*Simple over easy*](#simple-over-easy) 100%) — they should be readable, self-explanatory, easy to tweak, and loosely seen as examples of how to use [models](#models) and [schedulers](#schedulers). Pipelines are not feature complete, to build feature-complete user interfaces on top of Diffusers, consider using [Modular Diffusers](../modular_diffusers/overview).
Pipelines, either standard or modular, are intended **only** for inference. Pipelines are designed to be easy to use (therefore do not follow [*Simple over easy*](#simple-over-easy) 100%) — they should be readable, self-explanatory, easy to tweak, and loosely seen as examples of how to use [models](#models) and [schedulers](#schedulers). Pipelines are not feature complete, to build feature-complete user interfaces on top of Diffusers, consider using [Modular Diffusers](../modular_diffusers/overview).

Copy link
Copy Markdown
Member

@stevhliu stevhliu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the update!

### Pipelines

Pipelines are designed to be easy to use (therefore do not follow [*Simple over easy*](#simple-over-easy) 100%), are not feature complete, and should loosely be seen as examples of how to use [models](#models) and [schedulers](#schedulers) for inference.
Pipelines are intended **only** for inference. Pipelines are designed to be easy to use (therefore do not follow [*Simple over easy*](#simple-over-easy) 100%) — they should be readable, self-explanatory, easy to tweak, and loosely seen as examples of how to use [models](#models) and [schedulers](#schedulers). Pipelines are not feature complete, to build feature-complete user interfaces on top of Diffusers, consider using [Modular Diffusers](../modular_diffusers/overview).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Pipelines are intended **only** for inference. Pipelines are designed to be easy to use (therefore do not follow [*Simple over easy*](#simple-over-easy) 100%) — they should be readable, self-explanatory, easy to tweak, and loosely seen as examples of how to use [models](#models) and [schedulers](#schedulers). Pipelines are not feature complete, to build feature-complete user interfaces on top of Diffusers, consider using [Modular Diffusers](../modular_diffusers/overview).
Pipelines, standard or modular, are intended only for inference. They're designed to be easy to use (so they don't follow [Simple over easy](#simple-over-easy) 100%): readable, self-explanatory, easy to tweak, and best seen as examples of how to use [models](#models) and [schedulers](#schedulers). They aren't feature complete. To build feature-complete user interfaces on top of Diffusers, use [Modular Diffusers](../modular_diffusers/overview).


### Modular Pipelines

Modular Pipelines is the composable alternative to standard pipelines: workflows are built from reusable **pipeline blocks** that can be mixed, matched, swapped, and shared. Where standard pipelines are loose reference examples of how to use models and schedulers, Modular Pipelines is the recommended path for building feature-complete user interfaces on top of Diffusers, and for the community to build and share new pipelines in a decentralized way.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Modular Pipelines is the composable alternative to standard pipelines: workflows are built from reusable **pipeline blocks** that can be mixed, matched, swapped, and shared. Where standard pipelines are loose reference examples of how to use models and schedulers, Modular Pipelines is the recommended path for building feature-complete user interfaces on top of Diffusers, and for the community to build and share new pipelines in a decentralized way.
Modular Diffusers is the composable alternative to standard pipelines. You build a workflow from reusable *pipeline blocks* that you can mix, match, swap, and share. Standard pipelines are loose reference examples of how to use models and schedulers. Modular Diffusers is the recommended path for building feature-complete user interfaces on top of Diffusers, and for the community to build and share new pipelines in a decentralized way.


Now, let's look a bit into the nitty-gritty details of the design philosophy. Diffusers essentially consists of three major classes: [pipelines](https://github.com/huggingface/diffusers/tree/main/src/diffusers/pipelines), [models](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models), and [schedulers](https://github.com/huggingface/diffusers/tree/main/src/diffusers/schedulers).
Let's walk through more in-detail design decisions for each class.
Now, let's look a bit into the nitty-gritty details of the design philosophy. Diffusers consists of [models](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models), [schedulers](https://github.com/huggingface/diffusers/tree/main/src/diffusers/schedulers), and two ways to compose them into a runnable workflow: standard [pipelines](https://github.com/huggingface/diffusers/tree/main/src/diffusers/pipelines) (monolithic, one task per pipeline class) and [Modular Diffusers](../modular_diffusers/overview) (composable, block-based). Let's walk through more in-detail design decisions for each.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Now, let's look a bit into the nitty-gritty details of the design philosophy. Diffusers consists of [models](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models), [schedulers](https://github.com/huggingface/diffusers/tree/main/src/diffusers/schedulers), and two ways to compose them into a runnable workflow: standard [pipelines](https://github.com/huggingface/diffusers/tree/main/src/diffusers/pipelines) (monolithic, one task per pipeline class) and [Modular Diffusers](../modular_diffusers/overview) (composable, block-based). Let's walk through more in-detail design decisions for each.
Now for the nitty-gritty details of the design philosophy. Diffusers gives you two ways to compose [models](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models) and [schedulers](https://github.com/huggingface/diffusers/tree/main/src/diffusers/schedulers) into a runnable workflow: standard [pipelines](https://github.com/huggingface/diffusers/tree/main/src/diffusers/pipelines), which are monolithic with one task per pipeline class, and Modular Diffusers, which is composable and block-based. The sections below cover pipelines, modular pipelines, models, and schedulers in turn.

Modular Pipelines is the composable alternative to standard pipelines: workflows are built from reusable **pipeline blocks** that can be mixed, matched, swapped, and shared. Where standard pipelines are loose reference examples of how to use models and schedulers, Modular Pipelines is the recommended path for building feature-complete user interfaces on top of Diffusers, and for the community to build and share new pipelines in a decentralized way.

The following design principles are followed:
- Modular pipelines also follow the single-file policy. Each modular pipeline lives in its own folder under [`src/diffusers/modular_pipelines/`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/modular_pipelines). A modular pipeline folder contains multiple files corresponding to each stage of the workflow — `encoders.py`, `before_denoise.py`, `denoise.py`, `decoders.py`, `modular_blocks_<model>.py` for assembly, and `modular_pipeline.py` for the per-model `ModularPipeline` subclass. Modular pipelines don't cross-import each other.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Modular pipelines also follow the single-file policy. Each modular pipeline lives in its own folder under [`src/diffusers/modular_pipelines/`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/modular_pipelines). A modular pipeline folder contains multiple files corresponding to each stage of the workflow — `encoders.py`, `before_denoise.py`, `denoise.py`, `decoders.py`, `modular_blocks_<model>.py` for assembly, and `modular_pipeline.py` for the per-model `ModularPipeline` subclass. Modular pipelines don't cross-import each other.
- Modular pipelines follow the single-file policy. Each one lives in its own folder under [src/diffusers/modular_pipelines/](https://github.com/huggingface/diffusers/tree/main/src/diffusers/modular_pipelines), and the folder splits the workflow across one file per stage: `encoders.py`, `before_denoise.py`, `denoise.py`, and `decoders.py`. Two more files complete the pipeline. `modular_blocks_<model>.py` assembles the stages, and `modular_pipeline.py` defines the per-model [`ModularPipeline`] subclass. Modular pipelines don't cross-import each other.


The following design principles are followed:
- Modular pipelines also follow the single-file policy. Each modular pipeline lives in its own folder under [`src/diffusers/modular_pipelines/`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/modular_pipelines). A modular pipeline folder contains multiple files corresponding to each stage of the workflow — `encoders.py`, `before_denoise.py`, `denoise.py`, `decoders.py`, `modular_blocks_<model>.py` for assembly, and `modular_pipeline.py` for the per-model `ModularPipeline` subclass. Modular pipelines don't cross-import each other.
- Each modular pipeline is defined as a set of `ModularPipelineBlocks` — leaf blocks in the stage files (`encoders.py`, `before_denoise.py`, `denoise.py`, `decoders.py`), then assembled into the full workflow in `modular_blocks_<model>.py` using container classes like `SequentialPipelineBlocks` and `AutoPipelineBlocks`. Unlike `DiffusionPipeline`, which both defines the computation logic and runs it, modular splits these into two concepts: blocks are pure definitions (declare inputs, outputs, and component dependencies — they do not hold weights and cannot be executed), and a `ModularPipeline` is the runnable counterpart, created via `.init_pipeline(repo_id)`. Keeping blocks stateless and weight-free is what makes them freely composable, swappable, and shareable across workflows.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Each modular pipeline is defined as a set of `ModularPipelineBlocks` — leaf blocks in the stage files (`encoders.py`, `before_denoise.py`, `denoise.py`, `decoders.py`), then assembled into the full workflow in `modular_blocks_<model>.py` using container classes like `SequentialPipelineBlocks` and `AutoPipelineBlocks`. Unlike `DiffusionPipeline`, which both defines the computation logic and runs it, modular splits these into two concepts: blocks are pure definitions (declare inputs, outputs, and component dependencies — they do not hold weights and cannot be executed), and a `ModularPipeline` is the runnable counterpart, created via `.init_pipeline(repo_id)`. Keeping blocks stateless and weight-free is what makes them freely composable, swappable, and shareable across workflows.
- Each modular pipeline is defined as a set of [`ModularPipelineBlocks`]. Leaf blocks live in the stage files (`encoders.py`, `before_denoise.py`, `denoise.py`, `decoders.py`), and `modular_blocks_<model>.py` assembles them into the full workflow with container classes like [`SequentialPipelineBlocks`] and [`AutoPipelineBlocks`]. This splits apart two concepts that [`DiffusionPipeline combines`]. A block is a pure definition. It declares inputs, outputs, and component dependencies, but holds no weights and can't run. A [`ModularPipeline`], created with `.init_pipeline(repo_id)`, is the runnable counterpart. Keeping blocks stateless and weight-free is what makes them freely composable, swappable, and shareable across workflows.

The following design principles are followed:
- Modular pipelines also follow the single-file policy. Each modular pipeline lives in its own folder under [`src/diffusers/modular_pipelines/`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/modular_pipelines). A modular pipeline folder contains multiple files corresponding to each stage of the workflow — `encoders.py`, `before_denoise.py`, `denoise.py`, `decoders.py`, `modular_blocks_<model>.py` for assembly, and `modular_pipeline.py` for the per-model `ModularPipeline` subclass. Modular pipelines don't cross-import each other.
- Each modular pipeline is defined as a set of `ModularPipelineBlocks` — leaf blocks in the stage files (`encoders.py`, `before_denoise.py`, `denoise.py`, `decoders.py`), then assembled into the full workflow in `modular_blocks_<model>.py` using container classes like `SequentialPipelineBlocks` and `AutoPipelineBlocks`. Unlike `DiffusionPipeline`, which both defines the computation logic and runs it, modular splits these into two concepts: blocks are pure definitions (declare inputs, outputs, and component dependencies — they do not hold weights and cannot be executed), and a `ModularPipeline` is the runnable counterpart, created via `.init_pipeline(repo_id)`. Keeping blocks stateless and weight-free is what makes them freely composable, swappable, and shareable across workflows.
- To support a new workflow/task, write the task-specific block(s), compose them with existing ones, and declare the new workflow in `_workflow_map` on the top-level block assembly. Unlike `DiffusionPipeline`, each `ModularPipeline` can support many workflows (text2img, img2img, inpaint, etc.).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- To support a new workflow/task, write the task-specific block(s), compose them with existing ones, and declare the new workflow in `_workflow_map` on the top-level block assembly. Unlike `DiffusionPipeline`, each `ModularPipeline` can support many workflows (text2img, img2img, inpaint, etc.).
- To support a new task, write the task-specific blocks, compose them with existing ones, and register the workflow in `_workflow_map` on the top-level block assembly. A single `ModularPipeline` can support many workflows, such as text-to-image, image-to-image, and inpainting, whereas a `DiffusionPipeline` runs only one.

### Models

Models are designed as configurable toolboxes that are natural extensions of [PyTorch's Module class](https://pytorch.org/docs/stable/generated/torch.nn.Module.html). They only partly follow the **single-file policy**.
Models are designed as configurable toolboxes that are natural extensions of [PyTorch's Module class](https://pytorch.org/docs/stable/generated/torch.nn.Module.html). They should follow the **single-file policy**. Some older models predate this convention and are kept as-is as legacy exceptions — not patterns to follow for new models. E.g. the original [`UNet2DConditionModel`] class was used for different UNet variations.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Models are designed as configurable toolboxes that are natural extensions of [PyTorch's Module class](https://pytorch.org/docs/stable/generated/torch.nn.Module.html). They should follow the **single-file policy**. Some older models predate this convention and are kept as-is as legacy exceptionsnot patterns to follow for new models. E.g. the original [`UNet2DConditionModel`] class was used for different UNet variations.
Models are designed as configurable toolboxes that are natural extensions of [PyTorch's Module class](https://pytorch.org/docs/stable/generated/torch.nn.Module.html). They should follow the *single-file policy*. Some older models predate this convention and are kept as-is. Treat them as legacy exceptions, not patterns to follow for new models. For example, the original [`UNet2DConditionModel`] class was used for several UNet variations.

- Models correspond to **a type of model architecture**. *E.g.* the [`UNet2DConditionModel`] class is used for all UNet variations that expect 2D image inputs and are conditioned on some context.
- All models can be found in [`src/diffusers/models`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models) and every model architecture shall be defined in its file, e.g. [`unets/unet_2d_condition.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/unets/unet_2d_condition.py), [`transformers/transformer_2d.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/transformers/transformer_2d.py), etc...
- Models **do not** follow the single-file policy and should make use of smaller model building blocks, such as [`attention.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/attention.py), [`resnet.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/resnet.py), [`embeddings.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/embeddings.py), etc... **Note**: This is in stark contrast to Transformers' modeling files and shows that models do not really follow the single-file policy.
- Each model architecture type lives in its own folder under [`src/diffusers/models`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models) (e.g. [`transformers/`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models/transformers), [`autoencoders/`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models/autoencoders), [`unets/`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models/unets)), and each model family has its own file within that folder (e.g. [`transformer_flux.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/transformers/transformer_flux.py), [`transformer_wan.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/transformers/transformer_wan.py)).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Each model architecture type lives in its own folder under [`src/diffusers/models`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models) (e.g. [`transformers/`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models/transformers), [`autoencoders/`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models/autoencoders), [`unets/`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models/unets)), and each model family has its own file within that folder (e.g. [`transformer_flux.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/transformers/transformer_flux.py), [`transformer_wan.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/transformers/transformer_wan.py)).
- Each model architecture type lives in its own folder under [src/diffusers/models](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models), for example [transformers/](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models/transformers), [autoencoders/](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models/autoencoders), or [unets/](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models/unets). Each model family has its own file within that folder, such as [transformer_flux.py](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/transformers/transformer_flux.py) and [transformer_wan.py](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/transformers/transformer_wan.py).

- All models can be found in [`src/diffusers/models`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models) and every model architecture shall be defined in its file, e.g. [`unets/unet_2d_condition.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/unets/unet_2d_condition.py), [`transformers/transformer_2d.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/transformers/transformer_2d.py), etc...
- Models **do not** follow the single-file policy and should make use of smaller model building blocks, such as [`attention.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/attention.py), [`resnet.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/resnet.py), [`embeddings.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/embeddings.py), etc... **Note**: This is in stark contrast to Transformers' modeling files and shows that models do not really follow the single-file policy.
- Each model architecture type lives in its own folder under [`src/diffusers/models`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models) (e.g. [`transformers/`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models/transformers), [`autoencoders/`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models/autoencoders), [`unets/`](https://github.com/huggingface/diffusers/tree/main/src/diffusers/models/unets)), and each model family has its own file within that folder (e.g. [`transformer_flux.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/transformers/transformer_flux.py), [`transformer_wan.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/transformers/transformer_wan.py)).
- Models follow the **single-file policy** — each model file should be self-contained, except for a small number of standard modules that every model uses identically (e.g. timestep embeddings, normalization layers), which can be imported from [`embeddings.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/embeddings.py) and [`normalization.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/normalization.py).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Models follow the **single-file policy** — each model file should be self-contained, except for a small number of standard modules that every model uses identically (e.g. timestep embeddings, normalization layers), which can be imported from [`embeddings.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/embeddings.py) and [`normalization.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/normalization.py).
- Models follow the single-file policy. Each model file should be self-contained, except for a small number of standard modules that every model uses identically, such as timestep embeddings and normalization layers. Import those from [embeddings.py](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/embeddings.py) and [normalization.py](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/normalization.py).

- Pipelines should be named after the task they are intended to solve.
- In almost all cases, novel diffusion pipelines shall be implemented in a new pipeline folder/file.

### Modular Pipelines
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Modular Pipelines
### Modular Diffusers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/S PR with diff < 50 LOC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants