【ITニュース解説】Building Your First RAG System with Amazon Bedrock Agents and FAISS: A Developer's Journey

2025年09月03日に「Dev.to」が公開したITニュース「Building Your First RAG System with Amazon Bedrock Agents and FAISS: A Developer's Journey」について初心者にもわかりやすいように丁寧に解説しています。

作成日: 更新日:

ITニュース概要

Amazon Bedrock AgentsとFAISSを使い、初めてのRAGシステム構築法を解説。FAISSはローカルで動く高速なベクトルデータベースで、RAGの基本概念学習やプロトタイプ開発に最適だ。大規模言語モデルと外部データ連携の基礎が学べる。

ITニュース解説

AIを活用したインテリジェントなアプリケーション開発、特に生成AIの分野では、大規模言語モデル(LLM)が注目を集めている。しかし、LLMが学習した知識だけでは、常に最新の情報や特定の専門知識に対応することは難しいという課題がある。この課題を解決するための一つの強力な技術が、RAG(Retrieval-Augmented Generation、検索拡張生成)システムだ。RAGは、外部の知識源から関連情報を検索し、その情報をLLMに与えることで、より正確で、最新の、文脈に沿った回答を生成させる技術である。本解説では、システムエンジニアを目指す初心者がRAGシステムの基本を理解し、実際に構築を体験できるよう、Amazon Bedrock AgentsとFAISS(Facebook AI Similarity Search)を組み合わせたRAGシステムの構築手法を詳しく説明する。

RAGシステムを初めて構築する際に、FAISSを利用することには多くのメリットがある。FAISSは、テキストデータを数値の塊である「ベクトル」に変換し、それらのベクトルの中から似たものを高速に探し出すためのライブラリだ。最大の利点は、FAISSがローカル環境で動作し、追加のAWSインフラ設定や費用なしで利用できる点にある。これにより、データベースの設定に手間取ることなく、RAGシステムの核となる「検索」の仕組みに集中して学習できる。FAISSは高速な検索を可能にし、ベクトル操作に対する完全な制御を提供するため、実験やプロトタイプ開発に最適だ。本番環境への移行時には、Amazon OpenSearch ServerlessやAmazon MemoryDBのような、より大規模でマネージドなソリューションを検討することになるが、まずはFAISSで基礎を固めるのが良いアプローチである。

今回構築するRAGシステムは、以下の主要なコンポーネントで構成される。Amazon Bedrock Agentsは、システム全体のオーケストレーション(各コンポーネントの連携を調整すること)、推論、LLMとの対話を担当する。FAISSは、テキストが数値化されたベクトルデータを保存し、ユーザーからの問い合わせに対して類似するベクトルを検索する役割を果たす。そして、Custom Action Group(カスタムアクショングループ)が、Bedrock AgentとFAISSの間の橋渡しをする。システム全体の流れは、ユーザーからの問い合わせがまずBedrock Agentに送られ、Bedrock Agentは適切なアクショングループを呼び出す。アクショングループはFAISSに検索を依頼し、FAISSは関連する情報を返す。この情報は「コンテキスト」としてBedrock Agentを通じてLLMに渡され、LLMがそのコンテキストに基づいて最終的な回答を生成するという仕組みである。

FAISSをローカル環境でセットアップするには、いくつかのPythonライブラリが必要となる。テキストデータを数値ベクトルに変換するsentence_transformers、ベクトルを保存して検索するfaiss、数値計算を行うnumpy、そしてAWSサービスとの連携に使うboto3などだ。まず、SentenceTransformerモデルを用いてテキストデータを384次元の数値ベクトル(埋め込みベクトル)に変換し、FAISSのインデックスを初期化する。このインデックスは、テキストデータの意味的な類似度を効率的に計算するために使用される。同時に、元のドキュメントとその付随情報(メタデータ)を保存するためのシンプルなPython辞書も用意する。

ドキュメントの取り込みは、FAISSDocumentStoreというクラスによって管理される。このクラスは、まず指定された埋め込みモデル(例えばall-MiniLM-L6-v2)を初期化し、それを使ってテキストを埋め込みベクトルに変換する。変換された埋め込みベクトルはFAISSインデックスに追加され、元のテキストとメタデータは内部の辞書に保存される。この仕組みにより、後で類似するテキストを検索した際に、元のテキストやその情報を素早く取得できるようになる。また、searchメソッドは、与えられたクエリを埋め込みベクトルに変換し、FAISSインデックスで最も類似度の高いドキュメントを検索して、その結果を返す役割を担う。

次に、Bedrock AgentとFAISSを連携させるためのアクショングループを構築する。これは、AWS Lambda関数として実装される。Lambda関数は、Bedrock Agentから「ドキュメントを検索してほしい」というリクエストを受け取ると、そのリクエストに含まれるクエリ(問い合わせ内容)を解析する。そして、先ほど作成したFAISSDocumentStoresearchメソッドを呼び出し、FAISSによる類似ドキュメント検索を実行する。検索結果が得られたら、それをBedrock Agentが理解できる形式(例えば、取得したドキュメントの内容、類似度スコア、メタデータを含むJSON形式)に整形してAgentに返す。このLambda関数が、Bedrock AgentとローカルのFAISS検索機能をつなぐ重要な役割を果たすのだ。

Bedrock Agent自体の設定は、AWS CLI(コマンドラインインターフェース)を使って行う。まず、Agentの名前、説明、使用する基盤モデル(例: AnthropicのClaude 3 Sonnet)、そしてAgentがどのように振る舞うべきかを示す指示文(プロンプト)を設定してAgentを作成する。Agentが作成されたら、次にアクショングループをAgentに紐づける。これには、アクショングループの名前、説明、そして先ほどデプロイしたLambda関数のARN(Amazonリソースネーム)、そしてそのアクショングループがどのようなAPIを公開しているかを示すOpenAPIスキーマ定義が必要となる。このOpenAPIスキーマによって、Bedrock Agentはアクショングループの機能を理解し、いつ、どのような引数でそれを呼び出せば良いかを判断できる。

FAISSインデックスに実際にドキュメントをロードする際は、サンプルとなるテキストデータと、それに付随するメタデータ(例えば、どのAWSサービスについて書かれているか、カテゴリは何かなど)を用意し、FAISSDocumentStoreadd_documentsメソッドを使ってインデックスに追加する。これにより、FAISSはこれらのドキュメントの埋め込みベクトルを内部に保持し、検索可能な状態になる。システムが正しく機能しているかを確認するために、まずdoc_store.searchメソッドを直接呼び出して、特定のクエリに対してFAISSが適切に類似ドキュメントを返しているかをテストすることが重要だ。これにより、検索コンポーネントが単体で動作することを確認できる。

Bedrock Agentとの連携テストでは、boto3ライブラリを使ってPythonプログラムからBedrock Agentを呼び出す。bedrock_agent_runtime.invoke_agentメソッドに、Agent ID、Agent Alias ID、セッションID、そしてユーザーの問い合わせテキストを渡すことで、Agentとの対話を開始する。Agentは内部でアクショングループを呼び出してFAISS検索を行い、その結果に基づいてLLMが最終的な回答を生成し、その応答がプログラムにストリーミング形式で返される。このようにプログラム的にAgentと対話することで、RAGシステム全体のエンドツーエンドの動作を検証できる。

FAISSのパフォーマンスを最適化するためには、データ量に応じて適切なインデックスタイプを選択することが重要だ。小規模なデータセットではIndexFlatIPで十分だが、より大規模なデータセットでは、検索を高速化するIndexIVFFlatのようなインデックスタイプを検討すべきである。また、利用可能なGPUがある場合は、FAISSのGPUサポートを有効にすることで、検索処理を大幅に高速化できる。RAGシステム構築における一般的な落とし穴として、埋め込みモデルの一貫性の確保がある。ドキュメントのインデックス作成時とクエリの埋め込み生成時に、常に同じ埋め込みモデルを使用しないと、類似度検索の精度が著しく低下する。また、コサイン類似度を使用する場合は、埋め込みベクトルを必ず正規化する必要がある。大規模なドキュメントセットを扱う場合は、メモリ不足を避けるために、ドキュメントの追加をバッチ処理で行うことも重要である。

このFAISSをローカルで利用するアプローチは、RAGシステムの基礎を学ぶ上で非常に優れている。しかし、本番環境での利用を考える際には、いくつかの重要な考慮点がある。FAISSインデックスはメモリ上に構築されるため、システムを再起動するとデータが失われる。そのため、faiss.write_indexを使ってインデックスをディスクに保存し、必要に応じてロードする「永続化」が必要となる。スケーラビリティを確保するためには、Amazon OpenSearch Serverlessのような、マネージドなベクトルデータベースソリューションへの移行が推奨される。さらに、Lambda関数のログやメトリクスを監視し、適切なIAMロールやVPC設定によってセキュリティを強化することも不可欠である。このアプローチは、RAGの概念を深く理解し、段階的に洗練されたシステムへと発展させるための確実な第一歩となる。