# 快速入门

Modular Diffusers 是一个用于快速构建灵活且可定制流水线的框架。这些流水线能够超越标准 `DiffusionPipeline` 的功能。Modular Diffusers 的核心是 [ModularPipelineBlocks](/docs/diffusers/v0.43.0/zh/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks)，它们可以与其他块组合，以适应新的工作流。这些块会被转换为 [ModularPipeline](/docs/diffusers/v0.43.0/zh/api/modular_diffusers/pipeline#diffusers.ModularPipeline)，这是一个面向用户的友好接口，用于运行生成任务。

本指南将向您展示如何运行模块化流水线、理解其结构，并通过修改组成流水线的各个模块来进行自定义。如果您熟悉 [DiffusionPipeline](/docs/diffusers/v0.43.0/zh/api/pipelines/overview#diffusers.DiffusionPipeline)，请先阅读 [来自 DiffusionPipeline](./coming_from_diffusion_pipeline)，以了解其中的差异。

## 运行流水线

[ModularPipeline](/docs/diffusers/v0.43.0/zh/api/modular_diffusers/pipeline#diffusers.ModularPipeline) 是用于加载、运行和管理模块化流水线的主要接口。
```py
import torch
from diffusers import ModularPipeline, ComponentsManager

# Use ComponentsManager to enable auto CPU offloading for memory efficiency
manager = ComponentsManager()
manager.enable_auto_cpu_offload(device="cuda:0")

pipe = ModularPipeline.from_pretrained("Qwen/Qwen-Image", components_manager=manager)
pipe.load_components(dtype=torch.bfloat16)

image = pipe(
    prompt="cat wizard with red hat, gandalf, lord of the rings, detailed, fantasy, cute, adorable, Pixar, Disney",
).images[0]
image
```

[from_pretrained()](/docs/diffusers/v0.43.0/zh/api/modular_diffusers/pipeline#diffusers.ModularPipeline.from_pretrained) 采用延迟加载机制——它会读取配置以了解各组件的加载来源，但直到你调用 [load_components()](/docs/diffusers/v0.43.0/zh/api/modular_diffusers/pipeline#diffusers.ModularPipeline.load_components) 时才会实际加载模型权重。这让你能够控制组件的加载时机和方式。

> [!TIP]
> `ComponentsManager` 配合 `enable_auto_cpu_offload` 可自动在 CPU 和 GPU 之间移动模型，从而降低 Qwen-Image 等大型模型的内存占用。详情请参阅 [ComponentsManager](./components_manager) 指南。
>
> 如果不需要 offloading，请移除 `components_manager` 参数，并使用 `to("cuda")` 手动将 pipeline 移至您的设备。

有关创建和加载管道的更多信息，请参阅[创建管道](https://huggingface.co/docs/diffusers/modular_diffusers/modular_pipeline#creating-a-pipeline)和[加载组件](https://huggingface.co/docs/diffusers/modular_diffusers/modular_pipeline#loading-components)指南。

## 理解结构

[ModularPipeline](/docs/diffusers/v0.43.0/zh/api/modular_diffusers/pipeline#diffusers.ModularPipeline) 由两部分组成：**定义**（即各个 block）和 **状态**（即已加载的组件和配置）。

打印 pipeline 以查看其状态——包括各组件及其加载状态和配置。
```py
print(pipe)
```
```
QwenImageModularPipeline {
  "_blocks_class_name": "QwenImageAutoBlocks",
  "_class_name": "QwenImageModularPipeline",
  "_diffusers_version": "0.37.0.dev0",
  "transformer": [
    "diffusers",
    "QwenImageTransformer2DModel",
    {
      "pretrained_model_name_or_path": "Qwen/Qwen-Image",
      "revision": null,
      "subfolder": "transformer",
      "type_hint": [
        "diffusers",
        "QwenImageTransformer2DModel"
      ],
      "variant": null
    }
  ],
  ...
}
```

通过 `pipe.blocks` 访问定义 —— 这是 [ModularPipelineBlocks](/docs/diffusers/v0.43.0/zh/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks)，用于定义流水线的工作流、输入、输出和计算逻辑。
```py
print(pipe.blocks)
```
```
QwenImageAutoBlocks(
  Class: SequentialPipelineBlocks

  Description: Auto Modular pipeline for text-to-image, image-to-image, inpainting, and controlnet tasks using QwenImage.
      
      Supported workflows:
        - `text2image`: requires `prompt`
        - `image2image`: requires `prompt`, `image`
        - `inpainting`: requires `prompt`, `mask_image`, `image`
        - `controlnet_text2image`: requires `prompt`, `control_image`
        ...

  Components:
      text_encoder (`Qwen2_5_VLForConditionalGeneration`)
      vae (`AutoencoderKLQwenImage`)
      transformer (`QwenImageTransformer2DModel`)
      ...

  Sub-Blocks:
    [0] text_encoder (QwenImageAutoTextEncoderStep)
    [1] vae_encoder (QwenImageAutoVaeEncoderStep)
    [2] controlnet_vae_encoder (QwenImageOptionalControlNetVaeEncoderStep)
    [3] denoise (QwenImageAutoCoreDenoiseStep)
    [4] decode (QwenImageAutoDecodeStep)
)
```

输出返回：
- 支持的工作流（text2image、image2image、inpainting 等）
- 它由以下子模块组成（text_encoder、vae_encoder、denoise、decode）

### 工作流程

此流水线支持多种工作流，并根据您提供的输入调整其行为。例如，如果您向流水线传入 `image`，它将执行图像到图像的工作流，而不是文本到图像的工作流。有关其底层工作原理的更多信息，请参阅 [AutoPipelineBlocks](https://huggingface.co/docs/diffusers/modular_diffusers/auto_pipeline_blocks) 指南。

```py
from diffusers.utils import load_image

input_image = load_image("https://github.com/Trgtuan10/Image_storage/blob/main/cute_cat.png?raw=true")

image = pipe(
    prompt="cat wizard with red hat, gandalf, lord of the rings, detailed, fantasy, cute, adorable, Pixar, Disney",
    image=input_image,
).images[0]
```

使用 `get_workflow()` 可提取特定工作流的块。传入工作流名称（例如 `"image2image"`、`"inpainting"`、`"controlnet_text2image"`）即可仅获取与该工作流相关的块。当您想要自定义或调试特定工作流时，此方法非常有用。您可以查看 `pipe.blocks.available_workflows` 以查看所有可用的工作流。
```py
img2img_blocks = pipe.blocks.get_workflow("image2image")
```

### 子块

块可以包含其他块。`pipe.blocks` 提供顶层块定义（此处为 `QwenImageAutoBlocks`），而 `sub_blocks` 则用于访问其中的较小块。

`QwenImageAutoBlocks` 由以下部分组成：`text_encoder`、`vae_encoder`、`controlnet_vae_encoder`、`denoise` 和 `decode`。

这些子块按顺序依次执行，数据从一个块线性流向下一个块——每个块的 `intermediate_outputs` 都会作为 `inputs` 提供给下一个块。[`SequentialPipelineBlocks`](./sequential_pipeline_blocks) 正是这样工作的。

您可以通过 `sub_blocks` 属性访问它们。`doc` 属性可用于查看任何块的完整文档，包括其输入、输出和组件。
```py
vae_encoder_block = pipe.blocks.sub_blocks["vae_encoder"]
print(vae_encoder_block.doc)
```

此代码块可以转换为流水线，从而能够通过 [init_pipeline()](/docs/diffusers/v0.43.0/zh/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks.init_pipeline) 独立运行。
```py
vae_encoder_pipe = vae_encoder_block.init_pipeline()

# Reuse the VAE we already loaded, we can reuse it with update_components() method
vae_encoder_pipe.update_components(vae=pipe.vae)

# Run just this block
image_latents = vae_encoder_pipe(image=input_image).image_latents
print(image_latents.shape)
```

它复用了原始流水线中的 VAE，而不是重新加载，从而保持内存使用效率。有关详细信息，请参阅 [加载组件](https://huggingface.co/docs/diffusers/modular_diffusers/modular_pipeline#loading-components) 指南。

由于 block 是可组合的，你可以通过添加、删除或替换 block 来修改 pipeline 的定义，从而创建新的工作流。在下一节中，我们将向 ControlNet pipeline 添加一个 canny 边缘检测 block，这样你就可以传入一张普通图像，而不是一张预先处理好的 canny 边缘图。

## 组合新的工作流

让我们向 ControlNet 流水线添加一个 canny 边缘检测块。首先，从 Hub 加载一个预构建的 canny 块（参见 [构建自定义块](https://huggingface.co/docs/diffusers/modular_diffusers/custom_blocks) 以创建您自己的块）。
```py
from diffusers.modular_pipelines import ModularPipelineBlocks

# Load a canny block from the Hub
canny_block = ModularPipelineBlocks.from_pretrained(
    "diffusers-internal-dev/canny-filtering",
    trust_remote_code=True,
)

print(canny_block.doc)
```
```
class CannyBlock

  Inputs:
      image (`Union[Image, ndarray]`):
          Image to compute canny filter on
      low_threshold (`int`, *optional*, defaults to 50):
          Low threshold for the canny filter.
      high_threshold (`int`, *optional*, defaults to 200):
          High threshold for the canny filter.
      ...

  Outputs:
      control_image (`PIL.Image`):
          Canny map for input image
```

使用 `get_workflow` 从 `QwenImageAutoBlocks` 中提取 ControlNet 工作流。
```py
# Get the controlnet workflow that we want to work with
blocks = pipe.blocks.get_workflow("controlnet_text2image")
print(blocks.doc)
```
```
class SequentialPipelineBlocks

  Inputs:
      prompt (`str`):
          The prompt or prompts to guide image generation.
      control_image (`Image`):
          Control image for ControlNet conditioning.
      ...
```

提取出的工作流是一个 [`SequentialPipelineBlocks`](./sequential_pipeline_blocks)，目前它需要 `control_image` 作为输入。请在开头插入 canny 块，以便该流水线能够接受普通图像作为输入。
```py
# Insert canny at the beginning
blocks.sub_blocks.insert("canny", canny_block, 0)

# Check the updated structure: CannyBlock is now listed as first sub-block
print(blocks)
# Check the updated doc
print(blocks.doc)
```
```
class SequentialPipelineBlocks

  Inputs:
      image (`Union[Image, ndarray]`):
          Image to compute canny filter on
      low_threshold (`int`, *optional*, defaults to 50):
          Low threshold for the canny filter.
      high_threshold (`int`, *optional*, defaults to 200):
          High threshold for the canny filter.
      prompt (`str`):
          The prompt or prompts to guide image generation.
      ...
```

现在，pipeline 以 `image` 作为输入，而不是 `control_image`。由于序列中的各个 block 会自动共享数据，canny block 的输出（`control_image`）会流向需要它的 denoise block，而 canny block 的输入（`image`）则成为 pipeline 的输入，因为没有更早的 block 提供该数据。

使用修改后的模块创建 pipeline，并加载 ControlNet 模型。ControlNet 不属于原始模型仓库，因此需要单独加载，并通过 [update_components()](/docs/diffusers/v0.43.0/zh/api/modular_diffusers/pipeline#diffusers.ModularPipeline.update_components) 将其添加进去。
```py
pipeline = blocks.init_pipeline("Qwen/Qwen-Image", components_manager=manager)

pipeline.load_components(dtype=torch.bfloat16)

# Load the ControlNet model
controlnet_spec = pipeline.get_component_spec("controlnet")
controlnet_spec.pretrained_model_name_or_path = "InstantX/Qwen-Image-ControlNet-Union"
controlnet = controlnet_spec.load(dtype=torch.bfloat16)
pipeline.update_components(controlnet=controlnet)
```

现在运行流水线 - canny 块会为 ControlNet 对图像进行预处理。
```py
from diffusers.utils import load_image

prompt = "cat wizard with red hat, gandalf, lord of the rings, detailed, fantasy, cute, adorable, Pixar, Disney"
image = load_image("https://github.com/Trgtuan10/Image_storage/blob/main/cute_cat.png?raw=true")

output = pipeline(
    prompt=prompt,
    image=image,
).images[0]
output
```

## 后续步骤

了解 Modular Diffusers 的核心构建模块：

- [ModularPipelineBlocks](./pipeline_block)：用于定义流水线中一个步骤的基本单元。
- [SequentialPipelineBlocks](./sequential_pipeline_blocks)：将多个块串联起来，按顺序执行。
- [AutoPipelineBlocks](./auto_pipeline_blocks)：创建支持多种工作流的流水线。
- [状态](./modular_diffusers_states)：数据在块之间如何共享。

在 [构建自定义块](./custom_blocks) 指南中，学习如何创建具有自定义逻辑的块。

使用 [`ComponentsManager`](./components_manager) 在多个流水线之间共享模型并高效管理内存。

将模块化流水线连接到 [Mellon](https://github.com/cubiq/Mellon)，这是一个用于构建工作流的可视化节点式界面。使用 Modular Diffusers 构建的自定义模块可直接在 Mellon 中运行，无需编写任何 UI 代码。请参阅 Mellon 指南以了解更多信息。

