ハイブリッド検索とRRF — 語彙検索とベクトル検索を融合する
ベクトル検索だけでは型番や固有名詞を取りこぼす理由が分かり、BM25との併用で穴を塞げるようになる。スコアの正規化を回避して2つの順位を統合するRRFの式まで実装できる。
- ベクトル検索は意味の近さに強いが、正確な型番・エラーコード・社内固有語のような「その文字列そのもの」を探す用途で取りこぼす。BM25はその逆で、両者は失敗の仕方が相補的。
- スコアを直接足すのは危険。BM25は非有界、コサイン類似度は-1〜1で、分布も揃わないため重みの意味が安定しない。順位だけを使うRRFがこの正規化問題を回避する。
- RRFは 1/(k+rank) を足すだけの単純な式で、k=60が広く使われる既定値。スコアの絶対値を捨てることで、異種の検索器を追加コストなしで何本でも統合できる。
ベクトル検索を導入したのに、「エラーコード E4021 について教えて」と聞くと全然違う文書が返ってくる。この現象はモデルの性能不足ではなく、ベクトル検索という手法の構造的な弱点です。
横にスクロール
2つの検索は失敗の仕方が違う
| 語彙検索(BM25) | ベクトル検索 | |
|---|---|---|
| 何を見るか | クエリと文書で共有される単語の出現 | 意味空間での距離 |
| 強い場面 | 型番・エラーコード・固有名詞・略語の完全一致 | 言い換え・同義語・概念的な問い |
| 弱い場面 | 同義語や言い換えを取りこぼす(語が違えばゼロ) | その文字列そのものを探す用途 |
| 未知語の扱い | そのまま照合できる | 学習時に無かった語は意味が付かず埋もれる |
| 説明のしやすさ | どの語が効いたか示せる | なぜ近いか説明しにくい |
この「出現が少ない語ほど意味空間での位置が定まらない」現象は、埋め込み2D可視化で実際に確かめられます(点の大きさが出現記事数で、小さい点ほど近傍が納得しにくくなります)。
決定的なのは最後から2番目の行です。社内の製品コードや新しい型番は、埋め込みモデルの学習データに存在しません。 そういう文字列は意味空間で特定の位置を持たず、周辺のありふれた語に引きずられた曖昧な位置に置かれます。結果として E4021 のクエリが E4102 の文書と近くなる、といったことが平然と起こります。
一方 BM25 のような語彙検索は、E4021 という文字列が出現するかどうかだけを見るので、この用途では完璧に働きます。逆に「接続が切れる問題」という問いに対し「コネクションのタイムアウト」と書かれた文書は、共有する語が無いので BM25 では引けません。
両者は互いの穴を埋める関係にあり、だからこそ併用が定石になります。
スコアを足してはいけない
素朴な統合方法は「両方のスコアを重み付きで足す」ですが、これは思ったより難しい問題を抱えます。
最終スコア = α × BM25スコア + (1-α) × コサイン類似度
問題は3つあります。
- 値域が違う。 BM25 は上限がなく、文書やコーパスによって数値の大きさが変わります。コサイン類似度は -1 から 1 の範囲です。そのまま足せば BM25 が支配します。
- 分布が違う。 正規化しても、片方は上位が急峻に落ち、もう片方はなだらか、といった形の違いが残ります。
- クエリごとに揺れる。 語彙が珍しいクエリでは BM25 のスコアが跳ね上がり、同じ α でも実効的な重みが変わります。
正規化を工夫する方法(最小最大正規化、z-score)もありますが、そもそもスコアの絶対値を使うのをやめるという割り切りのほうが実務では安定します。
RRF:順位だけを使う
Reciprocal Rank Fusion(RRF) は、各検索器が返した順位だけを使って統合します。
RRFスコア(d) = Σ 1 / (k + rank_i(d))
i
d : 文書(チャンク)
i : 検索器(BM25、ベクトル、…)
rank_i(d): 検索器 i における d の順位(1位なら1)
k : 平滑化定数。60 が広く使われる
具体例で確かめます。k=60 として、あるチャンクが BM25 で3位・ベクトルで7位だったとします。
1/(60+3) + 1/(60+7) = 0.01587 + 0.01493 = 0.03080
比較: 両方で1位なら 1/61 + 1/61 = 0.03279
片方で1位・もう片方は圏外なら 1/61 = 0.01639
ここに RRF の性質が現れています。両方の検索器がそこそこ上位に入れた文書が、片方だけで1位の文書を上回る。これは「複数の独立した観点から支持された結果を優先する」という、投票に近い挙動です。
k の役割は上位の突出を抑えることです。k が小さいと1位と2位の差が極端になり、実質的に「どれか1つの検索器の1位」が勝ちます。k=60 は経験的に広く使われる値で、まずこれで始めて問題が出てから調整するので十分です。
RRFはスコアの絶対値を捨てるので、検索器を何本足しても正規化の設計が要りません。BM25・ベクトル・タイトル完全一致・タグ検索・別の埋め込みモデル——どれを追加しても式は同じで、重みの再調整も不要です。「あとから検索器を1本足す」が無コストでできるのは、実務では大きな価値があります。重み付き和では、1本足すたびに全体の重み調整をやり直すことになります。
実装で気をつけること
各検索器の取得件数を揃えて多めに取る。 統合前に各検索器から上位 50〜100 件を取り、RRF で並べ替えてから上位 k 件をリランカへ渡す、という流れが標準です。各検索器から10件ずつしか取らないと、片方で圏外だった良い文書を救えません。
日本語の語彙検索には形態素解析かN-gramが要る。 英語と違い日本語は空白で区切られないため、BM25 をそのまま適用しても語に分かれません。形態素解析(未知語に弱いが精度が高い)か文字N-gram(未知語に強いがノイズが多い)を選びます。型番や社内固有語を確実に引きたいという目的からすると、N-gramのほうが目的に合うことが多いのは押さえておく価値があります。
同一文書の重複を潰す。 2つの検索器が同じチャンクを返すのは正常ですが、隣接する別チャンクが両方入ると内容が重複します。統合後に文書IDで軽く間引くと、文脈枠を有効に使えます。
ハイブリッド検索は「ベクトル検索が苦手な種類のクエリ」を救いますが、チャンク設計が悪くて意味が壊れている場合は、BM25側でも同じ壊れたチャンクを引くだけです。ハイブリッド化は基礎ができたうえでの上積みであって、土台の代わりにはなりません。導入して効果が薄いなら、チャンク粒度と見出しパスの前置を先に見直してください。
まとめ
- ベクトル検索と語彙検索は失敗の仕方が相補的。型番・エラーコード・社内固有語は埋め込みモデルの学習データに無く、意味空間で正しい位置を持てない。
- スコアの重み付き和は避ける。値域・分布・クエリごとの揺れという3つの問題があり、安定した重みを決められない。
- RRF は順位だけを使う
Σ 1/(k+rank)。k=60 が既定値。両方でそこそこ上位の文書が、片方だけ1位の文書を上回る投票的な挙動になる。 - RRF の実利は検索器をあとから何本でも足せること。重みの再調整が要らない。
- 統合前は各検索器から多めに取る(50〜100件)。日本語の語彙検索は形態素解析かN-gramの選択が要り、固有語重視ならN-gramが目的に合う。
RAG設計パターンの記事ガイド
ハイブリッド検索とRRF — 語彙検索とベクトル検索を融合するを実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
RAG
比較で見る軸
難易度: advanced / カテゴリ: RAG設計パターン / タグ数: 5
導入後に効く点
スコアを直接足すのは危険。BM25は非有界、コサイン類似度は-1〜1で、分布も揃わないため重みの意味が安定しない。順位だけを使うRRFがこの正規化問題を回避する。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- RAG設計パターン
- タグ数
- 5
判断チェックリスト
- 自社の用途が「RAG / ハイブリッド検索」に近いか確認する。
- 強みである「ベクトル検索は意味の近さに強いが、正確な型番・エラーコード・社内固有語のような「その文字列そのもの」を探す用途で取りこぼす。BM25はその逆で、両者は失敗の仕方が相補的。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。