Dev Study
← AIを部品として組み込む仕組み
レッスン 9 / 12·約 9 分·第20期 AIを部品として組み込む仕組み

検索が落としたものは、生成の側から見えない

リクエストがアプリケーションに届くまで
  1. ブラウザURL入力
  2. DNS名前→IP
  3. ルータ経路選択
  4. ロードバランサ振り分け
  5. Nginx受け口
  6. アプリ処理今ここ
  7. DB保存

確率で答える部品の確かさは、部品の外側にしか書けません。今回は、生成器の手前にある検索という部品の取りこぼしを、どこで測るかを見ます。

まず結論

検索拡張生成(RAG)の生成器は、検索が返した上位 k 件しか読みません。正解の文書が k 件の外に落ちると、その文書は答えに一切効かず、しかも誤った答えは正しい答えと同じ形で出てくることがあります。

だから答えだけを見ても、検索が落としたかどうかは分かりません。正解の文書を付けた問いで、検索がそれを上位 k 件に入れた割合を、生成とは別に測ります。

? 読む前に予測

8件の正解文書に、同じ書式のエラー説明文を足して512件にしました。8問のうち、埋め込み検索が正解文書を上位5件に入れられた問いはいくつでしょうか。

当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。

抽象原理

生成器が読むのは、検索が渡した k 件だけ

RAG(検索拡張生成)は、問いで文書を探し、見つけた文書を添えて生成器に答えさせる構成です。RAG 論文(Lewis et al.)は要旨でこう書きます。

the non-parametric memory is a dense vector index of Wikipedia, accessed with a pre-trained neural retriever.

検索器が返すものについては、§2 にこうあります。

a retriever pη(z|x) with parameters η that returns (top-K truncated) distributions over text passages given a query x

[PDF 抽出で落ちた空白を補った]。答えの確率は、上位 k 件の文書についての和で近似されます。

p(y|x) ≈ Σ[z ∈ top-k] pη(z|x) pθ(y|x,z)(RAG-Sequence の式。RAG-Token も和の範囲は同じ)

和の範囲が上位 k 件に限られているので、k 件の外の文書は項として現れず、答えに一切寄与しません。 これは式の読みで、論文が文章でそう書いているのではありません。論文自身も top-K approximation と近似であることを断っています。さらに論文の索引は Hierarchical Navigable Small World approximation を使っており、上位 k 件の選び方そのものも近似です。

生成器から見えるのは、検索が渡した k 件だけ
問いWhy do I get error E1240?
検索器が全文書を似ている順に並べる
上位 k 件生成器に渡る
k 件の外正解文書が14位にいても渡らない
生成器は k 件だけを読む
答えと出典正しいときと同じ形で出る
  • ・k 件の外の文書は、答えにも出典欄にも現れない
  • ・だから答えの側から、正解が落ちたかどうかは見えない
具体実物

同じ書式の文書を512件に増やす

手元で試しました。8件の正解文書 Error E1240 occurs when the certificate has expired. などに、同じ書式の文書を足していきます。足す文書のコードは0〜4の数字4桁を乱数(種を固定)で選び、正解のコードとは重ねません。原因は16種から選びます。問いは Why do I get error E1240? の形で8問です。

埋め込み(embedding)ベクトルの検索には all-MiniLM-L6-v2 を使い、比較に語の一致で順位を付ける BM25 も並べました。生成器は LLM ではなく台本のおもちゃです。上位5件だけを読み、問いのコードと一致する文書があればその原因を、無ければ上位5件で最初に原因を書いた文書の原因を、同じ書式で答えます。

l9-recall2.py の出力から抜粋(sentence-transformers 6.1.0、torch 2.14.0+cpu、rank_bm25 0.2.2。2回実行して同一)コマンド出力
docs= 8 dense recall@1=6/8 recall@5=8/8 recall@20=8/8 toy answers from top5 wrong=0/8
docs= 32 dense recall@1=5/8 recall@5=8/8 recall@20=8/8 toy answers from top5 wrong=0/8
docs=128 dense recall@1=3/8 recall@5=8/8 recall@20=8/8 toy answers from top5 wrong=0/8
docs=512 dense recall@1=3/8 recall@5=3/8 recall@20=8/8 toy answers from top5 wrong=5/8
docs=512 bm25 recall@1=8/8 recall@5=8/8 recall@20=8/8 toy answers from top5 wrong=0/8

ここでの recall@5 は、正解文書が上位5件に入った問いの数です。埋め込み検索では128件まで 8/8、512件で 3/8 に落ち、誤答も5問になりました。上位5件から落ちた5問と、誤答の5問は同じ問いです。

BM25 が全部 8/8 なのは、問いのコードが文書ごとに一意な語で、完全一致で拾えるからです。語が一致しない言い換えの問いでは逆になりえます。BM25 なら落ちない、という話ではありません。

問いごとの行を2つ並べます。

同じ出力の問いごとの行から2行を抜粋(ログの順序のまま)コマンド出力
Why do I get error E1240? gold rank(dense,512 docs)= 14 toy answer: 'Error E1240 occurs when the port is already in use.' correct=False
Why do I get error E2104? gold rank(dense,512 docs)= 1 toy answer: 'Error E2104 occurs when the port is already in use.' correct=True

E1240 の正解は the certificate has expired で、正解文書は14位でした。E2104 は1位で正答です。2つの答えは書式も断定の強さも同じです(台本の生成器がそう答えるよう作ってある)。

✓ ここまでの確認

512件の実演で、E1240 の答えは port is already in use、E2104 の答えも port is already in use でした。答えの文面から分かることはどれですか。

抽象原理

文書に基づく答えの上限は、検索の recall@k で決まる

生成器がどれほど正確でも、上位 k 件に無い文書は読めません。正解文書が入らなかった問いでは、生成器にできるのは「分からない」と言うか、手元の k 件から何かを答えるか、自分の重み(パラメトリックな記憶)から答えるかです。RAG 論文は §4.1 で、NQ では正解がどの取得文書にも無い場合でも achieving 11.8% accuracy in such cases for NQ と報告しています。ただしその答えは、渡した文書を根拠にしていません。どの場合も、答えは正しい場合と見分けがつかないことがあります。

出典を付けさせても、取りこぼしは見えるようになりません。出典は読んだ k 件から付くので、落ちた正解文書は出典欄にも出ません。 出典の裏取りで見つかるのは誤った根拠で、欠けた根拠ではありません。

したがって測る場所を分けます。

  • 検索の recall@k: 正解の文書が分かっている問いで、上位 k 件に入った割合を数える
  • 生成: 正解文書を渡したときに正しく答えるかを見る

RAG 論文も、Figure 3 の中央で Retrieval recall performance in NQ. を答えの成績とは別の図に描いています。k を増やせば済むとも限りません。§4.5 は、RAG-Token では performance peaks for RAG-Token at 10 retrieved documents と書いています。

具体実物

プロファイラの取りこぼしと比べる

第13期『写っていないことは、起きていない証拠ではない』で、サンプリング型のプロファイラを見ました。一定の間隔で実行位置を覗くだけなので、間隔より短い処理は写らないことがあり、同じ条件で測っても出る回と出ない回が混ざります。

検索も一部だけを生成器に見せる手続きで、現れなかったことが「無い」の証拠にならない点は同じです。

違うのは、取りこぼしの出方です。プロファイラの取りこぼしは確率的で、繰り返すと写る回が混ざります。この実演の検索は総当たりのコサイン類似度なので、同じ索引・同じ問い・同じモデルなら毎回同じ文書が落ちます。2回の実行は完全に一致しました。繰り返しても揺れとして現れないので、正解を知っている問いで数える必要があります。RAG 論文が使う近似索引で落ち方が実行ごとに変わるかは、ここでは確かめていません。

✓ ここまでの確認

検索の取りこぼしに気づくため、同じ問いを10回投げ直して答えが揺れるかを見る案があります。この実演の設定で、この案はどうなりますか。

⇄ 2つを見比べる
具体例 A

RAG の上位 k 件

生成器は検索が渡した k 件だけを読みます。この実演の総当たり検索では、同じ問いなら毎回同じ文書が落ち、答えは正しいときと同じ形で出ました。繰り返しても気づけません。

具体例 B

サンプリング型のプロファイラ

一定の間隔で実行位置を覗くだけなので、短い処理は写らないことがあります。取りこぼしは確率的で、同じ条件で測り直すと出る回と出ない回が混ざります。

両方とも「一部だけを見る」手続きです。取りこぼしに気づく方法が、両者で違うのはなぜでしょうか。

同じ条件で2回やったとき、落ちるものが変わるかどうかを比べてください。

この章のまとめ

  • RAG の答えは、上位 k 件の文書についての和で近似される。k 件の外の文書は寄与しない(式の読み)。
  • 実演では同じ書式の文書を512件に増やすと、埋め込み検索の recall@5 が 8/8 から 3/8 に落ち、台本の生成器は落ちた5問で誤答した。
  • 誤答は正答と同じ書式・同じ断定の強さで出た(台本の生成器がそう答えるよう作ってある)。出典も k 件から付くので、落ちた文書は出典欄にも出ない。
  • BM25 が 8/8 だったのはコードの完全一致の問いだから。どちらの検索なら落ちない、とは言えない。
  • この実演の検索の取りこぼしは毎回同じで、繰り返しでは気づけない。正解付きの問いで recall@k を、生成と分けて測る。

自分の現場で確かめる

読んだだけでは身につきません。手元の環境で実際に見てみてください。

理解度チェック

読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。

問題 1 / 3正解: 0

RAG 論文(Lewis et al.)の式で、上位 k 件に入らなかった文書は答えの確率にどう関わりますか。

用語集(2語)
RAG(検索拡張生成)
問いで文書を検索し、取り出した文書を文脈として生成器に渡して答えさせる構成。Lewis et al. 2020 が RAG models として示した。
検索の recall@k
この教材での定義は、正解の文書が上位 k 件に入った問いの割合。答えの正しさとは別に、検索だけを測る。