Hugging Face diffusers の GitHub リポジトリを Git Clone して FLUX.1 [schnell] をデバッグ実行

1. 概要

2025年12月21日(日)に開催予定の第10回 岐阜AI勉強会のため、Black Forest Labs の FLUX.1 [schnell]を動かしました。今回は Google Colab PRO で A100 GPU を選択して実行しました。

コードの処理内容の調査を目的として、Hugging Face のdiffusers の GitHub リポジトリを Git Clone してデバッガでステップ実行する手順を試しました。

2. ブレイクポイントをセットしてデバッグ実行
2.1. Google Drive に Hugging Face の diffusers の GitHub リポジトリを Git Clone

Google Drive for Desktop を Windows にインストールし、Windows にインストールした Git Bash で下記のコマンドを実行しました。G ドライブの「マイドライブ」フォルダに diffusers の GitHub リポジトリを Git Clone しています。

$ cd /g/マイドライブ/
$ git clone https://github.com/huggingface/diffusers.git

上記のコマンドを実行すると、Google Drive 側からは /content/drive/MyDrive/diffusers/src で diffusers の Python スクリプトを参照できます。

2.2. diffusers のソースコードにブレイクポイントをセット

Google Colab でも利用可能な ipdb を使用してデバッグ実行しました。Windows 側で diffusers の Python スクリプトを開き、ブレイクポイントをセットしたい箇所に下記の行を追加します。

import ipdb; ipdb.set_trace()

下記のスクリプトの FluxTransformer2DModel の forward メソッドの先頭に

src/diffusers/models/transformers/transformer_flux.py

下記のようにブレイクポイントをセットして試しました。

             If `return_dict` is True, an [`~models.transformer_2d.Transformer2DModelOutput`] is returned, otherwise a
             `tuple` where the first element is the sample tensor.
         """
+        import ipdb; ipdb.set_trace()
+        
         if joint_attention_kwargs is not None:
             joint_attention_kwargs = joint_attention_kwargs.copy()
             lora_scale = joint_attention_kwargs.pop("scale", 1.0)
2.3. FLUX.1 [schnell] による画像生成を実行し、ブレイクポイントで停止させる

こちらのリンク先に用意した Google Colab のページの下記のコードセルを順に実行します。

2.3.1. Google Drive のマウント

Google Drive をマウントします。

from google.colab import drive
drive.mount('/content/drive')
2.3.2. git clone した diffusers のソースコードの優先参照

git clone した diffusers のソースコードを優先して参照するようにします。

import sys
sys.path.insert(0, "/content/drive/MyDrive/diffusers/src")
2.3.3. git clone した diffusers のソースコードが実行されることの確認

pip 等でインストールされたコードではなく、git clone した diffusers のソースコードが実行されることを確認します。

import diffusers
print(diffusers.__file__)

git clone した diffusers のソースコードが参照されていれば下記のように出力されます。

/content/drive/MyDrive/diffusers/src/diffusers/__init__.py
2.3.4. diffusers を使用して FLUX.1 [schnell] を実行する際に必要なパッケージのインストール

下記のコードセルを実行し、diffusers を使用して FLUX.1 [schnell] を実行する際に必要なパッケージをインストールします。

!pip install torch torchvision torchaudio
!pip install transformers accelerate safetensors
!pip install sentencepiece protobuf einops
2.3.5. Python デバッガ ipdb をインストール
!pip install ipdb
2.3.6. FLUX.1 [schnell] を使用した Pipeline を用意
import torch
from diffusers import FluxPipeline

pipe = FluxPipeline.from_pretrained(
    "black-forest-labs/FLUX.1-schnell",
    torch_dtype=torch.float16
).to("cuda")
2.3.7. FLUX.1 [schnell] を使用して画像を生成

FLUX.1 [schnell] は 4 step で画像を生成できるため、num_inference_steps=4 のようにステップ数 4 を指定しています。

prompt = 'The phrase "Gifu AI Study Group" formed from small colorful geometric shapes.'

image = pipe(
    prompt,
    guidance_scale=0.0,
    num_inference_steps=4,
    max_sequence_length=256
).images[0]

image.save("Gifu-AI-study-group.png")
2.4. ipdb によるステップ実行

上記 2.3.7. のコードセルを実行すると上記 2.2. でセットしたブレイクポイントにヒットします。

下記のように表示されるので Google Colab 上で ipdb> の後に c (continue) と入力して Enter キーを押します。c と入力して Enter キーを押す操作を 4 回繰り返すとコードセルが最後まで実行されて画像が生成されます。

> /content/drive/MyDrive/diffusers/src/diffusers/models/transformers/transformer_flux.py(680)forward()
    679 
--> 680         if joint_attention_kwargs is not None:
    681             joint_attention_kwargs = joint_attention_kwargs.copy()

ipdb> c

もう一度同じコードセルを実行すると、また上記の箇所でブレイクポイントにヒットします。c と入力して Enter キーを押す操作を 3 回繰り返し、画像生成の直前まで処理を進めます。

ここで Google Colab 上で ipdb> の後に w (where) と入力して Enter キーを押すと下記のようにスタックトレースが表示されます。

ipdb> w
    [... skipping 21 hidden frame(s)]

  /tmp/ipython-input-3053860109.py(8)<cell line: 0>()
      7 prompt = "A cat holding a sign that says hello world"
----> 8 image = pipe(
      9     prompt,

  /usr/local/lib/python3.12/dist-packages/torch/utils/_contextlib.py(120)decorate_context()
    119         with ctx_factory():
--> 120             return func(*args, **kwargs)
    121 

  /content/drive/MyDrive/diffusers/src/diffusers/pipelines/flux/pipeline_flux.py(944)__call__()
    943                 with self.transformer.cache_context("cond"):
--> 944                     noise_pred = self.transformer(
    945                         hidden_states=latents,

  /usr/local/lib/python3.12/dist-packages/torch/nn/modules/module.py(1775)_wrapped_call_impl()
   1774         else:
-> 1775             return self._call_impl(*args, **kwargs)
   1776 

  /usr/local/lib/python3.12/dist-packages/torch/nn/modules/module.py(1786)_call_impl()
   1785                 or _global_forward_hooks or _global_forward_pre_hooks):
-> 1786             return forward_call(*args, **kwargs)
   1787 

  /usr/local/lib/python3.12/dist-packages/accelerate/hooks.py(175)new_forward()
    174         else:
--> 175             output = module._old_forward(*args, **kwargs)
    176         return module._hf_hook.post_forward(module, output)

> /content/drive/MyDrive/diffusers/src/diffusers/models/transformers/transformer_flux.py(680)forward()
    679 
--> 680         if joint_attention_kwargs is not None:
    681             joint_attention_kwargs = joint_attention_kwargs.copy()

Google Colab 上で ipdb> の後に u (up) と入力すると呼び出し元フレームへ移動します。u と入力して Enter を押す操作を 4 回繰り返すと pipeline_flux.py の下記の呼び出し元に移動します。

ipdb> u
    ...

ipdb> u
    ...

ipdb> u
    ...

ipdb> u
> /content/drive/MyDrive/diffusers/src/diffusers/pipelines/flux/pipeline_flux.py(944)__call__()
    943                 with self.transformer.cache_context("cond"):
--> 944                     noise_pred = self.transformer(
    945                         hidden_states=latents,

Google Colab 上で ipdb> の後に n (next) と入力すると関数の中に入らないで次の行へ進みます。n と入力して Enter を押す操作を何回か繰り返し、pipeline_flux.py の下記の行まで実行します。

ipdb> n
    ...

ipdb> n
    ...

ipdb> n
> /content/drive/MyDrive/diffusers/src/diffusers/pipelines/flux/pipeline_flux.py(1004)__call__()
   1003         else:
-> 1004             latents = self._unpack_latents(latents, height, width, self.vae_scale_factor)
   1005             latents = (latents / self.vae.config.scaling_factor) + self.vae.config.shift_factor

下記の例のように Google Colab 上で ipdb> の後に p latents と入力すると latents の内容が表示されます。p は print です。また、p latents.shape と入力すると多次元配列 (tensor) の各軸のサイズが表示されます。

ipdb> p latents
tensor([[[ 1.0859,  0.1621,  0.1572,  ..., -1.6406, -2.0781, -1.8125],
         [ 0.2773,  0.2148, -0.4512,  ..., -1.7500, -2.1250, -2.0000],
         [ 0.2441,  0.2598, -0.1777,  ..., -1.7344, -2.0000, -1.9922],
         ...,
         [-0.4922, -0.0186, -0.0430,  ..., -1.5938, -1.7500, -1.3125],
         [ 0.4531, -0.0596, -0.1523,  ..., -2.0000, -1.6406, -1.4688],
         [-0.4102, -0.4062, -0.0442,  ..., -1.7578, -1.3906, -1.3438]]],
       device='cuda:0', dtype=torch.bfloat16)
ipdb> p latents.shape
torch.Size([1, 4096, 64])

下記の例は、Google Colab 上で ipdb> の後に n と入力し、次の行まで実行を進めてから更新された latents と image の各軸のサイズを表示する操作を繰り返した例になります。

ipdb> n
> /content/drive/MyDrive/diffusers/src/diffusers/pipelines/flux/pipeline_flux.py(1005)__call__()
   1004             latents = self._unpack_latents(latents, height, width, self.vae_scale_factor)
-> 1005             latents = (latents / self.vae.config.scaling_factor) + self.vae.config.shift_factor
   1006             image = self.vae.decode(latents, return_dict=False)[0]

ipdb> p latents.shape
torch.Size([1, 16, 128, 128])
ipdb> n
> /content/drive/MyDrive/diffusers/src/diffusers/pipelines/flux/pipeline_flux.py(1006)__call__()
   1005             latents = (latents / self.vae.config.scaling_factor) + self.vae.config.shift_factor
-> 1006             image = self.vae.decode(latents, return_dict=False)[0]
   1007             image = self.image_processor.postprocess(image, output_type=output_type)

ipdb> p latents.shape
torch.Size([1, 16, 128, 128])
ipdb> n
> /content/drive/MyDrive/diffusers/src/diffusers/pipelines/flux/pipeline_flux.py(1007)__call__()
   1006             image = self.vae.decode(latents, return_dict=False)[0]
-> 1007             image = self.image_processor.postprocess(image, output_type=output_type)
   1008 

ipdb> p image.shape
torch.Size([1, 3, 1024, 1024])

下の表は ipdb 及び pdb でよく使用されるコマンドをまとめた表になります。

実行制御系
省略形 正式名 意味
c continue 次のブレークポイントまで実行
n next 次の行へ進む(関数には入らない)
s step 次の行へ進む(関数に入る)
省略形なし until 指定行まで実行
r return 現在の関数から戻るまで実行
q quit デバッガを終了
スタック・位置確認系
省略形 正式名 意味
w where スタックトレース(コールスタック)を表示
u up 呼び出し元のスタックフレームへ移動
d down 呼び出し先のスタックフレームへ移動
表示・確認系
省略形 正式名 意味
l list 周辺のソースコードを表示
p print 変数を表示
pp pretty print 変数を整形して表示
a args 現在の関数の引数を表示
whatis whatis 変数の型を表示

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA