x-amz-bedrock-kb-data-source-id フィールドが欠落する事象について、AWS サポートに問い合わせを行いました。AWS サポートが事象を確認し、担当部署に共有済みとのことです。ベクトルストアに OpenSearch Serverless を使用した場合には発生しないようです。
はじめに
Amazon Bedrock Knowledge Basesを使用してデュアルデータソース構成で検索の精度を検証するの記事では、1 つのナレッジベースに異なるチャンクサイズ設定を持つ 2 つのデータソース(小チャンク設定と大チャンク設定)を配置し、1 回の Retrieve API 呼び出しで両方の利点を活かせるハイブリッド戦略の効果を検証しました。この検証の中で、S3 Vectors をベクトルストアとした場合に、Retrieve API のレスポンスメタデータから x-amz-bedrock-kb-data-source-id フィールドが欠落する事象を確認しました。本記事では、具体的にどのような事象が発生するのかをサンプルコードを用いて検証します。
x-amz-bedrock-kb-data-source-idとは
x-amz-bedrock-kb-data-source-id は、Amazon Bedrock Knowledge Bases が Retrieve API のレスポンスに自動付与するメタデータフィールドの一つです。AWS 公式ドキュメントでは「データソース識別子(コンテンツの出所追跡用)」として定義されており、検索結果がどのデータソースから取得されたかを示します。このフィールドを参照することで、複数のデータソースを持つナレッジベースにおいて、各検索結果の出所を特定できます。
参考情報
構成図
本検証の全体構成を以下に示します。
検証手順
- S3バケットに検証データをアップロードする
- ナレッジベースを作成する。構成図にあるとおり、1 つのナレッジベースに異なるチャンクサイズ設定を持つ 2 つのデータソース(小チャンク設定と大チャンク設定)を配置する。このとき、データソースのタイプは S3 を選択し、同一の S3 バケットを指定する。
- Retrieve API で検索を実行し、レスポンスメタデータを確認する
検証
検証データ
検証データとして、以下のような架空の議事録をMarkdown形式で100件用意しました。これをS3バケットにアップロードします。
検証データ(クリックで展開)
# 議事録: A/Bテスト結果レビューと施策方針
## 基本情報
| 項目 | 内容 |
|------|------|
| 日時 | 2025年02月20日 09:00 〜 09:30 |
| 場所 | Zoom オンライン |
| 担当部門 | プロダクト部門 |
| 文書番号 | MTG-20250220-001 |
## 参加者
- 小林 俊介(品質保証部)(議長)
- 加藤 由美(法務部)(書記)
- 斎藤 明日香(情報システム部)
- 松本 剛(カスタマーサクセス部)
- 佐藤 健(データサイエンス部)
- 吉田 拓也(プロダクト部)
- 鈴木 花子(研究開発部)
- 橋本 隆(営業部)
## 議題
1. A/Bテスト結果レビューと施策方針
2. 現状確認と課題の整理
3. 対応方針の検討
4. 役割分担とスケジュールの確認
5. その他・連絡事項
## 決定事項
- 優先度の判断基準をユーザー影響度と実装コストの2軸で評価することを決定した。
- KPI とマイルストーンを今週中に策定し、全体に共有することを合意した。
- 「A/Bテスト結果レビューと施策方針」の推進方針を承認する。
- 外部ベンダーとの契約交渉を開始することを決定した。
- 上半期末までにリリースを目指すマイルストーンを設定した。
## ネクストアクション
| タスク | 担当者 | 期限 |
|--------|--------|------|
| KPI・マイルストーン草案の作成 | 鈴木 花子 | 今週金曜日 |
| ステークホルダーへの合意取り付け | 加藤 由美 | 今月末 |
| 外部ベンダー選定のための RFP 作成 | 吉田 拓也 | 来月上旬 |
| パイロット実施計画書の作成 | 斎藤 明日香 | 次回MTG前 |
## 議事録
**小林 俊介(議長)**: みなさん、お集まりいただきありがとうございます。本日は「A/Bテスト結果レビューと施策方針」に関して、現状の課題と今後の方向性について話し合います。各自から意見をいただきながら、具体的なアクションにつなげていきたいと思います。よろしくお願いします。
**橋本 隆**: 前回ミーティング以降の進捗を共有します。プロダクト部門では先月比で20%の改善が確認できており、特に処理速度とユーザーの満足度スコアで顕著な向上が見られています。一方で、3週間以内に対応が必要な積み残し課題が5件あり、本日はその優先順位についても整理したいと考えています。
**小林 俊介(議長)**: ありがとうございます。橋本 隆さん、改善が見られているのは良い知らせですね。積み残し課題の詳細を少し教えていただけますか?
**橋本 隆**: 積み残しのうち最も深刻なのはパフォーマンス問題です。ピーク時にレスポンスが3秒以上かかるケースが報告されており、ユーザー体験への影響が出ています。加えて、セキュリティ監査の指摘事項が2件未対応のまま残っており、こちらも早急な対応が必要です。
**斎藤 明日香**: 補足させてください。私のほうでステークホルダーへのヒアリングを実施したのですが、特に速度改善と操作性の向上に対する要望が強く出ていました。また、4社の競合が類似機能を既にリリースしていることも確認しており、対応を急がないと市場での競争優位性が薄れるリスクがあります。
**斎藤 明日香**: ありがとうございます。聞いていて気になったのですが、競合への対応を急ぐ場合、現在の開発リソースで本当に対応できるのでしょうか?今のチームには既に4週間分のバックログが積み上がっていると聞いています。無理に詰め込むと品質が下がりかねません。
**吉田 拓也**: おっしゃる通りで、リソースの問題は深刻です。ただ、全部を一度にやろうとするのではなく、まず最も影響範囲の大きい課題に絞って対応することで、リソースを集中投下できると思います。具体的には、パフォーマンス改善だけに絞れば4週間で成果を出せる見込みです。
**斎藤 明日香**: なるほど、優先順位をしっかり絞るということですね。では何を最優先にするかの判断基準はどうしましょうか?ユーザー影響度ですか、それとも工数の少なさで判断しますか?
**小林 俊介(議長)**: この点は重要なので少し時間を取りたいと思います。皆さん、優先度の判断基準についてご意見はありますか?
**斎藤 明日香**: 予算の観点からも一言申し上げます。現在の計画では当初見積もりより約34%のオーバーランが予想されており、追加承認なしに進める場合は機能スコープを削減する必要があります。優先度判断の際には、この予算制約も加味していただけると助かります。個人的には、まず既存機能の安定化に投資し、新機能開発は次のサイクルに回す方が長期的にはコスト効率が高いと考えています。
**松本 剛**: 法務・コンプライアンスの観点からも確認させてください。今回の対応に個人情報やデータ保護に関わる変更が含まれる場合、法的レビューが必須になります。スケジュールには最低2週間のバッファを見ておいてください。後から修正が入ると余計なコストが発生するので、早い段階で確認を取る流れにしたいです。
**鈴木 花子**: 一つ提案があります。まず小規模PoCを実施して効果を検証するアプローチを採用することで、リスクを最小化しながら早期に価値を届けられると思います。具体的には、第1フェーズでコア機能のみを行い、結果を見て第2フェーズ以降の計画を柔軟に調整する形です。これなら追加の承認待ちをせずに動き出せますし、学習しながら進められます。
**斎藤 明日香**: その方向性には賛成ですが、フェーズの区切り方をもう少し明確にしないと、第1フェーズが終わったタイミングで「まだ終わっていない」という認識のズレが起きやすいです。マイルストーンの定義を具体的にしておく必要があると思います。
**鈴木 花子**: ご指摘ありがとうございます。おっしゃる通りです。マイルストーンの定義とKPIについては、今週中に加藤 由美さんと一緒に叩き台を作り、次回のミーティングまでに共有する形にしましょうか。
**松本 剛**: 私もその進め方が良いと思います。加えて、他部門との連携が必要になる場面では、早めに声掛けをしておいたほうが良いです。特にカスタマーサクセスとの調整は時間がかかることが多いので、並行して進めることを提案します。
**小林 俊介(議長)**: ここまでの議論を整理させてください。方針としては段階的なアプローチで進めることに大きな異論はなさそうです。優先度の判断はユーザー影響度と実装コストの2軸で行い、予算制約も考慮する。KPIとマイルストーンは鈴木 花子さんと加藤 由美さんで今週中に草案を作成する。この方向で進めてよいでしょうか?
**松本 剛**: 概ね賛成です。一点だけ確認させてください。外部ベンダーとの協業が必要になるケースは想定していますか?社内リソースだけで対応できない場合に備えて、早めにコンタクトしておいたほうが安全かもしれません。
**橋本 隆**: それは検討済みです。現時点ではベンダー依存は最小化する方向ですが、専門知識が必要な部分については外部の支援を想定しています。具体的には来月上旬までに選定プロセスを始められるよう、RFPの草案を準備する予定です。
**小林 俊介(議長)**: ありがとうございます。では本日の決定内容と役割分担を確認します。推進方針の承認、KPI・マイルストーンの策定、ベンダー選定の検討、それぞれについて担当と期限を明確にして、次回のミーティングで進捗を確認しましょう。何か追加の懸念点や確認事項はありますか?
**吉田 拓也**: 一点だけ。今後の進捗共有は週次で行うことを提案します。課題が多く、状況が変わりやすいフェーズなので、情報の鮮度を保つことが重要だと思っています。Slackのチャンネルを作って非同期でも共有できる仕組みを作るのも良いかもしれません。
**小林 俊介(議長)**: 良い提案ですね。週次の進捗共有チャンネルを設けましょう。では本日はここまでにします。皆さん、お忙しい中ありがとうございました。引き続きよろしくお願いします。
## サマリー
8名の参加のもと、「A/Bテスト結果レビューと施策方針」に関する現状確認と今後の方針について意見交換が行われた。
既存の仕組みの限界と、新しいアプローチへの移行に伴うリスクについて活発な意見交換が行われた。
短期・中期・長期に分けたロードマップを策定し、早期に効果を確認しながら本格展開へ移行する方針が承認された。
最終的に5件の決定事項が承認され、5件の具体的なアクションアイテムを設定し、担当者が期日内に対応することで合意した。
引き続き週次での進捗確認を行いながら、目標達成に向けて取り組みを継続する。
---
*本議事録は 加藤 由美(書記)が作成しました。*
*内容に誤りがある場合は、会議から3営業日以内に書記までご連絡ください。*%
検証コード
サンプルコード(クリックで展開)
#!/usr/bin/env python3
"""
生データでのデータソースIDメタデータ確認スクリプト
大量の結果を取得して欠落率を検証
"""
import boto3
import json
# 設定
REGION = 'us-east-1'
KB_ID = 'FNHCPWCWDN'
DATASOURCE_SMALL_ID = 'N3NVPIZ7T8'
DATASOURCE_LARGE_ID = 'I1RJGQPEKH'
# テストクエリ
TEST_QUERY = "コンテンツ戦略と顧客の抱える課題"
# Bedrockクライアント作成
client = boto3.client('bedrock-agent-runtime', region_name=REGION)
print(f"Knowledge Base ID: {KB_ID}")
print(f"テストクエリ: {TEST_QUERY}")
# 生データで100件取得
response = client.retrieve(
knowledgeBaseId=KB_ID,
retrievalQuery={'text': TEST_QUERY},
retrievalConfiguration={
'vectorSearchConfiguration': {
'numberOfResults': 100
}
}
)
results = response.get('retrievalResults', [])
total = len(results)
# 統計情報
missing_count = 0
small_count = 0
large_count = 0
metadata_examples: dict[str, dict | None] = {'with_id': None, 'without_id': None}
print(f"実際の取得件数: {total}件\n")
# 各結果を分析
for i, item in enumerate(results, 1):
metadata = item.get('metadata', {})
datasource_id = metadata.get('x-amz-bedrock-kb-data-source-id')
if not datasource_id:
missing_count += 1
# 欠落例を保存(最初の1件のみ)
if not metadata_examples['without_id']:
metadata_examples['without_id'] = {
'index': i,
'metadata': metadata
}
else:
if datasource_id == DATASOURCE_SMALL_ID:
small_count += 1
elif datasource_id == DATASOURCE_LARGE_ID:
large_count += 1
# ID有り例を保存(最初の1件のみ)
if not metadata_examples['with_id']:
metadata_examples['with_id'] = {
'index': i,
'datasource_id': datasource_id,
'metadata': metadata
}
# 結果サマリー
print("=== 検証結果 ===")
print(f"総結果数: {total}件")
print(f"データソースID欠落: {missing_count}件 ({missing_count/total*100:.1f}%)")
print(f"データソースID有り: {total - missing_count}件 ({(total - missing_count)/total*100:.1f}%)")
print(f" - 小チャンク設定: {small_count}件")
print(f" - 大チャンク設定: {large_count}件")
# メタデータの実例を表示
print("\n=== メタデータの実例 ===")
if metadata_examples['with_id']:
ex = metadata_examples['with_id']
print(f"\n【データソースID有りのケース】(結果{ex['index']}番目)")
print(f"データソースID: {ex['datasource_id']}")
print(f"メタデータ: {json.dumps(ex['metadata'], ensure_ascii=False, indent=2)}")
if metadata_examples['without_id']:
ex = metadata_examples['without_id']
print(f"\n【データソースID欠落のケース】(結果{ex['index']}番目)")
print(f"メタデータ: {json.dumps(ex['metadata'], ensure_ascii=False, indent=2)}")
検証結果
検索結果 62 件中 11 件で x-amz-bedrock-kb-data-source-id フィールドが欠落していることが確認できます。このフィールドが欠落しても検索結果そのものには影響しません。しかし、欠落した検索結果はどのデータソースから得たものかが判定できません。
メタデータが取得できた 51 件では、小チャンク設定から 2 件、大チャンク設定から 49 件の結果が得られたことが分かります。この結果から、「意図どおりの結果が得られた」あるいは「検索結果の取得に片寄りがある」などの評価が行えます。一方、欠落した 11 件はどのデータソースからの結果かが判定できないため、評価の対象外となります。
複数のデータソースを持つナレッジベースの検索精度を検証する際には注意が必要です。
Knowledge Base ID: xxxxxxxxxx
テストクエリ: コンテンツ戦略と顧客の抱える課題
実際の取得件数: 62件
=== 検証結果 ===
総結果数: 62件
データソースID欠落: 11件 (17.7%)
データソースID有り: 51件 (82.3%)
- 小チャンク設定: 2件
- 大チャンク設定: 49件
=== メタデータの実例 ===
【データソースID有りのケース】(結果9番目)
データソースID: xxxxxxxxxx
メタデータ: {
"x-amz-bedrock-kb-source-file-modality": "TEXT",
"x-amz-bedrock-kb-data-source-id": "xxxxxxxxxx"
}
【データソースID欠落のケース】(結果1番目)
メタデータ: {
"x-amz-bedrock-kb-source-file-modality": "TEXT"
}
まとめ
特定の環境下において、Retrieve API のレスポンスメタデータから x-amz-bedrock-kb-data-source-id フィールドが欠落する事象が発生することが確認できました。この事象は、ベクトルストアに S3 Vectors を使用した場合に発生し、OpenSearch Serverless を使用した場合には発生しないようです。
複数のデータソースを持つナレッジベースを構築し、x-amz-bedrock-kb-data-source-id フィールドの値を評価の判断材料として使用する場合には注意が必要です。