Stable Diffusionのimg2imgを使ったサービスが人気がありそうなので作ってみる。
ゴール
顔画像をポストして似顔絵イラストが複数枚返ってくるAPIを作る。
画像生成に時間がかかるようなら、tokenを返して、そのtokenを使用して生成された画像にアクセスできるようにする。
GCPの環境構築
GCPでプロジェクトの作成
プロジェクト一覧から新しいプロジェクトを選択して適当に名前をつけて作成する
gcloudコマンドが使えるようにする
gcloud CLI をインストールする | Google Cloud
Deep Learning VMの作成
結構大変。デフォルト設定のままぽちぽち進めると、「 GPU グローバル割り当てを GPU 1 個超過しています 」って怒られる。
IAMと管理->割り当て からgpuでフィルタして使用するregionのgpuの上限数を増やせば解決する。
sshする
VMインスタンスを選択するとsshが上に表示される。ブラウザでsshしても良いのたが、gcloudコマンドラインを使用してターミナルからsshする。
一応、lscpu, lspciコマンドでcpuとgpuの情報を確認しとく。
FastAPIでHello World
とりあえずFastAPIにする。今回はHTMLが送れてimg2imgが動けば問題ない。Pythonサーバーは必要そうなのでFastAPIにする。
FastAPIプロジェクトの作成
Githubでプロジェクトを作って、FastAPIのHello Worldを表示する。localhostでできたらcommitしてpushする。
GCPにクローンする
GitHubのリポジトリをprivateで作っていたらトークンを発行してGCP上にプロジェクトをクローンする。GitHubにログインしても良いがトークンを発行する方が好き。
参考: Githubのリポジトリにトークンを使ってアクセスする | Notes to Forget
/var/wwwディレクトリを作成して権限を777にしてクローンする。
GCPのインスタンスでサーバーを起動
最初はlocalhostで起動する。起動するプロセスと起動を確認するプロセスが必要なのでtmuxを使用する。一つ目のウィンドウでFastAPIを起動し(uvicorn main:app –reload)、 二つ目のウィンドウでFastAPIの起動を確認する(curl http://localhost:8000)。
外部からアクセス可能にする
localhostだけではどうしようもないので外部からもアクセス可能にする。
http, httpsを許可
デフォルトではHTTP, HTTPSが許可されてないようなので、GCPのインスタンスを選択して編集からAllow HTTP trafficとAllow HTTPS trafficを許可する。
nginxをインストール
osを確認(cat /etc/os-release)したらDebianだった。nginxのインストール方法を調べてインストールする(sudo apt install nginx)。
nginxを起動(sudo service nginx start)して、ipアドレスにアクセスするとWelcome to nginx!が表示される。
参考: Hello Nginx | Notes to Forget
IPアドレスはGCPのVMインスタンスのネットワーク インターフェースに書いてある。エフェメラル(固定IP)に勝手になっていて嬉しい。
ドメインを持っていればDNSの設定をする。
外部からのアクセスを内部のFastAPIに繋げる
nginxのconf.d/portrait-ai-api.confを作成して繋げる。今回は簡単のために proxy_pass http://localhost:8000; みたいにportを指定する。時間があればソケットでやった方が良いと思う。
ssl
httpsでアクセスできるようにする。
参考サイト: sudo systemctl status certbot.timer
Stable Diffusionのimg2imgを使ってみる
やっと環境構築などが終わったのでStable Diffusionを使ってみる。
CompVis/stable-diffusion: A latent text-to-image diffusion model GitHubのReadmeを忠実に実行する。モデルはwgetコマンドで取得する。
img2imgを実行すると以下のエラーが出る。
RuntimeError: CUDA out of memory. Tried to allocate 8.00: If reserved memory is >> allocated memory try setting max_split_size_mb to avoid fragmentation. See documentation for Memory Management and PYTORCH_CUDA_ALLOC_CONF
pythonの実行の前に、PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:100をつけると解決するって書いてある記事もあったが解決しない。
結論、画像のサイズが大きすぎるとエラーになるみたい。512*256だと動いたが、1024*512だとメモリが足りなかった。256*128だと画像サイズが小さすぎて出力される画像が意味わからんものになった。
終わりに
途中までで完成しなかったので、いつか完成させる。
Comments