埋め込みとベクトル検索 — 意味で探す検索の仕組み
このブログの RAG 深掘りシリーズでベクトル検索は何度も登場しましたが、埋め込みとベクトル検索そのものを基礎から整理した記事がありませんでした。今回整理します。結論を先に書くと、埋め込みはテキストを意味が保存された数値ベクトルに変換する技術で、ベクトル検索はそのベクトル空間で距離が近いものを探す技術です。 キーワードが重ならなくても「返金規定」で「決済キャンセルポリシー」の文書を見つけられる理由がここにあります。
埋め込み — テキストを座標に変換する #
埋め込みモデルはテキストを受け取り、固定長の実数配列、つまりベクトルを出力します。次元数はモデルによって数百から数千の間です。核心となる性質はひとつです。意味が近いテキストは、ベクトル空間上で近い位置に置かれます。 「ノートパソコンのバッテリーがすぐ切れる」と「ラップトップの電源が持たない」は共通する単語がほとんどありませんが、埋め込みベクトルは近い値になります。
あわせて知っておきたい実務的な事実がいくつかあります。
- 埋め込みモデルは生成系 LLM とは別のモデルです。呼び出し単価も生成モデルよりはるかに安く、大量の文書を埋め込むコストは全体から見れば大きな割合にならないのが普通です。
- テキストだけでなく画像やコードも埋め込めますし、テキストと画像を同じ空間に置くマルチモーダル埋め込みもあります。
- 埋め込みモデルにも入力トークンの上限があります。文書を丸ごと入れるのではなく適切なサイズに分割してから埋め込みますが、この分割(チャンキング)が検索品質を大きく左右します。チャンキング戦略は RAG 深掘り #2 で扱いました。
類似度 — 近さを測る方法 #
2 つのベクトルがどれだけ近いかは、通常次の 3 つのいずれかで測ります。
| 方式 | 何を測るか | 備考 |
|---|---|---|
| コサイン類似度 | 2 つのベクトルのなす角度 | 最も広く使われる。長さは無視 |
| 内積(dot product) | 角度 + ベクトルの大きさ | 正規化済みベクトルではコサインと同じ |
| ユークリッド距離 | 座標上の直線距離 | 値が小さいほど類似 |
多くの埋め込みモデルはベクトルを正規化して出力するか、コサイン類似度を推奨しているので、特別な理由がなければモデル提供元の推奨方式をそのまま使えば問題ありません。注意したいのは、類似度スコアの絶対値はモデルごとにスケールが違うことです。「0.8 以上なら関連あり」のような閾値は、モデルを替えたら取り直す必要があります。
ベクトル検索 — 全件走査から近似検索へ #
検索とは結局「クエリベクトルに最も近いベクトルを k 件探すこと(kNN)」です。最も単純な実装は保存された全ベクトルとの距離を計算する全件走査で、数万件規模まではこれで十分です。NumPy の行列演算 1 行で書けて、精度も 100% です。
問題は規模です。数百万〜数億件になると全件走査は遅くなるため、ANN(Approximate Nearest Neighbor、近似最近傍探索) のインデックスを使います。代表的なアルゴリズムが HNSW で、ベクトル同士を多層グラフでつないでおき、グラフをたどりながら候補を絞り込みます。全部を比較しない代わりに真の最近傍を取りこぼす可能性が生まれ、この精度を再現率(recall)と呼びます。ANN インデックスは共通して、速度、再現率、メモリのトレードオフをパラメータで調整します。
ストレージの選択 — 専用 DB が常に正解ではありません #
ベクトルをどこに保存して検索するかは、大きく 3 つの選択肢があります。
- 既存 DB のベクトル拡張: PostgreSQL の pgvector が代表です。すでに PostgreSQL を運用しているなら、追加のインフラなしでベクトルカラムを足し、メタデータのフィルタリングや JOIN を SQL で一緒に処理できます。数百万件規模までは十分実用的です。Elasticsearch、OpenSearch、Redis もベクトル検索をサポートしています。
- 専用ベクトル DB: Pinecone、Qdrant、Weaviate、Milvus などです。大規模ベクトルに最適化されたインデックス、シャーディング、フィルタリングを提供します。数千万件以上になる場合や、ベクトル検索がサービスの中核経路にある場合に検討します。
- ライブラリ組み込み: FAISS のようなライブラリをアプリケーションに組み込む方式です。サーバー不要でバッチ処理や小規模検索に向きますが、永続化と並行処理は自前で面倒を見る必要があります。
判断基準はシンプルです。すでに運用している DB で始めて、規模やレイテンシが問題になったときに専用 DB へ移します。 最初から専用ベクトル DB を導入すると、インフラがひとつ増える運用コストが先にやってきます。
埋め込みの弱点 — 完全一致とハイブリッド検索 #
ベクトル検索は意味の近さには強い一方、文字列の完全一致には弱いです。 エラーコード E4032、型番 RTX 5090、社内プロジェクトのコードネームのように、意味より表記そのものが重要なクエリでは、キーワード検索(BM25)がベクトル検索に勝ちます。そのため実務の検索システムは、ベクトル検索とキーワード検索を両方走らせて結果を統合するハイブリッド構成が標準に近い形です。具体的な統合方法は RAG 深掘り #3 ハイブリッド検索で扱いました。
運用で直面すること #
- モデル変更 = 全再インデックス: 埋め込みベクトルは生成したモデルに依存します。別のモデルのベクトルとは比較できないため、埋め込みモデルを替えたら保存済みの文書すべてを埋め込み直す必要があります。文書が多いなら、再インデックスのパイプラインを最初から設計に含めるべきです。
- 次元とメモリ: 1536 次元の float32 ベクトル 1 本は約 6KB です。1000 万件ならベクトルだけで 60GB になり、ANN インデックスは通常これをメモリに載せます。次元削減や量子化で減らせますが、再現率とのトレードオフです。
- 鮮度: 文書が更新されたら、該当チャンクを埋め込み直して更新する必要があります。原本とインデックスの同期の遅れは、検索結果にそのまま現れます。
まとめ #
- 埋め込みはテキストを意味が保存されたベクトルに変換し、ベクトル検索はその空間で近いものを探します。キーワードが違っても意味で見つけられる理由です。
- 小規模なら全件走査で十分で、大規模なら HNSW などの ANN インデックスで速度と再現率を交換します。
- ストレージは既存 DB のベクトル拡張(pgvector など)で始めて、規模が大きくなったら専用ベクトル DB を検討する順序が安全です。
- 完全一致には弱いため、キーワード検索と組み合わせたハイブリッドが実務の標準です。
- 埋め込みモデルを替えると全再インデックスが必要になります。運用設計にあらかじめ織り込んでおくべきです。