Diffusers documentation
快速入门
快速入门
Modular Diffusers 是一个用于快速构建灵活且可定制流水线的框架。这些流水线能够超越标准 DiffusionPipeline 的功能。Modular Diffusers 的核心是 ModularPipelineBlocks,它们可以与其他块组合,以适应新的工作流。这些块会被转换为 ModularPipeline,这是一个面向用户的友好接口,用于运行生成任务。
本指南将向您展示如何运行模块化流水线、理解其结构,并通过修改组成流水线的各个模块来进行自定义。如果您熟悉 DiffusionPipeline,请先阅读 来自 DiffusionPipeline,以了解其中的差异。
运行流水线
ModularPipeline 是用于加载、运行和管理模块化流水线的主要接口。
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]
imagefrom_pretrained() 采用延迟加载机制——它会读取配置以了解各组件的加载来源,但直到你调用 load_components() 时才会实际加载模型权重。这让你能够控制组件的加载时机和方式。
ComponentsManager配合enable_auto_cpu_offload可自动在 CPU 和 GPU 之间移动模型,从而降低 Qwen-Image 等大型模型的内存占用。详情请参阅 ComponentsManager 指南。如果不需要 offloading,请移除
components_manager参数,并使用to("cuda")手动将 pipeline 移动到目标设备上。
有关创建和加载管道的更多信息,请参阅创建管道和加载组件指南。
理解结构
ModularPipeline 由两部分组成:定义(即各个 block)和 状态(即已加载的组件和配置)。
打印 pipeline 以查看其状态——包括各组件及其加载状态和配置。
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,用于定义流水线的工作流、输入、输出和计算逻辑。
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 指南。
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 以查看所有可用的工作流。
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 就是这样工作的。
您可以通过 sub_blocks 属性访问它们。doc 属性可用于查看任何块的完整文档,包括其输入、输出和组件。
vae_encoder_block = pipe.blocks.sub_blocks["vae_encoder"]
print(vae_encoder_block.doc)此代码块可以转换为流水线,从而能够通过 init_pipeline() 独立运行。
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,而不是重新加载,从而保持内存使用效率。有关详细信息,请参阅 加载组件 指南。
由于块是可组合的,你可以通过添加、删除或替换块来修改流水线的定义,从而创建新的工作流。在下一节中,我们将向 ControlNet 流水线添加一个 canny 边缘检测块,这样你就可以传入一张普通图像,而不是一张预先处理好的 canny 边缘图。
组合新的工作流
让我们向 ControlNet 流水线中添加一个 canny 边缘检测块。首先,从 Hub 加载一个预构建的 canny 块(参见 构建自定义块 以创建您自己的块)。
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 工作流。
# 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,目前它需要 control_image 作为输入。请在开头插入 canny 块,以便该流水线能够接受普通图像作为输入。
# 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() 将其添加进去。
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 对图像进行预处理。
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:用于定义流水线中一个步骤的基本单元。
- SequentialPipelineBlocks:将多个块串联起来,按顺序执行。
- AutoPipelineBlocks:创建支持多种工作流的流水线。
- 状态:数据在块之间如何共享。
在 构建自定义块 指南中,学习如何创建具有自定义逻辑的块。
使用 ComponentsManager 在多个流水线之间共享模型并高效管理内存。
将模块化流水线连接到 Mellon,这是一个用于构建工作流的可视化节点式界面。使用 Modular Diffusers 构建的自定义模块可直接在 Mellon 中运行,无需编写任何 UI 代码。请参阅 Mellon 指南以了解更多信息。