ベクトルデータベースの仕組み、作り方、使い方をわかりやすく解説

ベクトルデータベースベクトルデータベースとは、データ (文書、音声、画像など) をベクトルとして保存・検索するデータベースです。
ベクトル埋め込みベクトル埋め込みとは、データ (文書、音声、画像など) の意味や関係性をベクトルに変換する方法です。

ベクトル埋め込みのコンテキストでは、埋め込みとベクトルは同じものです。

https://www.elastic.co/jp/what-is/vector-embedding

ベクトルデータベースを利用する理由は、主に次の2つです。

  • 画像や音楽などの非構造化データを検索
  • キーワードに含まれないが、関連するテキストを検索
画像検索ができている
「東京スカイツリー 観光」とキーワードが一致しないが、近くのおすすめランチがヒットしている
RAG (検索拡張生成)
スポンサーリンク

ベクトルデータベースの種類一覧

ベクトルデータベースには、主に以下のデータベースが利用されます。

本記事では、OpenSearch (Elasticsearch の fork) を元に、ベクトルデータベースを解説します。

ベクトルデータベースの作り方

OpenSearch のベクトル検索 (ベクトルデータベースを使った検索) は、主に 2 種類存在します。

  • OpenSearch 外でベクトルを生成して、保存・検索
  • OpenSearch 内でベクトルを生成して、保存・検索
スポンサーリンク

OpenSearch 外でベクトルを生成

OpenSearch 外で生成したベクトルを検索する方法について説明します。

0. ベクトル埋め込み

まずは、ベクトル埋め込みを利用してデータをベクトルに変換する必要があります。
※ OpenSearch 外の作業

変換前のデータベクトル埋め込み
単語Word2Vec, GloVe, FastText
文章Universal Sentence Encoder (USE)
ドキュメントDoc2Vec
画像CNN
地理空間国土地理院 API

今回は、各都道府県を緯度と経度の 2 次元ベクトルで表現して検索してみます。

なお、今回は既に都道府県を緯度と経度に変換済みのデータを利用します。
(自分で変換したい方は、国土地理院 API などをご利用ください)

都道府県地名緯度 (N)経度 (E)
沖縄県那覇市26.212127.681
大阪府大阪市34.686135.520
神奈川県横浜市35.448139.692
東京都東京35.689139.692
北海道札幌市43.065141.347
一部抜粋
http://agora.ex.nii.ac.jp/digital-typhoon/search_place.html.ja

1. k-NN インデックスを作成

k-NN インデックスk-NN インデックスとは、kNN で最も"近い"要素をベクトル検索できるインデックスです。
k=3 の場合、最も近い 3 要素を検索

何をもって"近い"とするかは、OpenSearch の space_type で設定できます。(こちら)

絶対値に強く影響を受け、C の方が近くなります
緯度、経度を例にすると、地理的距離が近い方が近くなります
カテゴリで分ける傾向にあり、B の方が近くなります
緯度、経度を例にすると、方角が近い方が近くなります。
PUT prefectures
{
  "settings": {
    "index.knn":true
  },
  "mappings": {
    "properties": {
      "location": {
        "type": "knn_vector",
        "dimension": 2
      }
    }
  }
}

2. k-NN インデックスにデータを追加

以下のデータを追加します。

都道府県地名緯度 (N)経度 (E)
沖縄県那覇市26.212127.681
大阪府大阪市34.686135.520
東京都東京35.689139.692
北海道札幌市43.065141.347
POST /_bulk
{ "index": { "_index": "prefectures", "_id": "沖縄" } }
{ "location": [26.212, 127.681] }
{ "index": { "_index": "prefectures", "_id": "大阪" } }
{ "location": [34.686, 135.520] }
{ "index": { "_index": "prefectures", "_id": "東京" } }
{ "location": [35.689, 139.692] }
{ "index": { "_index": "prefectures", "_id": "北海道" } }
{ "location": [43.065, 141.347] }

3. k-NN インデックスを検索

神奈川の緯度経度と近いベクトルの都道府県を検索してみます。

都道府県地名緯度 (N)経度 (E)
神奈川県横浜市35.448139.692
POST /prefectures/_search
{
  "query": {
    "knn": {
      "location": {
        "vector": [35.448, 139.642],
        "k": 3
      }
    }
  }
}

神奈川に緯度経度が近い県から順番に検索結果が表示されます。
(近いほど _score が高くなります)

    "hits": [
      {
        "_index": "prefectures",
        "_id": "東京",
        "_score": 0.9428803,
        "_source": {
          "location": [
            35.689,
            139.692
          ]
        }
      },
      {
        "_index": "prefectures",
        "_id": "大阪",
        "_score": 0.053846005,
        "_source": {
          "location": [
            34.686,
            135.52
          ]
        }
      },
      {
        "_index": "prefectures",
        "_id": "北海道",
        "_score": 0.016148392,
        "_source": {
          "location": [
            43.065,
            141.347
          ]
        }
      },
      {
        "_index": "prefectures",
        "_id": "沖縄",
        "_score": 0.0043597827,
        "_source": {
          "location": [
            26.212,
            127.681
          ]
        }
      }
スポンサーリンク

OpenSearch 内でベクトルを生成

OpenSearch では、Neural search を利用すると、クエリに含まれるデータをベクトルに変換してから保存・検索できます。

ニューラル検索で利用できるベクトル変換モデル (ML モデル) は以下のとおりです。

検索方法用途ベクトル変換モデル (ML モデル)
セマンティック検索テキストの意味を考慮して検索テキスト埋め込みモデル
マルチモーダル検索画像検索マルチモーダル埋め込みモデル
スパース検索スパース検索
(計算コストの削減)
スパース埋め込みモデル
会話型検索自然言語で会話するように検索大規模言語モデル (LLM)

今回は MS MARCO モデルを利用して、セマンティック検索を行います。

1. ML モデルをセットアップ

前提条件:メモリの潤沢なマシンを使ってください。

PUT _cluster/settings
{
  "persistent": {
    "plugins.ml_commons.only_run_on_ml_node": false
  }
}

msmarco-distilbert-base-tas-b という MS MARCO モデルを登録します。

POST /_plugins/_ml/models/_register
{
  "name": "huggingface/sentence-transformers/msmarco-distilbert-base-tas-b",
  "version": "1.0.1",
  "model_format": "TORCH_SCRIPT"
}
GET /_plugins/_ml/tasks/_search
{}
          "state": "COMPLETED",
          "model_id": "0123456789abcdefghij",

※state が CREATED から COMPLETED になると、model_id が表示されます。

POST /_plugins/_ml/models/model_id/_deploy

デプロイが完了したかどうかは、GET /_plugins/_ml/tasks/_search で確認できます。

2. Neural search でデータ取込

PUT /_ingest/pipeline/nlp-ingest-pipeline
{
  "processors": [
    {
      "text_embedding": {
        "model_id": "model_id",
        "field_map": {
          "text": "passage_embedding"
        }
      }
    }
  ]
}

OpenSearch 外でベクトルを生成する場合と同じく、k-NN インデックスを作成します。

PUT /my-nlp-index
{
  "settings": {
    "index.knn": true,
    "default_pipeline": "nlp-ingest-pipeline"
  },
  "mappings": {
    "properties": {
      "passage_embedding": {
        "type": "knn_vector",
        "dimension": 768
      },
      "text": {
        "type": "text"
      }
    }
  }
}

dimension はモデルの次元に合わせて 768 にします。

POST _bulk
{ "index": { "_index": "my-nlp-index", "_id": "東京" } }
{ "text": "Tokyo is the capital of Japan and one of the most populous cities in the world, with a population of over 14 million residents as of 2023 and the second-most-populated capital in the world." }
{ "index": { "_index": "my-nlp-index", "_id": "北海道" } }
{ "text": "Hokkaido is the second-largest island of Japan and comprises the largest and northernmost prefecture, making up its own region." }
{ "index": { "_index": "my-nlp-index", "_id": "沖縄" } }
{ "text": "Okinawa Prefecture is the southernmost and westernmost prefecture of Japan." }
{ "index": { "_index": "my-nlp-index", "_id": "大阪" } }
{ "text": "Osaka is a designated city in the Kansai region of Honshu in Japan, and one of the three major cities of Japan (Tokyo-Osaka-Nagoya)." }

OpenSearch 外でベクトルを生成する場合と異なり、事前にベクトルに変換する必要が無いです。
※利用しているモデルは英語のモデルなので、英語で投入します。

3. データを検索

GET /my-nlp-index/_search
{
  "_source": {
    "excludes": [
      "passage_embedding"
    ]
  },
  "query": {
    "neural": {
      "passage_embedding": {
        "query_text": "vast area",
        "model_id": "model_id",
        "k": 4
      }
    }
  }
}
     {
        "_index": "my-nlp-index",
        "_id": "北海道",
        "_score": 0.014841334,
        "_source": {
          "text": "Hokkaido is the second-largest island of Japan and comprises the largest and northernmost prefecture, making up its own region."
        }
      },
      {
        "_index": "my-nlp-index",
        "_id": "東京",
        "_score": 0.014191683,
        "_source": {
          "text": "Tokyo is the capital of Japan and one of the most populous cities in the world, with a population of over 14 million residents as of 2023 and the second-most-populated capital in the world."
        }
      },
      {
        "_index": "my-nlp-index",
        "_id": "大阪",
        "_score": 0.013411345,
        "_source": {
          "text": "Osaka is a designated city in the Kansai region of Honshu in Japan, and one of the three major cities of Japan (Tokyo-Osaka-Nagoya)."
        }
      },
      {
        "_index": "my-nlp-index",
        "_id": "沖縄",
        "_score": 0.012613818,
        "_source": {
          "text": "Okinawa Prefecture is the southernmost and westernmost prefecture of Japan."
        }
      }

vast area (広大な面積) で検索したところ、北海道が一番上にヒットしました。

ドキュメントには vast や area が一切含まれていませんが、second-largest island と相関が高いのか、無事に北海道が取得できました。

最後に

関連記事

RAG (検索拡張生成)
Elasticsearch & OpenSearch の使い方
ディープラーニング