16
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ElixirAdvent Calendar 2022

Day 20

Elixir Bumblebee のStable Diffusionを Docker 上の Livebook で動かして画像生成してみた

Last updated at Posted at 2022-12-12

はじめに

@the_haigo さんの記事を参考に Docker 上で動かした記事です

Bumblebee を使うと、 Stable Diffusion を使った画像生成が Elixir で超簡単に実装できます

他にも Bumblebee でできることを一通りやってみました

このシリーズの記事

実装の全文はこちら

実行環境

  • MacBook Pro 13 inchi
    • 2.4 GHz クアッドコアIntel Core i5
    • 16 GB 2133 MHz LPDDR3
  • macOS Ventura 13.0.1
  • Rancher Desktop 1.6.2
    • メモリ割り当て 12 GB
    • CPU 割り当て 6 コア

Livebook 0.8.0 の Docker イメージを元にしたコンテナで動かしました

コンテナ定義はこちらを参照

セットアップ

必要なモジュールをインストールし、 Nx のバックエンドを EXLA.Backend に指定します

Mix.install(
  [
    {:bumblebee, "~> 0.1"},
    {:nx, "~> 0.4"},
    {:exla, "~> 0.4"},
    {:kino, "~> 0.8"}
  ],
  config: [nx: [default_backend: EXLA.Backend]]
)

設定

Nx バックエンドを確認します

Nx.default_backend()

スクリーンショット 2022-12-12 16.19.17.png

ちゃんと EXLA.Backend になっています

Stable Diffusion モデルのダウンロード元リポジトリーを指定します

repository_id = "CompVis/stable-diffusion-v1-4"

このように指定すると、以下の Hugging Face のリポジトリーからダウンロードしてきます

モデルファイルのキャッシュ用ディレクトリーを指定します

ここは Docker ならではの設定です(詳細は以下の注釈参照)

cache_dir = "/tmp/bumblebee_cache"

私の用意した実行環境だと docker-compose.yml で以下のように設定しています

...
    volumes:
      - ./tmp:/tmp

つまりローカルの ./tmp をコンテナ上の /tmp にマウントしています

この状態で Bumblebee のモデルロードを動かすと、まずコンテナ上の /tmp にモデルファイルをダウンロードします

キャッシュディレクトリーを指定していない場合、ダウンロード完了後、 ~/.cache 配下にダウンロードしたファイルを移動しようとします

このとき、 /tmp は macOS のファイルシステムで、 ~/.cache は Linux のファイルシステムになっている関係で、以下のようなエラーが発生します

could not rename ~ cross-domain link ~

これは Elixir に限らず Docker 上だと度々発生する現象です

ファイルシステムが同じ /tmp 内であればコピー可能なので、キャッシュディレクトリーを /tmp/bumblebee_cache に指定しておきます

また、こうすることでコンテナをビルドし直してもキャッシュがローカルに残るため、ダウンロードし直さなくて良くなります

モデルのダウンロード

以下のコードを逐次実行して Hugging Face からモデルファイルをダウンロードし、読み込みます

{:ok, tokenizer} =
  Bumblebee.load_tokenizer({
    :hf,
    "openai/clip-vit-large-patch14",
    cache_dir: cache_dir
  })
{:ok, clip} =
  Bumblebee.load_model({
    :hf,
    repository_id,
    subdir: "text_encoder", cache_dir: cache_dir
  })
{:ok, unet} =
  Bumblebee.load_model(
    {
      :hf,
      repository_id,
      subdir: "unet", cache_dir: cache_dir
    },
    params_filename: "diffusion_pytorch_model.bin"
  )
{:ok, vae} =
  Bumblebee.load_model(
    {
      :hf,
      repository_id,
      subdir: "vae", cache_dir: cache_dir
    },
    architecture: :decoder,
    params_filename: "diffusion_pytorch_model.bin"
  )
{:ok, scheduler} =
  Bumblebee.load_scheduler({
    :hf,
    repository_id,
    subdir: "scheduler", cache_dir: cache_dir
  })
{:ok, featurizer} =
  Bumblebee.load_featurizer({
    :hf,
    repository_id,
    subdir: "feature_extractor", cache_dir: cache_dir
  })
{:ok, safety_checker} =
  Bumblebee.load_model({
    :hf,
    repository_id,
    subdir: "safety_checker", cache_dir: cache_dir
  })

初回は以下のような進行状況が表示されて 100% になればダウンロード終了です

|=============================================================| 100% (334.70 MB)

2回目以降はキャッシュが読まれるので、モデルファイルのロードだけが実行されます

ちなみにモデルファイルは合計 5.48 GB あるので、ストレージの空き容量には気をつけましょう

画像生成の実行

Nx 0.4.1 で追加された Nx.Serving を利用して、画像生成サービスを提供します

serving =
  Bumblebee.Diffusion.StableDiffusion.text_to_image(
    clip,
    unet,
    vae,
    tokenizer,
    scheduler,
    num_steps: 20,
    num_images_per_prompt: 2,
    safety_checker: safety_checker,
    safety_checker_featurizer: featurizer,
    compile: [batch_size: 1, sequence_length: 60],
    defn_options: [compiler: EXLA]
  )

画像生成の元となるプロンプトの入力エリアを作ります

prompt_input = Kino.Input.text("PROMPT")

スクリーンショット 2022-12-12 16.50.43.png

今回は以下のような文言を入れてみました

Cartoon of a blue raccoon-like robot pulling futuristic tools out of its pockets.

画像生成サービスにプロンプトを渡して実行します

※私の M1 ではない MacBook では10分以上かかります

output = Nx.Serving.run(serving, Kino.Input.read(prompt_input))

実行結果を表示します

output.results
|> Enum.map(fn result ->
  Kino.Image.new(result.image)
end)
|> Kino.Layout.grid(columns: 2)

スクリーンショット 2022-12-12 17.18.33.png

まとめ

コンテナ特有の気をつけるべき点はありますが、 Docker 上で実行できました

16
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?