Halaman ini menunjukkan cara menggunakan Cloud Firestore untuk melakukan penelusuran vektor tetangga K-terdekat (KNN) menggunakan teknik berikut:
- Menyimpan nilai vektor
- Membuat dan mengelola indeks vektor KNN
- Membuat kueri tetanggan K-terdekat (KNN) menggunakan salah satu fungsi jarak vektor yang didukung
Menyimpan embedding vektor
Anda dapat membuat nilai vektor seperti embedding teks dari data Cloud Firestore, dan menyimpannya di dokumen Cloud Firestore.
Operasi tulis dengan embedding vektor
Contoh berikut menunjukkan cara menyimpan embedding vektor dalam dokumen 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]) });
Menghitung embedding vektor dengan Cloud Function
Untuk menghitung dan menyimpan embedding vektor setiap kali dokumen diperbarui atau dibuat, Anda dapat menyiapkan Cloud Function:
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, }); }
Membuat dan mengelola indeks vektor
Sebelum Anda dapat melakukan penelusuran tetangga terdekat dengan embedding vektor, Anda harus membuat indeks yang sesuai. Contoh berikut menunjukkan cara membuat dan mengelola indeks vektor.
Membuat indeks vektor
Untuk membuat indeks vektor, gunakan
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
dengan:
- collection-group adalah ID grup koleksi.
- vector-field adalah nama kolom yang berisi embedding vektor.
- database-id adalah ID database.
- vector-configuration mencakup vektor
dimension
dan jenis indeks.dimension
adalah bilangan bulat hingga 2048. Jenis indeks harusflat
. Format konfigurasi indeks sebagai berikut:{"dimension":"DIMENSION", "flat": "{}"}
.
Contoh berikut membuat indeks komposit, termasuk indeks vektor untuk kolom vector-field
dan indeks menaik untuk kolom color
. Anda dapat menggunakan jenis indeks ini untuk melakukan pra-pemfilteran data sebelum penelusuran tetangga terdekat.
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
Mencantumkan semua indeks vektor
gcloud
gcloud alpha firestore indexes composite list --database=database-id
Ganti database-id dengan ID database.
Menghapus indeks vektor
gcloud
gcloud alpha firestore indexes composite delete index-id --database=database-id
dengan:
- index-id adalah ID indeks yang akan dihapus.
Gunakan
indexes composite list
untuk mengambil ID indeks. - database-id adalah ID database.
Menjelaskan indeks vektor
gcloud
gcloud alpha firestore indexes composite describe index-id --database=database-id
dengan:
- index-id adalah ID indeks yang akan dijelaskan. Gunakan atau
indexes composite list
untuk mengambil ID indeks. - database-id adalah ID database.
Membuat kueri tetangga terdekat
Anda dapat melakukan penelusuran kesamaan untuk menemukan tetangga terdekat dari embedding vektor. Penelusuran kesamaan memerlukan indeks vektor. Jika indeks tidak ada, Cloud Firestore akan menyarankan indeks yang akan dibuat menggunakan 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();
Jarak vektor
Kueri tetangga terdekat mendukung opsi berikut untuk jarak vektor:
EUCLIDEAN
: Mengukur jarak EUCLIDEAN antarvektor. Untuk mempelajari lebih lanjut, lihat Euclidean.COSINE
: Membandingkan vektor berdasarkan sudut antarvektor yang memungkinkan Anda mengukur kesamaan yang tidak didasarkan pada besaran vektor. Sebaiknya gunakanDOT_PRODUCT
dengan vektor yang dinormalisasi unit, bukan jarak COSINE, yang secara matematis setara dengan performa yang lebih baik. Untuk mempelajari lebih lanjut, lihat Kesamaan kosinus untuk mempelajari lebih lanjut.DOT_PRODUCT
: Serupa denganCOSINE
tetapi dipengaruhi oleh besarnya vektor. Untuk mempelajari lebih lanjut, lihat Perkalian titik.
Data prafilter
Untuk melakukan prafilter data sebelum menemukan tetangga terdekat, Anda dapat menggabungkan penelusuran kesamaan dengan filter lain kecuali filter ketidaksetaraan. Filter komposit and
dan or
didukung. Untuk filter kolom, filter berikut didukung:
==
sama denganin
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();
Batasan
Saat Anda bekerja dengan embedding vektor, perhatikan batasan berikut ini:
- Dimensi embedding maksimal yang didukung adalah 2048. Untuk menyimpan indeks yang lebih besar, gunakan pengurangan dimensi.
- Jumlah maksimal dokumen untuk ditampilkan dari kueri tetangga terdekat adalah 1.000.
- Penelusuran vektor tidak mendukung pemroses snapshot real-time.
- Anda tidak dapat menggunakan filter ketidaksetaraan untuk melakukan prafilter data.
- Hanya library klien Python dan Node.js yang mendukung penelusuran vektor.
Langkah selanjutnya
- Baca praktik terbaik untuk Cloud Firestore.
- Memahami pembacaan dan penulisan dalam skala besar