10月6日、AWSが「Agentic retrieval with LangChain and Amazon Bedrock Knowledge Bases」と題した記事を公開した。この記事では、LangChainとAmazon Bedrock Knowledge Basesを組み合わせ、マルチパートな質問に対応するアジェンティックRAGを構築する方法について詳しく紹介されている。以下に、その内容を紹介する。
「1つの質問」に6つの意図が隠れている問題
RAGアプリケーションで「チェックアウトサービスと在庫サービスを、オンコールエスカレーション・バックアップとリストア・デプロイロールバックの3軸で比較してください」と質問すると、実質的に6つの意図が同時に問われている(2サービス × 3軸)。
通常の類似検索(Similarity Search)は、その6つの意図を1本のクエリベクトルに押し込んで検索する。結果は返ってくる。エラーも出ない。スコアも悪くない。しかし取得されたチャンクは、問いの一部しかカバーしていない。
記事では、この構造的な限界を数字で示している。numberOfResults=5で検索すると、6つのサブ意図のうち4つしかカバーできない。numberOfResults=10に増やすと全6つをカバーできるが、今度はサブ意図が重複して取得されたり、無関係なチャンクが混入したりする無駄が生じる。
| numberOfResults | チャンク数 | コーパス占有率 | カバーしたサブ意図 | 欠落 |
|---|---|---|---|---|
| 5 | 5 | 10% | 4 / 6 | checkout on-call, inventory restore |
| 10 | 10 | 19% | 6 / 6 | なし(ただし重複あり) |
1つのベクトルで6つの意図を表現しようとする限り、この問題は構造的に解決しない。
アジェンティックRAGが何を変えるか
Amazon Bedrock Managed Knowledge BasesのAgenticRetrieveStream APIは、この問題にアプローチを変えて対処する。単一の検索ではなく、プランニングループを実行する。
- 複雑な質問をサブクエリに分解する
- それぞれのサブクエリを個別に検索する
- 取得した証拠が十分かどうかを判断する
- 不十分なら再検索する
LangChainからはlangchain_awsパッケージのagentic_retrieve関数として呼び出せる。
from langchain_aws.retrievers.bedrock import agentic_retrieve
result = agentic_retrieve(
knowledge_base_id=KB_ID,
query=COMPLEX_QUERY,
region_name=REGION,
generate_response=True,
number_of_results=10,
)
print(result["generatedResponse"]["answer"])
generate_response=Trueを指定すると、取得したチャンクからの回答生成と引用情報も一緒に返ってくる。別途モデル呼び出しを組む必要がない。
一方、AmazonKnowledgeBasesRetriever(標準のLangChainリトリーバー)とは異なり、agentic_retrieveはストリーミングAPIのラッパーであるため、BaseRetrieverインターフェースには適合していない。**AmazonKnowledgeBasesRetrieverにフラグ一つで切り替えるオプションは存在しない**点に注意が必要だ。
プランナーの内部を見る:traceイベントの読み方
agentic_retrieveヘルパーはプランニングの内部ステップを捨てて最終結果だけを返す。プランナーがどう質問を分解したかを確認したい場合は、bedrock-agent-runtimeクライアントのagentic_retrieve_streamを直接呼ぶ必要がある。
runtime = boto3.client("bedrock-agent-runtime", region_name=REGION)
response = runtime.agentic_retrieve_stream(
messages=[{"role": "user", "content": {"text": COMPLEX_QUERY}}],
retrievers=[{
"configuration": {
"knowledgeBase": {
"knowledgeBaseId": KB_ID,
"retrievalOverrides": {"maxNumberOfResults": 10},
}
}
}],
agenticRetrieveConfiguration={
"foundationModelType": "MANAGED",
"rerankingModelType": "MANAGED",
"maxAgentIteration": 5, # デフォルト値。4未満だとプランナーが分解を止める
},
generateResponse=False,
)
for event in response["stream"]:
if "traceEvent" in event:
attrs = event["traceEvent"]["attributes"]
print(f"{attrs.get('step')}: {attrs.get('status')}")
maxAgentIterationの値が4未満になるとプランナーがクエリ分解を停止するという挙動は見落としがちな仕様だ。デフォルトの5から下げる際は注意が必要である。
権限設定の落とし穴
IAM設定では見落としやすいポイントがある。bedrock:GetDocumentContentだ。
アジェンティック検索にはFullDocumentExpansionというステップがあり、取得したパッセージの文脈が不十分だと判断された場合にドキュメント全体を取得しにいく。bedrock:Retrieveだけを付与したポリシーでは、この時点でクエリが途中で失敗する。
{
"Sid": "AgenticRetrievalAndPlannerModel",
"Effect": "Allow",
"Action": [
"bedrock:AgenticRetrieveStream",
"bedrock:InvokeModelWithResponseStream"
],
"Resource": "*"
},
{
"Sid": "RetrieveAndFullDocumentExpansion",
"Effect": "Allow",
"Action": ["bedrock:Retrieve", "bedrock:GetDocumentContent"],
"Resource": "arn:aws:bedrock:<region>:111122223333:knowledge-base/<knowledge-base-id>"
}
なおbedrock:AgenticRetrieveStreamとbedrock:InvokeModelWithResponseStreamはKnowledge Base ARNへのスコープが効かないため、Resource: "*"が必要となる。
どちらを使うべきか
記事は「アジェンティック検索を常に使え」とは言っていない。
- 単一の明確な意図を持つ質問:標準の
AmazonKnowledgeBasesRetrieverが適切。1回の呼び出しで低レイテンシ、コスト低。 - 複数サービス・複数軸の比較、または複合条件の質問:アジェンティック検索が有効。ただし複数回のモデル呼び出しが発生するためコストと時間がかかる。
本番アシスタントが受ける質問の大半は前者の形をしており、すべての質問にプランニングループを使うのは無駄だ、と記事は明示している。
また、boto3>=1.43.32が必須要件で、agentic_retrieve_streamはそれ以前のバージョンには存在しない点も事前確認が必要である。
詳細はAgentic retrieval with LangChain and Amazon Bedrock Knowledge Basesを参照していただきたい。




