埋め込みとベクトル検索:初心者向けロードマップ
アプリにセマンティック検索を追加したい——ユーザーがクエリを入力すると、完全一致のキーワードではなく意味に基づいて結果が返るように。しかし、どこから始めればいいのか分からない:埋め込みとは何か?ベクトルデータベースは必要か?類似度はどう測るのか?このロードマップでは、これらの疑問に実践的なステップと今すぐ実行できるコードで答えます。
埋め込みとは何か?
埋め込み(embedding)とは、入力(テキスト、画像、音声など)の意味を表す浮動小数点数の密なベクトルです。テキストの場合、text-embedding-3-small やオープンソースの代替(例:all-MiniLM-L6-v2)のようなモデルが、文を例えば384次元のベクトルに変換します。意味が似ている単語や文は、このベクトル空間内で近くに配置されます。
例:「cat」と「kitten」のベクトルは、「cat」と「airplane」よりも近くなります。この性質によりセマンティック検索が可能になります:ドキュメントとクエリを埋め込み、最も近いドキュメントベクトルを見つけるのです。
ベクトル検索の仕組み
ベクトル検索(類似検索とも呼ばれる)は、データセット内でクエリベクトルに最も類似したベクトルを見つけます。類似度は通常、コサイン類似度または内積で測定されます。正規化されたベクトルでは、コサイン類似度と内積は等価です。
総当たり検索はクエリをすべてのベクトルと比較します——数千のベクトルなら問題ありませんが、数百万になると遅すぎます。そこで近似最近傍(ANN)アルゴリズムの出番です。例えばHNSW(Hierarchical Navigable Small World)やIVF(Inverted File Index)があります。これらはわずかな精度を犠牲にして、大幅な速度向上を得ます。
ステップバイステップ:セマンティック検索プロトタイプの構築
- 埋め込みモデルを選ぶ。 英語テキストなら、Sentence Transformersの
all-MiniLM-L6-v2(384次元)のような小さく高速なモデルから始めましょう。本番環境では、OpenAIのtext-embedding-3-small(1536次元)やtext-embedding-3-large(3072次元)を検討してください。 - ドキュメントを埋め込む。 長いテキストはチャンク(例:200〜500語)に分割し、各チャンクが一貫したアイデアを捉えるようにします。元のテキストをベクトルと一緒に保存します。
- ベクトルストアを選ぶ。 クイックスタートには、FAISSやシンプルなNumPy配列のようなインメモリライブラリを使います。本番環境では、専用のベクトルデータベースを選びます(下の表を参照)。
- クエリを埋め込む。 同じモデルを使ってユーザーの検索クエリを埋め込みます。
- 検索する。 クエリベクトルとすべてのドキュメントベクトル間の類似度を計算し(またはANNインデックスを使用)、上位k件の結果を返します。
- 反復する。 結果を評価し、チャンクサイズ、モデル、類似度指標を調整します。
Sentence TransformersとFAISSを使った最小限のPython例
from sentence_transformers import SentenceTransformer
import faiss
import numpy as np
# 1. モデルを読み込む
model = SentenceTransformer('all-MiniLM-L6-v2')
# 2. サンプルドキュメント
docs = [
"The cat sat on the mat.",
"A kitten is playing with yarn.",
"The stock market crashed today.",
"Investors are worried about inflation."
]
# 3. 埋め込みを作成
embeddings = model.encode(docs, convert_to_numpy=True)
# 4. FAISSインデックスを構築
dim = embeddings.shape[1]
index = faiss.IndexFlatL2(dim) # L2距離;コサインの場合は先に正規化
index.add(embeddings)
# 5. 検索
query = "feline resting"
query_vec = model.encode([query], convert_to_numpy=True)
D, I = index.search(query_vec, k=2)
print([docs[i] for i in I[0]])
# 出力例:['The cat sat on the mat.', 'A kitten is playing with yarn.']
ベクトルデータベースの選び方
小規模なプロジェクトでは、ベクトルをシンプルなファイルやインメモリインデックスに保存できます。スケールするにつれて、専用のベクトルデータベースが永続性、フィルタリング、ANNインデックスを提供します。簡単な比較はこちら:
| データベース | タイプ | 最適な用途 |
|---|---|---|
| FAISS | ライブラリ | プロトタイピング、ローカル実験 |
| Chroma | 組み込み / クライアントサーバー | 中小規模アプリ、簡単なセットアップ |
| Pinecone | マネージドクラウド | 本番環境、サーバーレススケーリング |
| Weaviate | オープンソース / クラウド | ハイブリッド検索、GraphQL API |
| Qdrant | オープンソース / クラウド | 高性能、フィルタリング |
| pgvector | PostgreSQL拡張 | 既存のPostgresスタック |
ベストプラクティスとよくある落とし穴
- ベクトルを正規化する——コサイン類似度を使う場合。多くのライブラリは内積に単位ベクトルを仮定しています。
- 賢くチャンク分割する: 大きすぎると具体性を失い、小さすぎると文脈を失います。オーバーラップを試してみましょう。
- 同じモデルを使う——ドキュメントとクエリで。モデルを混ぜると類似度が壊れます。
- 次元削減を検討する(例:PCA)——ストレージや速度が重要な場合のみ。精度が低下する可能性があります。
- ハイブリッド検索(キーワードとベクトルの組み合わせ)は、完全一致の結果を改善することがよくあります。
FAQ
小規模プロジェクトにベクトルデータベースは必要ですか?
いいえ。数千ベクトルまでなら、FAISSやNumPy配列のようなインメモリライブラリを使えます。ベクトルデータベースは、永続性、フィルタリング、メモリを超えるスケールが必要になったときに役立ちます。
埋め込みモデルはどう選べばいいですか?
プロトタイピングにはall-MiniLM-L6-v2のような小さく高速なモデルから始めましょう。より高い精度が必要でAPIコストを許容できるなら、OpenAIのtext-embedding-3-smallやtext-embedding-3-largeを試してください。常に自分のデータで評価しましょう。
コサイン類似度とユークリッド距離の違いは何ですか?
コサイン類似度はベクトル間の角度を測定し、大きさを無視します。ユークリッド距離は直線距離を測定します。正規化されたベクトルでは、同じランキングになります。コサインは方向(意味)に焦点を当てるため、テキスト埋め込みで一般的です。
次のステップ
基本を理解したので、自分のノートやドキュメントで小さなセマンティック検索を構築してみましょう。チャンクサイズとモデルを試してみてください。成長するにつれて、マネージドベクトルデータベースに移行し、ハイブリッド検索を追加しましょう。この分野は進歩が速いですが、これらの基本は今後も relevant であり続けます。
埋め込みサービスからのAPIレスポンスを整形したり、JSONペイロードをデバッグしたりする必要があるときは、JSON Formatterがデータを素早く検査・検証するのに役立ちます。