Firestore の ベクトル検索を試す
「Firestore」の「ベクトル検索」を試したので、まとめました。
1. Firestore の ベクトル検索
「Firestore」にプレビュー版ですが、「ベクトル検索」の機能が付きました。
2. ベクトルインデックスの作成と削除
2-1. ベクトルインデックスの作成
(1) ローカルマシンで「gcloud CLU」をセットアップ。
(2) 以下のコマンドを実行。
コレクショングループを「sample」、埋め込みの次元を「1536」(OpenAIの埋め込みの次元数)、データベースIDを「(default)」としています。
$ gcloud alpha firestore indexes composite create \
--collection-group=sample \
--query-scope=COLLECTION \
--field-config field-path=embedding_field,vector-config='{"dimension":"1536", "flat": "{}"}' \
--database="(default)"
2-2. ベクトルインデックスの一覧の表示
(1) 以下のコマンドを実行。
プロジェクトIDとデータベースIDを確認します。
$ gcloud alpha firestore indexes composite list --database="(default)"
---
fields:
- fieldPath: __name__
order: ASCENDING
- fieldPath: embedding_field
vectorConfig:
dimension: 1536
flat: {}
name: projects/<プロジェクトID>/databases/(default)/collectionGroups/sample/indexes/<インデックスID>
queryScope: COLLECTION
state: READY
2-3. ベクトルインデックスの削除
$ gcloud alpha firestore indexes composite delete <インデックスID> --database="(default)"
今回はベクトルインデックスを使うので、削除は使用後にします。
3. ベクトルインデックスへのデータ追加
(1) 「Firebase」のコンソールで「サービスアカウントキー」(serviceAccountKey.json)を取得。
(2) 以下のコードを作成して実行。
<OpenAI_APIキー>には自分のAPIキーを入力してください。
import os
import firebase_admin
from openai import OpenAI
from firebase_admin import credentials, firestore
from google.cloud.firestore_v1.vector import Vector
# ====================
# OpenAIの前準備
# ====================
# 環境変数の準備
os.environ["OPENAI_API_KEY"] = "<OpenAI_APIキー>"
# クライアントの準備
client = OpenAI()
# 埋め込み関数の準備
def embedding(texts):
response = client.embeddings.create(
input=texts,
model="text-embedding-3-small"
)
return [d.embedding for d in response.data]
# ====================
# Firestoreの前準備
# ====================
# Firestoreの前準備
cred = credentials.Certificate("serviceAccountKey.json")
default_app = firebase_admin.initialize_app(cred)
firestore_client = firestore.client()
collection = firestore_client.collection("sample")
# ====================
# ベクトルインデックスへのデータ追加
# ====================
# 対象テキスト
target_texts = [
"好きな食べ物は何ですか?",
"どこにお住まいですか?",
"朝の電車は混みますね",
"今日は良いお天気ですね",
"最近景気悪いですね"
]
# 埋め込みベクトルの生成
target_embeds = embedding(target_texts)
# ベクトルインデックスへのデータ追加
for i in range(len(target_texts)):
doc = {
"text_field": target_texts[i],
"embedding_field": Vector(target_embeds[i]),
}
collection.add(doc)
(3) Firestoreコンソールでデータ追加を確認。
4. ベクトル検索
(2) 以下のコードを作成して実行。
<OpenAI_APIキー>には自分のAPIキーを入力してください。
import os
import firebase_admin
from openai import OpenAI
from firebase_admin import credentials, firestore
from google.cloud.firestore_v1.vector import Vector
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure
# ====================
# OpenAIの前準備
# ====================
# 環境変数の準備
os.environ["OPENAI_API_KEY"] = "<OpenAI_APIキー>"
# クライアントの準備
client = OpenAI()
# 埋め込み関数の準備
def embedding(texts):
response = client.embeddings.create(
input=texts,
model="text-embedding-3-small"
)
return [d.embedding for d in response.data]
# ====================
# Firestoreの前準備
# ====================
# Firestoreの前準備
cred = credentials.Certificate("serviceAccountKey.json")
default_app = firebase_admin.initialize_app(cred)
firestore_client = firestore.client()
collection = firestore_client.collection("sample")
# ====================
# ベクトル検索
# ====================
# 入力テキスト
in_texts = [
"今日は雨振らなくてよかった"
]
# 埋め込みベクトルの生成
in_embeds = embedding(in_texts)
# ベクトル検索
snapshot = collection.find_nearest(
vector_field="embedding_field",
query_vector=Vector(in_embeds[0]),
distance_measure=DistanceMeasure.EUCLIDEAN,
limit=1).get()
# 検索結果の確認
for doc in snapshot:
print(f"id: {doc.id}")
print(f"text_field: {doc.get('text_field')}")
print("---")
id: NGX5arH7veVQDa1wZPce
text_field: 今日は良いお天気ですね
近傍検索は、collection.find_nearest()で行います。
ベクトル距離のオプションは、次のとおりです。
「今日は雨振らなくてよかった」に一番近い言葉は「今日は良いお天気ですね」であることがわかりました。