🚀 ニフティ’s Notion

【後半】画像生成AI(Stability AI) ✖ マイクロサービス の作成

まず最初に料金の話


  • 今回は 「Stability AI/SDXL 1.0(Stable Diffusion XL 1.0)」を使用します
    • 画面解像度:1024 x 1024 まで
    • ステップ数:多いほどより詳細で高画質な画像を生成することが可能だが処理時間も増加
  • むやみやたらに生成しすぎると金額が多く掛かります。節度を持って!
    image block
    出典:

今回作成するサービスについて


  • 生成AIのAWSサービスと他AWSサービスを連携して、小さいマイクロサービスを作ってみよう
    • 「外部よりプロンプトを指定してURLを叩くと、画像が生成される」システム

  • 以下が作成する構成図
    image block
    • 私たちは AWS Lambda を叩き、署名URLを受け取る
    • AWS Lambda が Amazon Bedrockで生成AI(Stability AI)に生成をお願いし、画像を受け取る
    • AWS Lambda が 生成された画像をS3に保存し、署名URLを受け取る

クォータ的に1分に60回以上叩くと止まるので、控えめに叩いてね

ハンズオン


①Amazon Bedrock:Stability AI が利用可能であることを確認

  1. AWSにアクセス
  2. Amazon Bedrock にアクセス
  3. リージョンを us-east-1 であることを確認
    ※ 画像生成AIは現在 (2024/06/10)、東京リージョンでは取り扱っておりません
  4. モデルアクセス にアクセスします
    手順
    1. 左上のハンバーガーメニューをクリックする
      image block
    2. 左下の「モデルアクセス」をクリック
      image block
  5. Stability AI の 「SDXL 1.0」 について、「アクセスが付与されました」となっていることを確認
    image block

💡
※ 事前に「モデルアクセスのリクエスト」を行っています。
 ⇒ 使用したいAIを利用したい旨をAWSにリクエストします。初期は何も使用できません。
リクエストする方法
  1. 「リクエスト可能」を押下し、モデルアクセスをリクエストを押下
    image block
  2. すると選択できるようになるので、選択して「Next」を押下
    image block
  3. 確認画面がでるのでSubmitを押す

    ※ Claude 3 Haiku を使用する際は利用者情報を入力する必要があります

②コンソール上からStability AI を使用してみる

  1. 先程のハンバーガーメニューより、「プレイグラウンド/イメージ」を押下
    image block
  2. 「モデルを選択」を押下
    image block
  3. SDXL 1.0 モデルを選択し、「適用」を押下します
    image block
    1. カテゴリ - Stability AI 2. モデル - SDXL 1.0 3. スループット - オンデマンド
  4. 下方の入力箇所に画像生成させたい言葉を入れて「実行」を押下
    image block
  5. 生成されたことを確認します
    image block
  6. これで体験は以上です

スタイルを加えると幅が広がったり…。
富士山を「pixel art」風に
image block
③Amazon S3:画像の保存用リソースを作成

  1. Amazon S3 にアクセス
  2. 「バケットを作成」を押下
    image block
  3. バケット名を「 bucket-bedrock-sdxl- &任意の英数字 」と入力
    bucket-bedrock-sdxl-aiueo
  4. 他はデフォルトで、「作成」を押下
    image block
  5. 作成されたS3にアクセス
  6. プロパティを押下
  7. Amazon リソースネーム(ARN)をコピーし、メモ
    arn:aws:s3:::bucket-bedrock-sdxl-aiueo
  8. S3の作成完了

    ※コピーしたARNは⑤IAMで使用します

④AWS Lambda:外部との連携用関数を作成

  1. AWS Lambda にアクセス
    手動
    1. Lambda と検索
    2. 左側のハンバーガーメニューを押下
    3. 関数を押下
  2. 「関数の作成」を押下
    image block
  3. 関数名を「 bedrock-sdxl- &任意の英数字 」とし、ランタイムを Python 3.12 とする
    bedrock-sdxl-aiueo
  4. 他はデフォルトで「関数の作成」を押下
    image block
  5. コードソースに以下のコードを貼り付け
    コード
    # 必要なライブラリを読み込み
    import json
    import boto3
    import base64
    import uuid
    import urllib.parse
    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 = 'bucket-bedrock-sdxl-&任意の英数字'
    
    def lambda_handler(event, context):
        # S3に保存するためのランダムなオブジェクト名を生成
        random_uuid = uuid.uuid4().hex 
    
        # 入力を受け取る
        try: 
    	    if 'version' in event.keys():
    	        if 'body' not in event.keys():
    	            param = event['queryStringParameters']
    	        else:
    	            param = json.loads(event['body'])
    	            
    	        prompt = param['prompt']
    	    else:
    	        return {
    	            'statusCode': 200,
    	            'body': {'text': 'This is a test result. If you want to generate an image, please specify the `prompt` key in the URL query or POST request.'}
    	        }
        except Exception as e:
          return {
              'statusCode': 400,
              'body': {'text': f'Occuerd Error by using Japanese or other things :{e}'}
          }
      
        # Amazon Bedrockで用意した基盤モデルへAPIリクエストし、画像を生成する
        response = bedrock_runtime.invoke_model(
            body='{"text_prompts": [{"text":"'+prompt+'"}]}',
            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': json.dumps(presigned_url)
        }
  6. &任意の英数字 となっているところを、先程作成したS3のバケット名に合う用に修正
    • bucket_name = 'bucket-bedrock-sdxl-aiueo'
  7. 「Deploy」を押下
    image block
  8. Lambda 関数のタイムアウト値を変更
    ※ 画像生成は 10 ~ 60秒程度掛かります
    1. 「設定」を押下
      image block
    2. 「一般設定」の「編集」を押下
      image block
    3. 「タイムアウト」を3分0秒に変更する
      image block
    4. 「保存」を押下
      image block
  9. 完了
    image block

⑤IAM:AWS Lambda からの各サービスへの実行権限を付与

  1. 「設定」をクリック
  2. 「アクセス権限」のタブをクリック
    image block
  3. 「ロール名」のリンクをクリック
  4. 「許可ポリシー」の「ポリシー名」をクリック
  5. 「編集」をクリック
    image block
    ここで同時に、CloudWatch Logsにしかアクセス権限を持っていないんだなと理解できる
💡
以下の権限を追加します!
  1. Amazon Bedrock によって用意された 基盤モデルを実行するための権限
    • Stability AI 社の SDXL 1.0 に対して、 bedrock: InvokeModel アクションを許可
  • S3 バケットにオブジェクトを保存・取得する権限
    • 作成した S3 バケットに対して、GetObject、PutObject アクションを許可
  1. Bedrock InvokeModel 用のステートメントを追加
    1. 「新しいステートメントを追加」をクリック
    2. 右側の「アクションを追加」より、以下にチェック
      アクション:Bedrock → InvokeModel
      image block
    3. 右側の「リソースを追加」を押下
    4. 以下を選択/入力し、押下します
      • サービス: Bedrock
      • リソースのタイプ: foundation-model
      • リソースARN: arn:aws:bedrock:us-east-1::foundation-model/stability.stable-diffusion-xl-v1
      image block
  2. S3 GetObject/PutObject 用のステートメントを追加
    1. 「新しいステートメントを追加」をクリック
    2. 右側の「アクションを追加」より、以下にチェック
      アクション:S3 → GetObject, PutObject(複数選択)
      • JSONの方が以下のようになっているはず
        image block
    3. 右側の「リソースを追加」を押下
    4. 以下を選択/入力し、押下します
      • サービス: S3
      • リソースのタイプ: object
      • リソースARN: &先程メモしたS3のARN /*
        • /* を必ずつけてください
        • 例: arn:aws:s3:::bucket-bedrock-sdxl-aiueo /*
  3. 右下の「次へ」を押下
    image block
  4. 「変更を保存」を押下
  5. 完了

⑥AWS Lambda:外部より画像が生成できることを確認

  1. 先程作成した AWS Lambda に戻る
  2. AWS Lambda 特有の機能「関数URL」を用いて、外部より Lambdaだけで 関数を呼び出せるようにします( 気になった人は
    1. 「設定」を押下
    2. 「関数URL」を押下
    3. 「関数URLを作成」を押下
      image block
    4. 「認証タイプ」を「NONE」に変更
      image block
      😡
      通常運用時は 必ずNONEを使わない こと
    5. 「保存」を押下
      image block
    6. 関数URLが生成されたと思うので、メモする( &関数URL
      image block
      □を押すとコピーされる
      • https://wcw333zdp63oldo3ygkchyu6xi0btnza.lambda-url.us-east-1.on.aws/
  3. 以下2通りのいずれかで叩いてみてください。
    1. (英語のみ使用可能)ブラウザでURLをURLクエリ付きで叩く
      &関数URL?prompt=&描写したい指令
      https://wcw333zdp63oldo3ygkchyu6xi0btnza.lambda-url.us-east-1.on.aws/?prompt=an_image_of_a_cat
    2. (日本語に対応)Cloud Shell を使用し、POSTする
      1. AWS上部にあるマークからCloud Shell を起動する
        image block
      2. CLIが表示されたら、以下を入力する
        curl '&関数URL' \
        -H 'content-type: application/json' \
        -d '{ "prompt": "&描写したい指令" }'
        curl 'https://wcw333zdp63oldo3ygkchyu6xi0btnza.lambda-url.us-east-1.on.aws/' \
        -H 'content-type: application/json' \
        -d '{ "prompt": "サンドイッチ" }'
  4. S3の署名URLが返却される
    CloudShellを用いたPOSTの場合
    [cloudshell-user@ip-10-130-86-160 ~]$ curl 'https://wcw333zdp63oldo3ygkchyu6xi0btnza.lambda-url.us-east-1.on.aws/' \
    > -H 'content-type: application/json' \
    > -d '{ "prompt": "サンドイッチ" }'
    "https://bucket-bedrock-sdxl-aiueo.s3.amazonaws.com/d7efe3c7f2b4473e869957cd9dfaa0ae.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIA6A3KW7MM5MQGU2LA%2F20240528%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240528T102637Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEHMaCXVzLWVhc3QtMSJIMEYCIQDdJnyftt8iBdKkXZNyn8YomFmwwHTTdXqw1QXmMlp%2BGwIhAIWQQfvL%2FF6fIPx%2BUfKdhQzA7Wp4uUAhKl4DMe3Lz6IoKocDCOz%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEQAhoMOTYzOTA3MDkxMjI1IgwYrLmEUESRE3yZ2K0q2wK1c9i8TRI5QdX9RWqXL3H6pGNPAvlroQwcrbrcnAOCwJKPmiwctCbQ%2BRgf8dSbMQ89QXuT6%2Buc6Trs7dvuS7mZxKSB62rrttAKzb5GWoum0yztr5snKuag8vofl8KgJnWJfbrL06Mo6UoGWMKC4XojkRp7eGHnAb57AWInlkJsa%2BwI0%2BP5g9EcBrcIEUdZlm%2F4TGx8MgVep5wJfNaDTyqWTFfpQJ%2BeuWbRo70N8mPSlmFGpUAoyF0WqeFZB0gh7yw4dWqxiZ7pGYYvyufk2FaIb0gejYWSVIAcShNYJGM6W2Fuhl7lQYAEDY9XUycnBdFNVCV174zha5kqwfxngRBcgZGUWTL%2BaB8vN7JOekZKrc2rCrlUEAvbZ9i12h6zPWAGgFWAh6djuxw7HkWYKF6R2cTJ45LJkCFCA%2FvYUICu%2Bm2Ht8qcIcMJMEU5FQXLkeIhd49rNeNOAVmn%2BzD04dayBjqdARuys%2B4zSn7gOQItgEFBR0J3zgki5GFHH40yabatW7bQHUTfisgk284n4Nd3Mt8NuOzLIpRVMXRzTaROX20QqpkZMHl%2F2rZOBvUdDSGVuL4tmu6YgRHutDcMd%2Fxd2fU0SVMiizBNxmf3SU9Mv%2BRb0vhcEUDsFLqeaTvFH0WJALlqHOlpTx03XFdtDNDJmHDa7WqIykQaRgm95nd5%2BEI%3D&X-Amz-Signature=25d6ee4526340f96bb09cb991491b0bce04fcd57f33728426741b6d0175b345a"
  5. 署名URLを開くと、生成された画像を見れる
    image block
    nekoda…
    • CloudShell
      image block
      日本語にはあまり強くないかも…。
    • image of sandwich 指定
      image block