RAGのハイブリッド検索についてまとめてみた

に公開

RAGとは

RAG(Retrieval-Augmented Generation)は「外部知識を検索してから生成AIに渡す」仕組みです。社内文書検索やFAQ対応などに広く使われています。
詳しくは以下の記事でまとめています。
https://zenn.dev/ugongone/articles/2dd7e3d75e849d

ハイブリッド検索とは

「キーワード検索」と「ベクター検索」を合わせた検索方法で、
それぞれの長所を組み合わせることで精度が安定しやすくなります。(Elastic より)

ハイブリッド検索のイメージ

ユーザーから以下のクエリが入力されたとする。

社内VPNがつながらないときの対処は?」

また、以下4つの社内ドキュメントがあるとする。

Doc A: 「VPN接続ができない場合の手順。エラーメッセージ“認証に失敗しました” …」
Doc B: 「リモートアクセスが不安定なときの一般的な診断フロー(“VPN”の語は少ない)」
Doc C: 「Zscalerのトンネル確立失敗の原因と対処(“VPN”を使わず専門語多め)」
Doc D: 「経費精算のやり方」

この中から取得するドキュメントの優先順位をハイブリッド検索によって決めたい。


A) キーワード検索(BM25)のイメージ

考えかた:クエリ語と同じ語がたくさん含まれている文書ほど高得点
(語の頻度、珍しさ、文書の長さでスコア化する手法に BM25 というものがある)

1) まず単語に分けて「逆引きインデックス」をつくる

"VPN" → [Doc A(10回), Doc B(2回)] 
"接続" → [Doc A(6回), Doc C(1回)]
"つながらない" → [Doc A(2回)]
…(略)

2) クエリ語でスコア(ざっくり図)

クエリ: ["VPN", "つながらない", "対処"]

Doc A: VPN(10) + つながらない(2) + 対処(1) → 高スコア
Doc B: VPN(2)  + (他は薄い)               → 中
Doc C: ("VPN"という語は少ない/無い)       → 低
Doc D: 関係語なし                           → ほぼ0

3) 並び順イメージ(BM25)

BM25順位:  A > B > C >>> D

※ BM25は 語の頻度逆文書頻度(珍しさ)文書長の補正などで順位を出します。


B) ベクター検索(意味検索)のイメージ

考えかた:文章の意味を数値ベクトルにして、意味が近い(コサイン類似など)ものを探す。語が違っても、意味が近ければ上位に来やすい。

1) 文章 → ベクトル化(埋め込み)

"社内VPNがつながらない" →  [0.12, -0.03, 0.77, …]
"トンネル確立失敗の対処"  →  [0.10, -0.04, 0.75, …]  ← 似た方向
"経費精算のやり方"        →  [ -0.51, 0.22, -0.33, …]  ← 遠い

近い=角度が小さい/コサイン類似が高い)

2) k近傍(top-k)で“意味が近い”文書を取る

クエリ埋め込み ↔ 各Docの埋め込み で類似度を計算

類似度:  A=0.92,  C=0.90,  B=0.65,  D=0.05

3) 並び順イメージ(ベクター)

ベクター順位:  A ≈ C > B >>> D

Doc Cは“VPN”という語が少なくても「トンネル確立失敗=VPN障害の一種」という意味の近さで上位に来やすい。


C) 2つを合体=ハイブリッド検索(RRFなど)

ねらい

  • 固有名詞・品番・エラー文に強い BM25 と、
  • 言い換え・曖昧表現に強い ベクター
    両取りして、一つの順位にまとめる。

1) まず個別の順位を用意

BM25    :  A > B > C >>> D
ベクター:  A ≈ C > B >>> D

2) **RRF(Reciprocal Rank Fusion)**で“順位”を合算

直感図:  「各方式の上位に“何度も”出てくるほど総合点↑」
         (スコアの単位が違っても、順位を使うので混ぜやすい)

合体後の例:   A > C > B >>> D

RRFは各メソッドの順位から合成スコアを計算し、BM25とベクターのようにスコア尺度が違う結果も頑健に融合できます。OpenSearch/Weaviateなどが公式でサポート。

3) 図で全体像

           ┌───────────┐
Query ───▶ │  BM25検索  │──┐
           └───────────┘  │  上位k(例10件)
                         ├─▶  RRF/重み付け  ──▶  最終順位(上位k)
           ┌───────────┐  │
Query ───▶ │ ベクター検索│──┘
           └───────────┘

両者の長所を組み合わせると精度が安定しやすいとされています。

参考資料

https://www.elastic.co/docs/solutions/search/ranking
https://www.pinecone.io/learn/series/rag/embedding-models-rundown
https://www.pinecone.io/learn/vector-embeddings
https://www.elastic.co/what-is/hybrid-search
https://opensearch.org/blog/introducing-reciprocal-rank-fusion-hybrid-search
https://docs.weaviate.io/weaviate/search/hybrid
https://www.elastic.co/search-labs/blog/improving-information-retrieval-elastic-stack-hybrid
https://weaviate.io/blog/hybrid-search-explained
https://www.elastic.co/search-labs/blog/lexical-and-semantic-search-with-elasticsearch
https://weaviate.io/blog/cross-encoders-as-reranker

Discussion