ヌーラボで Product SREs for Backlog を担当している 山崎 です。普段はSREの役割を担っていますが、生成AI分野の知識を深めようと日々学習を重ねています。
SREの取り組みについては、ぜひこちらの記事を御覧ください。
【10問10答】SRE 山崎 / ユーザーに近い環境が自身を成長させている。“リアルな声”が新たな挑戦の原動力に
Product SREs for Backlogの日常的なタスクの取り組みを紹介- プロダクトバックログの改善や生成AIなど幅広くチャレンジ –
目次
はじめに
社内文書などを検索し生成AIによって要約された回答を得る RAG (Retrieval-Augmented Generation) を構築する事例を多く見かけるようになりました。
RAGは、大規模言語モデル (LLM) を活用した情報検索と生成を組み合わせたアプローチです。独自のデータや文書をベクトルデータベースに格納し、ユーザーの質問に関連する情報を検索した上で、LLMがその情報を基に回答を生成します。これにより、最新かつ正確な情報に基づいた応答が可能となります。このような特徴を活かし、社内文書の検索や顧客サポートなどのアプリケーションで活用されています。
Amazon Bedrockでは、Knowledge Basesのデータストアに文書とともにメタデータファイルを配置することで検索を行う際にメタデータに基づいたフィルタリングが行えます。キーワード指定や数字の大小といった条件でフィルタリングを行うことでRAGの検索精度向上が期待できます。また、検索を行うユーザーの属性にもとづいてアクセス可能な範囲を絞り込むといった権限管理を行うことも可能です。
社内文書を用いてRAGを構築する際、所属部署や役職などの属性に沿ったアクセス権を整備したいケースがあります。このようなケースでは、このフィルタリングが有用ではないでしょうか。
この記事では、ユーザーの属性に基づいたフィルタリングとメタデータファイルの例を考えます。
参考情報
- Knowledge Bases for Amazon Bedrock がメタデータフィルタリングをサポートし検索精度向上
- Multi-tenant RAG with Amazon Bedrock Knowledge Bases
- Configure and customize queries and response generation
- RetrievalFilter
- MetadataAttribute
- MetadataAttributeValue
ユースケース
この記事のユースケースは以下のとおりです。
ユーザーは自分が所属するプロジェクトに関する文書を検索できます。メタデータフィルタを使って特定のプロジェクトIDに紐付く文書を絞り込み、検索することができます。これにより、ユーザーは所属していないプロジェクトの文書にアクセスすることもLLMから回答を得ることもできません。
社内文書にもとづいたRAGや、マルチテナント向けに提供するRAGでこのようなケースが当てはまるのではないでしょうか。

構成図
アプリケーションの構成は以下のとおりです。S3バケットに文書とメタデータファイルを配置し、ベクトルストアはPineconeを使用します。

RAGの要素
使用する文書
IPA(独立行政法人情報処理推進機構)、総務省、経済産業省が刊行したものをRAGのデータとして使用します。文書名とProjectIDは以下の表のとおりです。ひとつの文書には、章などに別れて複数のPDFファイルが含まれます。
|
ProjectID |
刊行者 |
文書名 |
|---|---|---|
|
1 |
IPA |
|
|
2 |
IPA |
|
|
3 |
IPA |
|
|
4 |
IPA |
|
|
5 |
経済産業省 |
|
|
6 |
総務省 |
サイバーセキュリティの基礎知識 ( PDF版 ) |
|
7 |
総務省 |
|
|
8 |
総務省 |
メタデータファイル
それぞれの文書に対して、以下のメタデータファイルを用意します。メタデータファイルは、元の文書名に.metadata.jsonというサフィックスを付与して命名します。
ここではProjectIdに着目するので、それ以外のフィールドは参考程度に捉えてください。
{
"metadataAttributes": {
"PageURL": {
"value": {
"type": "STRING",
"stringValue": "https://www.ipa.go.jp/archive/security/crypto/dev_setting.html"
}
},
"PageTitle": {
"value": {
"type": "STRING",
"stringValue": "情報漏えいを防ぐためのモバイルデバイス等設定マニュアル"
}
},
"FileURL": {
"value": {
"type": "STRING",
"stringValue": "https://www.ipa.go.jp/archive/security/crypto/gmcbt80000005tnj-att/000026760.pdf"
}
},
"FileTitle": {
"value": {
"type": "STRING",
"stringValue": "解説編(PDF:2.0 MB)"
}
},
"Category": {
"value": {
"type": "STRING",
"stringValue": "crypto"
}
},
"ProjectId": {
"value": {
"type": "STRING",
"stringValue": "1"
}
}
}
}
これらのメタデータはそれぞれ PageURL や ProjectId といったキーの他に、値のタイプが文字列であることを示すSTRING、文字列型の値を示す stringValue とその値といった要素で構成されています。
ProjectIdのタイプ
ProjectIdは数値 (2や4など) を使用しているため、typeをSTRINGではなくNUMBERとすることも考えられます。しかし、Configure and customize queries and response generationの Manual metadata filtering をみると、IN句がサポートするデータタイプは string list と書かれています。そのため、データタイプは NUMBER ではなく STRING を指定し"2"のようにクォートで囲みます。
動作確認
コード
上記を踏まえ、RetrieveAndGenerate APIを使って動作を確認します。モデルにはクロスリージョン推論のプロファイルを設定していますが、他のモデルでも動作します。コストや生成される回答の精度などによりモデルを選択します。
import json
import logging
import sys
from typing import Any, Dict
import boto3
logging.basicConfig(format="%(asctime)s [%(levelname)s] %(message)s", level=logging.INFO)
logger = logging.getLogger(__name__)
def generate_queries(input_text: str) -> Dict[str, Any]:
client = boto3.client(
service_name='bedrock-agent-runtime',
region_name="us-east-1",
)
return client.retrieve_and_generate(
input={
"text": input_text
},
retrieveAndGenerateConfiguration={
"type": 'KNOWLEDGE_BASE',
"knowledgeBaseConfiguration": {
"knowledgeBaseId": "ナレッジベースID", # ナレッジベースIDを指定
"modelArn": "arn:aws:bedrock:us-east-1:531713114752:inference-profile/us.anthropic.claude-3-5-sonnet-20241022-v2:0",
'generationConfiguration': {
'inferenceConfig': {
'textInferenceConfig': {
'maxTokens': 2048,
'temperature': 0,
}
},
},
'retrievalConfiguration': {
'vectorSearchConfiguration': {
'numberOfResults': 5,
'overrideSearchType': 'SEMANTIC',
"filter": {
"in":{
"key": "ProjectId",
"value": ["4", "5", "8"] # 検索対象のProjectIdを指定
}
}
}
},
'orchestrationConfiguration': {
'queryTransformationConfiguration': {
'type': 'QUERY_DECOMPOSITION'
}
},
},
},
)
def main():
# コマンドライン引数を取得する
if len(sys.argv) < 2:
print("Usage: python3 ./app.py <input_text>")
sys.exit(1)
input_text = sys.argv[1]
logger.info("Original query: %s", input_text)
queries_response = generate_queries(input_text)
print("Queries response: %s", json.dumps(queries_response, indent=2, ensure_ascii=False))
print(queries_response["output"]["text"])
if __name__ == "__main__":
main()
クエリ
ProjectIdに 4, 5, 8を指定
先のユースケースにあげたユーザーAがProjectId 4 , 5 , 8 の情報にアクセスできるものとしてクエリを実行します。
"filter": {
"in":{
"key": "ProjectId",
"value": ["4", "5", "8"] # 検索対象のProjectIdを指定
}
}
python ./app.py "生成AIの活用について行政と民間企業のそれぞれが気をつけることを解説してください。"
レスポンスを確認すると、ProjectId 4 , 5 , 8 を参照していることが分かります。(INFOログから抜粋)
"metadata": {
"x-amz-bedrock-kb-source-uri": "s3://xxxxx/meti/mono_info_service/ai_shakai_jisso/1.
01/20241122_1.pdf",
"FileTitle": "「AI事業者ガイドライン(第1.01版)」本編(PDF形式:1,827KB)",
"FileURL": "https://www.meti.go.jp/shingikai/mono_info_service/ai_shakai_jisso/pdf/20241122_1.pdf",
"x-amz-bedrock-kb-document-page-number": 15.0,
"Category": "guideline",
"PageURL": "https://www.meti.go.jp/shingikai/mono_info_service/ai_shakai_jisso/20240419_report.html",
"x-amz-bedrock-kb-data-source-id": "X1GCYEGGH5",
"PageTitle": "AI事業者ガイドライン(第1.01版)本編",
"ProjectId": "5"
}
...
"metadata": {
"x-amz-bedrock-kb-source-uri": "s3://xxxxxx/soumu/whitepaper/2024/n1510000.pdf",
"FileTitle": "国民・企業における利用状況",
"FileURL": "https://www.soumu.go.jp/johotsusintokei/whitepaper/ja/r06/pdf/n1510000.pdf",
"x-amz-bedrock-kb-document-page-number": 3.0,
"Category": "whitepaper",
"PageURL": "https://www.soumu.go.jp/johotsusintokei/whitepaper/ja/r06/pdf/index.html",
"x-amz-bedrock-kb-data-source-id": "X1GCYEGGH5",
"PageTitle": "令和6年版情報通信白書",
"ProjectId": "8"
}
...
"metadata": {
"x-amz-bedrock-kb-source-uri": "s3://xxxxx/ipa/whitepaper/2024/2024_Chap3.pdf",
"FileTitle": "「情報セキュリティ白書2024」3章(PDF:5.9 MB)",
"FileURL": "https://www.ipa.go.jp/publish/wp-security/eid2eo0000007gv4-att/2024_Chap3.pdf",
"x-amz-bedrock-kb-document-page-number": 17.0,
"Category": "whitepaper",
"PageURL": "https://www.ipa.go.jp/publish/wp-security/2024.html",
"x-amz-bedrock-kb-data-source-id": "X1GCYEGGH5",
"PageTitle": "第3章 情報セキュリティ対策強化や取り組みの動向",
"ProjectId": "4"
}
そして、以下のような回答が得られました。
行政側の観点からは、以下の点に注意を払う必要があります: 1. 個人の権利・利益保護:AIによるプロファイリングを行う際は、個人の尊厳を尊重し、予測や判断の限界を理解した上で利用する必要があります 。 2. 不当な操作の防止:人間の意思決定や感情を不当に操作することを目的としたAIシステムの開発・提供・利用を行わないようにします。 3. 社会的影響への配慮:特に選挙やコミュニティでの意思決定など、社会に重大な影響を与える場面でのAI出力については慎重に取り扱う必要があ ります。 4. 包摂性の確保:情報弱者や技術弱者を生じさせないよう、社会的弱者によるAIの活用を容易にすることに注意を払います。 民間企業の観点からは、以下の点に注意を払う必要があります: 1. セキュリティリスクへの対応:社内情報の漏洩などのセキュリティリスクに十分な注意を払う必要があります。 2. 著作権への配慮:生成AIの使用に際して、著作権等の権利侵害に注意を払う必要があります。 3. 出力情報の検証:生成AIから出力された情報の正確性を確認し、虚偽情報の拡散を防ぐ必要があります。 4. プライバシーの保護:個人情報が意図せず学習されないよう、データ入力時の配慮が必要です
ProjectIdに 4, 6, 7を指定
先のユースケースにあげたユーザーBがProjectId 4, 6, 7 の情報にアクセスできるものとしてクエリを実行します。
"filter": {
"in":{
"key": "ProjectId",
"value": ["4","6","7"]
}
}
python ./app.py "生成AIの活用について行政と民間企業のそれぞれが気をつけることを解説してください。"
レスポンスを確認すると、ProjectId 4 のみを参照していることが分かります。(INFOログから抜粋)
回答に必要な情報はProjectID 4, 5, 8にあるものの、ProjectID 5, 8が検索対象に含まれないためProjectId 4のみで回答が生成されました。
"metadata": {
"x-amz-bedrock-kb-source-uri": "s3://xxxxx/ipa/whitepaper/2024/2024_Chap2.pdf",
"FileTitle": "「情報セキュリティ白書2024」2章(PDF:7.3 MB)",
"FileURL": "https://www.ipa.go.jp/publish/wp-security/eid2eo0000007gv4-att/2024_Chap2.pdf",
"x-amz-bedrock-kb-document-page-number": 74.0,
"Category": "whitepaper",
"PageURL": "https://www.ipa.go.jp/publish/wp-security/2024.html",
"x-amz-bedrock-kb-data-source-id": "X1GCYEGGH5",
"PageTitle": "第2章 情報セキュリティを支える基盤の動向",
"ProjectId": "4"
}
...
"metadata": {
"x-amz-bedrock-kb-source-uri": "s3://xxxxx/ipa/whitepaper/2024/2024_Chap4.pdf",
"FileTitle": "「情報セキュリティ白書2024」4章(PDF:4.9 MB)",
"FileURL": "https://www.ipa.go.jp/publish/wp-security/eid2eo0000007gv4-att/2024_Chap4.pdf",
"x-amz-bedrock-kb-document-page-number": 27.0,
"Category": "whitepaper",
"PageURL": "https://www.ipa.go.jp/publish/wp-security/2024.html",
"x-amz-bedrock-kb-data-source-id": "X1GCYEGGH5",
"PageTitle": "第4章 注目のトピック",
"ProjectId": "4"
}
...
"metadata": {
"x-amz-bedrock-kb-source-uri": "s3://xxxxx/ipa/whitepaper/2024/2024_Chap4.pdf",
"FileTitle": "「情報セキュリティ白書2024」4章(PDF:4.9 MB)",
"FileURL": "https://www.ipa.go.jp/publish/wp-security/eid2eo0000007gv4-att/2024_Chap4.pdf",
"x-amz-bedrock-kb-document-page-number": 30.0,
"Category": "whitepaper",
"PageURL": "https://www.ipa.go.jp/publish/wp-security/2024.html",
"x-amz-bedrock-kb-data-source-id": "X1GCYEGGH5",
"PageTitle": "第4章 注目のトピック",
"ProjectId": "4"
}
...
"metadata": {
"x-amz-bedrock-kb-source-uri": "s3://xxxxx/ipa/whitepaper/2024/2024_Chap3.pdf",
"FileTitle": "「情報セキュリティ白書2024」3章(PDF:5.9 MB)",
"FileURL": "https://www.ipa.go.jp/publish/wp-security/eid2eo0000007gv4-att/2024_Chap3.pdf",
"x-amz-bedrock-kb-document-page-number": 17.0,
"Category": "whitepaper",
"PageURL": "https://www.ipa.go.jp/publish/wp-security/2024.html",
"x-amz-bedrock-kb-data-source-id": "X1GCYEGGH5",
"PageTitle": "第3章 情報セキュリティ対策強化や取り組みの動向",
"ProjectId": "4"
}
そして、以下のような回答が得られました。
生成AIは公共機関、民間企業、非営利団体など、あらゆる種類・規模の組織で活用可能です。組織が生成AIを導入・活用する際には、以下の主要な リスクに注意を払う必要があります: 1. プライバシー保護とセキュリティ - 個人情報や生体情報の漏えい防止 - サイバー攻撃やフィッシングへの対策 - 情報セキュリティの確保 2. 情報の信頼性 - 誤情報や虚偽情報の拡散防止 - 出力情報の正確性の確認 - 真偽不明な情報の取り扱い 3. 具体的な注意点として: - 入力データに関するプライバシーへの配慮 - 出力された情報の正確性の確認 - 生成された情報の適切な活用方法の確立 - 虚偽情報の不用意な拡散防止 - 情報の真実性や事実関係の慎重な確認 特に組織での活用においては、既存のシステムとの連携や社内規定との整合性、セキュリティ対策、プライバシー保護などを総合的に検討することが重要です。
ユースケースに当てはめた場合
先の図に示したようなユースケースを実現する場合は、前段階で認証・認可などの仕組みを利用したProjectIDの取得が必要です。例えばチャットアプリでは、ログインを行った際にProjectIDを取得する方法が考えられます。マルチテナントでこのようなRAGを利用する場合は、ProjectIDに加えてTenantIDで絞り込む方法が考えられます。もっとも、マルチテナントの場合はテナントごとにknowledge baseを分けるほうが安全です。
マルチテナントの考え方については、AWS Blog Multi-tenant RAG with Amazon Bedrock Knowledge Bases が参考になります。
まとめ
AWS BedrockのメタデータフィルタリングでIN句を使ったフィルタリングを検証しました。ProjectIDを条件にしたフィルタリングで、ユーザーの属性にあわせた検索結果が得られました。このようなフィルタリングを活用することで、プロジェクトメンバー限定の文書を検索し、生成AIにアイデアを求めるといった使い方に応用できるのではないでしょうか。
メタデータファイルは柔軟に記述できるため、様々な要素を用意しフィルタリングに活用できます。メタデータフィルタリングは、値の大小や含む・含まない、AND/ORといった指定が可能です。これらから、検索画面のプルダウンメニューで文書カテゴリや作成年の範囲などを指定し、絞り込んだ内容に基づいて生成AIに回答を求めるといった使い方も考えられます。
この記事がAWS Bedrockの活用にお役に立てれば幸いです。