ベクトル埋め込みのコンテキストでは、埋め込みとベクトルは同じものです。
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 などをご利用ください)
http://agora.ex.nii.ac.jp/digital-typhoon/search_place.html.ja
都道府県 地名 緯度 (N) 経度 (E) 沖縄県 那覇市 26.212 127.681 大阪府 大阪市 34.686 135.520 神奈川県 横浜市 35.448 139.692 東京都 東京 35.689 139.692 北海道 札幌市 43.065 141.347 一部抜粋
1. k-NN インデックスを作成
何をもって"近い"とするかは、OpenSearch の space_type で設定できます。(こちら)
PUT prefectures { "settings": { "index.knn":true }, "mappings": { "properties": { "location": { "type": "knn_vector", "dimension": 2 } } } }
2. k-NN インデックスにデータを追加
以下のデータを追加します。
都道府県 | 地名 | 緯度 (N) | 経度 (E) |
---|---|---|---|
沖縄県 | 那覇市 | 26.212 | 127.681 |
大阪府 | 大阪市 | 34.686 | 135.520 |
東京都 | 東京 | 35.689 | 139.692 |
北海道 | 札幌市 | 43.065 | 141.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.448 | 139.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 の使い方 | |||||
---|---|---|---|---|---|
学習ロードマップ | |||||
---|---|---|---|---|---|
ディープラーニング | ||||
---|---|---|---|---|