Diffusers documentation

模块化管道

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.35.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

模块化管道

ModularPipelineModularPipelineBlocks 转换为可执行的管道,加载模型并执行块中定义的计算步骤。它是运行管道的主要接口,与 DiffusionPipeline API 非常相似。

主要区别在于在管道中包含了一个预期的 output 参数。

text-to-image
image-to-image
inpainting
import torch
from diffusers.modular_pipelines import SequentialPipelineBlocks
from diffusers.modular_pipelines.stable_diffusion_xl import TEXT2IMAGE_BLOCKS

blocks = SequentialPipelineBlocks.from_blocks_dict(TEXT2IMAGE_BLOCKS)

modular_repo_id = "YiYiXu/modular-loader-t2i-0704"
pipeline = blocks.init_pipeline(modular_repo_id)

pipeline.load_default_components(torch_dtype=torch.float16)
pipeline.to("cuda")

image = pipeline(prompt="Astronaut in a jungle, cold color palette, muted colors, detailed, 8k", output="images")[0]
image.save("modular_t2i_out.png")

本指南将向您展示如何创建一个ModularPipeline并管理其中的组件。

添加块

块是InsertableDict对象,可以在特定位置插入,提供了一种灵活的方式来混合和匹配块。

使用insert()在块类或sub_blocks属性上添加一个块。

# BLOCKS是块类的字典,您需要向其中添加类
BLOCKS.insert("block_name", BlockClass, index)
# sub_blocks属性包含实例,向该属性添加一个块实例
t2i_blocks.sub_blocks.insert("block_name", block_instance, index)

使用pop()在块类或sub_blocks属性上移除一个块。

# 从预设中移除一个块类
BLOCKS.pop("text_encoder")
# 分离出一个块实例
text_encoder_block = t2i_blocks.sub_blocks.pop("text_encoder")

通过将现有块设置为新块来交换块。

# 在预设中替换块类
BLOCKS["prepare_latents"] = CustomPrepareLatents
# 使用块实例在sub_blocks属性中替换
t2i_blocks.sub_blocks["prepare_latents"] = CustomPrepareLatents()

创建管道

有两种方法可以创建一个ModularPipeline。从ModularPipelineBlocks组装并创建管道,或使用from_pretrained()加载现有管道。

您还应该初始化一个ComponentsManager来处理设备放置和内存以及组件管理。

有关它如何帮助管理不同工作流中的组件的更多详细信息,请参阅ComponentsManager文档。

ModularPipelineBlocks
from_pretrained

使用init_pipeline()方法从组件和配置规范创建一个ModularPipeline。此方法从modular_model_index.json文件加载规范,但尚未加载模型

from diffusers import ComponentsManager
from diffusers.modular_pipelines import SequentialPipelineBlocks
from diffusers.modular_pipelines.stable_diffusion_xl import TEXT2IMAGE_BLOCKS

t2i_blocks = SequentialPipelineBlocks.from_blocks_dict(TEXT2IMAGE_BLOCKS)

modular_repo_id = "YiYiXu/modular-loader-t2i-0704"
components = ComponentsManager()
t2i_pipeline = t2i_blocks.init_pipeline(modular_repo_id, components_manager=components)

加载组件

一个ModularPipeline不会自动实例化组件。它只加载配置和组件规范。您可以使用load_default_components()加载所有组件,或仅使用load_components()加载特定组件。

load_default_components
load_components
import torch

t2i_pipeline.load_default_components(torch_dtype=torch.float16)
t2i_pipeline.to("cuda")

打印管道以检查加载的预训练组件。

t2i_pipeline

这应该与管道初始化自的模块化仓库中的modular_model_index.json文件匹配。如果管道不需要某个组件,即使它在模块化仓库中存在,也不会被包含。

要修改组件加载的来源,编辑仓库中的modular_model_index.json文件,并将其更改为您希望的加载路径。下面的例子从不同的仓库加载UNet。

# 原始
"unet": [
  null, null,
  {
    "repo": "stabilityai/stable-diffusion-xl-base-1.0",
    "subfolder": "unet",
    "variant": "fp16"
  }
]

# 修改后
"unet": [
  null, null,
  {
    "repo": "RunDiffusion/Juggernaut-XL-v9",
    "subfolder": "unet",
    "variant": "fp16"
  }
]

组件加载状态

下面的管道属性提供了关于哪些组件被加载的更多信息。

使用component_names返回所有预期的组件。

t2i_pipeline.component_names
['text_encoder', 'text_encoder_2', 'tokenizer', 'tokenizer_2', 'guider', 'scheduler', 'unet', 'vae', 'image_processor']

使用null_component_names返回尚未加载的组件。使用from_pretrained()加载这些组件。

t2i_pipeline.null_component_names
['text_encoder', 'text_encoder_2', 'tokenizer', 'tokenizer_2', 'scheduler']

使用pretrained_component_names返回将从预训练模型加载的组件。

t2i_pipeline.pretrained_component_names
['text_encoder', 'text_encoder_2', 'tokenizer', 'tokenizer_2', 'scheduler', 'unet', 'vae']

使用 config_component_names 返回那些使用默认配置创建的组件(不是从模块化仓库加载的)。来自配置的组件不包括在内,因为它们已经在管道创建期间初始化。这就是为什么它们没有列在 null_component_names 中。

t2i_pipeline.config_component_names
['guider', 'image_processor']

更新组件

根据组件是预训练组件还是配置组件,组件可能会被更新。

在更新组件时,组件可能会从预训练变为配置。组件类型最初是在块的 expected_components 字段中定义的。

预训练组件通过 ComponentSpec 更新,而配置组件则通过直接传递对象或使用 ComponentSpec 更新。

ComponentSpec 对于预训练组件显示 default_creation_method="from_pretrained",对于配置组件显示 default_creation_method="from_config

要更新预训练组件,创建一个 ComponentSpec,指定组件的名称和从哪里加载它。使用 load() 方法来加载组件。

from diffusers import ComponentSpec, UNet2DConditionModel

unet_spec = ComponentSpec(name="unet",type_hint=UNet2DConditionModel, repo="stabilityai/stable-diffusion-xl-base-1.0", subfolder="unet", variant="fp16")
unet = unet_spec.load(torch_dtype=torch.float16)

update_components() 方法用一个新的组件替换原来的组件。

t2i_pipeline.update_components(unet=unet2)

当组件被更新时,加载规范也会在管道配置中更新。

组件提取和修改

当你使用 load() 时,新组件保持其加载规范。这使得提取规范并重新创建组件成为可能。

spec = ComponentSpec.from_component("unet", unet2)
spec
ComponentSpec(name='unet', type_hint=<class 'diffusers.models.unets.unet_2d_condition.UNet2DConditionModel'>, description=None, config=None, repo='stabilityai/stable-diffusion-xl-base-1.0', subfolder='unet', variant='fp16', revision=None, default_creation_method='from_pretrained')
unet2_recreated = spec.load(torch_dtype=torch.float16)

get_component_spec() 方法获取当前组件规范的副本以进行修改或更新。

unet_spec = t2i_pipeline.get_component_spec("unet")
unet_spec
ComponentSpec(
    name='unet',
    type_hint=<class 'diffusers.models.unets.unet_2d_condition.UNet2DConditionModel'>,
    repo='RunDiffusion/Juggernaut-XL-v9',
    subfolder='unet',
    variant='fp16',
    default_creation_method='from_pretrained'
)

# 修改以从不同的仓库加载
unet_spec.repo = "stabilityai/stable-diffusion-xl-base-1.0"

# 使用修改后的规范加载组件
unet = unet_spec.load(torch_dtype=torch.float16)

模块化仓库

一个仓库 如果管道块使用预训练组件,则需要y。该存储库提供了加载规范和元数据。

ModularPipeline特别需要模块化存储库(参见示例存储库),这比典型的存储库更灵活。它包含一个modular_model_index.json文件,包含以下3个元素。

  • libraryclass显示组件是从哪个库加载的及其类。如果是null,则表示组件尚未加载。
  • loading_specs_dict包含加载组件所需的信息,例如从中加载的存储库和子文件夹。

与标准存储库不同,模块化存储库可以根据loading_specs_dict从不同的存储库获取组件。组件不需要存在于同一个存储库中。

模块化存储库可能包含用于加载ModularPipeline的自定义代码。这允许您使用不是Diffusers原生的专用块。

modular-diffdiff-0704/
├── block.py                    # 自定义管道块实现
├── config.json                 # 管道配置和auto_map
└── modular_model_index.json    # 组件加载规范

config.json文件包含一个auto_map键,指向block.py中定义自定义块的位置。

{
  "_class_name": "DiffDiffBlocks",
  "auto_map": {
    "ModularPipelineBlocks": "block.DiffDiffBlocks"
  }
}
< > Update on GitHub