Stable Diffusion Web UI on AWS の Cloudformation テンプレートを試してときのメモ

Update

Python 3.10 で動くようにUpdateされたもよう。

feat/text-to-image updated README + update python to 3.10
https://github.com/aws-samples/aws-ml-jp/commit/40acafec344b6af504102de0e829b3cbbe6a03f1

---
いつの間にか、EC2 インスタンス上で [AUTOMATIC1111/stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui) を起動するためのサンプルの CloudFormation テンプレートが公開されてました。

https://github.com/aws-samples/aws-ml-jp/tree/main/tasks/generative-ai/text-to-image/inference/stable-diffusion-webui

ただ、__プライベートエンドポイント__ としてデプロイするパターンを試したところ、いくつか修正しないと動かなかったので、そのメモです。おそらく以前は動いていたんでしょうが、パッケージの更新とかで動かなくなったのかな？


---


`sd-webui-private.yaml` を使うパターンの場合、二箇所修正が必要そうでした。

1. SSMに関するインスタンスプロファイルがEC2に割り当てられてないので、手順通りだとSession Managerでアクセスできない
2. web-uiセットアップ中に失敗する （python3.8だとうまくいかない）

失敗した時のログ
```bash:sd-webui-log.txt
---snip
Launching Web UI with arguments:
Traceback (most recent call last):
  File "launch.py", line 38, in <module>
    main()
  File "launch.py", line 34, in main
    start()
  File "/home/ubuntu/stable-diffusion-webui/modules/launch_utils.py", line 330, in start
    import webui
  File "/home/ubuntu/stable-diffusion-webui/webui.py", line 14, in <module>
    from fastapi import FastAPI, Response
  File "/home/ubuntu/stable-diffusion-webui/venv/lib/python3.8/site-packages/fastapi/__init__.py", line 7, in <module>
    from .applications import FastAPI as FastAPI
  File "/home/ubuntu/stable-diffusion-webui/venv/lib/python3.8/site-packages/fastapi/applications.py", line 15, in <module>
    from fastapi import routing
  File "/home/ubuntu/stable-diffusion-webui/venv/lib/python3.8/site-packages/fastapi/routing.py", line 22, in <module>
    from fastapi import params
  File "/home/ubuntu/stable-diffusion-webui/venv/lib/python3.8/site-packages/fastapi/params.py", line 4, in <module>
    from pydantic.fields import FieldInfo, Undefined
ImportError: cannot import name 'Undefined' from 'pydantic.fields' (/home/ubuntu/stable-diffusion-webui/venv/lib/python3.8/site-packages/pydantic/fields.py)
```

### Cloudformation テンプレートの修正
`sd-webui-private.yaml` を以下のように修正しました。多分もっといい方法があると思いますが、とりあえず。です。

```diff
@@ -11,6 +11,9 @@
   Ec2InstanceType:
     Type: String
     Default: g4dn.xlarge
+  EC2InstanceProfileName:
+    Type: String
+    Description: Name of the existing IAM instance profile whic has access to Systems Manager (arn:aws:iam::<account>:instance-profile/<EC2InstanceProfileName>)
   SDWebUIVersion:
     Type: String
     Description: Branch of AUTOMATIC1111/stable-diffusion-webui
@@ -21,6 +24,7 @@
     Properties:
       InstanceType: !Ref Ec2InstanceType
       ImageId: !Ref Ec2ImageId
+      IamInstanceProfile: !Ref EC2InstanceProfileName
       SubnetId: !Ref SubnetId
       BlockDeviceMappings:
         - DeviceName: /dev/sda1
@@ -59,6 +63,11 @@
             sudo apt -y install wget git
             sudo apt -y install python3 python-is-python3 python3-pip python3-venv
 
+            # python3.8 to python3.10
+            sudo apt -y install python3.10 python3.10-venv
+            python3.10 -m pip install --upgrade pip
+            sudo ln -fs /usr/bin/python3.10 /usr/bin/python3
+
             # Launch Stable Diffusion Web UI
             cd /home/ubuntu
             # setup script uses existing folder if it exists. Feel free to change version here.
```

### ロールの準備
公式の AWS Systems Manager ハンズオン があるので、その中の下記ページの手順を流用しましょう。下記ページだけで良いです。他のページの手順は実行する必要はないです。

AWS Systems Manager ハンズオン
https://catalog.us-east-1.prod.workshops.aws/workshops/7e60f6e3-0c8f-488a-bedc-632aa8d526ea/ja-JP/phase2/01

手順通りすすめると、最後にロール名をつけます。どんな名前で作ってもいいです。とりあえず、`RoleForSSM`とでもしておきます。

### デプロイ
g4dn.xlarge 使うので、コストには気を付けましょうね。

以下のコマンドを実行します。githubの手順には、`ParameterKey=EC2InstanceProfileName,ParameterValue=<InstanceProfile>`の部分がありませんので、追加してます。

```bash
aws cloudformation create-stack --stack-name sd-webui-stack --template-body file://sd-webui-private.yaml --region us-east-1 --parameters ParameterKey=SubnetId,ParameterValue=<SubnetId> ParameterKey=EC2InstanceProfileName,ParameterValue=<InstanceProfile>
```

それぞれの設定値は以下です。
|  項目  |  値  |
| :---- | :---- |
|  \<SubnetId>  |  EC2インスタンスを配置するサブネットのID  |
|  \<InstanceProfile>  |  EC2に割り当てるインスタンスプロファイルの名前。先ほど作ったロールの名前になります。|

注意 : このテンプレートの場合、利用しているAMIのイメージが us-east-1 のものなので。region　は　us-east-1　を指定してます。

### アクセス
これは [github](https://github.com/aws-samples/aws-ml-jp/tree/main/tasks/generative-ai/text-to-image/inference/stable-diffusion-webui) にある通りの手順でアクセスできます。

ポートフォワーディングの設定をして、http://localhost:7860 にアクセスすれば、web-ui を参照できます。
```bash
./port-forwarding.sh <instance_id> <region> 7860 8080
```

それぞれの設定値は以下です。

|  項目  |  値  |
| :---- | :---- |
|  \<instance_id>  | EC2インスタンスのID |
|  \<region>  | us-east-1 |


### まとめ
Stable Diffusion Web UI へのリモートアクセスはどうしようかなと思っていたのですが、SSMを使ったポートフォワードの方法はなかなか良いですね。