[Amazon Bedrock] Lambda関数からBedrockを呼び出してみた

Bedrockをプログラムから利用する「最初の一歩」を試してみました。
2023.09.29

みなさん、こんにちは!
福岡オフィスの青柳です。

Amazonの生成AIサービス「Amazon Bedrock」がいよいよ正式公開されました!

みなさん、さっそくBedrockのマネジメントコンソールからいろいろと試してみていらっしゃるのではないでしょうか。

今回は、マネジメントコンソールからではなく「プログラムからBedrockを利用する方法」について試してみました。

Lambda関数からBedrockを呼び出す

BedrockはGUIからの利用のみではなく、プログラムやサービスから利用するためのAPIも用意されています。 また、Bedrockを利用するプログラムを効率良く記述するために、各種プログラム言語向けのSDKも用意されています。

今回は、Python言語で利用できる「AWS SDK for Python」(Boto3) を使って、Lambda関数を作成してみます。

(※) リージョンについて

当記事の執筆時点 (2023/09/29) では、Bedrockが利用可能なリージョンは以下に限られています。

  • バージニア北部 (us-east-1)
  • オハイオ (us-east-2)
  • オレゴン (us-west-2)
  • シンガポール (ap-southeast-1)

今回の記事では、BedrockおよびLambda等全てのAWSサービスについて「バージニア北部」を利用する前提で進めます。

(※ 記事初出時に「シンガポールリージョン」の記載が漏れておりました)

(※) 2023/10/03 追記

上記の4リージョンに加えて「東京リージョン (ap-northeast-1)」でもBedrockが利用可能になりました。
https://dev.classmethod.jp/articles/bedrock-tokyo-region/

なお、「バージニア北部」「オレゴン」以外のリージョンでは利用できるLLMモデルが限られていますので注意してください。

(参考情報) Boto3のバージョンが古い場合の対応方法

当記事の執筆時点 (2023/09/29) では、Lambda関数の標準の状態ではBedrockを利用することができません。 何故なら、Lambda関数に標準で組み込まれているBoto3のバージョンが、Bedrockに対応していないためです。

  • Lambda関数に標準で組み込まれているBoto3のバージョン: 1.27.01
  • Bedrockを利用可能なBoto3のバージョン: 1.28.57

参考: Boto3のバージョン更新履歴ページ
https://github.com/boto/boto3/blob/develop/CHANGELOG.rst

リリース直後のAWSサービスをLambda関数から利用しようとした場合、このようなことが時々あるんですね。

これを解決するには、Lambda関数で最新バージョンのBoto3を利用できるように「Lambdaレイヤー」を設定します。

詳細な手順は上記ブログ記事を参照して頂ければと思いますが、参考までに今回行った設定内容を以下に紹介します。

最新のBoto3ライブラリの取得とzipファイル作成

ローカルPC上で、以下のコマンドラインを実行します。

$ mkdir boto3work
$ pip install -t ./boto3work boto3
$ mv ./boto3work ./python
$ zip -r boto3-1.28.57.zip ./python

これで、最新バージョンのBoto3ライブラリがアーカイブされたzipファイルboto3-1.28.57.zipが作成されました。

Lambdaレイヤーの作成

Lambdaマネジメントコンソールの「レイヤー」から「レイヤーの作成」をクリックして、以下のように設定します。

  • 名前: boto3-1_28_57
  • 説明: boto3 1.28.57
  • アップロード方法: 「.zipファイルをアップロード」を選択
  • (「アップロード」ボタンをクリックして、上記で作成したzipファイルをアップロード)
  • 互換性のあるアーキテクチャ: 「x86_64」「arm64」の両方にチェック
  • 互換性のあるランタイム: 「Python 3.11」にチェック (使用するランタイムに合わせてください)

あとは、Lambda関数を作成する際に、ここで作成したレイヤーを使うように指定すればOKです。

(おまけ) Boto3のバージョンが古い場合のもう一つの対応方法

Lambdaレイヤーを使う方法の他にも、別の対応方法があります。こちらも併せてご確認ください。

準備

Bedrockの「モデル」を利用可能にする

Bedrockマネジメントコンソールの「Model access」から、利用したい「モデル」へのアクセスを有効化しておきます。

具体的な手順は、冒頭で紹介したブログ記事に掲載されていますので、参考にしてください。

AWSの生成AIサービス Amazon Bedrock がリリースされました | DevelopersIO

「利用したい『モデル』へのアクセスを有効化」と書きましたが、現時点で利用可能なモデルは全て有効化しておいて問題ありません。

Bedrockへのアクセス権限を持つIAMロールを作成する

Lambda関数からBedrockのAPIを呼び出すために必要なアクセス権限を定義した「IAMロール」を作成します。

アクセス権限のポリシー定義は以下のようになります:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "bedrock:*",
      "Resource": "*"
    }
  ]
}

信頼関係のポリシー定義は以下のようになります:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "sts:AssumeRole"
      ],
      "Principal": {
        "Service": [
          "lambda.amazonaws.com"
        ]
      }
    }
  ]
}

Lambda関数を作成する

以下のパラメーターを指定してLambda関数を作成します。

  • 関数名: bedrock-example
  • ランタイム情報: Python 3.11
  • アーキテクチャ情報: arm64 (x86_64でも問題ありません)
  • アクセス権限情報
    • 実行ロール: 既存のロールを使用 → 前項で作成したIAMロールを指定

Bedrock APIを呼び出すPythonコードの記述

AWS SDK for Python (Boto3) では、Bedrock関連のライブラリを2つ用意しています。

  • Bedrock: Bedrockの設定などを行う
  • BedrockRuntime: Bedrockのモデルを利用する

今回は、Bedrockのモデルに対して質問を行い回答を返してもらうLambda関数を作成するために、後者の「BedrockRuntime」を使用します。

Bedrockのモデルを呼び出すにはinvoke_modelメソッドを使います。

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/bedrock-runtime/client/invoke_model.html

invoke_modelメソッドを使った最小限のプログラムコードとして、以下のようなコードを用意しました。

lambda_function.py

import boto3
import json

bedrock_runtime = boto3.client('bedrock-runtime')

def lambda_handler(event, context):
    # プロンプトに設定する内容を取得
    prompt = event.get('prompt')

    # 各種パラメーターの指定
    modelId = 'ai21.j2-mid-v1' 
    accept = 'application/json'
    contentType = 'application/json'

    # リクエストBODYの指定
    body = json.dumps({
        "prompt": prompt,
        "maxTokens": 100,
        "temperature": 0.7,
        "topP": 1,
    })

    # Bedrock APIの呼び出し
    response = bedrock_runtime.invoke_model(
    	modelId=modelId,
    	accept=accept,
    	contentType=contentType,
        body=body
    )

    # APIレスポンスからBODYを取り出す
    response_body = json.loads(response.get('body').read())

    # レスポンスBODYから応答テキストを取り出す
    outputText = response_body.get('completions')[0].get('data').get('text')

    print(outputText)

どの「モデル」を使用するのかの指定は、11行目のmodelId = 'ai21.j2-mid-v1'で指定しています。

その他のパラメーターについては、下記ページなどを参照して、適宜設定してください。
Inference parameters for foundation models - Amazon Bedrock

Lambdaレイヤーの設定 (必要な場合のみ)

「(参考情報) boto3のバージョンが古い場合の対応方法」でBoto3最新バージョンのレイヤーを作成した場合は、関数の作成後にレイヤーを追加する必要があります。(画面の一番下までスクロールして「レイヤーの追加」をクリックして設定します)

その他の設定

Bedrock APIの呼び出し〜応答には少し時間がかかる場合がありますので、Lambda関数のタイムアウト時間をデフォルトの「3秒」から増やしておくと良いでしょう。(「30秒」程度で良いかと思います)

Lambda関数を実行する

全ての準備ができましたので、Lambda関数を実行して「Bedrock」を利用してみましょう。

プロンプト (質問の文章) をLambda関数の「イベント」として外部から与えるようにしていますので、「テストイベント」を作成します。

「Test」ボタンを押して「テストイベントを設定」画面を開き、一番下の「イベントJSON」欄に以下のように入力します。

{
  "prompt": "富士山の高さは何メートルですか?"
}

テストイベントを保存した後、再度「Test」ボタンを押すと、指定したテストイベントを指定してLambda関数が実行されます。

ちゃんと回答が返ってきましたね!

おわりに

「Lambdaレイヤー」など、いくつか準備が必要なところもありましたが、比較的簡単にBedrockのAPI (SDK) を使ったプログラムが作れることに驚きました。

もちろん、今回試したプログラムはごくシンプルなものですので、まだまだいろいろな機能や設定を使う方法について調べる余地があると思います。 それでも、最初の一歩として今回ご紹介した内容が参考になれば幸いです。