Diffusers documentation
模块化管道
模块化管道
ModularPipeline
将 ModularPipelineBlocks
转换为可执行的管道,加载模型并执行块中定义的计算步骤。它是运行管道的主要接口,与 DiffusionPipeline
API 非常相似。
主要区别在于在管道中包含了一个预期的 output
参数。
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文档。
使用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()
加载特定组件。
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个元素。
library
和class
显示组件是从哪个库加载的及其类。如果是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"
}
}