本頁面說明如何透過下列技術,使用 Cloud Firestore 執行最鄰近 (KNN) 向量搜尋:
- 儲存向量值
- 建立及管理 KNN 向量索引
- 使用系統支援的向量距離函式,執行 K-nearest-Neighbor (KNN) 查詢
儲存向量嵌入
您可以從 Cloud Firestore 資料建立向量值 (例如文字嵌入),並將其儲存在 Cloud Firestore 文件中。
使用向量嵌入功能寫入運算
以下範例說明如何在 Cloud Firestore 文件中儲存向量嵌入:
Python
from google.cloud import firestore from google.cloud.firestore_v1.vector import Vector firestore_client = firestore.Client() collection = firestore_client.collection("coffee-beans") doc = { "name": "Kahawa coffee beans", "description": "Information about the Kahawa coffee beans.", "embedding_field": Vector([1.0 , 2.0, 3.0]) } collection.add(doc)
Node.js
import { Firestore, FieldValue, } from "@google-cloud/firestore"; const db = new Firestore(); const coll = db.collection('coffee-beans'); await coll.add({ name: "Kahawa coffee beans", description: "Information about the Kahawa coffee beans.", embedding_field: FieldValue.vector([1.0 , 2.0, 3.0]) });
使用 Cloud 函式計算向量嵌入
如要在更新或建立文件時計算及儲存向量嵌入,您可以設定 Cloud 函式:
Python
@functions_framework.cloud_event def store_embedding(cloud_event) -> None: """Triggers by a change to a Firestore document. """ firestore_payload = firestore.DocumentEventData() payload = firestore_payload._pb.ParseFromString(cloud_event.data) collection_id, doc_id = from_payload(payload) # Call a function to calculate the embedding embedding = calculate_embedding(payload) # Update the document doc = firestore_client.collection(collection_id).document(doc_id) doc.set({"embedding_field": embedding}, merge=True)
Node.js
/** * A vector embedding will be computed from the * value of the `content` field. The vector value * will be stored in the `embedding` field. The * field names `content` and `embedding` are arbitrary * field names chosen for this example. */ async function storeEmbedding(event: FirestoreEvent<any>): Promise<void> { // Get the previous value of the document's `content` field. const previousDocumentSnapshot = event.data.before as QueryDocumentSnapshot; const previousContent = previousDocumentSnapshot.get("content"); // Get the current value of the document's `content` field. const currentDocumentSnapshot = event.data.after as QueryDocumentSnapshot; const currentContent = currentDocumentSnapshot.get("content"); // Don't update the embedding if the content field did not change if (previousContent === currentContent) { return; } // Call a function to calculate the embedding for the value // of the `content` field. const embeddingVector = calculateEmbedding(currentContent); // Update the `embedding` field on the document. await currentDocumentSnapshot.ref.update({ embedding: embeddingVector, }); }
建立及管理向量索引
您必須先建立對應的索引,才能使用向量嵌入執行最鄰近搜尋。以下範例說明如何建立及管理向量索引。
建立向量索引
如要建立向量索引,請使用 gcloud alpha firestore indexes composite create
:
gcloud
gcloud alpha firestore indexes composite create \ --collection-group=collection-group \ --query-scope=COLLECTION \ --field-config field-path=vector-field,vector-config='vector-configuration' \ --database=database-id
其中:
- collection-group 是產品素材資源集合群組的 ID。
- vector-field 是包含向量嵌入的欄位名稱。
- database-id 是資料庫的 ID。
- vector-configuration 包含向量
dimension
和索引類型。dimension
是最大 2048 的整數。索引類型必須是flat
。索引設定的格式設定如下:{"dimension":"DIMENSION", "flat": "{}"}
。
以下範例會建立複合式索引,包括 vector-field
欄位的向量索引,以及 color
欄位的遞增索引。您可以使用這類索引預先篩選資料,再進行最鄰近搜尋。
gcloud
gcloud alpha firestore indexes composite create \ --collection-group=collection-group \ --query-scope=COLLECTION \ --field-config=order=ASCENDING,field-path="color" \ --field-config field-path=vector-field,vector-config='{"dimension":"1024", "flat": "{}"}' \ --database=database-id
列出所有向量索引
gcloud
gcloud alpha firestore indexes composite list --database=database-id
請將 database-id 替換為資料庫 ID。
刪除向量索引
gcloud
gcloud alpha firestore indexes composite delete index-id --database=database-id
其中:
- index-id 是要刪除的索引 ID。使用
indexes composite list
擷取索引 ID。 - database-id 是資料庫的 ID。
說明向量索引
gcloud
gcloud alpha firestore indexes composite describe index-id --database=database-id
其中:
- index-id 是要說明的索引 ID。使用或
indexes composite list
擷取索引 ID。 - database-id 是資料庫的 ID。
執行最鄰近查詢
您可以執行相似度搜尋,找出向量嵌入中最鄰近的項目。相似度搜尋需要向量索引。如果索引不存在,Cloud Firestore 會建議使用 gcloud CLI 建立索引。
Python
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure collection = collection("coffee-beans") # Requires vector index collection.find_nearest( vector_field="embedding_field", query_vector=Vector([3.0, 1.0, 2.0]), distance_measure=DistanceMeasure.EUCLIDEAN, limit=5)
Node.js
import { Firestore, FieldValue, VectorQuery, VectorQuerySnapshot, } from "@google-cloud/firestore"; // Requires single-field vector index const vectorQuery: VectorQuery = coll.findNearest('embedding_field', FieldValue.vector([3.0, 1.0, 2.0]), { limit: 5, distanceMeasure: 'EUCLIDEAN' }); const vectorQuerySnapshot: VectorQuerySnapshot = await vectorQuery.get();
向量距離
最鄰近查詢支援下列向量距離選項:
EUCLIDEAN
:測量向量之間的 EUCLIDEAN 距離。詳情請參閱 Euclidean。COSINE
:根據向量之間的角度比較向量,讓您測量非以向量規模的角度所得相似度。建議您針對單位正規化向量使用DOT_PRODUCT
,而不要使用 COSINE 距離,這兩者在數學上相等,可獲得更好的效能。詳情請參閱餘弦相似度。DOT_PRODUCT
:與COSINE
類似,但受到向量的規模影響。詳情請參閱 Dot 產品。
預先篩選資料
如要在尋找最鄰近的項目前先預先篩選資料,您可以結合相似度搜尋與其他篩選器 (不相等篩選器除外)。系統支援 and
和 or
複合篩選器。欄位篩選器支援下列篩選器:
==
等於in
array_contains
array_contains_any
Python
# Similarity search with pre-filter # Requires composite vector index collection.where("color", "==", "red").find_nearest( vector_field="embedding_field", query_vector=Vector([3.0, 1.0, 2.0]), distance_measure=DistanceMeasure.EUCLIDEAN, limit=5)
Node.js
// Similarity search with pre-filter // Requires composite vector index const preFilteredVectorQuery: VectorQuery = coll .where("color", "==", "red") .findNearest("embedding_field", FieldValue.vector([3.0, 1.0, 2.0]), { limit: 5, distanceMeasure: "EUCLIDEAN", }); vectorQueryResults = await preFilteredVectorQuery.get();
限制
使用向量嵌入時,請注意下列限制:
- 支援的嵌入維度上限為 2048。如要儲存較大的索引,請使用縮減維度。
- 最鄰近查詢傳回的文件數量上限為 1000。
- Vector Search 不支援即時快照事件監聽器。
- 您無法使用不等式篩選器來預先篩選資料。
- 只有 Python 和 Node.js 用戶端程式庫支援向量搜尋。