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

组件管理器

ComponentsManager 是 Modular Diffusers 的模型注册和管理系统。它添加和跟踪模型,存储有用的元数据(模型大小、设备放置、适配器),防止重复模型实例,并支持卸载。

本指南将展示如何使用 ComponentsManager 来管理组件和设备内存。

添加组件

ComponentsManager 应与 ModularPipeline 一起创建,在 from_pretrained()init_pipeline() 中。

collection 参数是可选的,但可以更轻松地组织和管理组件。

from_pretrained
init_pipeline
from diffusers import ModularPipeline, ComponentsManager

comp = ComponentsManager()
pipe = ModularPipeline.from_pretrained("YiYiXu/modular-demo-auto", components_manager=comp, collection="test1")

组件仅在调用 load_components()load_default_components() 时加载和注册。以下示例使用 load_default_components() 创建第二个管道,重用第一个管道的所有组件,并将其分配到不同的集合。

pipe.load_default_components()
pipe2 = ModularPipeline.from_pretrained("YiYiXu/modular-demo-auto", components_manager=comp, collection="test2")

使用 null_component_names 属性来识别需要加载的任何组件,使用 get_components_by_names() 检索它们,然后调用 update_components() 来添加缺失的组件。

pipe2.null_component_names 
['text_encoder', 'text_encoder_2', 'tokenizer', 'tokenizer_2', 'image_encoder', 'unet', 'vae', 'scheduler', 'controlnet']

comp_dict = comp.get_components_by_names(names=pipe2.null_component_names)
pipe2.update_components(**comp_dict)

要添加单个组件,请使用 add() 方法。这会使用唯一 id 注册一个组件。

from diffusers import AutoModel

text_encoder = AutoModel.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0", subfolder="text_encoder")
component_id = comp.add("text_encoder", text_encoder)
comp

使用 remove() 通过其 id 移除一个组件。

comp.remove("text_encoder_139917733042864")

检索组件

ComponentsManager 提供了几种方法来检索已注册的组件。

get_one

get_one() 方法返回单个组件,并支持对 name 参数进行模式匹配。如果多个组件匹配,get_one() 会返回错误。

模式 示例 描述
exact comp.get_one(name="unet") 精确名称匹配
wildcard comp.get_one(name="unet*") 名称以 “unet” 开头
exclusion comp.get_one(name="!unet") 排除名为 “unet” 的组件
or comp.get_one(name="unet|vae") 名称为 “unet” 或 “vae”

get_one() 还通过 collection 参数或 load_id 参数过滤组件。

comp.get_one(name="unet", collection="sdxl")

get_components_by_names

get_components_by_names() 方法接受一个名称列表,并返回一个将名称映射到组件的字典。这在 ModularPipeline 中特别有用,因为它们提供了所需组件名称的列表,并且返回的字典可以直接传递给 update_components()

component_dict = comp.get_components_by_names(names=["text_encoder", "unet", "vae"])
{"text_encoder": component1, "unet": component2, "vae": component3}

重复检测

建议使用 ComponentSpec 加载模型组件,以分配具有唯一 id 的组件,该 id 编码了它们的加载参数。这允许 ComponentsManager 自动检测并防止重复的模型实例,即使不同的对象代表相同的底层检查点。

from diffusers import ComponentSpec, ComponentsManager
from transformers import CLIPTextModel

comp = ComponentsManager()

# 为第一个文本编码器创建 ComponentSpec
spec = ComponentSpec(name="text_encoder", repo="stabilityai/stable-diffusion-xl-base-1.0", subfolder="text_encoder", type_hint=AutoModel)
# 为重复的文本编码器创建 ComponentSpec(它是相同的检查点,来自相同的仓库/子文件夹)
spec_duplicated = ComponentSpec(name="text_encoder_duplicated", repo="stabilityai/stable-diffusion-xl-base-1.0", subfolder="text_encoder", ty
pe_hint=CLIPTextModel)

# 加载并添加两个组件 - 管理器会检测到它们是同一个模型
comp.add("text_encoder", spec.load())
comp.add("text_encoder_duplicated", spec_duplicated.load())

这会返回一个警告,附带移除重复项的说明。

ComponentsManager: adding component 'text_encoder_duplicated_139917580682672', but it has duplicate load_id 'stabilityai/stable-diffusion-xl-base-1.0|text_encoder|null|null' with existing components: text_encoder_139918506246832. To remove a duplicate, call `components_manager.remove('<component_id>')`.
'text_encoder_duplicated_139917580682672'

您也可以不使用 ComponentSpec 添加组件,并且在大多数情况下,即使您以不同名称添加相同组件,重复检测仍然有效。

然而,当您将相同组件加载到不同对象时,ComponentManager 无法检测重复项。在这种情况下,您应该使用 ComponentSpec 加载模型。

text_encoder_2 = AutoModel.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0", subfolder="text_encoder")
comp.add("text_encoder", text_encoder_2)
'text_encoder_139917732983664'

集合

集合是为组件分配的标签,用于更好的组织和管理。使用 add() 中的 collection 参数将组件添加到集合中。

每个集合中只允许每个名称有一个组件。添加第二个同名组件会自动移除第一个组件。

from diffusers import ComponentSpec, ComponentsManager

comp = ComponentsManager()
# 为第一个 UNet 创建 ComponentSpec
spec = ComponentSpec(name="unet", repo="stabilityai/stable-diffusion-xl-base-1.0", subfolder="unet", type_hint=AutoModel)
# 为另一个 UNet 创建 ComponentSpec
spec2 = ComponentSpec(name="unet", repo="RunDiffusion/Juggernaut-XL-v9", subfolder="unet", type_hint=AutoModel, variant="fp16")

# 将两个 UNet 添加到同一个集合 - 第二个将替换第一个
comp.add("unet", spec.load(), collection="sdxl")
comp.add("unet", spec2.load(), collection="sdxl")

这使得在基于节点的系统中工作变得方便,因为您可以:

  • 使用 collection 标签标记所有从一个节点加载的模型。
  • 当新检查点以相同名称加载时自动替换模型。
  • 当节点被移除时批量删除集合中的所有模型。

卸载

enable_auto_cpu_offload() 方法是一种全局卸载策略,适用于所有模型,无论哪个管道在使用它们。一旦启用,您无需担心设备放置,如果您添加或移除组件。

comp.enable_auto_cpu_offload(device="cuda")

所有模型开始时都在 CPU 上,ComponentsManager 在需要它们之前将它们移动到适当的设备,并在 GPU 内存不足时将其他模型移回 CPU。

您可以设置自己的规则来决定哪些模型要卸载。

< > Update on GitHub