👨‍🎓

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