ハイブリッド検索
セマンティック検索(ベクトル検索)とキーワード検索(BM25など)を組み合わせる手法。両者の弱点を補完し、検索精度を向上させる。
なぜハイブリッドか
ベクトル検索の弱点
- 固有名詞: 「user_id_12345」のような文字列は意味ベースで見つけにくい
- 完全一致: 正確なIDやコード番号の検索には不向き
- 専門用語: 社内略語、製品コードは埋め込みモデルが理解できない
キーワード検索の弱点
- 同義語: 「認証」と「ログイン」は別の単語として扱われる
- 言い換え: 「エラーが出た」と「例外が発生した」を同じと見なせない
- 意味の近さ: 文字列一致しか見ない
仕組み
- 並列検索:
- ベクトル検索でTop-20を取得
- キーワード検索(BM25)でTop-20を取得
- スコア統合:
- 各検索結果にスコアを付与
- 重み付けして統合(例: ベクトル70%、キーワード30%)
- 重複排除: 同じ文書が両方に含まれる場合はマージ
- 最終ランキング: 統合スコアでTop-Kに絞る
スコア統合手法
1. Reciprocal Rank Fusion (RRF)
スコア = 1 / (順位 + k)
- 順位ベースで統合
- シンプルで効果的
2. 重み付け線形結合
最終スコア = α × ベクトルスコア + β × キーワードスコア
- α, β は調整可能(例: α=0.7, β=0.3)
具体例
クエリ: 「JWT トークンの有効期限 設定方法」
ベクトル検索結果:
- 「認証システムの概要」(意味は近いが的外れ)
- 「トークン発行の仕組み」(関連するが浅い)
- 「JWT有効期限設定のコード例」(正解)
キーワード検索結果:
- 「JWT有効期限設定のコード例」("JWT" "有効期限" が含まれる)
- 「設定ファイルのサンプル」("設定" が含まれる)
- 「トークンの種類」("トークン" が含まれる)
ハイブリッド結果:
- 「JWT有効期限設定のコード例」(両方で高スコア → 1位)
- 「トークン発行の仕組み」(ベクトルで高い)
- 「認証システムの概要」(ベクトルで高い)
使い分け
| 検索対象 | 推奨手法 |
|---|---|
| 固有名詞、ID、コード番号 | キーワード検索を高めに設定(例: 50%以上) |
| 自然言語の質問 | ベクトル検索を高めに設定(例: 70%以上) |
| 混在(製品名を含む質問など) | バランス型(例: 60% ベクトル、40% キーワード) |
実装例
Elasticsearch + Dense Vector
- Elasticsearchのキーワード検索
- Dense Vectorでベクトル検索
- 両方のスコアを統合
Weaviate Hybrid Search
- ネイティブでハイブリッド検索対応
alphaパラメータで重みを調整(0=キーワードのみ、1=ベクトルのみ)
カスタム実装
- ベクトルデータベース(Pinecone、Chromaなど)
- 別途Elasticsearch/Solrでキーワード検索
- アプリケーション層でスコア統合
ベストプラクティス
- ドメインに応じて重みを調整: 技術文書ならキーワード高め、FAQならベクトル高め
- 評価データで最適化: A/Bテストで最適な重みを見つける
- クエリに応じて動的調整: 固有名詞が含まれる場合はキーワード重視
- リランキングと併用: ハイブリッド検索後に再ランク付けでさらに精度向上
コストとレイテンシ
- レイテンシ: 2つの検索を並列実行すれば遅い方に合わせる(100〜200ms程度)
- コスト: 両方のインフラが必要(ベクトルDB + 全文検索エンジン)