Amazon Bedrock を利用して、画像生成アプリケーションを開発してみた!

2024-02-01
How to be a Developer

Author : 青木 克臣

こんにちは!テクニカルインストラクターの青木です。

突然ですが、Amazon Bedrock というサービスをご存知でしょうか ? 2023 年の 9 月に一般提供された生成 AI アプリケーションの開発を支援するサービスです !

この記事では、Amazon Bedrock の初学者や興味がある方を対象に、Amazon Bedrock を用いた画像生成アプリケーション開発の流れを解説します。

このクラウドレシピ (ハンズオン記事) を無料でお試しいただけます »

毎月提供されるクラウドレシピのアップデート情報とともに、クレジットコードを受け取ることができます。 


1. 今回開発するアプリケーションについて

今回開発するアプリケーションでは、ユーザーの任意の入力に対して画像を出力します。これを実現するために、Amazon Bedrock、AWS Lambda、Amazon S3、Amazon API Gateway というサービスを利用し、最終的に以下のアーキテクチャを設計します。(このアーキテクチャの解説は、後ほど行います。)

今回のアプリケーションを構築すると、使用したサービスごとに料金が発生するので、builders.flash のメールメンバー登録 の上、クレジットコードの当選にチャレンジしていただくのも良いと思います。


2. 利用するサービスについて

まずは、今回利用するサービスについて簡単に解説します。

2-1. Amazon Bedrock とは

Amazon Bedrock は、API を通じて主要な基盤モデル (FM) を利用できるようにするフルマネージドサービスです。Amazon Bedrock によって、API を通じて AI21 Labs、Anthropic、Cohere、Meta、Stability AI、Amazon などの提供する様々な FM を簡単に利用することができます。

また、Amazon Bedrock はサーバーレスであるため、インフラストラクチャを管理する必要もありません ! 詳細は こちら をご参照ください。

2-2. AWS Lambda とは

AWS Lambda は、サーバーレスなコンピューティングサービスです。
Python や Java などのプログラミング言語のコードを書くだけで、簡単に関数を実行できます ! 詳細は こちら をご参照ください。

2-3. Amazon API Gateway とは

Amazon API Gateway は、簡単に API の作成、公開、保守、モニタリング、保護が行えるサーバーレスなサービスです。
詳細はこちらをご参照ください。

2-4. Amazon Simple Storage Service (Amazon S3) とは

Amazon S3 は、可用性やスケーラビリティに優れたサーバーレスなオブジェクトストレージサービスです。
HTTPS リクエストによって、オブジェクトの保存や取得が簡単に行えます。詳細は こちら をご参照ください。

2-5. AWS Identity and Access Management (IAM) とは

IAM は、AWS リソースへのアクセスを安全に管理するためのサービスで、認証・認可を担っているサービスです。
詳細は こちら をご参照ください。


3. 開発の流れ

それでは早速、開発の流れを手順に沿って解説していきます !

3-1. Amazon Bedrock で、画像生成用の基盤モデルを利用可能にする

まずは、Amazon Bedrock で、画像生成用の基盤モデルを利用可能にしましょう。

Amazon Bedrock では、選択されたリージョンによって使える基盤モデルが異なる場合があります。今回は、us-east-1 (バージニア北部) リージョンを選択して、リソースを構築していきます。

それでは、Amazon Bedrock のコンソール画面の「Model Access」から、今回利用する Stability AI 社の「SDXL 1.0」を選択し、アクセスリクエストを送ります。

クリックすると拡大します

その後、すぐに利用可能になります。なんと、Amazon Bedrock についての操作はこれだけです !!

また、Playgrounds セクションから、基盤モデルのテストが可能です。
このセクションで、画像生成をちょっと遊んでみる、なんてことが簡単にできます !

3-2. S3 バケットの作成

次に、生成した画像を保存するための S3 バケットを作成しましょう。

S3 のコンソール画面から、「バケットを作成」を押下し、汎用タイプのバケットを作成します。

バケット名を入力し、その他の項目はデフォルトのままで OK です !

3-3. Lambda 関数の作成

次に、Lambda 関数を作成しましょう。今回作成する Lambda 関数では、以下のことを行います。

  • Amazon Bedrock によって用意された API にリクエストを送り、レスポンスとして、生成された画像を受け取る
  • S3 バケットに画像をアップロードする
  • その画像の署名付き URL を取得する
    • 署名付き URL とは、S3 内のオブジェクトへの時間制限付きのアクセス権を付与できる仕組みのことです。
    • この仕組みを用いることで、ポリシーを修正することなくオブジェクトの共有が可能です。

では、AWS Lambda のコンソール画面から、「関数の作成」より、Lambda 関数を作成しましょう。

一から作成」より、適当な関数名を入力し、ランタイムに「Python 3.12」を選択しました。

その他の設定項目は、デフォルトのままで OK です !

クリックすると拡大します

次に、この Lambda 関数の IAM ロールを修正していきます。ここでは、大きく二つの権限を追加します。

  • Amazon Bedrock によって用意された 基盤モデルを実行するための権限
  • S3 バケットにオブジェクトを保存・署名付き URL を取得する権限

設定」タブの「アクセス権限」から、実行ロール名のリンクをクリックし、ロールの修正をしていきましょう。

クリックすると拡大します

許可」タブから、許可ポリシーのリンクをクリックします。

クリックすると拡大します

編集」ボタンを押下し、ロールの修正を行います。

クリックすると拡大します

新しいステートメントを追加」から、ポリシーを修正していきます。
以下の権限を追加します。

  • Amazon Bedrock によって用意された 基盤モデルを実行するための権限
    • Stability AI 社の SDXL 1.0 に対して、 bedrock: InvokeModel アクションを許可
  • S3 バケットにオブジェクトを保存・取得する権限
    • 作成した S3 バケットに対して、GetObject、PutObject アクションを許可

最終的に、以下のようなポリシーになっていれば OK です !

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "bedrock:InvokeModel"
            ],
            "Resource": [
                "arn:aws:bedrock:us-east-1::foundation-model/stability.stable-diffusion-xl-v1"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::{作成したバケット名}/*"
            ]
        }
    ]
}

それでは、 Lambda 関数の中身を記述していきましょう !

今回、AWS SDK for Python (Boto3) を使って、コードを記述します。最終的なコードは以下の通りです。それぞれのコードで何をやっているのか、コメントを添えておきましたので、ご確認ください。

# 必要なライブラリを読み込み
import json
import boto3
import base64
import uuid
from botocore.config import Config

bedrock_runtime = boto3.client('bedrock-runtime')
# 署名プロセスには、署名バージョン4(SigV4)を指定
my_config = Config(region_name="us-east-1", signature_version="s3v4")
s3 = boto3.client("s3", config=my_config)
bucket_name = '作成したS3バケット名'

def lambda_handler(event, context):
    # S3に保存するためのランダムなオブジェクト名を生成
    random_uuid = uuid.uuid4().hex 
    # 入力を受け取る
    input_text = event['input_text'] 
    
    # Amazon Bedrockで用意した基盤モデルへAPIリクエストし、画像を生成する
    response = bedrock_runtime.invoke_model(
        body='{"text_prompts": [{"text":"'+input_text+'"}]}',
        contentType='application/json',
        accept='image/png',
        modelId='stability.stable-diffusion-xl-v1'
    )
    
    s3_key = random_uuid + '.png'
    
    # 生成された画像をS3にアップロード    
    s3.upload_fileobj(response['body'], bucket_name, s3_key, ExtraArgs={'ContentType': 'image/png'})
    # 署名付きURLを取得
    presigned_url = s3.generate_presigned_url('get_object',Params={'Bucket': bucket_name,'Key': s3_key},ExpiresIn=3600) 
    
    # 署名付きURLを返す
    return {
        'statusCode': 200,
        'body': {'presigned_url': presigned_url}
    }

Boto3 について、詳しくは こちら をご参照ください。
Amazon Bedrock の API の操作方法について、詳しくは こちら をご参照ください。

次に、Lambda 関数のタイムアウト値を変更しましょう。

Lambda 関数のデフォルトのタイムアウト制限は 3 秒に設定されており、 実際の処理に 3 秒以上時間がかかってしまう場合、エラーが発生してしまいます。

設定」タブの「一般設定」の「編集」ボタンを押下し、タイムアウト値を長めに変更しましょう。今回は 15 分に変更しました。

クリックすると拡大します

それでは、この関数をテストしてみましょう。

Test」ボタンを押下してください。

クリックすると拡大します

テストイベントを設定します。

適当なイベント名を入力し、イベント JSON を修正します。

今回、 input_text というパラメータを受け付けているので、イベント JSON の修正が必要です。こちらのように設定し、「保存」ボタンを押下してください。

クリックすると拡大します

Test」ボタンを押下し、関数を手動実行してみましょう !
すると、関数のレスポンス結果として、以下のように S3 の署名付き URL が返ってくることが確認できました。

{
  "statusCode": 200,
  "body": {
    "presigned_url": "https://作成したS3バケット名.s3.amazonaws.com/951daf~.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASsaf~&X-Amz-Date=20240~&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Security-Token=IQ2Bu~&X-Amz-Signature=a9~"
  }
}

この URL をコピぺし、ブラウザで確認してみましょう !

このように、画像が生成されているのが確認できました !! 🎉
実際に、該当の S3 バケットを見ても、オブジェクトが保存されていることが確認できるかと思います。

3-4. Amazon API Gateway で API を作成

では、先ほど作成した Lambda 関数と Amazon API Gateway を組み合わせて、API を作成しましょう。

Amazon API Gateway のコンソール画面から、「API を作成」ボタンを押下し、REST API の「構築」ボタンを押下してください。

新しい API」から、API 名を入力し、「API を作成」ボタンを押下しましょう。

クリックすると拡大します

API の作成が完了しました !

次に、「メソッドを作成」ボタンを押下し、POST メソッドによって渡ってくるデータ (input_text) を Lambda 関数に渡す処理を実装します。

クリックすると拡大します

メソッドタイプで「POST」を選択し、統合タイプに「Lambda 関数」を選択しましょう。そして、Lambda 関数に、先ほど作成したLambda 関数を指定してください。

その後、「メソッドを作成」ボタンを押下し、メソッドを作成しましょう。

クリックすると拡大します

メソッドの作成が完了しました !

次に、「API をデプロイ」ボタンを押下し、API のデプロイを行いましょう。
New Stage」を選択し、適当なステージ名を入力し、「デプロイ」ボタンを押下します。

クリックすると拡大します

これで、デプロイが完了しました !

URL を呼び出す」に表示の URL が API のエンドポイントです。

クリックすると拡大します

フロントエンドからこの API にリクエストを送ることで、画像の生成を行いますが、一点注意点があります。それが、クロスオリジンリソース共有 (CORS) の設定です。CORS について、詳しくは こちら をご参照ください。

この設定に対応するために、サイドバーの「リソース」から、「CORS を有効にする」ボタンを押下しましょう。

クリックすると拡大します

その後、Access-Control-Allow-Methods の「POST」にチェックし、Access-Control-Allow-Origin にフロントエンド側のオリジンを入力します。

最後に、「保存」ボタンを押下しましょう。

クリックすると拡大します

保存が完了したら、再度 API のデプロイを行い、変更を反映させましょう。

クリックすると拡大します

これで、フロントエンドから API にリクエストを送ることができるようになります。

一点注意点ですが、Amazon API Gateway の REST API のタイムアウト値の上限が 29 秒 (2023 年 12 月現在) なので、Amazon Bedrock の処理に 29 秒以上の時間がかかる場合は、別途対応が必要です。

3-5. フロントエンド作成

今回、以下のような簡易的なフロントエンドを用意しました。ここではフロントエンドについて詳しい解説はしませんが、上記で用意した API にリクエストを送り、返ってきた画像を表示しています。

以下のような画像生成アプリケーションが完成しました !!

フロントエンドを用意せずに、作成した API を試したい方は、コマンドラインインターフェイス (CLI) から試すこともできます。
CLI 上で、以下の curl コマンドを実行すると、S3 の署名付き URL が返ってくるのを確認できます。

$ curl -X POST {作成した API のエンドポイント} -H 'Content-Type: application/json' -d '{"input_text":"an image of cat"}'

以下の curl コマンドで、返ってきた署名付き URL からオブジェクトをローカルにダウンロードできます。

$ curl -O "{レスポンスの署名付きURL}"

4. まとめ

今回、Amazon Bedrock を用いて画像生成のアプリケーションを開発し、その流れを解説しました。

具体的には、以下のようなアーキテクチャで、Amazon Bedrock によって画像生成用の API を有効にし、Lambda 関数が Amazon Bedrock の用意した API にリクエストを送り、生成された画像を S3 に保存します。

さらに、Lambda 関数は、S3 から署名付き URL を受け取ります。

最後に、Lambda 関数と Amazon API Gateway を組み合わせることでパブリックな API を用意し、フロントエンドで API リクエストを送れるようにしました。

Amazon Bedrock を用いることで、画面をぽちぽち押すだけで画像生成用の API が用意でき、そのおかげで機械学習に詳しくなくても、画像生成の部分を作り込まずにこのようなアプリケーションを開発できました ! また、画像生成だけでなく、チャットやテキスト要約などの API も今回と同じように簡単に使えます。

ご興味のある方は、ぜひ触ってみてください!

なお、Amazon Bedrock の他に生成 AI の活用するサービスとして Amazon CodeWhisperer の記事「Amazon CodeWhisperer を使ってみよう!」もありますので、よろしければ読んでみてください !


builders.flash メールメンバーへ登録することで
AWS のベストプラクティスを毎月無料でお試しいただけます

筆者プロフィール

青木 克臣
アマゾン ウェブ サービス ジャパン合同会社
AWS トレーニングサービス本部 テクニカルインストラクター

”分かりやすい”をモットーに、日々 AWS のトレーニングの登壇をしています。
趣味はフットサル、筋トレ、サウナで、推しのサウナはウェルビー栄 (名古屋) です。

AWS を無料でお試しいただけます

AWS 無料利用枠の詳細はこちら ≫
5 ステップでアカウント作成できます
無料サインアップ ≫
ご不明な点がおありですか?
日本担当チームへ相談する