Diffusers documentation
Быстрый старт
Быстрый старт
Modular Diffusers — это фреймворк для быстрого создания гибких и настраиваемых конвейеров. Такие конвейеры могут выполнять задачи, выходящие за рамки возможностей стандартных DiffusionPipeline. В основе Modular Diffusers лежат ModularPipelineBlocks, которые можно комбинировать с другими блоками для адаптации к новым рабочим процессам. Блоки преобразуются в ModularPipeline — удобный интерфейс для пользователя, предназначенный для выполнения задач генерации.
В этом руководстве показано, как запускать модульный конвейер, понимать его структуру и настраивать его, изменяя блоки, из которых он состоит. Если вы знакомы с DiffusionPipeline, сначала прочитайте Coming from 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").
Подробнее о создании и загрузке конвейеров см. в руководствах Создание конвейера и Загрузка компонентов.
Понимание структуры
ModularPipeline состоит из двух частей: определения (блоки) и состояния (загруженные компоненты и конфигурации).
Выведите конвейер, чтобы увидеть его состояние — компоненты, их статус загрузки и конфигурацию.
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 из нашего исходного конвейера, а не загружает его заново, что позволяет эффективно использовать память. Подробнее в руководстве Загрузка компонентов.
Поскольку блоки комбинируемы, вы можете изменять определение конвейера, добавляя, удаляя или заменяя блоки для создания новых рабочих процессов. В следующем разделе мы добавим блок обнаружения границ Canny в конвейер ControlNet, чтобы вы могли передавать обычное изображение вместо предварительно обработанной карты границ Canny.
Создавайте новые рабочие процессы
Добавим блок canny edge detection в пайплайн ControlNet. Сначала загрузим готовый блок canny с Hub (см. Building Custom Blocks, чтобы создать собственный).
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, чтобы извлечь рабочий процесс ControlNet из QwenImageAutoBlocks.
# 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.
...Извлечённый workflow представляет собой 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.
...Теперь конвейер принимает image в качестве входных данных вместо control_image. Поскольку блоки в последовательности автоматически разделяют данные, выход блока canny (control_image) поступает в блок denoise, которому он необходим, а вход блока canny (image) становится входом конвейера, так как ни один предыдущий блок его не предоставляет.
Создайте конвейер из модифицированных блоков и загрузите модель 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: создание конвейеров, поддерживающих несколько рабочих процессов.
- Состояния: как данные разделяются между блоками.
Узнайте, как создавать собственные блоки с собственной логикой в руководстве Building Custom Blocks.
Используйте ComponentsManager для совместного использования моделей в нескольких конвейерах и эффективного управления памятью.
Подключите модульные конвейеры к Mellon — визуальному интерфейсу на основе узлов для создания рабочих процессов. Пользовательские блоки, созданные с помощью Modular Diffusers, работают с Mellon из коробки — без необходимости писать код для интерфейса. Подробнее в руководстве по Mellon.