<p><!--META
{
"title": "RAGシステムの評価指標とプロンプト改良ループ",
"primary_category": "LLM工学",
"secondary_categories": ["プロンプト設計","評価戦略"],
"tags": ["RAG", "プロンプト設計", "RAGAS", "評価指標", "LLM-as-a-Judge", "CoT", "自動評価"],
"summary": "RAGシステムにおける評価指標(RAGASなど)の定義、入出力契約に基づいたプロンプト設計、そして評価結果をフィードバックする自動改良ループについて解説します。",
"mermaid": true,
"verify_level": "L0",
"tweet_hint": {"text":"RAGシステムの性能を最大化するための評価戦略と改良ループ(RAGAS、自動評価、CoTプロンプト)を解説。入出力契約を起点に失敗モードを抑制します。","hashtags":["#RAG","#LLM工学","#プロンプト"]},
"link_hints": ["https://arxiv.org/abs/2309.15217"]
}
-->
本記事は<strong>Geminiの出力をプロンプト工学で整理した業務ドラフト(未検証)</strong>です。</p>
<h1 class="wp-block-heading">RAGシステムの評価指標とプロンプト改良ループ</h1>
<p>RAG(Retrieval-Augmented Generation)システムは、外部知識を参照することでLLMの幻覚(Hallucination)を抑制し、応答の根拠を明確化します。しかし、RAGの性能は、コンテキスト取得の精度と、そのコンテキストを利用するプロンプト設計の質に大きく依存します。ここでは、堅牢なRAGシステムを構築するための評価指標と、評価結果をフィードバックする改良ループを定義します。</p>
<h2 class="wp-block-heading">1. ユースケース定義と入出力契約</h2>
<h3 class="wp-block-heading">1.1. ユースケース</h3>
<p>企業内知識ベース(約500件のPDFドキュメント)を情報源とする、開発者向け内部QAボット。応答は常に参照元ドキュメントを明記し、回答は事実に基づいたものであることが必須です。</p>
<h3 class="wp-block-heading">1.2. 制約付き仕様化(入出力契約)</h3>
<p>RAGシステムの堅牢性を確保するため、具体的な入出力契約を定義します。</p>
<figure class="wp-block-table"><table>
<thead>
<tr>
<th style="text-align:left;">項目</th>
<th style="text-align:left;">定義と制約</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;"><strong>入力 Q</strong></td>
<td style="text-align:left;">ユーザー質問(日本語、最大150字)</td>
</tr>
<tr>
<td style="text-align:left;"><strong>入力 C</strong></td>
<td style="text-align:left;">RAGモジュールが取得した関連コンテキスト(最大4,000トークン)</td>
</tr>
<tr>
<td style="text-align:left;"><strong>出力 A</strong></td>
<td style="text-align:left;">回答本文(日本語、簡潔な箇条書きまたは段落)</td>
</tr>
<tr>
<td style="text-align:left;"><strong>出力 R</strong></td>
<td style="text-align:left;">引用リスト(<code>[Doc ID: n]</code> 形式で、回答中に埋め込む)</td>
</tr>
<tr>
<td style="text-align:left;"><strong>失敗時の挙動</strong></td>
<td style="text-align:left;">関連情報がコンテキストCにない場合、「関連情報は見つかりませんでした」と回答し、引用リストRは空とする。</td>
</tr>
<tr>
<td style="text-align:left;"><strong>禁止事項</strong></td>
<td style="text-align:left;">コンテキストCにない情報(幻覚)の生成、感情的な表現、JSON形式以外の出力。</td>
</tr>
</tbody>
</table></figure>
<h2 class="wp-block-heading">2. プロンプト設計の比較(忠実性重視)</h2>
<p>高い忠実性(Faithfulness)を達成するため、3つのプロンプト案を比較検討します。</p>
<h3 class="wp-block-heading">P1. ゼロショット・プロンプト(Zero-shot)</h3>
<div class="codehilite">
<pre data-enlighter-language="generic">あなたは知識豊富なQAボットです。提供されたコンテキストのみに基づき、ユーザーの質問に回答してください。
コンテキストに根拠がない場合は、その旨を伝えてください。
---
コンテキスト: {{C}}
質問: {{Q}}
---
回答:
</pre>
</div>
<h3 class="wp-block-heading">P2. 少数例・プロンプト(Few-shot with Format Constraint)</h3>
<p>出力フォーマット(回答と引用リスト)を厳格に指定し、正例(Example)を1つ以上追加することで、モデルの出力を安定させます。</p>
<div class="codehilite">
<pre data-enlighter-language="generic">あなたは企業知識ベースQAボットです。必ず以下のルールに従ってください。
1. 回答は提供されたコンテキスト{{C}}内の情報に厳密に基づき、忠実性を保つこと。
2. 回答内の事実一つ一つに対し、対応するコンテキストの引用ID(例:[Doc ID: 1])を付与すること。
3. コンテキストに回答に必要な情報がない場合、「関連情報は見つかりませんでした。」と回答し、引用は付けないこと。
---
[Example]
コンテキスト: ID 1: 「プロジェクトAの開始日は2024年6月1日である」。
質問: プロジェクトAの開始日はいつですか?
回答: プロジェクトAの開始日は2024年6月1日です[Doc ID: 1]。
---
コンテキスト: {{C}}
質問: {{Q}}
回答:
</pre>
</div>
<h3 class="wp-block-heading">P3. CoT制約型・プロンプト(Chain-of-Thought with Verification)</h3>
<p>忠実性を最大限に高めるため、回答生成前に「思考」ステップを強制し、コンテキストCと質問Qの関連性を検証させます。</p>
<div class="codehilite">
<pre data-enlighter-language="generic">[SYSTEM]
あなたは高度な検証機能を持つQAエージェントです。ユーザー質問{{Q}}に対し、コンテキスト{{C}}を以下のステップで処理してください。
1. **検証 (Verification)**: コンテキスト{{C}}から質問{{Q}}の回答に必要な事実を抽出し、引用IDと共に箇条書きに列挙せよ。事実が抽出できない場合は「N/A」とせよ。
2. **回答構築 (Generation)**: 検証ステップで抽出された事実のみを用いて、自然な日本語で回答Aを構築せよ。
3. **出力 (Final Output)**: 以下のJSONフォーマットに厳密に従って出力せよ。
---
質問: {{Q}}
コンテキスト: {{C}}
---
{
"verification_facts": ["事実1 [Doc ID: n]", "事実2 [Doc ID: m]", "..."],
"answer": "...",
"citations": ["Doc ID: n", "Doc ID: m", "..."]
}
</pre>
</div>
<h2 class="wp-block-heading">3. RAG評価指標と自動評価ループ</h2>
<p>RAGシステムの評価には、従来の精度(Accuracy)だけでなく、LLM特有の指標が必要です。主要な評価フレームワークであるRAGAS(2023年10月23日公開)で推奨される指標を採用します[R1]。</p>
<figure class="wp-block-table"><table>
<thead>
<tr>
<th style="text-align:left;">指標</th>
<th style="text-align:left;">目的</th>
<th style="text-align:left;">評価対象</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;"><strong>Faithfulness (忠実性)</strong></td>
<td style="text-align:left;">回答が提供されたコンテキストCにどれだけ根拠づけられているか。</td>
<td style="text-align:left;">LLMの生成結果A</td>
</tr>
<tr>
<td style="text-align:left;"><strong>Answer Relevance (関連性)</strong></td>
<td style="text-align:left;">回答Aがユーザー質問Qに対してどれだけ焦点を当てているか。</td>
<td style="text-align:left;">LLMの生成結果A</td>
</tr>
<tr>
<td style="text-align:left;"><strong>Context Recall (再現率)</strong></td>
<td style="text-align:left;">正解回答に必要な情報がコンテキストCにどれだけ含まれていたか。</td>
<td style="text-align:left;">RAG取得モジュール</td>
</tr>
<tr>
<td style="text-align:left;"><strong>Latency</strong></td>
<td style="text-align:left;">応答速度(ミリ秒)。</td>
<td style="text-align:left;">システム全体</td>
</tr>
</tbody>
</table></figure>
<h3 class="wp-block-heading">3.1. 評価シナリオとデータセット設計</h3>
<p>評価データセットは、システムの弱点を特定するために難易度を分散させます。</p>
<ol class="wp-block-list">
<li><p><strong>正例</strong>: コンテキストに明確な回答があり、忠実性の確認が容易なケース。</p></li>
<li><p><strong>難例(ノイズ混入)</strong>: コンテキストに回答と無関係なノイズが多く含まれ、選択的に情報を抽出する必要があるケース。</p></li>
<li><p><strong>コーナーケース(幻覚誘発)</strong>: 質問がコンテキストにない情報について尋ねており、モデルが幻覚を起こしやすいケース(失敗モード検証)。</p></li>
</ol>
<h3 class="wp-block-heading">3.2. 自動評価の擬似コード(LLM-as-a-Judge)</h3>
<p>RAGASフレームワークでは、LLM(通常は強力なモデル)を採点者(Judge)として使用し、忠実性や関連性を評価します。</p>
<div class="codehilite">
<pre data-enlighter-language="generic"># RAG Evaluation Pseudo Code (Simplified RAGAS concept)
def calculate_faithfulness(question, context, answer):
"""
回答Aの各主張がコンテキストC内の事実に基づいているかを評価する。
評価基準: 0.0 (根拠なし) - 1.0 (完全な根拠あり)
"""
# [Judge Prompt]
# 'Given the Q, C, and A, identify all atomic statements in A.
# For each statement, is it supported by C? Output JSON score.'
judge_output = llm_judge(
prompt=FAITHFULNESS_JUDGE_PROMPT,
inputs={'Q': question, 'C': context, 'A': answer}
)
# 計算量 O(k * T_Judge) - kは主張数、T_Judgeは評価モデルの処理時間
return judge_output['faithfulness_score']
def evaluate_system(test_set):
scores = []
for q, ideal_answer, retrieved_context in test_set:
# 1. RAGシステム実行
predicted_answer = rag_model.generate(q, retrieved_context)
# 2. 自動評価
faithfulness = calculate_faithfulness(q, retrieved_context, predicted_answer)
relevance = calculate_relevance(q, predicted_answer)
# 3. 総合スコア記録
scores.append({'Q': q, 'F_Score': faithfulness, 'R_Score': relevance})
return sum(s['F_Score'] for s in scores) / len(scores)
</pre>
</div>
<h2 class="wp-block-heading">4. 誤り分析と改良ループ</h2>
<p>評価フェーズで低スコアを記録したデータセット(特に難例とコーナーケース)を分析し、システムの失敗モードを特定します。</p>
<h3 class="wp-block-heading">4.1. 失敗モードと抑制手法</h3>
<figure class="wp-block-table"><table>
<thead>
<tr>
<th style="text-align:left;">失敗モード</th>
<th style="text-align:left;">具体例</th>
<th style="text-align:left;">抑制手法 (プロンプトまたはシステム)</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;"><strong>幻覚 (Hallucination)</strong></td>
<td style="text-align:left;">コンテキストにない日付や数値を生成してしまう。</td>
<td style="text-align:left;">P3 (CoT制約型)の導入、System指示で「<strong>提供された情報に厳密に従うこと</strong>」を強調。</td>
</tr>
<tr>
<td style="text-align:left;"><strong>様式崩れ</strong></td>
<td style="text-align:left;">引用リストをJSONや指定フォーマットで出力しない。</td>
<td style="text-align:left;">Pydantic出力スキーマの強制、出力後の正規表現検証ステップ(Validation Layer)の追加。</td>
</tr>
<tr>
<td style="text-align:left;"><strong>脱線/無関係</strong></td>
<td style="text-align:left;">質問の意図から外れた、コンテキスト内の別話題に言及する。</td>
<td style="text-align:left;">Answer Relevanceの低スコアに着目。プロンプトで「質問の意図にのみ焦点を当てる」と明記。</td>
</tr>
<tr>
<td style="text-align:left;"><strong>コンテキスト不足</strong></td>
<td style="text-align:left;">回答根拠となるチャンクがRAGモジュールから取得できていない。</td>
<td style="text-align:left;">Context Recallの低スコアに着目。チャンクサイズや埋め込みモデルの再調整(RAGモジュールの改良)。</td>
</tr>
</tbody>
</table></figure>
<h3 class="wp-block-heading">4.2. プロンプト改良とフィードバックループ</h3>
<p>評価結果に基づき、プロンプトを反復的に改良します。例えば、幻覚スコアが低い場合、P1からP3へ切り替え、忠実性を高めるための内部検証ステップを強制します。</p>
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">
flowchart TD
A["要求定義・契約定義"] --> B{"RAGシステム実装"};
B --> C("プロンプト P1/P2/P3 設計");
C --> D["テストデータ作成 Q, C_ideal"];
D --> E("実行とメトリクス算出");
E --> F{"評価結果分析 Faithfulness / Relevance"};
F -- 高スコア --> G["リリース/運用監視"];
F -- 低スコア (幻覚/様式崩れ) --> H["誤り分析とプロンプト修正"];
H --> C;
F -- 低スコア (Context Recall) --> I["RAGモジュール改良: チャンク戦略/モデル更新"];
I --> B;
</pre></div>
<p>Mermaid図では、評価結果(F)がプロンプト修正(H)とRAGモジュール改良(I)の分岐点となり、システム全体の改善ループを形成していることを示しています。</p>
<h2 class="wp-block-heading">5. まとめ</h2>
<p>RAGシステムの性能は、単なる精度ではなく、特に回答の「忠実性(Faithfulness)」と「関連性(Relevance)」によって評価されるべきです。評価結果に基づき、プロンプトをゼロショットからCoT制約型(P3)へと段階的に洗練させ、システム入出力契約に違反する失敗モード(幻覚、様式崩れ)を自動評価と抑制手法によって体系的に除去することが、堅牢なRAG開発の鍵となります。この反復的な評価と改良のループによって、知識ベースの信頼性を維持することが可能となります。</p>
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証) です。
RAGシステムの評価指標とプロンプト改良ループ
RAG(Retrieval-Augmented Generation)システムは、外部知識を参照することでLLMの幻覚(Hallucination)を抑制し、応答の根拠を明確化します。しかし、RAGの性能は、コンテキスト取得の精度と、そのコンテキストを利用するプロンプト設計の質に大きく依存します。ここでは、堅牢なRAGシステムを構築するための評価指標と、評価結果をフィードバックする改良ループを定義します。
1. ユースケース定義と入出力契約
1.1. ユースケース
企業内知識ベース(約500件のPDFドキュメント)を情報源とする、開発者向け内部QAボット。応答は常に参照元ドキュメントを明記し、回答は事実に基づいたものであることが必須です。
1.2. 制約付き仕様化(入出力契約)
RAGシステムの堅牢性を確保するため、具体的な入出力契約を定義します。
項目
定義と制約
入力 Q
ユーザー質問(日本語、最大150字)
入力 C
RAGモジュールが取得した関連コンテキスト(最大4,000トークン)
出力 A
回答本文(日本語、簡潔な箇条書きまたは段落)
出力 R
引用リスト([Doc ID: n] 形式で、回答中に埋め込む)
失敗時の挙動
関連情報がコンテキストCにない場合、「関連情報は見つかりませんでした」と回答し、引用リストRは空とする。
禁止事項
コンテキストCにない情報(幻覚)の生成、感情的な表現、JSON形式以外の出力。
2. プロンプト設計の比較(忠実性重視)
高い忠実性(Faithfulness)を達成するため、3つのプロンプト案を比較検討します。
P1. ゼロショット・プロンプト(Zero-shot)
あなたは知識豊富なQAボットです。提供されたコンテキストのみに基づき、ユーザーの質問に回答してください。
コンテキストに根拠がない場合は、その旨を伝えてください。
---
コンテキスト: {{C}}
質問: {{Q}}
---
回答:
P2. 少数例・プロンプト(Few-shot with Format Constraint)
出力フォーマット(回答と引用リスト)を厳格に指定し、正例(Example)を1つ以上追加することで、モデルの出力を安定させます。
あなたは企業知識ベースQAボットです。必ず以下のルールに従ってください。
1. 回答は提供されたコンテキスト{{C}}内の情報に厳密に基づき、忠実性を保つこと。
2. 回答内の事実一つ一つに対し、対応するコンテキストの引用ID(例:[Doc ID: 1])を付与すること。
3. コンテキストに回答に必要な情報がない場合、「関連情報は見つかりませんでした。」と回答し、引用は付けないこと。
---
[Example]
コンテキスト: ID 1: 「プロジェクトAの開始日は2024年6月1日である」。
質問: プロジェクトAの開始日はいつですか?
回答: プロジェクトAの開始日は2024年6月1日です[Doc ID: 1]。
---
コンテキスト: {{C}}
質問: {{Q}}
回答:
P3. CoT制約型・プロンプト(Chain-of-Thought with Verification)
忠実性を最大限に高めるため、回答生成前に「思考」ステップを強制し、コンテキストCと質問Qの関連性を検証させます。
[SYSTEM]
あなたは高度な検証機能を持つQAエージェントです。ユーザー質問{{Q}}に対し、コンテキスト{{C}}を以下のステップで処理してください。
1. **検証 (Verification)**: コンテキスト{{C}}から質問{{Q}}の回答に必要な事実を抽出し、引用IDと共に箇条書きに列挙せよ。事実が抽出できない場合は「N/A」とせよ。
2. **回答構築 (Generation)**: 検証ステップで抽出された事実のみを用いて、自然な日本語で回答Aを構築せよ。
3. **出力 (Final Output)**: 以下のJSONフォーマットに厳密に従って出力せよ。
---
質問: {{Q}}
コンテキスト: {{C}}
---
{
"verification_facts": ["事実1 [Doc ID: n]", "事実2 [Doc ID: m]", "..."],
"answer": "...",
"citations": ["Doc ID: n", "Doc ID: m", "..."]
}
3. RAG評価指標と自動評価ループ
RAGシステムの評価には、従来の精度(Accuracy)だけでなく、LLM特有の指標が必要です。主要な評価フレームワークであるRAGAS(2023年10月23日公開)で推奨される指標を採用します[R1]。
指標
目的
評価対象
Faithfulness (忠実性)
回答が提供されたコンテキストCにどれだけ根拠づけられているか。
LLMの生成結果A
Answer Relevance (関連性)
回答Aがユーザー質問Qに対してどれだけ焦点を当てているか。
LLMの生成結果A
Context Recall (再現率)
正解回答に必要な情報がコンテキストCにどれだけ含まれていたか。
RAG取得モジュール
Latency
応答速度(ミリ秒)。
システム全体
3.1. 評価シナリオとデータセット設計
評価データセットは、システムの弱点を特定するために難易度を分散させます。
正例 : コンテキストに明確な回答があり、忠実性の確認が容易なケース。
難例(ノイズ混入) : コンテキストに回答と無関係なノイズが多く含まれ、選択的に情報を抽出する必要があるケース。
コーナーケース(幻覚誘発) : 質問がコンテキストにない情報について尋ねており、モデルが幻覚を起こしやすいケース(失敗モード検証)。
3.2. 自動評価の擬似コード(LLM-as-a-Judge)
RAGASフレームワークでは、LLM(通常は強力なモデル)を採点者(Judge)として使用し、忠実性や関連性を評価します。
# RAG Evaluation Pseudo Code (Simplified RAGAS concept)
def calculate_faithfulness(question, context, answer):
"""
回答Aの各主張がコンテキストC内の事実に基づいているかを評価する。
評価基準: 0.0 (根拠なし) - 1.0 (完全な根拠あり)
"""
# [Judge Prompt]
# 'Given the Q, C, and A, identify all atomic statements in A.
# For each statement, is it supported by C? Output JSON score.'
judge_output = llm_judge(
prompt=FAITHFULNESS_JUDGE_PROMPT,
inputs={'Q': question, 'C': context, 'A': answer}
)
# 計算量 O(k * T_Judge) - kは主張数、T_Judgeは評価モデルの処理時間
return judge_output['faithfulness_score']
def evaluate_system(test_set):
scores = []
for q, ideal_answer, retrieved_context in test_set:
# 1. RAGシステム実行
predicted_answer = rag_model.generate(q, retrieved_context)
# 2. 自動評価
faithfulness = calculate_faithfulness(q, retrieved_context, predicted_answer)
relevance = calculate_relevance(q, predicted_answer)
# 3. 総合スコア記録
scores.append({'Q': q, 'F_Score': faithfulness, 'R_Score': relevance})
return sum(s['F_Score'] for s in scores) / len(scores)
4. 誤り分析と改良ループ
評価フェーズで低スコアを記録したデータセット(特に難例とコーナーケース)を分析し、システムの失敗モードを特定します。
4.1. 失敗モードと抑制手法
失敗モード
具体例
抑制手法 (プロンプトまたはシステム)
幻覚 (Hallucination)
コンテキストにない日付や数値を生成してしまう。
P3 (CoT制約型)の導入、System指示で「提供された情報に厳密に従うこと 」を強調。
様式崩れ
引用リストをJSONや指定フォーマットで出力しない。
Pydantic出力スキーマの強制、出力後の正規表現検証ステップ(Validation Layer)の追加。
脱線/無関係
質問の意図から外れた、コンテキスト内の別話題に言及する。
Answer Relevanceの低スコアに着目。プロンプトで「質問の意図にのみ焦点を当てる」と明記。
コンテキスト不足
回答根拠となるチャンクがRAGモジュールから取得できていない。
Context Recallの低スコアに着目。チャンクサイズや埋め込みモデルの再調整(RAGモジュールの改良)。
4.2. プロンプト改良とフィードバックループ
評価結果に基づき、プロンプトを反復的に改良します。例えば、幻覚スコアが低い場合、P1からP3へ切り替え、忠実性を高めるための内部検証ステップを強制します。
flowchart TD
A["要求定義・契約定義"] --> B{"RAGシステム実装"};
B --> C("プロンプト P1/P2/P3 設計");
C --> D["テストデータ作成 Q, C_ideal"];
D --> E("実行とメトリクス算出");
E --> F{"評価結果分析 Faithfulness / Relevance"};
F -- 高スコア --> G["リリース/運用監視"];
F -- 低スコア (幻覚/様式崩れ) --> H["誤り分析とプロンプト修正"];
H --> C;
F -- 低スコア (Context Recall) --> I["RAGモジュール改良: チャンク戦略/モデル更新"];
I --> B;
Mermaid図では、評価結果(F)がプロンプト修正(H)とRAGモジュール改良(I)の分岐点となり、システム全体の改善ループを形成していることを示しています。
5. まとめ
RAGシステムの性能は、単なる精度ではなく、特に回答の「忠実性(Faithfulness)」と「関連性(Relevance)」によって評価されるべきです。評価結果に基づき、プロンプトをゼロショットからCoT制約型(P3)へと段階的に洗練させ、システム入出力契約に違反する失敗モード(幻覚、様式崩れ)を自動評価と抑制手法によって体系的に除去することが、堅牢なRAG開発の鍵となります。この反復的な評価と改良のループによって、知識ベースの信頼性を維持することが可能となります。
コメント