BM25とベクトル検索、それぞれの仕組み
検索システムを構築する際、BM25とベクトル検索という2つのアプローチがあります。どちらも情報検索の世界では広く使われていますが、仕組みはまったく異なります。
BM25は、ElasticsearchやLuceneといった検索エンジンで長年使われてきたキーワードマッチングアルゴリズムです。クエリに含まれる単語がドキュメント内にどれだけ出現するか、その単語がコレクション全体でどれだけ希少か、ドキュメントの長さはどうかという3つの要素でスコアを計算します。
特徴的なのは、Term Frequency飽和という仕組みです。k₁というパラメータ(通常1.2〜2.0)を使って、同じキーワードを何度も詰め込んでもスコアが際限なく上がらないよう制御しています。また、長さ正規化パラメータb(通常0.75)でドキュメントの長さを補正し、IDF(逆文書頻度)により希少な語に高い重みを付けます。
一方、ベクトル検索は、クエリとドキュメントを数値ベクトルに変換し、コサイン類似度でマッチングします。今回の記事ではOpenAIのtext-embedding-3-smallという埋め込みモデルを使用しており、各埋め込みは1,536次元のベクトルになります。この手法の強みは、「cardiac arrest」と「heart failure」のように単語が重ならなくても、意味的に近いものを検索できる点です。
実装の違いとコスト
両者の実装面での違いは大きいです。BM25を使う場合、rank_bm25というライブラリをインストールするだけで動き始めます。モデルの学習もGPUも不要で、APIを呼び出す必要もありません。そのため高速で軽量、スコアの計算過程も追いやすく説明可能です。
対してベクトル検索は、インデックス構築時とクエリ時の両方で埋め込みモデルを呼び出す必要があります。OpenAIのAPIを使う場合、リクエストごとに料金が発生し、レスポンスを待つ時間も考慮しなければなりません。スコアの解釈も直感的ではなく、なぜこのドキュメントが選ばれたのか説明しにくい面があります。
ただし、BM25には明確な限界があります。バッグオブワーズモデルという性質上、単語の順序や文脈、意味を認識できません。同義語やパラフレーズにも対応できないため、完全一致する単語がないと検索漏れが起きます。
どちらが優れているわけではない
記事では「どちらも厳密に優れているわけではなく、反対方向で失敗する」と述べられています。BM25はキーワードスタッフィングに耐性がある一方で意味理解ができず、ベクトル検索は意味理解ができる代わりにコストと複雑さが増します。
実際の本番システムでは、BM25とベクトル検索の両方を組み合わせたハイブリッド検索が標準になっていると記事は指摘しています。キーワードマッチングで高速にスコアリングしつつ、意味的な関連性も考慮するという使い分けです。
記事では12のテキストチャンク(Python、機械学習、BM25、Transformer、埋め込み、RAGなどのトピック)を使った実験コードも公開されており、GitHubで確認できます。実際に手を動かして両者の挙動を比較できる内容になっています。
フリーランスへの影響
この知識は、フリーランスでAIツールや検索機能を開発している方にとって実用的です。クライアントから「社内文書を検索できるシステムを作ってほしい」と依頼されたとき、BM25とベクトル検索のどちらを採用すべきか判断できるようになります。
予算やレスポンス速度を重視するならBM25、意味的な検索精度を求めるならベクトル検索、両方のメリットを取りたいならハイブリッド検索という選択肢が見えてきます。特に、ベクトル検索を使う場合はAPIコストが継続的に発生するため、見積もり段階でランニングコストを正確に伝えることが重要です。
また、RAGシステムを構築する際の基礎知識としても役立ちます。RAGは文書検索とLLMを組み合わせる技術ですが、その検索部分にBM25を使うかベクトル検索を使うかで性能とコストが大きく変わります。クライアントの要件に応じて最適な構成を提案できるスキルは、差別化要素になるでしょう。
まとめ
BM25とベクトル検索のどちらが優れているかではなく、用途に応じて使い分けることが重要です。GitHubに公開されている実装コードを試してみると、両者の特性を体感できます。検索システムやRAGの開発案件を受ける予定がある方は、一度手を動かしてみる価値があります。すぐに案件がない場合でも、基礎知識として押さえておくと、将来の提案の幅が広がります。
参考記事:GitHubノートブック


コメント