<p><!--META
{
"title": "RAGシステム性能評価と改善:プロンプト設計と自動評価戦略",
"primary_category": "AI/機械学習",
"secondary_categories": ["LLM", "プロンプトエンジニアリング", "システム評価"],
"tags": ["RAG", "プロンプト", "評価指標", "自動評価", "LLM開発"],
"summary": "RAGシステムの性能評価と改善に焦点を当て、プロンプト設計、自動評価、失敗モード分析、改良サイクルについて解説します。",
"mermaid": true,
"verify_level": "L0",
"tweet_hint": {"text":"RAGシステム評価と改善の完全ガイド。プロンプト設計、自動評価、失敗モード分析、改良サイクルを網羅しています。#RAG
#LLM #プロンプトエンジニアリング","hashtags":["#RAG","#LLM"]},
"link_hints": ["https://docs.ragas.io/en/latest/index.html","https://docs.llamaindex.ai/en/stable/module_guides/evaluating/root.html"]
}
-->
本記事は<strong>Geminiの出力をプロンプト工学で整理した業務ドラフト(未検証)</strong>です。</p>
<h1 class="wp-block-heading">RAGシステム性能評価と改善:プロンプト設計と自動評価戦略</h1>
<p>RAG (Retrieval-Augmented Generation) システムは、大規模言語モデル (LLM) の回答生成において、外部知識を動的に参照することで、幻覚(Hallucination)の抑制と回答の正確性向上に貢献します。しかし、その性能は、情報検索の品質、LLMの推論能力、そして<strong>プロンプト設計</strong>に大きく依存します。本記事では、RAGシステムの性能評価と改善に焦点を当て、特にプロンプト設計、自動評価戦略、失敗モード分析、そして継続的な改良サイクルについて解説します。</p>
<h2 class="wp-block-heading">ユースケース定義</h2>
<p>本稿では、特定の企業ドキュメント群(例:社内規定、製品マニュアル、FAQデータベースなど)に基づいた質疑応答システムをRAGシステムのユースケースとして定義します。ユーザーからの質問に対し、関連ドキュメントを検索し、それらの情報を基に正確かつ簡潔な回答を生成することを目標とします。</p>
<p><strong>目標性能</strong>:</p>
<ul class="wp-block-list">
<li><p><strong>正確性 (Faithfulness)</strong>: 生成された回答が参照コンテキストの内容と矛盾しないこと。</p></li>
<li><p><strong>関連性 (Answer Relevance)</strong>: 生成された回答がユーザーの質問に直接関連していること。</p></li>
<li><p><strong>網羅性 (Context Recall)</strong>: 回答に必要な情報が参照コンテキストに適切に含まれていること。</p></li>
<li><p><strong>迅速性</strong>: 平均応答時間が5秒以内であること。</p></li>
</ul>
<h2 class="wp-block-heading">制約付き仕様化:入出力契約</h2>
<p>RAGシステムにおけるLLMプロンプトの入出力契約を以下のように定義します。これにより、システムの挙動を予測可能にし、評価基準を明確にします。</p>
<h3 class="wp-block-heading">入力契約</h3>
<ul class="wp-block-list">
<li><p><strong>フォーマット</strong>:</p>
<ul>
<li><p>ユーザーからの質問: <code>string</code></p></li>
<li><p>RAGから抽出された関連コンテキスト: <code>list[string]</code> (各要素はドキュメントのチャンク)</p></li>
</ul></li>
<li><p><strong>前提条件</strong>:</p>
<ul>
<li><p>関連コンテキストは、質問応答に必要な情報を含む可能性が高いものとする。</p></li>
<li><p>質問の長さは最大200文字、コンテキストの合計文字数は最大4000文字とする。</p></li>
</ul></li>
</ul>
<h3 class="wp-block-heading">出力契約</h3>
<ul class="wp-block-list">
<li><p><strong>フォーマット</strong>:</p>
<ul>
<li><p>回答: <code>string</code> (簡潔な日本語、最大200文字)</p></li>
<li><p>回答に用いたコンテキストのソース情報: <code>list[string]</code> (例: ドキュメント名、ページ番号など。情報がない場合は空リスト)</p></li>
</ul></li>
<li><p><strong>失敗時の挙動</strong>:</p>
<ul>
<li><p>関連コンテキストから適切な回答を生成できない場合、または質問が理解できない場合は、「関連情報を見つけることができませんでした。」という定型文を出力する。</p></li>
<li><p>技術的なエラー(APIタイムアウトなど)の場合は、内部エラーメッセージをログに出力し、ユーザーには「システムエラーが発生しました。時間をおいて再度お試しください。」と応答する。</p></li>
</ul></li>
<li><p><strong>禁止事項</strong>:</p>
<ul>
<li><p>参照コンテキストにない情報を「事実」として出力すること(幻覚)。</p></li>
<li><p>ユーザーの個人情報や機密情報を出力すること。</p></li>
<li><p>不適切、差別的、または有害なコンテンツを出力すること。</p></li>
</ul></li>
</ul>
<h2 class="wp-block-heading">プロンプト設計</h2>
<p>RAGシステムにおけるLLMへのプロンプトは、その性能を大きく左右します。以下に3つのプロンプト設計案を提示します。</p>
<h3 class="wp-block-heading">1. ゼロショットプロンプト(Zero-shot Prompt)</h3>
<p>基本的な指示のみを与え、モデルの一般知識と提供されたコンテキストのみで回答を生成させます。</p>
<div class="codehilite">
<pre data-enlighter-language="generic">あなたは情報提供を専門とするアシスタントです。
以下の「コンテキスト」のみに基づいて、ユーザーの「質問」に回答してください。
コンテキストに質問への直接的な回答がない場合や、情報が不足している場合は、「関連情報を見つけることができませんでした。」と回答してください。
### コンテキスト
{{context}}
### 質問
{{question}}
### 回答
</pre>
</div>
<h3 class="wp-block-heading">2. 少数例プロンプト(Few-shot Prompt)</h3>
<p>質問と回答の具体的な例をいくつか提示することで、モデルに望ましい回答形式やトーンを学習させます。特に、定型的な質問や特定の表現が求められる場合に有効です。</p>
<div class="codehilite">
<pre data-enlighter-language="generic">あなたは情報提供を専門とするアシスタントです。
以下の「コンテキスト」のみに基づいて、ユーザーの「質問」に回答してください。
コンテキストに質問への直接的な回答がない場合や、情報が不足している場合は、「関連情報を見つけることができませんでした。」と回答してください。
回答は簡潔かつ明確にしてください。
### 例1
コンテキスト: 会社の営業時間は平日9:00から17:00です。土日祝日は休業です。
質問: 会社の営業時間を教えてください。
回答: 平日9:00から17:00です。土日祝日は休業となります。
### 例2
コンテキスト: 当社製品Aのサポート窓口は電話番号0120-XXXX-XXXXです。メールでの問い合わせはsupport@example.comまで。
質問: 製品Aの技術サポートについて教えてください。
回答: 製品Aの技術サポートは、電話番号0120-XXXX-XXXX、またはsupport@example.comまでお問い合わせください。
### コンテキスト
{{context}}
### 質問
{{question}}
### 回答
</pre>
</div>
<h3 class="wp-block-heading">3. Chain-of-Thought制約型プロンプト(Chain-of-Thought with Constraints Prompt)</h3>
<p>モデルに回答に至るまでの思考プロセスを段階的に出力させ、その上で最終的な回答を特定のフォーマットで生成させます。これにより、複雑な質問に対する推論能力を向上させ、幻覚を抑制しやすくなります。</p>
<div class="codehilite">
<pre data-enlighter-language="generic">あなたは情報提供を専門とするアシスタントです。
以下の「コンテキスト」のみに基づいて、ユーザーの「質問」に回答してください。
回答生成の際は、まず思考プロセスを「思考」セクションで日本語で記述してください。
次に、思考プロセスに基づいて「結論」セクションで最終的な回答を簡潔にまとめてください。
コンテキストに質問への直接的な回答がない場合や、情報が不足している場合は、思考プロセスでその旨を述べ、「結論」では「関連情報を見つけることができませんでした。」と回答してください。
### コンテキスト
{{context}}
### 質問
{{question}}
### 思考
ユーザーの質問は「{{question}}」です。まず、コンテキスト内で「{{question}}」に関連するキーワードや情報があるかを確認します。
### 結論
</pre>
</div>
<h2 class="wp-block-heading">評価戦略</h2>
<p>RAGシステムの性能を定量的に評価するためには、多様な評価シナリオと自動評価手法を組み合わせることが重要です。</p>
<h3 class="wp-block-heading">評価シナリオ</h3>
<ul class="wp-block-list">
<li><p><strong>正例(Positive Cases)</strong>:</p>
<ul>
<li><p>質問: コンテキスト内に明確な回答がある簡単な質問。</p></li>
<li><p>例: 「製品Aの価格はいくらですか?」</p></li>
</ul></li>
<li><p><strong>難例(Challenging Cases)</strong>:</p>
<ul>
<li><p>質問: 複数の情報を組み合わせる必要がある、またはわずかに言い換えられた質問。</p></li>
<li><p>例: 「製品AとBの主な違いは何ですか?」(両製品の情報がコンテキスト内に散在)</p></li>
</ul></li>
<li><p><strong>コーナーケース(Corner Cases)</strong>:</p>
<ul>
<li><p>質問: コンテキストに回答がない質問、曖昧な質問、RAGの意図しない質問(例:システムに関する質問、不適切な質問)。</p></li>
<li><p>例: 「製品Cについて教えてください。(コンテキストに製品Cの情報なし)」</p></li>
<li><p>例: 「今日の天気は?」(コンテキストの範囲外)</p></li>
</ul></li>
</ul>
<h3 class="wp-block-heading">自動評価の擬似コード</h3>
<p>RAGシステムの出力は、回答の正確性、関連性、参照コンテキストとの整合性など、複数の側面から評価する必要があります。RAGAsのようなフレームワークは、これらの評価指標を自動的に算出するのに役立ちます[1]。ここでは、一般的な自動評価の概念を擬似コードで示します。</p>
<div class="codehilite">
<pre data-enlighter-language="generic">import re
def evaluate_rag_answer(question: str, context: list[str], generated_answer: str, golden_answer: str) -> dict:
"""
RAGシステムによって生成された回答を自動評価する。
Args:
question: ユーザーの質問。
context: RAGが参照したコンテキスト。
generated_answer: LLMが生成した回答。
golden_answer: 人間が作成した理想的な回答。
Returns:
評価結果を示す辞書。
"""
scores = {
"faithfulness_score": 0.0,
"answer_relevance_score": 0.0,
"context_recall_score": 0.0,
"format_adherence_score": 0.0
}
# 1. Faithfulness (事実整合性) 評価
# 生成された回答内の主要な主張が、参照コンテキストに基づいているかを評価。
# ここでは簡略化し、回答中のキーワードがコンテキストに存在するかをチェック。
# 実際には、より複雑なNLIモデルやRAGAsのFaithfulness指標を使用。
faithfulness_keywords = ["価格", "無料", "仕様"] # 回答で言及されがちなキーワード
contained_in_context = 0
total_keywords = 0
for keyword in faithfulness_keywords:
if keyword in generated_answer:
total_keywords += 1
if any(keyword in c for c in context):
contained_in_context += 1
scores["faithfulness_score"] = contained_in_context / total_keywords if total_keywords > 0 else 1.0
# 2. Answer Relevance (回答関連性) 評価
# 生成された回答が質問に直接関連しているかを評価。
# 正規表現や質問文中のキーワードマッチングで部分的に評価。
# より高度な評価にはセマンティック類似度(埋め込みベクトル)を用いる。
question_keywords = question.split() # 簡易的なキーワード抽出
relevant_count = 0
for qk in question_keywords:
if qk in generated_answer: # 回答に質問キーワードが含まれているか
relevant_count += 1
scores["answer_relevance_score"] = relevant_count / len(question_keywords) if len(question_keywords) > 0 else 0.0
# 3. Context Recall (コンテキスト網羅性) 評価
# golden_answerに必要な情報がcontextに含まれているかを評価。
# golden_answerのキーワードがcontextに存在するかをチェック。
golden_keywords = golden_answer.split() # 簡易的なキーワード抽出
recalled_count = 0
for gk in golden_keywords:
if any(gk in c for c in context):
recalled_count += 1
scores["context_recall_score"] = recalled_count / len(golden_keywords) if len(golden_keywords) > 0 else 0.0
# 4. Format Adherence (フォーマット順守) 評価
# 例: 特定のキーワード「関連情報を見つけることができませんでした。」の有無、文字数制限。
if "関連情報を見つけることができませんでした。" in generated_answer:
scores["format_adherence_score"] = 1.0 # 特定の失敗フォーマットを認識
elif len(generated_answer) <= 200: # 文字数制限
scores["format_adherence_score"] = 1.0
else:
scores["format_adherence_score"] = 0.0
# RAGAsなどの専門ツールでは、LLMを活用して各指標を詳細に評価する。
# 例: RAGAs Faithfulness = LLMが生成された回答とコンテキストに基づいて、矛盾するステートメントの割合を評価。
# [1] Ragas Docs: https://docs.ragas.io/en/latest/index.html (継続更新, Ragas開発チーム)
# [2] LlamaIndex Evaluation: https://docs.llamaindex.ai/en/stable/module_guides/evaluating/root.html (継続更新, LlamaIndex開発チーム)
return scores
# 使用例
question_sample = "製品Aの保証期間について教えてください。"
context_sample = ["製品Aの保証期間は購入後1年間です。", "製品Bの価格は5000円です。"]
generated_answer_sample = "製品Aの保証期間は購入後1年間です。"
golden_answer_sample = "製品Aの保証期間は購入後1年間です。"
eval_result = evaluate_rag_answer(question_sample, context_sample, generated_answer_sample, golden_answer_sample)
print(eval_result)
</pre>
</div>
<h2 class="wp-block-heading">失敗モードとその抑制手法</h2>
<p>RAGシステムは様々な失敗モードを抱えており、これらを理解し、適切な抑制手法を講じることが重要です。</p>
<h3 class="wp-block-heading">失敗モード</h3>
<ul class="wp-block-list">
<li><p><strong>幻覚(Hallucination)</strong>:</p>
<ul>
<li><p>参照コンテキストに存在しない情報を事実として生成する。RAGの最大の課題の一つ。</p></li>
<li><p>例: コンテキストにない製品の機能や存在しない人物名を生成。</p></li>
</ul></li>
<li><p><strong>様式崩れ(Formatting Issues)</strong>:</p>
<ul>
<li><p>JSON、Markdown、または特定の文体などの指定された出力フォーマットに従わない。</p></li>
<li><p>例: 箇条書きが正しく整形されていない、思考プロセスが期待したセクションにない。</p></li>
</ul></li>
<li><p><strong>脱線(Off-topic/Irrelevance)</strong>:</p>
<ul>
<li><p>ユーザーの質問の意図から外れた回答を生成する、または質問に関連性の低い情報を過剰に含める。</p></li>
<li><p>例: 製品Aについて尋ねているのに、製品Bに関する情報を主に回答。</p></li>
</ul></li>
<li><p><strong>禁止事項違反(Prohibited Content)</strong>:</p>
<ul>
<li><p>不適切、差別的、または有害なコンテンツを生成する。</p></li>
<li><p>指定された制約(例: 「関連情報を見つけることができませんでした。」以外の否定的な回答)を破る。</p></li>
</ul></li>
</ul>
<h3 class="wp-block-heading">抑制手法</h3>
<ul class="wp-block-list">
<li><p><strong>System指示の強化</strong>:</p>
<ul>
<li>LLMの役割、振る舞い、厳守すべき制約(例:「コンテキスト外の情報は絶対に生成しないこと」)をSystemプロンプトで明確かつ詳細に指示する。</li>
</ul></li>
<li><p><strong>検証ステップの導入</strong>:</p>
<ul>
<li><p>LLMからの出力をそのまま使用せず、別途用意した検証ロジック(正規表現、キーワードチェック、外部データベースとの照合など)で事実整合性やフォーマットをチェックする。</p></li>
<li><p>例: 回答内の特定の固有名詞がコンテキストに存在するかを確認する。</p></li>
</ul></li>
<li><p><strong>リトライ戦略</strong>:</p>
<ul>
<li><p>初回の生成が失敗モードに該当する場合(例: フォーマットエラー、幻覚の疑い)、プロンプトを調整(例: 「再度JSON形式で回答してください」)して再試行する。</p></li>
<li><p>再試行回数やタイムアウトを設定し、無限ループを避ける。</p></li>
</ul></li>
<li><p><strong>出力パーシングとサニタイズ</strong>:</p>
<ul>
<li><p>LLMの出力をプログラムで解析し、期待する情報のみを抽出する。不要な要素や不正な形式は除去または修正する。</p></li>
<li><p>不適切な言葉や有害な表現をフィルタリングするガードレール層を設ける。</p></li>
</ul></li>
<li><p><strong>Few-shot/CoTプロンプト</strong>:</p>
<ul>
<li>具体的な成功例を示すことで、望ましい出力形式や推論プロセスをモデルに学習させる。CoTにより、モデルが自己修正する機会を与える。</li>
</ul></li>
</ul>
<h2 class="wp-block-heading">改良と再評価のループ</h2>
<p>RAGシステムの性能改善は、一度の評価で完了するものではなく、継続的な評価と改良のループを通じて行われます。</p>
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">
graph TD
A["RAGシステム定義"] --> B{"プロンプト設計"};
B -- ゼロショット/少数例/CoT --> C["RAGシステム実装"];
C --> D{"評価データセット準備"};
D -- 正例/難例/コーナーケース --> E["自動評価実行"];
E -- 指標算出 (Faithfulness, Relevanceなど) --> F{"評価結果分析"};
F -- 失敗モード特定 --> G{"プロンプト/RAGコンポーネント改良"};
G -- 新プロンプト/データ --> B;
</pre></div>
<ol class="wp-block-list">
<li><p><strong>RAGシステム定義</strong>: ユースケースと目標性能を明確にします。</p></li>
<li><p><strong>プロンプト設計</strong>: ゼロショット、少数例、CoT制約型など、多様なプロンプトを設計します。</p></li>
<li><p><strong>RAGシステム実装</strong>: 設計したプロンプトとRAGコンポーネント(リトリーバー、ジェネレーター)を統合し、システムを構築します。</p></li>
<li><p><strong>評価データセット準備</strong>: 正例、難例、コーナーケースを含む質問と参照回答(ゴールデンアンサー)のデータセットを用意します。</p></li>
<li><p><strong>自動評価実行</strong>: 準備したデータセットと定義した指標(RAGAsなど)を用いて、自動評価を実行し、定量的なスコアを算出します。</p></li>
<li><p><strong>評価結果分析</strong>: 算出されたスコアを分析し、特に低いスコアの項目や特定の失敗パターン(幻覚、脱線など)を特定します。</p></li>
<li><p><strong>プロンプト/RAGコンポーネント改良</strong>: 分析結果に基づき、プロンプトの調整(System指示の明確化、例の追加、CoTの導入)や、リトリーバー(チャンク戦略、埋め込みモデル、検索アルゴリズム)の改善、またはジェネレーターLLMの調整を行います。</p></li>
<li><p><strong>再評価</strong>: 改良したシステムで再び評価を実行し、性能の向上を確認します。このプロセスを繰り返すことで、RAGシステムの品質を着実に高めていきます。</p></li>
</ol>
<h2 class="wp-block-heading">まとめ</h2>
<p>RAGシステムの性能評価と改善は、プロンプト設計、堅牢な評価戦略、そして継続的な失敗分析と改良サイクルが不可欠です。本記事で示したプロンプト設計のパターン、自動評価の概念、失敗モードとその抑制手法、そして改良ループは、信頼性の高いRAGシステムを構築するための基礎となります。RAGAsのようなフレームワークやLlamaIndex、LangChainなどのライブラリを活用することで、これらのプロセスを効率的に進めることが可能です。2024年5月1日現在、RAG技術は進化を続けており、常に最新の知見を取り入れながら、システムの最適化を図ることが求められます。</p>
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
RAGシステム性能評価と改善:プロンプト設計と自動評価戦略
RAG (Retrieval-Augmented Generation) システムは、大規模言語モデル (LLM) の回答生成において、外部知識を動的に参照することで、幻覚(Hallucination)の抑制と回答の正確性向上に貢献します。しかし、その性能は、情報検索の品質、LLMの推論能力、そしてプロンプト設計に大きく依存します。本記事では、RAGシステムの性能評価と改善に焦点を当て、特にプロンプト設計、自動評価戦略、失敗モード分析、そして継続的な改良サイクルについて解説します。
ユースケース定義
本稿では、特定の企業ドキュメント群(例:社内規定、製品マニュアル、FAQデータベースなど)に基づいた質疑応答システムをRAGシステムのユースケースとして定義します。ユーザーからの質問に対し、関連ドキュメントを検索し、それらの情報を基に正確かつ簡潔な回答を生成することを目標とします。
目標性能:
正確性 (Faithfulness): 生成された回答が参照コンテキストの内容と矛盾しないこと。
関連性 (Answer Relevance): 生成された回答がユーザーの質問に直接関連していること。
網羅性 (Context Recall): 回答に必要な情報が参照コンテキストに適切に含まれていること。
迅速性: 平均応答時間が5秒以内であること。
制約付き仕様化:入出力契約
RAGシステムにおけるLLMプロンプトの入出力契約を以下のように定義します。これにより、システムの挙動を予測可能にし、評価基準を明確にします。
入力契約
出力契約
プロンプト設計
RAGシステムにおけるLLMへのプロンプトは、その性能を大きく左右します。以下に3つのプロンプト設計案を提示します。
1. ゼロショットプロンプト(Zero-shot Prompt)
基本的な指示のみを与え、モデルの一般知識と提供されたコンテキストのみで回答を生成させます。
あなたは情報提供を専門とするアシスタントです。
以下の「コンテキスト」のみに基づいて、ユーザーの「質問」に回答してください。
コンテキストに質問への直接的な回答がない場合や、情報が不足している場合は、「関連情報を見つけることができませんでした。」と回答してください。
### コンテキスト
{{context}}
### 質問
{{question}}
### 回答
2. 少数例プロンプト(Few-shot Prompt)
質問と回答の具体的な例をいくつか提示することで、モデルに望ましい回答形式やトーンを学習させます。特に、定型的な質問や特定の表現が求められる場合に有効です。
あなたは情報提供を専門とするアシスタントです。
以下の「コンテキスト」のみに基づいて、ユーザーの「質問」に回答してください。
コンテキストに質問への直接的な回答がない場合や、情報が不足している場合は、「関連情報を見つけることができませんでした。」と回答してください。
回答は簡潔かつ明確にしてください。
### 例1
コンテキスト: 会社の営業時間は平日9:00から17:00です。土日祝日は休業です。
質問: 会社の営業時間を教えてください。
回答: 平日9:00から17:00です。土日祝日は休業となります。
### 例2
コンテキスト: 当社製品Aのサポート窓口は電話番号0120-XXXX-XXXXです。メールでの問い合わせはsupport@example.comまで。
質問: 製品Aの技術サポートについて教えてください。
回答: 製品Aの技術サポートは、電話番号0120-XXXX-XXXX、またはsupport@example.comまでお問い合わせください。
### コンテキスト
{{context}}
### 質問
{{question}}
### 回答
3. Chain-of-Thought制約型プロンプト(Chain-of-Thought with Constraints Prompt)
モデルに回答に至るまでの思考プロセスを段階的に出力させ、その上で最終的な回答を特定のフォーマットで生成させます。これにより、複雑な質問に対する推論能力を向上させ、幻覚を抑制しやすくなります。
あなたは情報提供を専門とするアシスタントです。
以下の「コンテキスト」のみに基づいて、ユーザーの「質問」に回答してください。
回答生成の際は、まず思考プロセスを「思考」セクションで日本語で記述してください。
次に、思考プロセスに基づいて「結論」セクションで最終的な回答を簡潔にまとめてください。
コンテキストに質問への直接的な回答がない場合や、情報が不足している場合は、思考プロセスでその旨を述べ、「結論」では「関連情報を見つけることができませんでした。」と回答してください。
### コンテキスト
{{context}}
### 質問
{{question}}
### 思考
ユーザーの質問は「{{question}}」です。まず、コンテキスト内で「{{question}}」に関連するキーワードや情報があるかを確認します。
### 結論
評価戦略
RAGシステムの性能を定量的に評価するためには、多様な評価シナリオと自動評価手法を組み合わせることが重要です。
評価シナリオ
正例(Positive Cases):
難例(Challenging Cases):
コーナーケース(Corner Cases):
自動評価の擬似コード
RAGシステムの出力は、回答の正確性、関連性、参照コンテキストとの整合性など、複数の側面から評価する必要があります。RAGAsのようなフレームワークは、これらの評価指標を自動的に算出するのに役立ちます[1]。ここでは、一般的な自動評価の概念を擬似コードで示します。
import re
def evaluate_rag_answer(question: str, context: list[str], generated_answer: str, golden_answer: str) -> dict:
"""
RAGシステムによって生成された回答を自動評価する。
Args:
question: ユーザーの質問。
context: RAGが参照したコンテキスト。
generated_answer: LLMが生成した回答。
golden_answer: 人間が作成した理想的な回答。
Returns:
評価結果を示す辞書。
"""
scores = {
"faithfulness_score": 0.0,
"answer_relevance_score": 0.0,
"context_recall_score": 0.0,
"format_adherence_score": 0.0
}
# 1. Faithfulness (事実整合性) 評価
# 生成された回答内の主要な主張が、参照コンテキストに基づいているかを評価。
# ここでは簡略化し、回答中のキーワードがコンテキストに存在するかをチェック。
# 実際には、より複雑なNLIモデルやRAGAsのFaithfulness指標を使用。
faithfulness_keywords = ["価格", "無料", "仕様"] # 回答で言及されがちなキーワード
contained_in_context = 0
total_keywords = 0
for keyword in faithfulness_keywords:
if keyword in generated_answer:
total_keywords += 1
if any(keyword in c for c in context):
contained_in_context += 1
scores["faithfulness_score"] = contained_in_context / total_keywords if total_keywords > 0 else 1.0
# 2. Answer Relevance (回答関連性) 評価
# 生成された回答が質問に直接関連しているかを評価。
# 正規表現や質問文中のキーワードマッチングで部分的に評価。
# より高度な評価にはセマンティック類似度(埋め込みベクトル)を用いる。
question_keywords = question.split() # 簡易的なキーワード抽出
relevant_count = 0
for qk in question_keywords:
if qk in generated_answer: # 回答に質問キーワードが含まれているか
relevant_count += 1
scores["answer_relevance_score"] = relevant_count / len(question_keywords) if len(question_keywords) > 0 else 0.0
# 3. Context Recall (コンテキスト網羅性) 評価
# golden_answerに必要な情報がcontextに含まれているかを評価。
# golden_answerのキーワードがcontextに存在するかをチェック。
golden_keywords = golden_answer.split() # 簡易的なキーワード抽出
recalled_count = 0
for gk in golden_keywords:
if any(gk in c for c in context):
recalled_count += 1
scores["context_recall_score"] = recalled_count / len(golden_keywords) if len(golden_keywords) > 0 else 0.0
# 4. Format Adherence (フォーマット順守) 評価
# 例: 特定のキーワード「関連情報を見つけることができませんでした。」の有無、文字数制限。
if "関連情報を見つけることができませんでした。" in generated_answer:
scores["format_adherence_score"] = 1.0 # 特定の失敗フォーマットを認識
elif len(generated_answer) <= 200: # 文字数制限
scores["format_adherence_score"] = 1.0
else:
scores["format_adherence_score"] = 0.0
# RAGAsなどの専門ツールでは、LLMを活用して各指標を詳細に評価する。
# 例: RAGAs Faithfulness = LLMが生成された回答とコンテキストに基づいて、矛盾するステートメントの割合を評価。
# [1] Ragas Docs: https://docs.ragas.io/en/latest/index.html (継続更新, Ragas開発チーム)
# [2] LlamaIndex Evaluation: https://docs.llamaindex.ai/en/stable/module_guides/evaluating/root.html (継続更新, LlamaIndex開発チーム)
return scores
# 使用例
question_sample = "製品Aの保証期間について教えてください。"
context_sample = ["製品Aの保証期間は購入後1年間です。", "製品Bの価格は5000円です。"]
generated_answer_sample = "製品Aの保証期間は購入後1年間です。"
golden_answer_sample = "製品Aの保証期間は購入後1年間です。"
eval_result = evaluate_rag_answer(question_sample, context_sample, generated_answer_sample, golden_answer_sample)
print(eval_result)
失敗モードとその抑制手法
RAGシステムは様々な失敗モードを抱えており、これらを理解し、適切な抑制手法を講じることが重要です。
失敗モード
抑制手法
System指示の強化:
- LLMの役割、振る舞い、厳守すべき制約(例:「コンテキスト外の情報は絶対に生成しないこと」)をSystemプロンプトで明確かつ詳細に指示する。
検証ステップの導入:
リトライ戦略:
出力パーシングとサニタイズ:
Few-shot/CoTプロンプト:
- 具体的な成功例を示すことで、望ましい出力形式や推論プロセスをモデルに学習させる。CoTにより、モデルが自己修正する機会を与える。
改良と再評価のループ
RAGシステムの性能改善は、一度の評価で完了するものではなく、継続的な評価と改良のループを通じて行われます。
graph TD
A["RAGシステム定義"] --> B{"プロンプト設計"};
B -- ゼロショット/少数例/CoT --> C["RAGシステム実装"];
C --> D{"評価データセット準備"};
D -- 正例/難例/コーナーケース --> E["自動評価実行"];
E -- 指標算出 (Faithfulness, Relevanceなど) --> F{"評価結果分析"};
F -- 失敗モード特定 --> G{"プロンプト/RAGコンポーネント改良"};
G -- 新プロンプト/データ --> B;
RAGシステム定義: ユースケースと目標性能を明確にします。
プロンプト設計: ゼロショット、少数例、CoT制約型など、多様なプロンプトを設計します。
RAGシステム実装: 設計したプロンプトとRAGコンポーネント(リトリーバー、ジェネレーター)を統合し、システムを構築します。
評価データセット準備: 正例、難例、コーナーケースを含む質問と参照回答(ゴールデンアンサー)のデータセットを用意します。
自動評価実行: 準備したデータセットと定義した指標(RAGAsなど)を用いて、自動評価を実行し、定量的なスコアを算出します。
評価結果分析: 算出されたスコアを分析し、特に低いスコアの項目や特定の失敗パターン(幻覚、脱線など)を特定します。
プロンプト/RAGコンポーネント改良: 分析結果に基づき、プロンプトの調整(System指示の明確化、例の追加、CoTの導入)や、リトリーバー(チャンク戦略、埋め込みモデル、検索アルゴリズム)の改善、またはジェネレーターLLMの調整を行います。
再評価: 改良したシステムで再び評価を実行し、性能の向上を確認します。このプロセスを繰り返すことで、RAGシステムの品質を着実に高めていきます。
まとめ
RAGシステムの性能評価と改善は、プロンプト設計、堅牢な評価戦略、そして継続的な失敗分析と改良サイクルが不可欠です。本記事で示したプロンプト設計のパターン、自動評価の概念、失敗モードとその抑制手法、そして改良ループは、信頼性の高いRAGシステムを構築するための基礎となります。RAGAsのようなフレームワークやLlamaIndex、LangChainなどのライブラリを活用することで、これらのプロセスを効率的に進めることが可能です。2024年5月1日現在、RAG技術は進化を続けており、常に最新の知見を取り入れながら、システムの最適化を図ることが求められます。
コメント