学習パスの概要:なぜ「ベクトル」だけでは足りないのか
このステップで学ぶこと
- 所要時間: 5分
- 学習内容: ベクトル検索単体の限界と、ハイブリッド検索が必要とされる背景の理解
「PoC(概念実証)では動いたけれど、実務レベルの質問を投げると期待通りの回答が返ってこない」。
もし今、RAGシステムの開発でこの壁にぶつかっているなら、それは「ベクトル検索への過度な期待」が原因かもしれません。実務の現場において自動応答システムを導入する際、こうした課題は頻繁に発生する傾向にあります。
近年、LLM(大規模言語モデル)とベクトルデータベースを組み合わせたRAGは、AI開発の標準的なアーキテクチャとなりました。しかし、AIが得意な「意味論的検索(Semantic Search)」だけでは、ユーザーの意図を完全に汲み取れず、顧客体験を損ねるケースが多々あります。
例えば、製造業の現場で「型番 A-123 の仕様書を見せて」と検索されたとき、ベクトル検索はどう反応するでしょうか。「A-123」という記号列の意味を深く理解できないモデルは、文脈が似ているだけの全く別の製品マニュアル(例えば「B-456の仕様書」)を上位に表示してしまうことがあります。これでは、現場のエンジニアの業務効率は低下し、システムは使い物にならないと判断されてしまいます。
ここで必要になるのが、古くからある検索技術である「キーワード検索(Lexical Search)」の再評価です。特定の単語がドキュメントに含まれているかどうかを厳密にチェックするこの技術は、固有名詞や型番、専門用語の検索において、今でも圧倒的な強さを誇ります。
本記事では、この「ベクトル検索」と「キーワード検索」を組み合わせ、互いの弱点を補完し合う「ハイブリッド検索」の設計と実装について詳しく解説していきます。単にライブラリを組み合わせるだけでなく、裏側にあるアルゴリズム(特にRRF)を理解し、自社のデータに合わせてチューニングすることで、顧客満足度と生産性の向上を両立できるシステムを目指しましょう。
本コースのゴールと成果物
このガイドを読み終える頃には、以下のことができるようになります。
- 検索手法の使い分け: データ特性や顧客の検索意図に応じて、Dense VectorとSparse Vectorの役割分担を設計できる。
- RRFの実装: 異なる検索スコアを公平に統合するアルゴリズムをコードレベルで理解する。
- 精度の定量評価: 「なんとなく良くなった」ではなく、数値で改善効果を定量的に証明できる。
それでは、まずは検索メカニズムの基礎から深掘りしていきましょう。
Step 1:検索メカニズムの基礎理解(Dense vs Sparse)
このステップで学ぶこと
- 所要時間: 10分
- 学習内容: 密ベクトル(Dense)と疎ベクトル(Sparse)の特性の違いと、それぞれの得意領域
ハイブリッド検索を実装する前に、ここで扱う「2つの検索技術」について、その性質を正しく理解しておく必要があります。これらは単に「新しい技術」と「古い技術」という関係ではなく、「意味」を捉える技術と「記号」を捉える技術という補完関係にあります。
Dense Vector(密なベクトル)の世界観:意味を捉える
一般的に「ベクトル検索」と呼ばれているのは、正確には Dense Vector(密ベクトル) を用いた検索です。OpenAIの text-embedding-3 や Hugging Face の各種モデルが生成するのはこれです。
- 特徴: 数百から数千次元の浮動小数点数の配列(例:
[0.12, -0.54, 0.88, ...])。全ての次元に値が詰まっています。 - 強み: 「車」と「自動車」、「購入」と「買う」のように、単語が異なっていても意味が近いものを関連付けることができます。表記ゆれや類義語に非常に強く、自然な顧客の言い回しを吸収できます。
- 弱み: 「ドメイン固有の専門用語」や「未知の造語」、「型番」などの厳密な一致が苦手です。モデルが学習していない単語は、意味空間上の適切な位置に配置されないためです。
Sparse Vector(疎なベクトル)の世界観:単語を捉える
一方、キーワード検索で用いられるのは Sparse Vector(疎ベクトル) です。代表的なアルゴリズムに BM25 があります。
- 特徴: 数万次元(語彙数分)の配列ですが、ほとんどの要素が
0で、ドキュメントに含まれる単語のインデックス部分にのみ値が入ります。 - 強み: 「完全一致」が得意です。ユーザーが入力したキーワードそのものがドキュメントに含まれているかどうかがスコアに直結するため、的確な情報提供に直結します。
- 弱み: 「パソコン」で検索しても「PC」という単語しか含まないドキュメントはヒットしません(シノニム辞書などで補う必要がありますが、メンテナンスコストがかかります)。
BM25アルゴリズムの仕組みを直感的に理解する
ここで、キーワード検索の主役である BM25 について少し触れておきましょう。これは単純な単語の出現頻度(TF)だけでなく、「レアな単語が含まれているか(IDF)」や「ドキュメントの長さ」を考慮してスコアリングする手法です。
例えば、「RAG の 精度」というクエリの場合、「の」という単語はどのドキュメントにも頻出するため、スコアへの貢献度は低くなります。一方で「RAG」や「精度」といった特定のドキュメントにしか現れない単語が含まれていると、スコアが跳ね上がります。
ハイブリッド検索では、このBM25が弾き出したスコアと、ベクトル検索(コサイン類似度など)のスコアを混ぜ合わせることになります。しかし、ここで一つの問題が生じます。
「BM25のスコア(例: 15.4)」と「コサイン類似度(例: 0.85)」は、尺度が全く異なるため、単純に足し算ができないのです。
この問題をどう解決するか? それが後述する Reciprocal Rank Fusion (RRF) の役割になりますが、その前に、まずはデータを入れる器である「インデックス」の設計について考えましょう。
Step 2:ハイブリッド・インデックスの設計戦略
このステップで学ぶこと
- 所要時間: 15分
- 学習内容: 日本語特有のトークナイズ問題と、検索精度を高めるためのインデックス構造の設計
「とりあえずデータをVector DBに保存すればいい」と考えていないでしょうか。実は、ハイブリッド検索の成否は、実装前のインデックス設計で8割決まると言っても過言ではありません。特に日本語を扱う場合、注意すべき落とし穴があります。
トークナイザーの選定:日本語処理の落とし穴
英語は単語がスペースで区切られていますが、日本語は繋がっています。そのため、キーワード検索を行うには、文章を単語に分割する「トークナイズ(形態素解析)」が必須です。
ここで問題になるのが、ベクトル化用モデルのトークナイザーと、キーワード検索用のトークナイザーが異なる場合があることです。
- ベクトル化: BERTベースのトークナイザー(Subword方式など)が主流。
- キーワード検索: MeCab, Sudachi, Kuromojiなどの形態素解析器が主流。
例えば「東京都」という単語を、ベクトルモデルは「東京」「都」と分けるかもしれませんが、キーワード検索エンジンは「東京都」という一つの名詞として扱うかもしれません。この不一致が検索漏れを引き起こし、結果として顧客の自己解決率を下げてしまいます。
実践的アドバイス:
ElasticsearchやOpenSearchなどを利用する場合は、日本語用のアナライザー(kuromoji や sudachi)を明示的に指定することが推奨されます。また、PineconeやWeaviateなどのモダンなVector DBもハイブリッド検索(Sparse Vector)に対応し始めていますが、日本語のトークナイズ処理が内部でどう行われているか、ドキュメントを確認することが重要です。場合によっては、Python側で事前にトークナイズを行い、その結果(単語リストと重み)をSparse VectorとしてDBに登録するアプローチ(SPLADE等のモデル利用含む)が確実です。
データ構造の設計:メタデータとテキストの分離
RAGの精度を上げるためには、検索対象のテキストだけでなく、フィルタリング用のメタデータをリッチにすることが有効です。
例えば、社内規定RAGを作る場合、以下のような構造を推奨します。
{
"text_content": "...規定の本文...",
"metadata": {
"doc_id": "DOC-2024-001",
"category": "人事規定",
"updated_at": "2024-04-01",
"keywords": ["有給休暇", "申請フロー", "HR-System"]
}
}
特に keywords フィールドは重要です。本文中には「PC」としか書かれていなくても、メタデータに「パソコン」「パーソナルコンピュータ」と付与しておくことで、キーワード検索のヒット率を擬似的に向上させることができます。LLMを使って、ドキュメント登録時に自動でキーワード抽出を行い、メタデータに付与するパイプラインを構築するのが一般的なトレンドです。
Step 3:統合検索の実装とReciprocal Rank Fusion (RRF)
このステップで学ぶこと
- 所要時間: 20分
- 学習内容: スコアの尺度が異なる2つの検索結果を統合するアルゴリズム(RRF)の実装ロジック
いよいよ本題の実装フェーズです。ベクトル検索とキーワード検索、それぞれの結果が返ってきたとして、これらをどう統合(Merge)して、最終的なランキングを作るのでしょうか。
2つの検索結果を統合する難しさ
前述の通り、BM25のスコア(0〜無限大)とコサイン類似度(-1〜1)は比較できません。正規化(Normalization)して0〜1の範囲に揃える方法もありますが、スコアの分布が異なるため、調整パラメータ(Alpha値)の設定が非常にシビアになります。
そこで推奨されるのが、Reciprocal Rank Fusion (RRF) です。これは「スコア」ではなく「順位(ランク)」を使って統合する方法です。
RRF(Reciprocal Rank Fusion)アルゴリズムの実装
RRFの考え方はシンプルです。「それぞれの検索手法で上位に来ているドキュメントは、きっと重要だろう」という前提に基づき、順位の逆数を足し合わせます。
数式で表すと以下のようになります。
$$ RRF_score(d) = \sum_{r \in R} \frac{1}{k + rank(d, r)} $$
- $d$: ドキュメント
- $R$: 検索結果のセット(ベクトル検索結果、キーワード検索結果)
- $rank(d, r)$: その検索結果におけるドキュメント $d$ の順位(1位なら1)
- $k$: 定数(通常は60が使われます)。順位の影響度をマイルドにするためのものです。
Pythonでの実装イメージ:
def reciprocal_rank_fusion(results_list, k=60):
"""
results_list: [[(doc1, rank1), (doc2, rank2)...], [(doc1, rank1)...]]
各検索手法の結果リスト(ドキュメントと順位のペア)のリスト
"""
fused_scores = {}
for results in results_list:
for rank, doc in enumerate(results):
if doc not in fused_scores:
fused_scores[doc] = 0.0
# 順位は0始まりのindexなので +1 する
fused_scores[doc] += 1 / (rank + 1 + k)
# スコアの高い順にソート
reranked_results = sorted(fused_scores.items(), key=lambda x: x[1], reverse=True)
return reranked_results
このロジックの利点は、スコアの尺度を気にする必要がないことです。ベクトル検索で1位、キーワード検索で1位なら、確実に上位に来ます。一方で、ベクトル検索で1位でもキーワード検索で圏外なら、そこそこの順位に落ち着きます。
重み付けパラメータの調整
RRFはパラメータ調整が少ないのが利点ですが、「キーワード検索の方をもう少し重視したい」というケースもあるでしょう。その場合は、RRFの計算式に重み(weight)を掛けることで調整可能です。
$$ Weighted_RRF = w_{vec} \times \frac{1}{k + rank_{vec}} + w_{key} \times \frac{1}{k + rank_{key}} $$
ユーザーが「型番」のような具体的なクエリを入力する傾向が強いシステムなら、$w_{key}$(キーワード検索の重み)を少し大きくするなどのチューニングが有効です。顧客の検索行動データを分析し、最適な重み付けを行うことが重要です。
Step 4:精度評価と継続的なチューニング
このステップで学ぶこと
- 所要時間: 10分
- 学習内容: ハイブリッド検索の導入効果を定量的に測定する指標(MRR, NDCG)と評価プロセス
実装ができたら、それが本当に「良くなった」のかをデータドリブンに証明する必要があります。「なんとなく回答が賢くなった気がする」という定性的な評価だけでは不十分です。
何をもって「精度向上」とするか
検索システムの評価指標として、以下の2つを把握しておくことが重要です。
Hit Rate (Recall@K):
上位K件の中に、正解ドキュメントが含まれている割合。「とにかく情報を見つけ出す力」を測ります。MRR (Mean Reciprocal Rank):
正解ドキュメントが「何位に表示されたか」の逆数の平均値。1位にあれば1.0、2位なら0.5。正解がより上位に来ることを評価します。
ハイブリッド検索を導入すると、特にこの MRR が改善する傾向にあります。ベクトル検索だけでは5位や6位に埋もれていた「正解」が、キーワードの一致によって1位や2位に浮上してくるからです。
「型番検索」と「質問応答」のテストケース作成
評価のためには「ゴールデンデータセット(クエリと正解ドキュメントのペア)」が必要です。ここで重要なのは、実際の顧客ジャーニーを想定し、クエリの種類をバランスよく混ぜることです。
- 具体的クエリ: 「エラーコード E-503 の対処法」(キーワード検索が得意)
- 抽象的クエリ: 「システムの調子が悪い時の確認事項」(ベクトル検索が得意)
- 複合クエリ: 「E-503が出た時の再起動手順」(両方の要素が必要)
これらを各20〜30件程度用意し、ベクトル検索単体、キーワード検索単体、ハイブリッド検索の3パターンでスクリプトを回し、MRRを比較します。この定量的な結果が、導入効果を示す明確な根拠となります。
実運用に向けたレイテンシーとコストのトレードオフ
最後に、コストとパフォーマンスのバランスについて触れておきます。ハイブリッド検索は2回の検索を行うため、理論上、検索にかかる時間は増えます。また、Vector DBによっては、Sparse Vector用のインデックスサイズが大きくなり、ストレージコストが増加することもあります。
しかし、顧客体験全体を俯瞰すれば、検索にかかる数百ミリ秒の遅延よりも、「LLMに渡すコンテキストの質」の方が圧倒的に重要です。不適切なドキュメントをLLMに渡してハルシネーション(事実に基づかない回答)を生成させるリスクや、それに伴うエスカレーション対応のコストを考慮すれば、ハイブリッド検索による精度の向上は、十分な投資対効果があると言えるでしょう。
まとめ:次のステージへ進むために
ここまで、RAGの精度を高めるためのハイブリッド検索の実装について、設計から評価までを解説してきました。
- ベクトルとキーワードは補完関係: どちらか一方ではなく、両方を組み合わせることで「意味」と「正確性」を両立できる。
- インデックス設計が肝: 日本語のトークナイズやメタデータ戦略が検索品質の土台となる。
- RRFで賢く統合: スコアの尺度に依存しないランクベースの統合で、安定した検索結果を得る。
- 数値で語る: MRRやHit Rateを用いて、改善効果を客観的かつ定量的に評価する。
ハイブリッド検索の実装は、RAGシステムの品質を実用レベルへと引き上げるための重要なステップです。しかし、これがゴールではありません。次は、ユーザーの検索クエリをLLMで最適化する「クエリ分類・拡張」や、検索結果をLLMでさらに精査する「リランキングモデル(Cross-Encoder)」の導入など、さらなる改善の余地があります。
まずは、手元の環境でRRFを実装し、定量的な変化を確認することをおすすめします。RAGシステムが、顧客体験の向上と業務効率化の両立を実現する真に頼れる基盤となるよう、継続的な改善を進めていきましょう。
コメント