画像生成AI Stable DiffusionをAWS Lambdaで動かす（img2img対応）

# はじめに
本記事はAWS Lambda上でStableDiffusion(img2img)を動作させることをゴールとします。
ソース一式はGitHubに置いてあるため、使い方の解説など特に必要ない方はそちらを参照してください。

https://github.com/densenkouji/stable_diffusion.openvino.lambda

:::note info
本プロジェクトは「stable_diffusion.openvino」プロジェクトを基にAWS Lambdaに移植したものです。
https://github.com/bes-dev/stable_diffusion.openvino
:::

# 実行結果
次節に示す手順を進めていただくことにより、AWS Lambda上で画像を作成することができます。
(コマンドの--function-nameにはデプロイしたLambda関数名を指定します)
```sh:実行例
aws lambda invoke \
   --function-name mySdFunction-yty7mdazmzzlywey \
   --invocation-type 'RequestResponse' \
   --payload '{"prompt":"Street-art painting of Tower in style of Banksy"}' \
   --cli-read-timeout 600 \
   --cli-binary-format raw-in-base64-out \
   output.text
```
- 作成した画像
![sd_2022-09-19-16-05-49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741318/36d4b3cc-42ca-26a6-344c-8cb37446f959.png)

:::note alert
費用に関する注意、および、免責事項
- 注意事項
本記事ではLambda関数に設定可能なメモリ上限の割り当てを行います。
また、画像の作成には1枚に数分程度かかるなど費用が高額になる可能性があるため内容を検証する場合は十分ご注意ください。
- 免責事項
当方はこの記事を使用して生成されたコンテンツについて責任を負うものではなく、また、このプロジェクトを違法、有害、攻撃的なコンテンツの作成に使用しないでください。
:::

# インストール手順
事前準備～AWS Lambdaにデプロイ、動作確認までの手順を示します。
手順の概要をざっくり示すと次のとおりです。
- AWS CLIのインストールと設定、Dockerのインストール(インストール済みの場合はスキップ可)
- ソースコードのダウンロード
- インストールスクリプトの実行(Lambda関数名だけ入力)
- 画像生成の実行

なお、本記事では基本的にターミナルを用いてコマンドラインから操作を行いますが、画面上(マネジメントコンソール)から操作を行いたい場合は次の記事が参考になるかと思います。

https://qiita.com/densenkouji/items/49f6f55b36bcf9218fa8

## 事前準備
AWS CLIとDockerをインストールします。
すでにインストールしていてAWS CLIも設定済みの場合は次の手順に進んでください。
- AWS CLIのインストール＆設定
AWS CLIをインストールします。

https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html

AWS CLIのインストール完了後、aws configureを実行して設定します。
AWS Access Key ID、AWS Secret Access Key、Default region nameの3つについては必須です。
```terminal:CMD
$ aws configure
AWS Access Key ID [None]: 
AWS Secret Access Key [None]: 
Default region name [None]:
Default output format [None]: 
```
- Docker
Dockerをインストールします。

https://docs.docker.com/engine/install/

## ソースコードの取得
1. プロジェクトのソースコード一式をクローン or ダウンロードします。
1. プロジェクトのディレクトリに移動します。
```sh:CMD
$ git clone https://github.com/densenkouji/stable_diffusion.openvino.lambda.git
$ cd stable_diffusion.openvino.lambda
```
## インストールスクリプトの実行
:::note warn
ご注意事項：インストールスクリプトを実行する前に
- インストールの所要時間はスクリプトを実行するPCのスペックやネットワークの状況により変動します。
(当方の環境では40～50分程度かかりました)
- モデルやライブラリなど、また、Dockerイメージのためのディスク容量が必要となります。
:::

1. 「install.sh」を実行します。
1. Lambda関数名の入力を求められるため、任意の関数名(例：mySdFunction)を入力します。
なお、実際に作成されるラムダ関数の名称は、入力された関数名にハイフン(-)＋ランダムな16桁の英数字の文字列を付加したものになります。
```console:CMD
$ sh ./install.sh
(Create New) Input AWS Lambda Function Name [ex.mySdFunction]: 任意のラムダ関数名
```
インストールが完了するとスクリプトにより作成された関数名などが表示されます。
```terminal:インストール結果例
（略）
TRACINGCONFIG   PassThrough
******* Complete!! *******
The following resources were created.
- Lmabda function: mySdFunction-yty7mdazmzzlywey
- Role: mySdFunction-yty7mdazmzzlywey-role
- ECR Repository: mysdfunction-yty7mdazmzzlywey-repo
- S3 Bucket: mysdfunction-yty7mdazmzzlywey-bucket
```
Lambda関数名、ロール、ECRリポジトリ名、S3バケット名が表示されていることを確認できます。
各リソースの名称は最初に入力されたLambda関数名を元に命名されます。

## テスト（Text-To-Image）
作成したLambda関数をテストします。
処理が問題なく終了すると、S3に画像が保存されます。
```terminal:テスト例
$ aws lambda invoke \
   --function-name mySdFunction-yty7mdazmzzlywey \
   --invocation-type 'RequestResponse' \
   --payload '{"prompt":"Street-art painting of Tower in style of Banksy"}' \
   --cli-read-timeout 600 \
   --cli-binary-format raw-in-base64-out \
   output.text
```
テストにて指定するパラメータは次のとおりです。
- --function-name：インストール結果として示された「Lmabda function」を指定します。
- --payload：promptに作成したい画像をイメージする文言を指定します。

```json:実行結果：正常終了した場合
{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}
```
- 実行例
![sd_2022-09-20-02-21-07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741318/e819b7ea-8591-f0ed-5dc9-23147ea0ae1b.png)

:::note warn
エラーについて
正常にインストールが行われてもエラーにより画像生成が失敗することがあります。
:::

# img2img
動作確認が終了したため、Image-To-Imageを試します。
```terminal:img2img
$ aws lambda invoke \
   --function-name mySdFunction-yty7mdazmzzlywey \
   --invocation-type 'RequestResponse' \
   --payload '{"prompt":"Street-art painting of cat in style of Banksy","init_image":"input.png","strength":0.8}'  \
   --cli-read-timeout 600 \
   --cli-binary-format raw-in-base64-out \
   output.text
```
ポイントは--payloadに指定したinit_imageになります。
元となる画像をS3に保存し、そのファイル名を指定します。

・元画像：ネコ？
![input2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741318/4fc5e01e-5a0a-b6ae-13ab-834c969e2dc8.png)

・作成された画像(strength:0.6)：ネコ
![sd_2022-09-21-02-02-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741318/0ac55dc3-025d-ac96-9455-3e199a20d1cb.png)

・作成された画像(strength:0.8)：ネコ！
![sd_2022-09-21-00-25-53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741318/6c825227-a6b8-3188-e7ba-cb052dcbb1fa.png)

# アンインストール
「install.sh」を実行すると、アンインストール用のスクリプト「uninstall-XXXXXXXXXXXXXXXX.sh」(XXX…の部分はランダムな16桁の英数字)が作成されます。
このスクリプトを実行するとインストール時に作成した次のリソースを削除します。
- Lambda関数
- ロール
- ECRリポジトリ
- S3バケット

```console:アンインストール実行例
$ sh ./uninstall-yty7mdazmzzlywey.sh
```
Lambda関数を実行するとCloudWatchにログが作成されますが、このログについては削除しません。
内容を確認いただき問題なければ手動で削除してください。

以上です。

# 謝辞/Acknowledgements
- stable_diffusion.openvino: https://github.com/bes-dev/stable_diffusion.openvino
- Original implementation of Stable Diffusion: https://github.com/CompVis/stable-diffusion
- diffusers library: https://github.com/huggingface/diffusers