Skip to content

Bedrock Night in 大阪(JAWS-UG AI/ML×大阪×東京支部コラボ)- 画像生成大喜利枠の話

2024年7月30日に開催された JAWS-UG AI/ML と JAWS-UG 大阪支部 そして JAWS-UG 東京支部のコラボによる「Bedrock Night in 大阪」が開催されました。

その中でトレノケート山下さんが企画された画像生成大喜利にオオギリストとして参加しました。

その際の生成AIの利用方法や、プロンプトの与え方、生成結果を残しておきます。

先に結果から

結果は、私と JAWS-UG 神戸支部の運営スタッフであるヤマダ氏( @benkyo_ganbaman )が優勝ということになり、結果的にイベント前に私がツイートしていた内容がフラグになってしまいました。

今回のライバルたち

笑いに貪欲な5名の回答者たち。

ちょうど真ん中、クイズダービーでいう「はらたいら」の位置が私です。

やっていたことの記録

今回の企画が発表されてすぐに申し込みを行い、早々に参加が確定していたので、ある程度の想定をもって準備と練習をしておきたいと考えていました。

DeepL などでプロンプト文章を翻訳しながら、Amazon Bedrock で用意されているプレイグラウンドを使った生成をしても良かったのですが、生成画像をいちいちダウンロードをしてから S3 バケットにアップロードし直す、とかが面倒だったので、AWS CLI というか bash が好きな私としてシェルスクリプトで用意しておき、何かあれば微調整できるようにしておこうと考えていました。

処理の概要

sequenceDiagram
  bash/local->>Amazon Translate: プロンプト入力(日本語)
  Amazon Translate-->>bash/local: 機械翻訳(英語)

  bash/local->>bash/local: ファイル名の指定
  bash/local->>bash/local: seed 値の指定
  bash/local->>bash/local: 画像サイズの指定
  bash/local->>bash/local: cfg_scale の値を指定
  bash/local->>bash/local: 利用モデルの指定

  alt Amazon Titan Image
      bash/local->>bash/local: Amazon Titan Image に合わせたリクエストボディの組み立て
      bash/local->>Amazon Bedrock: bedrock-runtime invoke-model サブコマンドの実行
      Amazon Bedrock-->>bash/local: Amazon Bedrock による生成
      bash/local->>bash/local: 生成結果のデコード、画像ファイル化
  else Stable Diffusion 
      bash/local->>bash/local: Stable Diffusion に合わせたリクエストボディの組み立て
      bash/local->>Amazon Bedrock: bedrock-runtime invoke-model サブコマンドの実行
      Amazon Bedrock-->>bash/local: Amazon Bedrock による画像生成
      bash/local->>bash/local: 生成結果のデコード、画像ファイル化
  end

  bash/local->>Amazon S3: s3 cp サブコマンドによるファイルアップロード

出来上がったシェルスクリプト

突貫で作成したので変数のスコープやエラーハンドリングの考慮などは一切なし。

実行ログの出力も一旦は iTerm2 の設定で記録するようにしたので、かなり雑なスクリプトだが、私自身が手元で実行するのでまあよしとした。作成時間は調査を含めて 1.5日 くらい。

なお、前提条件としてスクリプト2行目で選択しているリージョンで、Amazon Bedrock のモデルアクセスで Stability AI の SDXL 1.0 を有効化しておくこと。(ただし、画像の生成に Titan Image Generator G1 しか使用しない場合は不要)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/bin/bash
AWS_REGION=us-east-1
S3_BUCKET_NAME="山下さんが用意してくれた S3 バケット名が入る"
PROFILE=replace-your-aws-cli-config-name

# (現場での調整)本当は手入力による画像ファイル指定にしていたが、煩雑だったのでサイズ固定にした
HEIGHT=1024
WIDTH=1024

# S3 アップロード先として用意された山下さんの AWS アカウントに対しての assume-role を実施
function get_session_token () {
  ROLE_ARN="山下さんが用意してくれた IAM ロールの ARN が入る"

  SWROLE_ASSUME_ROLE_RESULT=$(aws sts assume-role --role-arn "${ROLE_ARN}" \
    --role-session-name jawsug-kazzpapa3 \
    --query 'Credentials.[AccessKeyId, SecretAccessKey, SessionToken]' \
    --profile ${PROFILE} \
    --output text)

  eval $(awk -F ' ' '{ printf("ACCESSKEY_ID=\"%s\" ; SECRET_ACCESSKEY=\"%s\" ; SESSION_TOKEN=\"%s\"",$1,$2,$3) }' <<< ${SWROLE_ASSUME_ROLE_RESULT} )
  export AWS_ACCESS_KEY_ID=$ACCESSKEY_ID
  export AWS_SECRET_ACCESS_KEY=$SECRET_ACCESSKEY
  export AWS_SESSION_TOKEN=$SESSION_TOKEN
}

# Bedrock のモデルの ARN の取得
function get-model-arn() {
  MODEL_ARN=$(aws bedrock get-foundation-model \
    --model-identifier $1 \
    --region ${AWS_REGION} \
    --query 'modelDetails.modelArn' \
    --profile ${PROFILE} \
    --output text
  )
}

function titan() {
  echo "amazon.titan-image-generator-v1 が選択されました"

  get-model-arn "amazon.titan-image-generator-v1"

cat << EOF > ${OUTFILE}.json
{
    "taskType": "TEXT_IMAGE",
    "textToImageParams": {
        "text": "${PROMPT_EN}"
    },
    "imageGenerationConfig": {
        "numberOfImages": 1,
        "height": ${HEIGHT},
        "width": ${WIDTH},
        "cfgScale": ${CFG_SCALE},
        "seed": ${SEED}
    }
}
EOF

  aws bedrock-runtime invoke-model \
    --model-id ${MODEL_ARN} \
    --content-type "application/json" \
    --region ${AWS_REGION} \
    --body fileb://${OUTFILE}.json \
    --profile ${PROFILE} \
    test

  IMAGE_BASE64=$(cat test | jq -r '.images[]')
  echo $IMAGE_BASE64 | base64 -d > ${OUTFILE}.png

  get_session_token
  aws s3 cp ${OUTFILE}.png s3://${S3_BUCKET_NAME}/

  rm -rf test
}

function sdxl() {
  echo "stability.stable-diffusion-xl-v1 が選択されました"

  get-model-arn "stability.stable-diffusion-xl-v1"

cat << EOF > ${OUTFILE}.json
{
    "text_prompts": [
        {
            "text": "${PROMPT_EN}",
            "weight":1
        }
    ],
    "cfg_scale": ${CFG_SCALE},
    "steps": 50,
    "seed": ${SEED},
    "width": ${WIDTH},
    "height": ${HEIGHT},
    "samples": 1
}
EOF

  aws bedrock-runtime invoke-model \
    --model-id ${MODEL_ARN} \
    --cli-binary-format raw-in-base64-out \
    --body fileb://${OUTFILE}.json \
    --region ${AWS_REGION} \
    --profile ${PROFILE} \
    test

  IMAGE_BASE64=$( cat test | jq -r '.artifacts[].base64')
  echo $IMAGE_BASE64 | base64 -d > ${OUTFILE}.png

  get_session_token
  aws s3 cp ${OUTFILE}.png s3://${S3_BUCKET_NAME}

  rm -rf test
}

echo "プロンプト?(日本語でおk)"
read PROMPT

PROMPT_EN=$(aws translate translate-text \
  --text $PROMPT \
  --source-language-code ja \
  --target-language-code en \
  --query 'TranslatedText' \
  --profile ${PROFILE} \
  --output text)

echo "英文翻訳したプロンプトは ${PROMPT_EN} となります"

echo "ファイル名(拡張子なしで記載)?"
read OUTFILE

echo "シード値?"
read SEED

# (現場での調整)本当は手入力による画像ファイル指定にしていたが、煩雑だったのでサイズ固定にするためコメントアウト

#echo "画像の高さ(ピクセル/1408 以下で指定すること)"
#read HEIGHT
#
#echo "画像の幅(ピクセル/1408 以下で指定すること)"
#read WIDTH

echo "cfg_scale の値を指定/目安 10.0 まで"
read CFG_SCALE

echo "利用するモデルを 1 or 2 で入力。amazon.titan-image-generator-v1 を利用する場合 1 を stability.stable-diffusion-xl-v1 の場合 2 を入力します。"
read MODEL

if [ "${MODEL}" -eq 1 ];then
    titan
elif [ "${MODEL}" -eq 2 ];then
    sdxl
fi

AWS が用意する開発支援

プレイグラウンド環境でなんらかの画像生成をやってみたのちに、「サンプルをロード」ボタンの右側の三点リーダーを縦にしたようなアイコンをクリックすると、いくつかのメニューが表示されます。

その中から「API リクエストを表示」を選択するとポップアップ画面で AWS CLI で実行した場合に投入するコマンドが表示されます。
このコマンドを確認することにより、リクエストボディに何を含めれば良いかが容易に理解できるため、今回のスクリプト作成では大いに役立ちました。

また、サンプルで output のファイルとして invoke-model-output.txt を指定しているように、生成画像が画像ファイルそのままとしてダウンロードできるわけではなく、いくつかの返却値のうちの 1 value として base64 エンコードされた文字列として併記されていること、その返却される JSON の形式が amazon.titan-image-generator-v1 と stability.stable-diffusion-xl-v1 で異なることや、そもそものリクエストボディに含めるパラメータが若干異なることを把握しました。

それらを受けて、前述のスクリプト内での処理のように選択されたモデルに応じたリクエストボディの組み立て〜実行結果の JSON ファイルからの取り出し部分の処理を分ける目的の個別のファンクション化につながっています。

jawsug-amazon-bedrock-night-osaka-2024-01

現地で気づいた大きな失敗

当日の 18時頃に、山下さんから、各オオギリストごとに用意したスイッチロール先の IAM ロール ARN、およびアップロード用の S3 バケットの案内がありました。

そこまで私がテストしていた内容でも直接 S3 バケットへのアップロードをするプログラムにしていたため、アップロード先の変更と assume-role する処理を含めるだけの軽微な修正で大喜利枠へ登壇しました。

その後、山下さんからとても意地悪な設問を次々投げられたのですが、今の処理だと、プロンプト入力 → 機械翻訳による英語化 → 利用するモデルの選択 → 選択されたモデルに応じたリクエストボディ組み立て → 画像生成 → S3 バケットへのアップロード、と一気通貫でやるスクリプトとなっているため、生成された画像を「私が見ていないままアップロードすることになる」という重大な事実に気づき、スクリプトの 69〜70行目、および 108〜109行目をコメントアウトし、ローカルで画像を確認してから、ブラウザで開いた S3 コンソールへ手動でアップロードする手順に変更しました。

その他、立ちはだかる壁

特に Amazon Titan を利用したときに特に多かった印象だが、投入するプロンプトで望ましくない文章やニュアンスが含まれていた時に、「Our filters automatically flagged this prompt because it may conflict our AUP or AWS Responsible AI Policy. Please adjust your text prompt to submit a new request.」として reject されてしまうケースが多かった。(出題者の山下さんが選定したお題が、直感ではネガティブ寄りな発想になりがちなキーワードだったのはこれへの誘導だったのか?だとしたら策士だわ)

クイズダービーでの竹下景子席に座っていたライバルの @Riz3f7 さんもこの部分でなかなか苦戦したようで、私のスクリプトでは bedrock-runtime invoke-model サブコマンドがエラーとなる想定をしていないこと、bedrock-runtime invoke-model がエラーとなっても output ファイル自体は発生エラーなどを含めた JSON の返却が行われるため、中に含まれる画像情報が格納されるべき value をデコードすると 0 バイトの画像が生成されてしまい、そのまま S3 のアップロードが行われて、空の画像を表示させてしまう原因も作ってしまったのは反省。

個人的に良かったと思う点

個人的には、1.5日程度の時間で一気通貫で行える処理を作れる体験を得られたので、Amazon Bedrock がうまく抽象化してさまざまなモデルを利用できるようにしていることを理解できた。

また、ログを後から確認できることで、投入したプロンプトやパラメータを容易に追跡できるため、意図した生成にならなかった理由を探るのにも役立つと感じた。

後でログと生成結果を確認してみたところ、今回は 日本語 → 英語 を Amazon Translate に自動翻訳していることと、その翻訳文章自体を確認するステップを挟めていないことで、英語文面ではどのようなプロンプトを与えていることになっているのかをノールックだったことも難しかった要因と思う。

生成された画像たち

iTerm2 でのログからどのような日本語を入力したのか、どのモデルを選択し、どのようなパラメータを投入したのかの後追いが容易だったので以下に晒す。

その1(お題は 炎上商法/出力に失敗)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
プロンプト?(日本語でおk)
宅配便の荷物を蹴り上げた様子を動画投稿する手法
英文翻訳したプロンプトは How to post a video showing a courier's luggage being kicked up となります
ファイル名(拡張子なしで記載)?
100001
シード値?
100
cfg_scale の値を指定/目安 10.0 まで
10
利用するモデルを 1 or 2 で入力。amazon.titan-image-generator-v1 を利用する場合 1  stability.stable-diffusion-xl-v1 の場合 2 を入力します。
1
amazon.titan-image-generator-v1 が選択されました

An error occurred (ValidationException) when calling the InvokeModel operation: This request has been blocked by our content filters. Our filters automatically flagged this prompt because it may conflict our AUP or AWS Responsible AI Policy. Please adjust your text prompt to submit a new request.
cat: test: No such file or directory
upload: ./100001.png to s3://jawsug-osaka-ai/xxxxxxxxx/100001.png

その2(お題は Amazon Web Services)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
プロンプト?(日本語でおk)
密林に蜘蛛の巣が張っている商店
英文翻訳したプロンプトは A store with cobwebs stretched in the jungle となります
ファイル名(拡張子なしで記載)?
20001
シード値?
10
cfg_scale の値を指定/目安 10.0 まで
10
利用するモデルを 1 or 2 で入力。amazon.titan-image-generator-v1 を利用する場合 1  stability.stable-diffusion-xl-v1 の場合 2 を入力します。
1
amazon.titan-image-generator-v1 が選択されました

jawsug-amazon-bedrock-night-osaka-2024-20001

日本語プロンプトの想定:「アマゾン」はそのまま、Web=蜘蛛の巣を連想、Services をお店的なイメージで書いたと思う。

その3(お題は Amazon Web Services)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
プロンプト?(日本語でおk)
密林 蜘蛛の巣
英文翻訳したプロンプトは Jungle spider web となります
ファイル名(拡張子なしで記載)?
2-2
シード値?
1000
cfg_scale の値を指定/目安 10.0 まで
10
利用するモデルを 1 or 2 で入力。amazon.titan-image-generator-v1 を利用する場合 1  stability.stable-diffusion-xl-v1 の場合 2 を入力します。
2
stability.stable-diffusion-xl-v1 が選択されました

jawsug-amazon-bedrock-night-osaka-2024-2-2

その4(お題は Amazon Web Services)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
プロンプト?(日本語でおk)
密林での奉仕作業で金儲け
英文翻訳したプロンプトは Earn money by doing service work in the jungle となります
ファイル名(拡張子なしで記載)?
2-3
シード値?
1111
cfg_scale の値を指定/目安 10.0 まで
10
利用するモデルを 1 or 2 で入力。amazon.titan-image-generator-v1 を利用する場合 1  stability.stable-diffusion-xl-v1 の場合 2 を入力します。
2
stability.stable-diffusion-xl-v1 が選択されました

jawsug-amazon-bedrock-night-osaka-2024-2-3

その5(お題は 裏口入学)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
プロンプト?(日本語でおk)
口裏を合わせている様子 学生 校長
英文翻訳したプロンプトは The student principal looks like they are putting their mouths together となります
ファイル名(拡張子なしで記載)?
3-1
シード値?
1000
cfg_scale の値を指定/目安 10.0 まで
10
利用するモデルを 1 or 2 で入力。amazon.titan-image-generator-v1 を利用する場合 1  stability.stable-diffusion-xl-v1 の場合 2 を入力します。
2
stability.stable-diffusion-xl-v1 が選択されました

jawsug-amazon-bedrock-night-osaka-2024-3-1

その6(お題は 隙間バイト)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
プロンプト?(日本語でおk)
クローゼットの隙間 メイド姿 女性
英文翻訳したプロンプトは Woman in a closet in a gap in a maid となります
ファイル名(拡張子なしで記載)?
4-3
シード値?
1000
cfg_scale の値を指定/目安 10.0 まで
10
利用するモデルを 1 or 2 で入力。amazon.titan-image-generator-v1 を利用する場合 1  stability.stable-diffusion-xl-v1 の場合 2 を入力します。
1

jawsug-amazon-bedrock-night-osaka-2024-4-3

その7(お題は 山崎春のパンまつり)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
プロンプト?(日本語でおk)
パンで作った日本の神輿を担ぐ人々
英文翻訳したプロンプトは People carrying Japanese mikoshi made with bread となります
ファイル名(拡張子なしで記載)?
5-1
シード値?
1000
cfg_scale の値を指定/目安 10.0 まで
10
利用するモデルを 1 or 2 で入力。amazon.titan-image-generator-v1 を利用する場合 1  stability.stable-diffusion-xl-v1 の場合 2 を入力します。
2
stability.stable-diffusion-xl-v1 が選択されました

jawsug-amazon-bedrock-night-osaka-2024-5-1

その8(お題は 独身貴族)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
プロンプト?(日本語でおk)
独身時代を謳歌するハーフパンツ姿の貴族
英文翻訳したプロンプトは An aristocrat in shorts who enjoys being single となります
ファイル名(拡張子なしで記載)?
6-1
シード値?
1000
cfg_scale の値を指定/目安 10.0 まで
10
利用するモデルを 1 or 2 で入力。amazon.titan-image-generator-v1 を利用する場合 1  stability.stable-diffusion-xl-v1 の場合 2 を入力します。
1
amazon.titan-image-generator-v1 が選択されました

jawsug-amazon-bedrock-night-osaka-2024-6-1

日本語プロンプトの想定:「ハーフパンツ姿」で髭男爵のひぐちくんのような出で立ちにしたかった想定

その9(お題は 矢場とん)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
プロンプト?(日本語でおk)
弓道の的と豚汁
英文翻訳したプロンプトは Kyudo targets and pork soup となります
ファイル名(拡張子なしで記載)?
10-1
シード値?
100
cfg_scale の値を指定/目安 10.0 まで
10
利用するモデルを 1 or 2 で入力。amazon.titan-image-generator-v1 を利用する場合 1  stability.stable-diffusion-xl-v1 の場合 2 を入力します。
2
stability.stable-diffusion-xl-v1 が選択されました

jawsug-amazon-bedrock-night-osaka-2024-10-1

日本語プロンプトの想定:やばい=矢場い、という語源から、矢場=弓道、みたいな感じにしたかった想定

感想

参加してみて、Amazon Bedrock を用いた画像生成が「出来はともかく」容易に行えることを理解できて学びになった。

やはり、こういった祭りイベントは参加して実際にヒリつくような思いをすることで、お題に対してプロンプトの検討を即応する難しさと、自分の実装上後から振り返れる経験も得られて楽しかったし有益だった。

ただ、お題の難易度が極悪・意地悪だったと(個人的に)思うので、もう少しマイルドにしたお題で JAWS-UG 神戸支部でのお楽しみコンテンツにしてもいいかもなと思った。

Comments