Amazon Bedrock KnowledgeBase のAPIをLambda と API Gatewayで利用してみた
おはようございます!
株式会社ベンジャミンの木村です!
今回、私はBedrock KnowledgeBaseを使って、以下のような自社のことを回答する簡易チャットアプリを作成しました。

その時の経験をもとに、Bedrock KnowledgeBaseのAPIをLambda + API Gatewayで利用できる手順を記載させていただきます!
目次
構成図
API取得に使っている技術
- Lambda: Python 3.12
- Bedrock Knowledgebase
- 埋め込みモデル:Cohere Embed Multilingual v3
- テキストモデル:Claude 3 Sonnet
- API Gateway:REST API
- Pinecone:無料枠

1. KnowledgeBase + Pineconeの作成
こちらは以下記事を参照し作成してください。
※KnowledgeBase作成後にナレッジベースIDはこの後のLambdaで使用しますので、控えておいてください。

2. Lambdaの作成
2-1. 以下URLよりLambdaのコンソール画面へ移動する
※Lambdaはバージニア北部で作成お願いします
https://us-east-1.console.aws.amazon.com/lambda/home?region=us-east-1#/functions
2-2. 左ペインの「関数」→「関数の作成」をクリックする

2-3. 以下値を入力し、「関数の作成」のボタンをクリックする
- 関数名:任意の値
- ランタイム:Python 3.12
※他はデフォルトの値でOK

2-4. ソースコードを入力し、「Deploy」ボタンをクリックする

ソースコードは下記を使用
※項番1で作成したBedrock KnowledgeBaseのIDを記載ください
import boto3
import json
bedrock_runtime = boto3.client("bedrock-agent-runtime")
def lambda_handler(event, context):
input_text = event.get('inputText')
response = bedrock_runtime.retrieve_and_generate(
input={"text": input_text},
retrieveAndGenerateConfiguration={
"type": 'KNOWLEDGE_BASE',
"knowledgeBaseConfiguration": {
"knowledgeBaseId": "<Bedrock KnowledgeBaseのID>",
"modelArn": "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0",
},
},
)
text = response["output"]["text"]
return {
'statusCode': 200,
'headers': {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS,POST'
},
'body': text
}
2-5. 「設定」タブ→「一般設定」→「編集」ボタンをクリックする

2-6. タイムアウト値を30秒に設定し、「保存」ボタンをクリックする
※API Gatewayのタイムアウトが29秒なのでそれに合わせた時間にしております。

2-7. 「テスト」タブ→「イベントJSON」に以下JSONを記載し、「保存」→「テスト」を実行する
- イベント名:任意の名前
- イベントJSON
{
"inputText": "<BedrockKnowledge Baseにする質問文>"
}

2-8. テストの結果が200ステータス返答があり、bodyにBedrockからの回答があれば作成完了

3. API Gatewayの作成
※この手順で作成する、API GatewayのURLの流出にはくれぐれも気をつけてください。
よりセキュリティを強化したい場合は、項番4で作成するAPI KEYの作成や、項番3-12でaccess-control-allow-originで指定する値を「*」ではなく、アクセスするURLを指定する方法をご検討ください。
3-1. 以下URLよりAPI Gatewayのコンソール画面へ移動する
※API Gatewayはバージニア北部で作成お願いします
https://us-east-1.console.aws.amazon.com/apigateway/main/apis?region=us-east-1
3-2. 左ペインの「API」→「APIを作成」ボタンをクリックする

3-3. 「REST API」の「構築」ボタンをクリックする

※REST APIについてわからない方は、下記Youtubeが大変分かりやすいのでご参照下さい。
3-4. 以下値を入力し、「APIを作成」ボタンをクリックする
- API名:任意の名前
その他はデフォルト値でOK

3-5. 「リソースを作成」ボタンをクリックする

3-6. 以下値を入力し、「リソースを作成」のボタンをクリックする
- リソースパス:「/」のまま
- リソース名:任意の名前
- CORS(クロスオリジンリソース共有):チェックを入れる

[OPTIONSメソッドについて]
CORS(クロスオリジンリソース共有)にチェックを入れると、OPTIONSメソッドが作成されます。こちらは、異なるオリジンからリソースへのアクセスが許可されているかを確認するためのメソッドになります。
「なぜ、こんな処理が必要なのか?」
「オリジン?CORS?何を言っているのかさっぱりだ!」
という方は、下記Youtubeが大変分かりやすいのでご参照下さい。

3-7. 「リソース」→「メソッドを作成」ボタンをクリックする

3-8. 以下値を入力し、「メソッドを作成」ボタンをクリックする
- メソッドタイプ:POST
- 統合タイプ:Lambda関数
- Lambda関数: us-east-1 / 項番2で作成したLambda
※他はデフォルト値でOK

3-9. 「メソッドレスポンス」タブ→「編集」ボタンをクリックする

3-10. 以下値を入力し、「保存」ボタンをクリックする
- ヘッダー名:Access-Control-Allow-Origin
※他はデフォルト値でOK

3-11. 「統合レスポンス」タブ→「編集」ボタンをクリックする

3-12. 以下値を入力し、「保存」ボタンをクリックする
- Mapping value: ‘*’
※シングルクォテーションも含めて記載ください

※APIが流出した場合に備えて、よりセキュリティを強化したい場合は、指定する値を「*」以外にしてください。指定する値については、下記サイトが大変分かりやすいのでご参照下さい。
CORSエラーが出てしまったらヘッダー情報を追加しよう
3-13. 「OPTIONS」→「統合リクエスト」タブ→「編集」ボタンをクリックする

3-14. 以下値を入力し、「保存」ボタンをクリックする
- 統合タイプ:Lambda関数
- Lambda関数: us-east-1 / 項番2で作成したLambda
他はデフォルト値でOK

3-15. 「統合レスポンス」タブ→「編集」ボタンをクリックする

3-16. 以下値を入力し、「保存」ボタンをクリックする
- method.response.header.Access-Control-Allow-Headers: ‘Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token’
- method.response.header.Access-Control-Allow-Methods:’OPTIONS,POST’
- method.response.header.Access-Control-Allow-Origin:’*’

3-17. 「APIをデプロイ」ボタンをクリックする

3-18. 以下値を入力し、「デプロイ」ボタンをクリックする
- ステージ:新しいステージ
- ステージ名:任意の名前

3-19. 「ステージ」→「OPTIONS(もしくはPOST)」をクリックし、表示されたURL(API)を控える

3-20. CloudShellを開き、以下コマンドを入力し、目的の回答があれば完了
curl -X POST -H "Content-Type: application/json" -d '{"inputText": "<質問文>"}' <項番3-17で控えたAPI>

4. API GatewayにAPIキーを設定
項番3までの手順でもAPIは使用可能ですが、API GatewayのURLが流出した場合のセキュリティ対策として、APIキーの設定が必要になります。
4-1. 左ペインの「使用量プラン」→「使用量プランを作成」をクリックする
使用量プランはAPIの使用制限を設定します。今回は制限をかけずにAPIキーのみを設置する設定にします。

4-2. 以下値を入力し、「保存」ボタンをクリックする
- 名前:任意の値
- スロットリング:オフ
- クォータ:オフ

4-3. 「APIステージを追加」ボタンをクリックする

4-4. 以下値を入力し、「使用量プランに追加」ボタンをクリックする
- API:項番3-4で作成したAPI
- ステージ:項番3-18で作成したステージ

4-5. 左ペインの「APIキー」→「APIキーの作成」をクリックする

4-6. 以下値を入力し、「保存」ボタンをクリックする
- 名前:任意の名前
※その他はデフォルトでOK

4-7. 作成した「APIキー」を控え、「使用量プランに追加」ボタンをクリックする

4-8. 以下値を入力し、「保存」ボタンをクリックする
- 使用量プラン:項番4-2で作成した使用量プランを選択する

4-9. 左ペインの「API」→「項番3で作成したAPI」をクリックする

4-10. 「POST」→「メソッドリクエスト」タブ→「編集」ボタンをクリックする

4-11.「APIキーは必須です」にチェック→「保存」ボタンをクリックする

4-12. 「APIをデプロイ」ボタンをクリックする

4-13. 以下値を入力し、「デプロイ」ボタンをクリックする
- ステージ:項番3-18で作成したステージ

4-14. 下記コマンドをCloudShellで実行し、目的の回答があれば完了
curl -X POST -H "Content-Type: application/json" -H "X-API-KEY: <項番4-7で控えたAPIキー>" -d '{"inputText": "<質問文>"}' <項番3-19で控えたAPI>
※反映が少し遅れる場合がありますので、その場合は少々お待ちください
ちなみに項番3-18で実行した以下コマンドをCloudShellで実行してみますと{"message":"Forbidden"}
とエラーになりますので、そちらも合わせてお試しください。
curl -X POST -H "Content-Type: application/json" -d '{"inputText": "<質問文>"}' <項番3-19で控えたAPI>
まとめ
いかがでしょうか? 今回はBedrock KnowledgeBase + Lambda + API GatewayでBedrockのAPIを利用する方法を記載いたしました。
ここまでできれば、Bedrockを利用したアプリ開発ができるようになると思います。
また、Lambdaで利用するBedrockのAPIを変えることで、AgentやノーマルなBedrock APIも利用できるようになりますので、そちらもお試しください。
次は、React上でこちら作成したAPIを利用して、ブラウザ上にBedrockからの返答文を表示されるようにしたいと思います。乞うご期待!!
記事をが完成しましたので、下記よりお試しいただければ嬉しいです!