RAGの心臓部 — Embeddingとベクトル検索で「意味」を捉える
ChatGPTやClaudeに「自社のデータを読み込ませたい」と思ったことはありませんか?そこで鍵になるのがEmbeddingとベクトル検索です。RAG(Retrieval-Augmented Generation)の中核を担うこの技術について、実装の視点から解説します。
なぜ「キーワード検索」では足りないのか
従来のキーワード検索は、文字が完全一致しないとヒットしません。「売上推移」で検索しても「営業収益の推移」と書かれた文書は出てきません。
しかし人間は「売上」と「営業収益」が同じ意味だと分かります。この**「意味の近さ」を機械に理解させる**技術がEmbeddingです。
Embeddingとは何か
Embeddingとは、テキストを数千次元の数値ベクトルに変換する技術です。意味が近いテキストはベクトル空間で近い位置に配置されます。
from openai import OpenAI
client = OpenAI()
response = client.embeddings.create(
model="text-embedding-3-small",
input="売上推移を教えてください"
)
# 1536次元のベクトルが返ってくる
vector = response.data[0].embedding
print(f"次元数: {len(vector)}")
# → 次元数: 1536
「売上推移」と「営業収益の推移」をそれぞれEmbeddingすると、コサイン類似度(ベクトルの向きの近さを測る指標)が高くなります。つまり機械が「意味が似ている」と判断できるのです。
ベクトル検索の実装
ベクトル化した文書を保存し、検索するのがベクトルデータベースです。ChromaDBを使った最小実装を見てみましょう。
import chromadb
client = chromadb.Client()
collection = client.create_collection("documents")
# 文書をベクトル化して保存
collection.add(
documents=[
"2024年度の売上は前年比12%増の1億2000万円でした。",
"営業収益の推移は過去3年間右肩上がりです。",
"新製品の発売は来年3月を予定しています。"
],
ids=["doc1", "doc2", "doc3"]
)
# 検索
results = collection.query(
query_texts=["売上の傾向は?"],
n_results=2
)
print(results['documents'][0])
# → ['2024年度の売上は前年比12%増の1億2000万円でした。',
# '営業収益の推移は過去3年間右肩上がりです。']
「売上の傾向は?」という問いに対し、キーワードが完全一致しなくても「営業収益の推移」がヒットします。これがベクトル検索の力です。
ハイブリッド検索で精度を上げる
実務では、ベクトル検索だけではなくキーワード検索も組み合わせるハイブリッド検索が主流です。
- ベクトル検索: 意味的な近さで検索(「売上」≈「営業収益」)
- キーワード検索: 正確な用語で検索(「売上」≠「営業収益」)
両方の結果をマージすることで、意味的な曖昧さと用語の正確さを両立できます。
実務で押さえるべきポイント
- チャンク分割: 長い文書を適切なサイズに分割しないと、検索精度が落ちる
- Embeddingモデル選択: 日本語特有の表現に強いモデルを選ぶ
- メタデータ付与: 検索結果の絞り込みに使う情報をベクトルと一緒に保存する
- リランキング: 検索結果を再評価し、より関連性の高い文書を上位に持ってくる
まとめ
RAGの精度は、Embeddingとベクトル検索の品質で決まると言っても過言ではありません。この技術を深く理解し、実装できるエンジニアは今まさに求められています。
Embeddingの基礎からベクトルDB選定、チャンク分割戦略、ハイブリッド検索、リランキング、LangChain/LlamaIndexを使ったパイプライン構築、評価手法まで網羅した実践書を書きました。
RAG構築入門 — LLMに「知識」を与える検索拡張生成の実践
Amazonで購入する(¥1,650・Kindle)
Kindle Unlimited会員は読み放題対象です。
葉山悠希 — AI×生産性向上の実践書を執筆しています。