Diffusers documentation

クイックスタート

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に精通している場合は、動作の違いについて理解するために、まず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ガイドを参照してください。

オフローディングが不要な場合は、components_manager 引数を削除し、to("cuda") を使用してパイプラインを手動でデバイスに移動してください。

パイプラインの作成およびコンポーネントの読み込みのガイドで、パイプラインの作成と読み込みについて詳しく学んでください。

構造を理解する

ModularPipeline は2つの部分から構成されています。定義(ブロック)と、状態(読み込まれたコンポーネントと設定)です。

パイプラインを出力して、その状態を確認します。コンポーネントとその読み込みステータス、設定が表示されます。

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 で構成されています。

これらのサブブロックは順次実行され、データは1つのブロックから次のブロックへ直線的に流れます。各ブロックの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を再読み込みせずに再利用することで、メモリ使用量を効率的に保ちます。詳細はコンポーネントの読み込みガイドを参照してください。

ブロックは合成可能であるため、ブロックの追加、削除、または交換によってパイプラインの定義を変更し、新しいワークフローを作成できます。次のセクションでは、ControlNet パイプラインに canny 辺検出ブロックを追加します。これにより、事前処理済みの canny 辺マップの代わりに通常の画像を渡すことができます。

新しいワークフローを構築

ControlNet パイプラインに canny エッジ検出ブロックを追加しましょう。まず、Hub から事前構築済みの canny ブロックを読み込みます(独自のブロックを作成するには、カスタムブロックの構築を参照してください)。

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 を使用して、QwenImageAutoBlocks から ControlNet ワークフローを抽出します。

# 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.
      ...

抽出されたワークフローは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.
      ...

これにより、パイプラインはcontrol_imageではなく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