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.42.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Быстрый старт

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]
image

from_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: создание конвейеров, поддерживающих несколько рабочих процессов.
  • Состояния: как данные разделяются между блоками.
Update on GitHub