WSL2 上にインストールした Stable Diffusion web UI を PHP で作ったデーモンから API で無限画像生成
この記事は2023/06/02に作成されました。
僕は普段 Web 開発の世界に居るので、Stable Diffusion が世に出たときは同じ IT 分野でもなんだか遠い世界の話だと思っていました。
やがて Stable Diffusion web UI というものを知り、試しに動作要件を調べてみたら、僕の相棒である 7 年前に購入したノート PC には VRAM がわずか 2G の GPU が乗っていたことに気が付きました。
Git やターミナルは普段から使用していたのでそこに苦労はしませんでしたが、それでも右往左往しながら初めての画像生成に成功したのが去年(2022)の 10 月頃。そこから楽しくなって、色々な画像を生成してきました。
しかし、2G の VRAM では速度を犠牲にするモードで動作させるしかありません。具体的には 512 × 512 の画像を 30 steps で作るとなると、 1 枚あたり 3 分ほどかかります。もっと現代的な GPU を持っている方からすると、楽しむどころか怒りを感じるような速度かもしれません。
それでもかわいい女の子を生成して、俺だけのミスコンを開催したい個人的に好きなマグリットやベクシンスキーの描いた絵画のような画像を沢山生成して比べてみたい、という欲求もあったため、そのためには夜通し生成を回し続けるしかないと考えました。
とは言え、そうなるとちょっとずつ違ったプロンプトに変える、といった作業も手作業でするわけにはいきません。同じプロンプトなら延々 seed を変えながら生成することができますが、プロンプトを自動で変化させるためには拡張機能を使うのが手っとり早そうでした。
でも拡張機能にはどんなものがあるのか? と、公式のドキュメントを読んでいたら、どうやら Stable Diffusion web UI には HTTP でアクセスする API が備わっており、だいたいの機能は API 越しに操作できることがわかりました。HTTP の API であれば、言語は問わないはずです。
ミスコン開催よりも、 PHPer としての興味が勝った瞬間でした。
今回作ったもの
Stable Diffusion web UI にはたくさんの機能がありますが、今回はシンプルに PHP から txt2img で画像を作るだけのシステムを作ってみました。
ただしプロンプトに変化をつけるため、プロンプトを書いた複数のテキストファイルを特定のディレクトリに置くことでランダムにプロンプトを変化させられるようにしました。
Linux 上のデーモンとして動く PHP が API を叩き続けるため、放っておけば延々と画像が生成されます。
今回は WIndows 上の WSL2 (Ubuntu) で検証・開発をしましたが、おそらく純粋な Linux 上でも動くかと思われます。
管理画面は無く、DB も使用しない代わりに、設定はファイルで行います。
動作要件
以下、ざっくりと動作要件を紹介します。() の中は実際に動作確認した環境情報です。
- OS Linux (Ubuntu 22.04.2 LTS on WSL2)
- PHP (PHP 8.1.2-1ubuntu2.11 (cli) (built: Feb 22 2023 22:56:18) (NTS))
- Stable Diffusion web UI (Commit Hash: 22bcc7be428c94e9408f589966c2040187245d81)
使い方 - 起動まで
まずは Stable Diffusiion web UI を起動するのですが、
set COMMANDLINE_ARGS=
に
--api
を足してから起動してください。これでブラウザの UI に加え、HTTP 越しに API を叩くことができるようになります。また使用するモデルの切り替えや settings タブで行うような設定は通常の Stable Diffusion web UI 画面で行ってください。
次にシステムをこちらからダウンロードし、解凍したものを任意のディレクトリに置いてください。これら PHP のシステムはブラウザからアクセスするわけではないので、/home/ユーザー名 下でも問題ありません。
また、解凍した後にデーモンが PHP を実行できるように、
- run.php
- exec.php
- sdl.sh
- logs
- outputs
には実行権限(x)を追加しておいてください。
この時点で問題がなければ PHP が動くと思うので、ターミナルなどで解凍先のディレクトリに移動し、
php run.php
を実行してみてください。
問題がなければ logs ディレクトリにログが、outputs ディレクトリに画像が自動で作成されるはずです。
最後に /etc/systemd/system に sdl.service というファイルを以下の内容で作成してください。
[Unit]
Description=StableDiffusionLine
[Service]
Type=forking
PIDFile=/run/sdl.pid
ExecStart=解凍先ディレクトリパス/sdl/sdl.sh
Restart=no
[Install]
WantedBy=multi-user.target
設置が終わったら
sudo systemctl start sdl
でデーモンを起動できるかと思います。これで延々と自動で画像が生成されるようになります。停止させる場合は
sudo systemctl stop sdl
で停止できます。
使い方・生成設定
設定は settings ディレクトリの中にあるファイルを編集することで行うことができます。
まず limit.json ですが、このファイルでそもそもファイルを生成するのか、ファイルを生成するのであればいつから & いつまで生成するのかを設定することができます。
- enable: true か false 。false にすると画像を生成しない。
- start: null か 'YYYY-mm-dd HH:ii:ss' 形式の文字列。 null だと無制限。
- end: null か 'YYYY-mm-dd HH:ii:ss' 形式の文字列。 null だと無制限。
txt2img.json では txt2img API を叩く際の設定が行えます。画像の大きさ、ステップ数、サンプラーなどはこのファイルで設定することになります。
- endpoint: txt2img API のエンドポイント設定です。ほとんどの場合変える必要はないと思いますが、ポート部分などを変更した場合はこの設定も合わせて変更する必要があります。
- parameters: そのまま txt2img API に渡す設定となります。詳細は Stable Diffusion web UI 自体の http://127.0.0.1:7860/docs で確認することができます。 prompt, negative_prompt は上書きされます。
prompts ディレクトリには Stable Diffusion web UI に渡すプロンプトを記載したテキストファイルを置きます。
初期状態でいくつかのサンプルファイルが存在しますが、これらサンプルファイルのようにファイル名の先頭は 0 ~ 100 の数値である必要があります。この数値が中に書かれているプロンプトが実際に使われるかどうかの確率(%)となります。先頭の数字以降は拡張子含め自由で、またファイル数の制限もありません。
これらファイル中にプロンプトを書いていくのですが、プロンプトを書く行の最初は「+ 」「- 」(両方とも記号の後に半角スペースあり)のどちらかから始める必要があります。どちらでもない行は無視されます。「+ 」から始めた場合は通常のプロンプト、「- 」から始めた場合はネガティブプロンプトとして作用します。
また、二連続の改行(=空行を一行挟む)を途中に入れた場合はそれを区切りとして、複数のグループとして認識されます。
一つのファイルの中で実際に採用されるのは一グループだけで、それぞれ均等な確率で一つのグループがランダムに選ばれます。
例を挙げると、 80-fruits.txt というファイルがあった場合、 80% の確率で 80-fruits.txt の中に書かれているプロンプトグループのうち一つが採用されます。
中身が
+ banana,melon
- human
+ apple,strawberry
+ mango,grape
- outdoor,forest,field
だったとすれば、
- 33.333333...% の確率で prompt: banana,melon, negative_prompt: human
- 33.333333...% の確率で prompt: apple,strawberry, negative_prompt:
- 33.333333...% の確率で prompt: mango,grape, negative_prompt: outdoor,forest,field
のようなプロンプトが選択されます。
まとめ
このシステム自体は 3 時間くらいでぱっと作ったものですが、平行して管理画面・ビューワー込みのシステムも開発しています。
僕は python もほとんど書いたこともなければ、数学知識や AI の仕組み理解も怪しいエンジニアなのですが、 API という形で機能を提供してくれているおかげでガワの開発のみに注力できています。
ちょっとのプログラミング経験があれば便利なシステムが簡単に作れそうなので、素敵なアイディアがあれば試してみても面白いかもしれません。
プログラマー/N.Go