ankuro.dev
← ブログ一覧に戻る
Bedrock retrieve_and_generate API——KB検索と回答生成を1回で完結させる仕組み
2026-03-19#AWS#Bedrock#Knowledge Base#RAG#Lambda

Bedrock retrieve_and_generate API——KB検索と回答生成を1回で完結させる仕組み

Bedrock Knowledge BaseのRAGを実装するとき、検索APIには retrieveretrieve_and_generate の2種類がある。この記事ではその違いと、retrieve_and_generate のリクエスト・レスポンス構造を実装コードをベースに解説する。

対象はカスタムLambdaからKBを呼び出す構成に絞っている。Bedrockの全体アーキテクチャよりも「実際に書くコードの構造」にフォーカスした記事。


retrieve と retrieve_and_generate の違い

API 動作
retrieve KB検索のみ。関連ドキュメントの断片を返す
retrieve_and_generate KB検索 + LLMによる回答生成を1回で完結

retrieve を使う場合、返ってきたドキュメント断片を自分でプロンプトに組み込んでLLMを呼び出す処理が別途必要になる。retrieve_and_generate はその2ステップをまとめて実行してくれるため、シンプルなRAGであればこちらを使うほうが実装コストが低い。

今回のカスタムLambdaでは retrieve_and_generate を採用している。


クライアントは bedrock-agent-runtime

retrieve_and_generatebedrock-agent-runtime クライアントを使う。bedrock-runtime(モデルを直接呼ぶAPI)とは別物なので注意。

import boto3

# bedrock-runtime ではなく bedrock-agent-runtime
client = boto3.client("bedrock-agent-runtime", region_name="ap-northeast-1")
クライアント 主なAPI 用途
bedrock-runtime invoke_model モデルを直接呼ぶ
bedrock-agent-runtime retrieve / retrieve_and_generate / invoke_agent KB・エージェントなどBedrockの上位レイヤーを使う

名前に agent が入っているが、エージェント専用ではなくKnowledge Baseの操作もこちらのクライアントを使う。


リクエスト構造

retrieve_and_generate のリクエストは以下の構造。

response = client.retrieve_and_generate(
    input={"text": query},                          # ユーザーの質問
    retrieveAndGenerateConfiguration={
        "type": "KNOWLEDGE_BASE",
        "knowledgeBaseConfiguration": {
            "knowledgeBaseId": knowledge_base_id,   # KBのID
            "modelArn": model_arn,                  # 回答生成に使うモデル
            "retrievalConfiguration": {
                "vectorSearchConfiguration": {
                    "numberOfResults": 5,           # 検索で取得するドキュメント数
                    "filter": { ... },              # メタデータフィルター(任意)
                }
            },
        },
    },
)

modelArn はリクエスト時に都度指定する

KBの設定画面にも「モデルを選ぶ」箇所があるため混乱しやすいが、役割が異なる。

モデル 役割 設定場所
埋め込みモデル(Titan など) ドキュメントをベクトル化してインデックスを作る KBの設定
生成モデル(Claude など) 検索結果をもとに回答文を生成する APIリクエスト時に指定

retrieve_and_generate は「KB検索」と「回答生成」を1回のAPIで行う設計のため、「どのモデルで生成するか」をリクエストのたびに指定する必要がある。

modelArnの書き方:

region = "ap-northeast-1"
model_arn = f"arn:aws:bedrock:{region}::foundation-model/anthropic.claude-3-haiku-20240307-v1:0"

レスポンスの読み方

レスポンスには回答文と引用元(citations)が含まれる。

answer = response["output"]["text"]   # LLMが生成した回答文

citations = []
for citation in response.get("citations", []):
    for ref in citation.get("retrievedReferences", []):
        citations.append({
            "text": ref.get("content", {}).get("text", ""),      # 参照したドキュメントの断片
            "location": ref.get("location", {}),                  # S3のロケーション情報
        })

citations の役割

citationsには「この回答はどのドキュメントのどの部分を根拠にしているか」が入っている。

{
  "text": "接待費は1人あたり1万円を上限とする",
  "location": {
    "type": "S3",
    "s3Location": {
      "uri": "s3://your-bucket/documents/営業部/営業部_規程.txt"
    }
  }
}

citations が空の場合、フィルター条件に合うドキュメントが見つからなかったことを意味する。回答文の内容はモデルによって変わるため、「ドキュメントが見つかったか」の判定はcitationsの件数で行うのが確実。

if not citations:
    # 該当ドキュメントなし
    ...

ハマりポイント

クロスリージョン推論プロファイルは閉域で使えない

modelArnにクロスリージョン推論プロファイル(apac. プレフィックス)を指定すると、閉域VPC内では ValidationException が発生する。

# NG: クロスリージョン推論プロファイル
model_arn = "arn:aws:bedrock:ap-northeast-1::foundation-model/apac.anthropic.claude-3-haiku..."

# OK: 同一リージョンのモデルARNを直接指定
model_arn = "arn:aws:bedrock:ap-northeast-1::foundation-model/anthropic.claude-3-haiku-20240307-v1:0"

クロスリージョン推論プロファイルは複数リージョンにリクエストをルーティングする仕組みのため、他リージョンへのアウトバウンド通信ができない閉域VPCでは使用不可。GenU標準のLambdaはこのプロファイルを使っていないため発生しないが、カスタムLambdaを新規実装する際に誤ったARNを書くと踏む。

IAMポリシーに3つのアクションが必要

Lambdaの実行ロールに以下を付与する。bedrock:InvokeModel を忘れがち。

{
  "Action": [
    "bedrock:RetrieveAndGenerate",
    "bedrock:Retrieve",
    "bedrock:InvokeModel"
  ],
  "Resource": "*"
}

まとめ

ポイント 内容
クライアント bedrock-agent-runtimebedrock-runtime ではない)
modelArn KBの埋め込みモデルとは別。リクエスト時に生成モデルを指定
クロスリージョンARN 閉域VPCでは使用不可。同一リージョンのARNを直接指定
0件判定 citationsの件数で判定する

→ メタデータフィルタリングの仕組みを解説した記事→ GenUのRAGに部署別アクセス制御を追加した(ハブ記事)