Vector DB 入門
初めに
近年、「ベクトルデータベース(Vector DB)」という言葉を耳にする機会が増えてきました。実際にどのように機能するのか仕組みが気になったため、作ってみました。
この記事では、そもそもVector DBとは何か、embeddingとの関係性、ユースケースについてまとめ、実際にVector DBを利用したSemantic Searchのハンズオンについて解説していきます。
概要説明
Embedding とは
Embedding(埋め込み)とは、文章や画像などの非構造化データを、多次元の数値ベクトルに変換する技術です。
例えば、以下のような文章があったとします:
- 「私はりんごが好きです」
- 「みかんが大好きです」
これらの文は単語は違いますが、意味としては「果物が好き」という共通点があります。Embeddingを使えば、この意味的な近さを数値的なベクトルで表現できます。こうして生成されたベクトルを「特徴ベクトル」と呼びます。
参照:How Do Vector Embeddings Work?
Vector DB とは
Vector DBは、Embeddingで変換された高次元ベクトルを大量に保存し、それらの「近さ(類似度)」をもとにデータを高速検索するためのデータベースです。
Embeddingの値はBLOB
(Binary Large Object)形式で格納し、入力された値と格納された値のEmbeddingの近さを比較し、近しいものを返却します。
実装によってはベクトルがFLOAT[]
やBLOB
形式で格納されることもありますが、多くのVector DBでは、専用のインデックス構造(例:HNSWやIVF)を用いて最適化された形で保存・検索されているようです。
ユースケース
実際にVector DBはどのように利用できるのでしょうか?
具体的なユースケースとして以下の例が挙げられます。
1. Semantic Search(意味検索)
従来のキーワード検索に代わって、意味に基づいた検索を可能にします。たとえば、「お寿司が食べたい」と検索したときに、「東京の和食レストラン」が出てくるようなケースです。ユーザーの意図を理解した検索結果を返すことでUXを向上できます。
2. Recommendation(推薦システム)
ユーザーの行動や好みに応じて、類似ユーザーや類似アイテムをベクトルで分析し、よりパーソナライズされた推薦が可能になります。例:NetflixやSpotifyでのコンテンツ推薦。
3. Clustering(クラスタリング)
ベクトル同士の類似度を使って、意味的に近いデータをグルーピングすることができます。文書の分類やユーザーセグメントの分析などに活用されます。
4. Classifications(分類タスク)
Embeddingされたデータに対して、ベクトル分類モデルを使うことで、スパム判定や感情分析などの教師あり学習に応用可能です。
ハンズオンの大きな流れ
① Embedding を作成する
まず最初に、検索対象となるテキストデータ(例:商品説明、FAQの質問、記事のタイトルなど)を ベクトル化(Embedding) します。
今回はOpenAIのAPI(text-embedding-ada-002)を利用し、自然言語を高次元の数値ベクトルに変換できます。
このリクエストの結果として、1536次元のベクトル(例: [0.123, -0.456, ...]
)が返されます。これが、検索の軸になる「特徴ベクトル」です。
② Vector DB に格納する
次に、取得したベクトルを Vector DB に格納します。多くの場合は、ベクトルに加えてその元データ(テキスト本文やURL、IDなど)も メタデータとして一緒に登録します。今回はSingleStoreという分散型SQLデータベースを利用します。これにより、「意味ベース」で検索できる準備が整います。
③ Semantic Search(意味検索)を実行
最後に、クエリテキストを入力して意味検索を行います。
クエリも同様にEmbeddingして、DB内にあるベクトルと比較し、類似度が最も高いもの(距離が近いもの)を返却します。たとえば、"I want to eat something sweet"と検索を行ったとします。
この文をベクトル化して検索すると、「cake」や「dessert」といった、キーワードには出てこないけれど意味が近いアイテムを返してくれます。
このプロセス全体が、従来のキーワード検索では難しかった「意味検索(Semantic Search)」を実現する鍵になります。
手順
① Embeddings を作成する
それでは実際にハンズオンを進めていきます。(赤枠が各フェーズの対象範囲です。)
1-1. エンドポイントの指定
まず、APIの実行環境を整えます。今回はOpen AIのAPI referenceを参考にAPIを実行します。
実行環境としてはPostmanを利用し、以下の情報を参考に新規でRequestを作成します。
// POST形式でリクエストを作成
https://api.openai.com/v1/embeddings
1-2. API keysを作成
次にOpen AIのAPI keyを作成します。こちらのリンクから作成可能です。
『Auth Type』は『Bear Token』を指定し、作成したAPI keyをコピペ
1-3. Request bodyを作成
Bodyのrowに以下を貼り付けます。
それぞれの意味は以下の通りです。
- input:埋め込みベクトルとして生成したいテキストを指定
- model:OpenAIの埋め込みモデルを指定
- encoding_format:エンコーディング形式を指定 (埋め込みベクトルが浮動小数点数の配列として表現される)
{
"input": "The food was delicious and the waiter...",
"model": "text-embedding-ada-002",
"encoding_format": "float"
}
1-4. リクエスト実行
レスポンスが返却されることを確認します。
レスポンス値では、作成されたembeddingと利用したtoken数が表示される
{
"object": "list",
"data": [
{
"object": "embedding",
"index": 0,
"embedding": [
0.0022756963,
0.014917395,
-0.009807394,
・・・・・・
-0.038264707,
-0.019424353,
-0.002800979
]
}
],
"model": "text-embedding-ada-002-v2",
"usage": {
"prompt_tokens": 8,
"total_tokens": 8
}
}
全体イメージはこんな感じ
1-5. inputの値を変更し、5件ほどリクエストを実行
ここではVector DBに格納するembeddingの値を生成します。
後の意味検索時に利用するため、適切な値をinputに入力し、embeddingの値を生成します。
※ モデルとしてtext-embedding-ada-002-v2を選択した場合、最大32,764文字をinputに入力可能。
今回は以下5つの単語を登録します。:
- apple
- fruit
- banana
- tomato
- cake
② Vector DBに格納する
次にembeddingの値を登録するVector DBを作成します。
2-1. 『SingleStore』にログイン
『SingleStore』にログインします。(アカウントがない場合は作成)
SingleStoreへのリンク。
2-2. WorkSpaceの作成
以下の手順に従い、検証環境を用意します。
- 左上の『Create New』から『Deployment』を選択
- 『WorkSpace』に対して、適切な命名を行う(例:OpenAI Vector Database WorkSpace)
- その他の値は、デフォルト値のままでOK
- 以下の画面が作成されたらOK(作成には数分要する)
2-3. データベースの作成
実際にデータベースを作成します。
- 『Create Database』ボタンを押下し、データベースを作成
- 『Databases』タブから作成したデータベースが表示されていること
2-4. テーブルの作成
次にテーブルを作成します。
- 『Develop』タブの『Data Studio』を選択し、SQLエディターを開く
- SQL実行前に作成したデータベースを選択すること
以下のクエリをエディターにコピペし、『RUN』ボタンを押下
※テーブル名は自由に変更可能
CREATE TABLE IF NOT EXISTS document_embeddings (
text TEXT,
vector BLOB
);
テーブルが作成できていることを確認
2-5. データ登録
最後に1-5で生成したembeddingの値をINSERT文で登録していきます。
※基本フォーマット
INSERT INTO document_embeddings (
text,
vector
) VALUES (
"inputの値",
JSON_ARRAY_PACK(
"[
embeddingのレスポンス値
]"
)
);
※サンプルクエリ
INSERT INTO document_embeddings (
text,
vector
) VALUES (
"The food was delicious and the waiter...",
JSON_ARRAY_PACK(
"[
0.0022756963,
0.014917395,
-0.009807394,
・・・・・・
-0.038264707,
-0.019424353,
-0.002800979
]"
)
);
実際の画面
レコードが追加されていることを確認
③ Semantic Search(意味検索)を実行
最後にランダムなテキストで生成したembeddingの値で検索し、類似するキーワードが返されるか確認します。
Postmanで検索したいテキストのembeddingを生成し、以下のクエリを実行
※基本フォーマット
SELECT text, dot_product(vector, JSON_ARRAY_PACK("[検索したいテキストのembeddingのレスポンス値]")) AS score
FROM document_embeddings
ORDER BY score DESC
LIMIT 5;
※サンプルクエリ
SELECT text, dot_product(vector, JSON_ARRAY_PACK("[0.0022756963,
0.014917395,
-0.009807394,
・・・・・・
-0.038264707,
-0.019424353,
-0.002800979]")) AS score
FROM document_embeddings
ORDER BY score DESC
LIMIT 5;
『fruit』のembedding値で検索した結果
text | score |
---|---|
fruit | 1.000000238418579 |
banana | 0.9199303984642029 |
apple | 0.9042364954948425 |
tomato | 0.8644180297851562 |
cake | 0.8537286520004272 |
『red fruit』のembedding値で検索した結果
text | score |
---|---|
fruit | 0.8975839018821716 |
apple | 0.8596481084823608 |
banana | 0.8593462109565735 |
tomato | 0.8536555767059326 |
cake | 0.8017322421073914 |
『yellow』のembedding値で検索した結果
text | score |
---|---|
banana | 0.8475435376167297 |
fruit | 0.8434903025627136 |
apple | 0.8415370583534241 |
tomato | 0.8146834969520569 |
cake | 0.809949517250061 |
『I want to eat something sweet』のembedding値で検索した結果
text | score |
---|---|
cake | 0.8145326972007751 |
fruit | 0.798363447189331 |
banana | 0.784806489944458 |
apple | 0.7805991172790527 |
tomato | 0.7706566452980042 |
実際の結果
あとがき
本記事では、embeddingからVector DBまでの流れを一通り確認してきました。
OpenAIのEmbedding APIを使って、「テキスト → ベクトル」へと変換し、それをVector DBに格納。そして、検索時にも同じようにベクトル化し、意味的に近いデータを取得するといった構成が、今では自然言語検索や推薦システムの基盤となっています。
実際に試してみた検索では、以下のようなクエリを投げてみました。
"I want to eat something sweet"
その結果、期待していた cake
がトップで返却されました。
単語に「cake」や「sweet」というキーワードが含まれていなくても、「甘いものを食べたい」という意味に基づいた検索結果が返ってきたことで、EmbeddingとVector DBの力を実感することができました。
現在、Retrieval-Augmented Generation(RAG)やModel Context Protocol(MCP)との組み合わせが話題になっていますね。これは、Vector DBを検索に使い、その結果をもとに生成系AIが回答するという構成で、ChatGPTや社内FAQボットのような「検索+自然言語応答」の実装でよく利用されています。次回はこれらとの組み合わせについても挑戦していきます。
Discussion