多くのRAGシステム開発者が直面する問題は、「なんとなく動くが、本当に精度が高いのか分からない」「プロンプトやチャンキングを調整しても、改善したのか客観的に判断できない」といった、品質評価と改善の壁です。特に、ハルシネーションや不適切な回答は、ビジネスへの信頼性低下に直結しかねません。
この記事では、RAGシステムを高精度化し、その品質を担保するための評価駆動開発の実践手法を解説します。RAGの精度を客観的に測定する具体的なメトリクスと、LangChain・RAGASを用いた評価パイプラインの構築、そして評価結果に基づいた改善アプローチまでを網羅的にご紹介します。
RAGシステムの精度評価がなぜ重要なのか
RAG(Retrieval Augmented Generation)システムは、LLMに外部知識を与えることで、ハルシネーションを抑制し、より正確で最新の回答を生成する強力な手法です。しかし、その性能は、情報の検索精度とLLMによる回答生成品質の両方に依存します。
感覚的な調整では、システム全体の品質を保証できません。例えば、チャンクサイズを変更した結果、特定の質問には良くなったが、別の質問では悪化した、といった「サイレントな品質低下」を見逃すリスクがあります。
RAGシステムにおける精度評価は、以下の目的のために不可欠です。
- ハルシネーションの抑制: 不正確な情報を生成していないかを確認する。
- 回答の関連性と正確性: ユーザーの質問に対して、適切で正確な回答を提供できているかを測定する。
- コンテキストの有効性: 検索されたドキュメントが、回答生成に十分かつ関連性の高い情報を含んでいるかを検証する。
- 継続的な改善: 変更がシステムに与える影響を客観的に把握し、効率的なチューニングを可能にする。
RAG評価の主要メトリクスとRAG Triad
RAGシステムの評価には、検索(Retrieval)と生成(Generation)の両側面から複数のメトリクスを使用します。主要なメトリクスとして、以下の5つが挙げられます。
- コンテキストの関連性 (Context Relevance): 検索されたドキュメントが、質問に対してどれだけ関連性が高いか。
- コンテキストの十分性 (Context Sufficiency): 検索されたドキュメントが、回答生成に十分な情報を含んでいるか。
- 回答の関連性 (Answer Relevance): 生成された回答が、質問に対してどれだけ関連性が高いか。
- 回答の正確性 (Answer Correctness): 生成された回答が、事実とどれだけ一致しているか。
- 回答のハルシネーション (Answer Hallucination) / 根拠性 (Groundedness): 生成された回答が、検索されたコンテキストにどれだけ基づいているか。コンテキストにない情報を生成していないか。
これらのうち、特に重要な「Context Relevance(コンテキスト関連性)」「Groundedness(根拠性)」「Answer Relevance(回答関連性)」の3つは、RAG Triadとして知られ、LLMの応答の信頼性と文脈的正確性を評価するための強力なフレームワークとなります。
LangChainとRAGASによるRAG精度評価の実践
ここでは、RAG評価に広く利用されているオープンソースライブラリRAGASと、LLMアプリケーション開発フレームワークLangChainを組み合わせた評価パイプラインの構築方法を解説します。
前提・環境
- Python 3.9+
- LangChain 0.2.x
- RAGAS 0.1.x
- OpenAI Python Client 1.x
-
langchain,langchain-openai,langchain-community,ragas,datasets,faiss-cpuをインストール済みであること。
pip install langchain langchain-openai langchain-community ragas datasets faiss-cpu
RAG評価ワークフローの全体像
LangChainにおけるRAG評価ワークフローは、以下のステップで構成されます。
- 評価用データセットの準備: 質問と期待される回答(Ground Truths)のペアを作成します。
- RAGアプリケーションの実行: 準備した質問に対し、評価対象のRAGシステムを実行し、回答と検索されたコンテキストを取得します。
- RAGASによるスコアリング: RAGASの評価メトリクスを用いて、RAGシステムの出力(質問、回答、コンテキスト、Ground Truths)を評価します。
実装例: LangChainとRAGASでRAG評価を実行する
以下のコードは、簡易的なRAGシステムを構築し、RAGASを用いて評価を行う基本的な流れを示しています。
import os
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from ragas import evaluate
from ragas.metrics import (
faithfulness,
answer_relevance,
context_relevance,
context_recall
)
from datasets import Dataset
# 環境変数にOpenAI APIキーを設定してください
# os.environ["OPENAI_API_KEY"] = "YOUR_OPENAI_API_KEY"
# --- 1. データ準備 ---
# 実際のアプリケーションでは、より大規模なドキュメントをロードします。
# 例: loader = TextLoader("path/to/your_document.txt")
# documents = loader.load()
# 簡易的なテキストデータ
raw_texts = [
"LangChainはLLMアプリケーション開発のためのフレームワークです。多くのコンポーネントを提供し、効率的な開発をサポートします。",
"RAGASはRAGシステムの品質を測定するためのPythonライブラリです。検索の有用性や回答の根拠性、関連性、正確性を評価します。",
"RAGシステムは、大規模言語モデルに外部知識を組み込むことで、ハルシネーションを減らし、より正確な回答を生成します。これは、特に最新情報や専門知識が必要な場合に有効です。",
"RAG評価では、検索されたコンテキストの品質と、そのコンテキストに基づいたLLMの回答品質の両方を測定することが重要です。これにより、システム全体のボトルネックを特定できます。"
]
# ドキュメントのチャンキング
# RAGシステムの性能に大きく影響する重要なステップです。
text_splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=50) # chunk_sizeを小さめに設定
split_docs = text_splitter.create_documents(raw_texts)
print(f"分割されたドキュメント数: {len(split_docs)}")
# for i, doc in enumerate(split_docs):
# print(f"--- Chunk {i+1} ---")
# print(doc.page_content)
# --- 2. 埋め込みとベクトルストアの作成 ---
# OpenAIEmbeddingsを使用。モデル名を明示することが推奨されます。
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
vectorstore = FAISS.from_documents(split_docs, embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 2}) # 取得するドキュメント数を調整
# --- 3. LLMの準備 ---
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
# --- 4. RetrievalQAチェーンの設定 ---
# RetrievalQA.from_chain_typeは、RAGAS評価に必要な`source_documents`を返しません。
# 評価のために、リトリーバーとLLMを個別に呼び出すか、LangChainのRunnableインターフェースを利用する方が柔軟です。
# ここでは、RAGASのデータセット形式に合わせて出力を準備する関数を定義します。
# 5. 評価用データセットの作成
# 実際には、質問と期待される回答のペアを含むデータセットを用意します。
# LangSmithなどのツールを使って、より簡単にデータセットを作成することも可能です。
questions = [
"LangChainは何のためのフレームワークですか?その主な機能は何ですか?",
"RAGASの主な目的は何ですか?",
"RAGシステムがLLMの回答を改善する仕組みについて教えてください。",
"RAG評価で測定すべき重要な側面は何ですか?"
]
ground_truths = [
["LLMアプリケーション開発のためのフレームワークで、効率的な開発をサポートするコンポーネントを提供します。"],
["RAGシステムの品質を測定するためのPythonライブラリで、検索の有用性や回答の根拠性、関連性、正確性を評価します。"],
["外部知識を組み込むことで、ハルシネーションを減らし、より正確な回答を生成します。特に最新情報や専門知識が必要な場合に有効です。"],
["検索されたコンテキストの品質と、そのコンテキストに基づいたLLMの回答品質の両方を測定することが重要です。"]
]
# 質問に対するRAGシステムの出力を取得する関数
def get_rag_output(question):
# まず、リトリーバーで関連ドキュメントを取得
retrieved_docs = retriever.get_relevant_documents(question)
contexts = [doc.page_content for doc in retrieved_docs]
# 次に、LLMで回答を生成
# プロンプトはRAGの性能に大きく影響します。ここでは簡易的なプロンプト。
prompt = f"以下のコンテキストに基づいて質問に答えてください。\n\nコンテキスト:\n{'\n'.join(contexts)}\n\n質問: {question}\n回答:"
response = llm.invoke(prompt)
answer = response.content
return {
"answer": answer,
"contexts": contexts
}
# 評価データセットの構築
rag_outputs = [get_rag_output(q) for q in questions]
# RAGAS評価用のDatasetオブジェクトを作成
ragas_dataset_data = {
"question": questions,
"answer": [output["answer"] for output in rag_outputs],
"contexts": [output["contexts"] for output in rag_outputs],
"ground_truths": ground_truths
}
ragas_dataset = Dataset.from_dict(ragas_dataset_data)
print("\n--- RAGAS評価用データセットのプレビュー ---")
print(ragas_dataset)
# --- 6. RAGASによる評価の実行 ---
# RAGASは、LLM-as-a-judgeとしてOpenAIモデルを使用し、評価メトリクスを計算します。
print("\n--- RAGAS評価を開始します ---")
result = evaluate(
ragas_dataset,
metrics=[
faithfulness, # 回答がコンテキストに忠実か(ハルシネーションがないか)
answer_relevance, # 回答が質問にどれだけ関連しているか
context_relevance, # 検索されたコンテキストが質問にどれだけ関連しているか
context_recall # 正解の回答に必要な情報がコンテキストに含まれているか
],
llm=llm, # 評価器として使用するLLM
embeddings=embeddings # 評価器として使用する埋め込みモデル
)
print("\n--- RAGAS評価結果 ---")
print(result)
# 結果をPandas DataFrameとして表示
print(result.to_pandas())
上記のコードを実行すると、各メトリクス(faithfulness, answer_relevance, context_relevance, context_recall)の平均スコアと、質問ごとの詳細なスコアがPandas DataFrameとして表示されます。これらのスコアを基に、RAGシステムのパフォーマンスを客観的に把握できます。
その他のRAG評価フレームワーク
RAGAS以外にも、以下のような評価フレームワークやサービスがあります。
- DeepEval: ユニットテストのような感覚でRAGシステムを評価できるPythonライブラリ。
- TruLens: LLMアプリケーションの可観測性(Observability)と評価を提供するライブラリ。
- LangSmith: LangChainが提供する開発者プラットフォーム。LLMアプリケーションのデバッグ、監視、評価を一元的に行えます。評価データセットの作成やHuman-in-the-loop評価にも対応。
- Vertex AI Gen AI Evaluation Service: Google Cloudが提供するマネージドサービスで、カスタムメトリクスに基づく評価やモデル比較をサポートします。
RAG精度改善のための実践的アプローチ
RAG評価の結果、特定のメトリクスが低い場合、それはRAGシステムのどこかにボトルネックがあることを示唆しています。以下に、よくあるハマりどころと、それらを回避・改善するためのアプローチを解説します。
1. 不適切なチャンキング戦略とデータ前処理
RAGシステムの基盤は、高品質で適切に準備されたデータです。ドキュメントのチャンキング戦略は、検索の品質に直結します。
-
ハマりどころ:
- 固定サイズチャンキングの問題: 文脈の途中でチャンクが切れてしまい、重要な情報が分断される。
- オーバーラップ不足: チャンク境界での情報欠落が発生しやすくなる。
- セマンティックな意味の欠如: チャンクが意味のある単位になっておらず、検索時にノイズが多い。
-
回避策・改善策:
-
セマンティックチャンキング: 文や段落、章など、意味的な区切りに基づいてチャンクを生成します。LangChainの
RecursiveCharacterTextSplitterは、複数の区切り文字を試行することで、ある程度のセマンティックなチャンキングを実現します。 -
オーバーラップの最適化:
chunk_overlapパラメータを適切に設定し、チャンク間の文脈の連続性を保ちます。 - メタデータエンリッチメント: チャンクに元のドキュメント名、セクションタイトルなどのメタデータを付与することで、検索時にコンテキストを豊かにし、リランキングの精度向上にも繋がります。
- ドキュメントのクリーンアップ: 重複コンテンツの削除、テキストフォーマットの標準化、ノイズの除去など、データ前処理を徹底します。
-
セマンティックチャンキング: 文や段落、章など、意味的な区切りに基づいてチャンクを生成します。LangChainの
2. 古い埋め込みとデータドリフトへの対応
知識ベースのデータは時間とともに変化します。埋め込みが古いままでは、RAGシステムは陳腐化した情報に基づいて回答を生成し、ハルシネーションを引き起こす可能性があります。
-
ハマりどころ:
- 埋め込みの不更新: 知識ベースの更新頻度に対して、ベクトルストアの再インデックス化が追いつかない。
- データドリフト: 時間の経過とともに、ユーザーのクエリパターンや参照すべき情報源が変化し、RAGシステムの性能が静かに劣化する。
-
回避策・改善策:
- 継続的な評価パイプライン: 定期的なRAG評価をCI/CDに組み込み、品質のしきい値を設定します。しきい値を下回った場合や、データソースが更新された場合に、自動的に再インデックス化や再学習をトリガーする仕組みを構築します。
- 増分的な更新: 大規模なベクトルストアの場合、全体を再構築するのではなく、変更があった部分のみを増分的に更新する仕組みを導入します。
3. コンテキストの過剰な取得(Over-retrieval)とリランキングの活用
関連性の低いドキュメントを大量に取得しすぎると、LLMがノイズに圧倒され、重要な情報を見落としたり、焦点のぼけた不正確な回答を生成したりする可能性があります。
-
ハマりどころ:
-
top-kの過大設定: 必要以上に多くのドキュメントを取得することで、LLMのコンテキストウィンドウを圧迫し、性能低下を招く。 - 単純な類似度検索: ベクトル類似度だけでは、必ずしも質問に対する最も関連性の高い情報が得られるとは限らない。
-
-
回避策・改善策:
-
top-kパラメータの最適化: 評価駆動で最適なtop-k値を探索します。 -
リランキングアルゴリズムの導入: 最初に取得した
top-k個のドキュメントを、さらに別のモデル(Cross-Encoder Rerankerなど)で関連性の高い順に並べ替えることで、LLMに渡すコンテキストの品質を大幅に向上させます。Hugging Faceのsentence-transformersライブラリなどで利用可能です。 -
高度なリトリーバー戦略:
- Multi-Query Retriever: 複数の質問バリエーションを生成し、それぞれの検索結果を統合してリランキングにかける。
- Parent Document Retriever: 小さなチャンクで検索し、そのチャンクを含む大きな親ドキュメント全体をLLMに渡すことで、文脈の連続性を保つ。
-
4. 評価データセットの品質とHuman-in-the-loop
評価データセット(ゴールドスタンダード)の品質は、RAG評価の信頼性を決定します。
-
ハマりどころ:
- 評価データセットの不足: 網羅性が低く、RAGシステムの実際の性能を反映しない。
- 合成データの偏り: 自動生成されたデータが、実際のユーザーのクエリパターンから乖離している。
-
回避策・改善策:
- ゴールドスタンダードの確立: 開発の早い段階で、特定のユースケースに合わせた高品質な質問と期待される回答のデータセットを作成します。
- リアルなデータでの評価: 可能であれば、実際のユーザーのクエリログ、過去のサポート履歴など、本番環境に近いデータを使用してテストケースを作成します。
- 合成データ生成の洗練: LLMを用いて評価データセットを自動生成する場合でも、生成されたデータに対して人間がレビューを行い、多様性と現実性を確保します。
- 人間による評価(Human-in-the-loop): 自動評価は効率的ですが、LLMのニュアンスやトーン、説明の明確さなどは人間の判断が必要です。定期的に人間による評価を組み込み、定量的・定性的なフィードバックループを構築します。LangSmithのようなツールは、このHuman-in-the-loop評価をサポートします。
設計上のトレードオフとベストプラクティス
RAGシステムの設計と改善には、常にトレードオフが伴います。
設計上のトレードオフ
- 精度 vs レイテンシ: 回答の精度を高めるために、より多くのドキュメントを検索したり、複雑なリランキングを行ったりすると、処理時間(レイテンシ)が増加します。ユーザー体験を考慮し、許容できるレイテンシ内で最大の精度を追求する必要があります。
- コスト vs 検索品質: 高品質な埋め込みモデルの使用、頻繁な再インデックス化、高度なリランキングは検索品質を向上させますが、計算リソースやAPI利用料といった運用コストが増大します。
- RAG vs 長いコンテキストウィンドウ: 最新のLLMは非常に長いコンテキストウィンドウを持つものもあります。これにより、RAGの複雑なインデックス管理が不要になる可能性もありますが、長いコンテキストウィンドウは処理コストが高く、特定の情報を見落とす「迷子」問題が発生する可能性も考慮する必要があります。大規模で動的なデータセットに対しては、RAGが依然として有効なソリューションです。
ベストプラクティス
- 継続的な評価パイプラインの構築: データドリフトやモデルの劣化を早期に検出し、RAGシステムの品質を継続的に担保するために不可欠です。
- コンポーネントごとの評価: RAGシステムは、検索(Retrieval)と生成(Generation)の2つの主要なコンポーネントから成ります。これらを個別に評価することで、問題の根本原因を特定しやすくなります。
- データ品質と前処理の徹底: RAGシステムの性能は、入力データの品質に大きく依存します。重複排除、フォーマット統一、メタデータ付与、適切なチャンキングを怠らないでください。
- リランキングの活用: 検索されたドキュメントの関連性をさらに高めるために、リランキングアルゴリズムの導入を強く推奨します。
- セキュリティメトリクスの確立: RAGシステムが機密情報を不適切に開示しないか、不正確な情報源を参照しないかなど、セキュリティに関するメトリクスも評価に含めることが重要です。
まとめ
この記事では、RAGシステムの高精度化と品質担保のため、評価駆動開発の重要性と具体的な実践手法を解説しました。
- RAG精度評価は、ハルシネーション抑制、回答の関連性・正確性、コンテキストの有効性を客観的に測定するために不可欠です。
- RAGASとLangChainを組み合わせることで、RAGシステムの評価パイプラインを構築し、主要なメトリクス(faithfulness, answer_relevance, context_relevance, context_recall)を自動で計算できます。
- 評価結果に基づき、チャンキング戦略の最適化、データドリフトへの対応、リランキングの導入、評価データセットの品質向上といった具体的な改善アプローチを適用することが重要です。
- 精度、レイテンシ、コストのトレードオフを理解し、継続的な評価パイプラインとコンポーネントごとの評価をベストプラクティスとして採用することで、本番環境で信頼性の高いRAGシステムを運用できます。
RAGシステムは進化し続ける領域です。本記事で紹介した手法を参考に、ぜひご自身のRAGシステムの精度評価と改善に取り組んでみてください。さらに深く学ぶには、RAGASやLangChainの公式ドキュメントを参照し、最新の評価メトリクスや最適化手法を探求することをおすすめします。