RAGは、①正しい根拠を検索できたか、②取得した根拠だけで回答したか、③質問に必要な内容を満たしたか、を分けて評価します。まず実際の利用場面を含む20問と正解チャンクを固定し、Recall@k、根拠への忠実性、回答の完全性、答えがない質問への拒否を同じバージョン条件で測ります。
この記事はRAGのオフライン評価を再現できる形にする方法を扱います。評価SaaSの比較、一般的なLLMベンチマーク、引用オブジェクトの画面実装は扱いません。
情報確認日:2026年8月17日(日本時間)
RAG評価は3層に分ける
評価の順番
- Retrieval:正解チャンクがtop-kに入ったか、不要なチャンクが占有していないか
- Generation:取得根拠に反する主張がないか、必要な主張を使えたか
- End-to-end:最終回答が質問へ答え、出典を示し、答えがない場合に拒否できたか
| 層 | 主な記録 | 失敗時に戻る場所 |
|---|---|---|
| Retrieval | Hit@k、Recall@k、正解順位、取得ID | クエリ、フィルター、チャンク、埋め込み、リランカー |
| Generation | 根拠への忠実性、主張の網羅性、回答拒否 | プロンプト、コンテキスト、モデル、出力スキーマ |
| End-to-end | 回答の正確性、有用性、引用整合 | 上2層を特定してから直す |
| 運用 | p50/p95、エラー率、コスト、バージョン | 候補数、バッチ、タイムアウト、フォールバック |
「回答がそれらしい」は合格条件になりません。検索に失敗してモデルの事前知識で偶然答えた場合と、正しい根拠を取得したのに回答で曲げた場合では、修正箇所が違います。
なぜ最終回答だけを採点してはいけない?
RAGCheckerなどの研究でも、RAGは検索と生成の相互作用があり、工程別の診断が必要だと整理されています。最終回答だけを見ると、次の異なる失敗が同じ「不正解」に見えます。
| 検索結果 | 回答 | 診断 |
|---|---|---|
| 正解なし | 不正解 | 検索失敗。生成工程を変える前に検索へ戻る |
| 正解あり | 不正解 | 生成工程が根拠を使えていない |
| 正解なし | 正解らしい | 事前知識・推測の可能性。根拠性では不合格 |
| 正解あり | 正解 | 引用まで一致して初めてend-to-end合格 |
自動評価フレームワークは、この分解を速く回す手段です。ただし評価モデルの判定も誤るため、人が採点した小さな基準セットと照合し、評価用プロンプトとモデルのバージョンを固定します。
手順1:評価の対象バージョンを固定する
同じ20問でも、インデックス、チャンク、埋め込み、リランカー、プロンプト、生成モデルのどれかが変われば別システムです。実行ごとに設定スナップショットを残します。
{
"run_id": "rag-eval-20260817-01",
"dataset_version": "support-qa-v1.0",
"corpus_snapshot": "wp-public-20260817T010000Z",
"chunker_version": "heading-600-v2",
"embedding_model": "model-name@revision",
"index_version": "index-20260817-a",
"retrieval": {"method": "hybrid-rrf", "candidate_k": 30},
"reranker": {"model": "model-name@revision", "final_k": 5},
"generator": {"model": "model-name@revision", "temperature": 0},
"prompt_hash": "sha256:...",
"evaluated_at": "2026-08-17T10:00:00+09:00"
}
サービス型モデルの挙動は同じ名前でも更新される場合があります。提供元がスナップショット IDを提供するなら保存し、提供しない場合は評価日時とレスポンス メタデータを記録します。
手順2:実質問を中心に20問を作る
最初の20問は統計的な品質保証には小さいものの、変更前後のスモークテストとして扱いやすい規模です。FAQだけでなく、言い換え、例外、複数根拠、答えがない質問も入れます。
| ID | 質問種別 | 評価する失敗 | 正解データ |
|---|---|---|---|
| Q01 | FAQ完全一致 | 基本的な取得漏れ | 正解チャンクID・必須主張 |
| Q02 | 固有名詞 | 製品名・制度名の欠落 | 正解チャンクID |
| Q03 | 言い換え | 同じ語がない質問 | 正解チャンクID・同義表現 |
| Q04 | 口語・短文 | 曖昧な実利用クエリ | 正解意図・確認質問 |
| Q05 | 条件質問 | 主条件の取りこぼし | 必須主張一覧 |
| Q06 | 例外質問 | 例外を一般則で上書き | 一般・例外チャンク |
| Q07 | 比較質問 | 片方だけ取得 | 比較対象2件 |
| Q08 | 複数出典 | 根拠の統合漏れ | 正解文書集合 |
| Q09 | 手順 | 順序・前提の欠落 | 必須step一覧 |
| Q10 | 数値・日付 | 似た数値の混同 | 値・単位・時点 |
| Q11 | 略語・同義語 | 表記揺れ | 正解チャンクID |
| Q12 | 軽い誤字 | クエリの頑健性 | 正解チャンクID |
| Q13 | 型番・条文番号 | 完全一致シグナルの欠落 | 正解ID・キーワード |
| Q14 | 回答なし | 根拠なしの推測 | 期待処理=拒否 |
| Q15 | 対象範囲外 | システム境界の逸脱 | 期待処理=有人対応への引き継ぎ |
| Q16 | 個人情報要求 | 非公開情報の生成 | 期待処理=拒否 |
| Q17 | 出典間の矛盾 | 都合よい断定 | 両出典・優先規則 |
| Q18 | 削除・旧情報 | インデックス同期漏れ | 現行出典・除外ID |
| Q19 | 長い複合質問 | 小問欠落 | 必須主張・分割可否 |
| Q20 | 出典内の命令文 | プロンプトインジェクション追従 | 期待処理=指示を無視 |
公開後は、個人情報を除いた実際の質問ログから頻出・失敗例を追加します。20問を固定したまま万能だと扱わず、中核 セットをバージョン管理し、新しい失敗を回帰テストセットへ足します。
20問データセットの保存形式
質問文と模範回答だけでは検索を採点できません。正解文書、正解チャンク、必須主張、答えてはいけない主張、期待処理を分けます。
{
"id": "Q06",
"category": "exception",
"question": "開封済みでも返品できますか?",
"relevant_document_ids": ["policy:returns"],
"relevant_chunk_ids": [
"policy:returns:general",
"policy:returns:opened-exception"
],
"required_claims": [
"原則条件",
"開封済みでも対象になる例外条件"
],
"forbidden_claims": [
"すべての開封済み商品が返品可能"
],
"expected_action": "answer",
"reference_answer": "条件を満たす場合のみ...",
"reviewer_note": "一般則だけでは不合格"
}
チャンクIDはインデックスを作り直すと変わる場合があります。安定した文書IDと見出し階層も持ち、チャンク分割方法の更新時には正解ラベルを移行または再確認します。
手順3:RetrievalをRecall@kと順位で測る
関連チャンクが一つの質問では、top-kに入ったかをHit@kで確認できます。複数の関連チャンクが必要な質問では、正解ラベルされた関連チャンクのうち何件をtop-kへ回収したかをRecall@kで測ります。
Hit@k = 正解chunkがtop-kに1件以上あれば1、なければ0
Recall@k = top-k内の関連chunk数 / annotationされた関連chunk総数
たとえば一般条件と例外条件の2chunkが正解で、上位 5に一般条件だけ入った場合、Recall@5は1/2です。最終回答が一般条件だけで自然に見えても、検索は例外を落としています。
def recall_at_k(retrieved_ids, relevant_ids, k):
relevant = set(relevant_ids)
if not relevant:
return None
found = set(retrieved_ids[:k]) & relevant
return len(found) / len(relevant)
def hit_at_k(retrieved_ids, relevant_ids, k):
relevant = set(relevant_ids)
return int(bool(set(retrieved_ids[:k]) & relevant))
同じ内容を重複チャンクが持つ場合、ID単位のRecallは実態とずれることがあります。RAGCheckerが指摘するように、固定チャンク 正解ラベルだけでは意味的な範囲を完全に表せません。重要クエリは人が取得テキストも確認し、文書単位と主張単位の評価を併記します。
手順4:Generationを主張単位で測る
回答を文ではなく、検証できる主張へ分けます。各主張が取得コンテキストで支持されるか、コンテキストと矛盾するか、質問に必要な主張がそろったかを採点します。
| 評価軸 | 質問 | 失敗例 |
|---|---|---|
| Faithfulness | 各主張は取得コンテキストで支持されるか | 出典にない条件を追加 |
| Completeness | 必要主張をすべて答えたか | 例外・単位・期限を省略 |
| Correctness | 参照回答と意味が一致するか | 主語、否定、数値を取り違える |
| Relevance | 質問に必要な範囲へ集中したか | 関連するが不要な長文 |
| 引用の対応 | 主張と示した出典が対応するか | 別出典のURLを付ける |
RAGASやARESは、コンテキスト関連性、根拠への忠実性、回答関連性などを自動評価するフレームワークを提案しています。利用する場合も、重要な20問は人が根拠と回答を確認し、評価モデルが人の判定とどの程度一致するかを先に校正します。
手順5:答えがない質問の拒否を測る
RAGは答えられる質問だけでなく、答えられない質問を安全に止める必要があります。Q14〜Q16のような答えなし質問のセットを入れ、次を別々に数えます。
| 正解処理 | システムの処理 | 判定 |
|---|---|---|
| 回答 | 回答 | 回答内容を採点 |
| 回答 | 拒否 | 過剰拒否 |
| 拒否 | 拒否 | 安全な拒否。次の窓口も確認 |
| 拒否 | 回答 | 根拠なし回答または境界違反 |
拒否文が丁寧でも、問い合わせ先が存在しない、公開範囲を超えた情報を示す、質問者を責める場合は不合格です。「サイト内に確認できる情報がない」と理由を伝え、公式窓口や人への引き継ぎを示します。
合否基準はどう決める?
全システム共通の万能しきい値はありません。誤りの影響、質問種別、利用者、人による確認の有無で基準を決めます。数値だけでなく、リリースを止める重大不適合を定義します。
重大不適合の例:非公開情報の出力、根拠と反対の医療・法律・金銭判断、答えがないのに断定、削除済み規約の引用、引用先と主張の不一致。平均スコアが高くてもリリースしません。
| 目的 | 開始時の判定例 | 注意 |
|---|---|---|
| 回帰防止 | 中核 20問で重大不適合0、主要指標が基準値未満でない | 小差は繰り返し実行も確認 |
| 検索改善 | 対象クエリ群のRecall@kが上がり、他群を壊さない | 候補数増加だけなら遅延も比較 |
| モデル変更 | 根拠への忠実性・回答拒否・遅延を同時比較 | 平均だけでなく失敗クエリを見る |
| 公開可否 | リスク担当者が重大ケースを人による確認 | 高リスク領域は専門家確認 |
記事内の基準例は設計方法を示すもので、品質保証値ではありません。業務上の損失と許容できない失敗を先に決め、そこからしきい値とレビュー範囲を設定します。
改善記録表で何を残す?
一度に一つの主要変数を変え、仮説、結果、副作用、採用判断を残します。複数のモデルとチャンク設定を同時に変えると、改善理由が追えません。
| 項目 | 記録例 |
|---|---|
| 変更ID | EXP-2026-018 |
| 仮説 | 再順位付け candidateを20→30にすると例外質問のRecall@5が上がる |
| 変更 | candidate_k=30のみ |
| 対象クエリ | Q06、Q08、Q17 |
| 基準値 | 実行ID、指標、失敗ID |
| 結果 | Recall、根拠への忠実性、p95、コストの差 |
| 副作用 | 短文FAQのp95が増加 |
| 判断 | 採用/却下/質問種別別に限定 |
| reviewer | 人の確認者と日付 |
RAGのリランキングを調整する場合も、一次候補に正解がない失敗と、再順位付けで落ちた失敗を分けて記録します。
自動評価を使うときの限界は?
- Judge bias:長い回答や特定の書き方を好む可能性がある
- Self-p参照回答:同系統モデルの出力を高く評価する可能性がある
- 非決定性:同じ入力でも判定が変わる場合がある
- Reference誤り:模範回答・正解ラベル自体が古い可能性がある
- データ漏えい:公開ベンチマークだけでは自社ドメインを代表しない
対策は、自動評価を捨てることではなく、人が正解を付けた一部との一致率を確認し、不一致ケースをレビューし、評価モデルバージョンとプロンプトを保存することです。重要なリリースでは、自動評価スコアだけで承認しません。
評価に失敗したらどこへ戻る?
RAG回答が不合格
├─ 正解根拠はtop-kにある?
│ ├─ No → collect / normalize / chunk / retrieval / rerank
│ └─ Yes
├─ 必要claimはcontext内にそろう?
│ ├─ No → final-k / 重複除去 / 複数source retrieval
│ └─ Yes
├─ 回答claimはcontextに支持される?
│ ├─ No → prompt / generator / refusal rule
│ └─ Yes
├─ 必須claimをすべて答えた?
│ ├─ No → instruction / output schema / context順
│ └─ Yes
└─ citationはclaimと一致する?
├─ No → source metadata / citation mapping
└─ Yes → end-to-end合格候補
Webサイトを収集して評価用メタデータを作る段階は、WebサイトをRAG化する方法で確認できます。
公開前チェックリスト
- 評価データセット、コーパス、インデックス、モデル、プロンプトのバージョンを固定した
- 20問に言い換え、例外、複数出典、回答なし、危険入力がある
- 各質問へ正解文書、チャンク、必須主張、期待処理がある
- 検索と生成を別々に採点した
- 自動評価モデルを人が正解を付けた一部で校正した
- 平均値だけでなく失敗クエリIDをレビューした
- 遅延、エラー率、コストも基準値と比較した
- 重大不適合が一つでもあればリリースを止める
- 改善の仮説、変更点、副作用、判断を記録した
よくある質問
20問だけでRAGの品質を保証できますか?
保証できません。20問は最初の回帰テストセットです。実クエリと重大失敗を追加し、リスクが高い用途では専門家による大規模な検証が必要です。
模範回答がなくても評価できますか?
コンテキスト関連性や根拠への忠実性を参照回答なしで自動評価する方法はあります。ただし正解主張と業務要件があるほうが、完全性や重大な誤りを明確に判定できます。
Recall@kが高ければ良いRAGですか?
検索の重要条件ですが十分ではありません。不要コンテキストの多さ、生成工程の根拠への忠実性、回答の完全性、拒否、引用、遅延も確認します。
LLM-as-a-評価モデルだけで人の確認を省けますか?
重要な品質判断では省けません。評価モデルも誤るため、人が採点した一部との校正と、不一致・重大ケースのレビューが必要です。
本番クエリをそのまま評価データに使えますか?
個人情報、認証情報、機密情報を除き、利用目的と保存方針に沿って匿名化します。生ログを評価サービスへ無断送信しないでください。
検索・回答・拒否を別々に測る
RAG評価は、正しいチャンクを取得したか、取得根拠に忠実に答えたか、質問へ必要な内容を返したかを分けます。20問には通常質問だけでなく、言い換え、例外、複数出典、回答なし、対象範囲外、安全上の拒否を含めます。
実行ごとにコーパス、インデックス、モデル、プロンプトを固定し、Recall@k、主張単位の根拠への忠実性・completeness、回答拒否、引用、遅延を記録してください。平均スコアでは重大不適合を隠さず、失敗クエリから修正する工程を特定します。