メインコンテンツへスキップ

8.1.8 RAG 評価

RAG 評価の三角図

学習目標

この節を終えると、あなたは次のことができるようになります。

  • RAG を 1 回のデモだけで良し悪し判断してはいけない理由を理解する
  • 検索評価と回答評価の違いを整理する
  • 小さなサンプルで簡単な指標を計算する
  • 「まず評価し、それから改善する」という開発習慣を身につける

一、なぜ RAG には特に評価が必要なのか?

単一のモジュールではないから

RAG は 1 つのモデルではなく、少なくとも次の要素を含みます。

  1. 文書処理
  2. 検索
  3. コンテキストの組み立て
  4. 回答生成

どれか 1 つでも失敗すると、最終的な答えは悪くなる可能性があります。

だから「正解したか」だけでは足りない

次の点も確認する必要があります。

  • 検索できなかったのか?
  • 検索はできたが、うまく使えなかったのか?
  • それとも、回答の文章がうまくまとまっていないのか?

だからこそ、RAG の評価は階層ごとに見る必要があります。


二、第一層:検索評価

最もよく使う直感的な指標:Hit@k

Hit@k の意味はとてもシンプルです。

正しい証拠が、上位 k 件の検索結果に入っているか?

ユーザーの質問に対する正しい証拠が top-3 にあれば、hit とみなします。

なぜこの指標が重要なのか?

正しい資料がそもそも取り出せていなければ、その後の生成で安定して正解するのはほぼ不可能だからです。

つまり、

検索評価は RAG 評価の土台です。


三、第二層:回答評価

「文章が自然」だけではまったく足りない

回答評価では、少なくとも次の点を見る必要があります。

  • 答えが正しいか
  • 根拠があるか
  • 勝手に作っていないか

よく見る観点

観点注目する点
Correctness事実として正しいか
Faithfulness与えられた資料に基づいているか
Relevanceユーザーの質問に答えているか
Completeness重要な情報が漏れていないか

実際の業務では、観点ごとの重要度は異なります。

RAG の階層評価ダッシュボード図

RAG 評価の閉ループ図

よい評価は 1 回で終わるものではなく、テストセット -> 検索 -> 回答 -> 引用 -> 失敗分析 -> 修正 -> 再評価、というループです。

図の読み方

最終回答のスコアだけを見ないでください。まず retrieval 層でヒットしているかを見て、次に generation 層で正しく完全かを見ます。最後に citation 層で、その結論を本当に支えているかを確認します。


四、最小の評価データセット

ここでは、手作業で作ったミニ評価データセットを用意します。

dataset = [
{
"question": "いつまで返金できますか?",
"gold_doc": "返金ポリシー",
"gold_answer": "コース購入後 7 日以内に返金を申請できます"
},
{
"question": "どうやって証明書を取得しますか?",
"gold_doc": "証明書の説明",
"gold_answer": "プロジェクトを完了し、テストに合格すると証明書を取得できます"
}
]

predictions = [
{
"retrieved_docs": ["返金ポリシー", "学習順序"],
"answer": "コース購入後 7 日以内に返金を申請できます"
},
{
"retrieved_docs": ["学習順序", "証明書の説明"],
"answer": "プロジェクトを完了し、テストに合格すると証明書を取得できます"
}
]

print(dataset)
print(predictions)

期待される出力:

[{'question': 'いつまで返金できますか?', 'gold_doc': '返金ポリシー', 'gold_answer': 'コース購入後 7 日以内に返金を申請できます'}, {'question': 'どうやって証明書を取得しますか?', 'gold_doc': '証明書の説明', 'gold_answer': 'プロジェクトを完了し、テストに合格すると証明書を取得できます'}]
[{'retrieved_docs': ['返金ポリシー', '学習順序'], 'answer': 'コース購入後 7 日以内に返金を申請できます'}, {'retrieved_docs': ['学習順序', '証明書の説明'], 'answer': 'プロジェクトを完了し、テストに合格すると証明書を取得できます'}]

このデータは「正解」と「予測」に分けて読みます。gold_doc / gold_answer は参照基準で、retrieved_docs / answer は RAG システムが出した結果です。


五、簡単な Hit@k を計算する

実行できる例

dataset = [
{
"question": "いつまで返金できますか?",
"gold_doc": "返金ポリシー"
},
{
"question": "どうやって証明書を取得しますか?",
"gold_doc": "証明書の説明"
}
]

predictions = [
{
"retrieved_docs": ["返金ポリシー", "学習順序"]
},
{
"retrieved_docs": ["学習順序", "証明書の説明"]
}
]

hits = 0
for item, pred in zip(dataset, predictions):
if item["gold_doc"] in pred["retrieved_docs"]:
hits += 1

hit_at_2 = hits / len(dataset)
print("Hit@2 =", round(hit_at_2, 4))

期待される出力:

Hit@2 = 1.0

正しい文書がすべて上位 2 件に入っていれば、この値は 1.0 になります。

この指標の限界

これで分かるのは「取り出せたかどうか」だけです。
次のことは分かりません。

  • 何位だったのか
  • 回答が本当に正しいのか

なので、これはあくまで最初の一歩です。


六、簡単な回答正解率を計算する

最もシンプルな Exact Match の考え方

構造化された短い回答なら、まずは素朴な方法で確認できます。

dataset = [
{
"gold_answer": "コース購入後 7 日以内に返金を申請できます"
},
{
"gold_answer": "プロジェクトを完了し、テストに合格すると証明書を取得できます"
}
]

predictions = [
{
"answer": "コース購入後 7 日以内に返金を申請できます"
},
{
"answer": "プロジェクトを完了し、テストに合格すると証明書を取得できます"
}
]

correct = 0
for item, pred in zip(dataset, predictions):
if item["gold_answer"] == pred["answer"]:
correct += 1

exact_match = correct / len(dataset)
print("Exact Match =", round(exact_match, 4))

期待される出力:

Exact Match = 1.0

でも実際の場面はそんなに単純ではない

同じ正解でも、言い方はいろいろあります。
そのため、実運用では次のような方法もよく使います。

  • 意味ベースのマッチング
  • LLM-as-a-judge
  • 人手によるサンプルチェック

七、Faithfulness: 回答は根拠に基づいているか?

「それっぽく見える」より大事

文章としては流暢でも、検索した資料に基づいていないなら危険です。

簡単な確認方法の例

以下の例はかなり単純ですが、「回答が証拠で支えられているか」を理解する助けになります。

evidence = "コース購入後 7 日以内に返金を申請できます"
answer = "コース購入後 7 日以内に返金を申請できます"

faithful = answer in evidence or evidence in answer
print("証拠に支えられているか:", faithful)

期待される出力:

証拠に支えられているか: True

RAG 評価実験結果図

実際のシステムでは、もちろんこんな文字列比較だけではありません。
ただ、考え方としては正しいです。

回答は、できるだけ検索した証拠の中で支えられるべきです。

Faithfulness と引用の真正性チェック図

図の読み方

回答をいくつかの重要な結論に分けて、それぞれを evidence に戻して確認します。つながるものは supported、つながらないものは unsupported です。これは「見た目が自然か」より信頼できます。


八、評価データセットはどう作る?

最小限で使える評価セット

少なくとも次を含めましょう。

  • ユーザーの質問
  • 標準回答
  • 正しい証拠文書または証拠スニペット

難しさの違う問題を混ぜるのがおすすめ

たとえば次のような問題です。

  • 簡単な事実問答
  • 同義表現の質問
  • 複数段落にまたがる質問
  • 混同しやすい質問

評価セットが単一的すぎると、改善結果が実態より良く見えてしまいます。


九、オンライン評価もとても重要

オフライン評価だけでは全部は分からない

ローカルのデータセットがどれだけ良くても、実際のユーザー質問を完全にはカバーできません。

よく見るオンラインのシグナル

たとえば次のようなものです。

  • ユーザーの追加質問率
  • ユーザーの修正率
  • いいね / 低評価
  • 人手による品質チェックのサンプリング

成熟した RAG システムでは、通常「オフライン評価 + オンラインフィードバック」をセットで見ます。


十、目標が「知識ベース駆動の教材生成アシスタント」なら、何を重視して評価する?

このタイプのプロジェクトは、普通の QA システムとは少し違います。
大事なのは「答えがそれっぽいか」だけではなく、次の点です。

  • テーマ資料を正しく見つけられているか
  • 例題を適切に取れているか
  • 最終的なセクションを正しい場所に置けているか
  • 出典をたどれるか

このようなプロジェクトに向いた評価表では、少なくとも次のような層を追加するとよいです。

観点何を見るか
テーマ命中そのテーマの核心資料を見つけられたか
例題の再現説明用の例題として適切な材料を見つけられたか
構造の正しさ概念、例題、練習が正しいセクションに入っているか
出典の完全性最終結果を元資料までたどれるか

まずは次のように理解するとよいです。

教材生成プロジェクトの評価は、「答えたか」ではなく「見つけたか、置けたか、引用できたか」を見ることです。

十一、教材生成プロジェクトに近い最小評価例

dataset = [
{
"topic": "割引の応用問題",
"gold_concepts": ["割引 = 元の価格 × 割引率"],
"gold_examples": ["商品は元値 100 円、8 割引後の価格はいくらですか?"],
}
]

prediction = {
"concepts": ["割引 = 元の価格 × 割引率"],
"examples": ["商品は元値 100 円、8 割引後の価格はいくらですか?"],
"source_refs": [{"doc_id": "word_001", "page_or_slide": 3}],
}

print(dataset[0])
print(prediction)

期待される出力:

{'topic': '割引の応用問題', 'gold_concepts': ['割引 = 元の価格 × 割引率'], 'gold_examples': ['商品は元値 100 円、8 割引後の価格はいくらですか?']}
{'concepts': ['割引 = 元の価格 × 割引率'], 'examples': ['商品は元値 100 円、8 割引後の価格はいくらですか?'], 'source_refs': [{'doc_id': 'word_001', 'page_or_slide': 3}]}

この例は小さいですが、初学者が評価の感覚をつかむのに役立ちます。

  • この種のシステムで最終的に評価するのは、たいてい「1 文の答え」ではない
  • 1 つの構造化された結果全体である

十二、初学者によくある誤解

1 つか 2 つの成功例だけを見る

デモはやる気を出させますが、評価の代わりにはなりません。

回答だけ評価して、検索を評価しない

これだと、問題がどの層で起きているのか分かりにくくなります。

システムを修正しながら、評価セットを固定しない

固定された評価セットがないと、本当に改善したのか、それともたまたま変動しただけなのか判断しにくくなります。


RAG プロジェクトの評価指標まとめ表

RAG プロジェクトでは、「答えがそれっぽいか」だけを見てはいけません。より安定した方法は、評価を検索、生成、引用、システムの 4 層に分けることです。

指標説明
検索層命中率、Recall@K、MRR正しい資料が見つかったか、上位に来ているか
生成層回答正解率、完全性、一貫性資料に基づいて答えられているか、重要条件を落としていないか
引用層引用カバレッジ、引用の真正性回答中の重要な結論が出典にたどれるか
システム層レイテンシ、コスト、失敗率実ユーザーに安定して、無理なく提供できるか

最小評価セットは、まず 20〜50 問ほど用意するのがおすすめです。各問題に標準回答、命中すべき文書、重要な引用を付けておきます。こうしておけば、chunk、embedding、rerank、query rewrite を改善したときに、本当に良くなったのか、それとも一部の例だけ見栄えが良くなったのかを判断できます。

層ごとの失敗原因の切り分け表

評価の価値は、単に総合点を出すことではありません。次にどこを直すべきかを知ることです。下の表は、実験記録にそのまま使えます。失敗が出たら、まずどの層の問題かを切り分けましょう。

失敗の現象失敗層確認すべき点次のアクション
正しい文書が top-k に入らない検索層query、chunk、embedding、キーワード一致チャンク分割を調整する、混合検索や query rewrite を加える
正しい文書は top-k にあるが、最終 context に入らないコンテキスト層context packing、重複除去、長さ制限並び順、圧縮、パッキング戦略を調整する
context に証拠はあるが、回答が重要条件を落としている生成層prompt、回答形式、モデルが証拠に従っているか証拠に基づいて 1 つずつ答えるように指示し、制約条件を残す
結論は正しいが、引用が支えていない引用層source_refs、引用スニペット、回答文引用の真正性チェックを行い、証拠のない引用を禁止する
オフライン評価は良いのに、ユーザーが何度も追い質問するプロダクト層実際の質問分布、評価セットのカバー範囲実際の質問を評価セットに追加する

「最終的に正解したか」だけを見ると、これらの問題は混ざってしまいます。層ごとに切り分けると、改善のアクションがはっきりします。検索が悪いなら prompt をいじる前に検索を直すべきですし、引用が悪いなら答えの自然さだけを見ても意味がありません。

そのまま使える評価記録テンプレート

RAG プロジェクトでは、毎回の評価を固定フォーマットで残すのがおすすめです。最初は十数件でも、単発のデモを見るよりずっと安定して状況を把握できます。

フィールド用途
questionコースはいつまで返金できますか?ユーザーの質問
gold_doc返金ポリシー命中すべき資料
gold_answerコース購入後 7 日以内に返金を申請できます標準回答または重要事実
retrieved_docs返金ポリシー, 学習順序実際に命中した文書
answer7 日以内に返金を申請できますシステムの回答
citation_oktrue引用が回答を支えているか
failure_typenone / retrieval / generation / citation失敗原因
notes正しく命中し、引用も支えている人手メモ

最小の CSV は次のように書けます。

question,gold_doc,gold_answer,retrieved_docs,answer,citation_ok,failure_type,notes
コースはいつまで返金できますか?,返金ポリシー,コース購入後 7 日以内に返金を申請できます,"返金ポリシー;学習順序",コース購入後 7 日以内に返金を申請できます,true,none,正しく命中し引用も支えている
どうやって証明書を取得しますか?,証明書の説明,プロジェクトを完了し、テストに合格すると証明書を取得できます,"学習順序;証明書の説明",プロジェクトを完了すると証明書を取得できます,false,generation,テストに合格するという重要条件が抜けている

このテンプレートのポイントは、項目が多いことではありません。各サンプルについて、次の 3 つが分かることです。何を命中すべきか、実際に何を命中したか、最終回答は証拠に支えられているか。

教材生成 RAG の受け入れ Rubric

プロジェクトの目的が教材や学習資料の生成なら、評価は QA の段階だけで終わらせるべきではありません。次の rubric は、ポートフォリオ用プロジェクトの受け入れ基準として使えます。

レベル検索要件生成要件引用要件
練習レベルテーマ関連資料を命中できる基本的な回答や断片を生成できる参照ファイル名を表示できる
プロジェクトレベルtopic と content_type に応じて概念、例題、練習を検索できる決まったセクション構成で出力できる重要セクションごとに出典がある
ポートフォリオレベル固定の評価セットと失敗サンプルがある失敗が検索・生成・テンプレートのどれか説明できる重要な結論を原文までたどれる
面接レベルbaseline、混合検索、rerank などの戦略を比較できる品質、コスト、レイテンシのトレードオフを説明できる引用の真正性を抽出確認し、改善記録を残せる

この表はそのまま README に入れられます。そうすれば、見る人に「ただ質問に答えるデモを作った」のではなく、「知識ベース駆動システムを工程として評価している」ことが伝わります。


まとめ

この節で最も大事なポイントは次の通りです。

RAG 評価はおまけではなく、システム改善のためのハンドルです。

評価がなければ、感覚でしか改善できません。
評価があれば、どこが悪いのか、変更が本当に効果を出したのかが分かります。


練習

  1. 評価セットにさらに 3 問追加して、自分で gold_docgold_answer を書いてみましょう。
  2. predictions を変更して、わざと 1 つの回答を間違えさせ、Hit@k と Exact Match をもう一度計算してみましょう。
  3. 考えてみましょう。Hit@k は高いのに、最終回答がよく間違うなら、問題はどの層にある可能性が高いでしょうか?