Cerca con incorporamenti vettoriali
La pagina mostra come utilizzare Firestore per eseguire ricerche vettoriali K-Neighbor (KNN) utilizzando queste tecniche:
- Archivia i valori dei vettori
- Crea e gestisci indici vettoriali KNN
- Esegui una query K-Neighbor (KNN) usando una delle funzioni di distanza vettoriale supportate
Archivia gli incorporamenti vettoriali
Puoi creare valori vettoriali come incorporamenti di testo dai tuoi dati Firestore e archiviarli nei documenti Firestore.
Operazione di scrittura con un incorporamento vettoriale
L'esempio seguente mostra come archiviare un incorporamento vettoriale in un documento 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]) });
Calcola gli incorporamenti vettoriali con una Cloud Function
Per calcolare e archiviare gli incorporamenti vettoriali ogni volta che un documento viene aggiornato o creato, puoi configurare una funzione Cloud Functions:
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, }); }
Crea e gestisci indici vettoriali
Prima di poter eseguire una ricerca per il vicino più prossimo con gli incorporamenti vettoriali, devi creare un indice corrispondente. I seguenti esempi mostrano come creare e gestire gli indici vettoriali.
Creare un indice vettoriale a campo singolo
Per creare un indice vettoriale a campo singolo, utilizza 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
dove:
- collection-group è l'ID del gruppo di raccolte.
- vector-field è il nome del campo che contiene l'incorporamento vettoriale.
- database-id è l'ID del database.
- vector-configuration include il vettore
dimension
e il tipo di indice.dimension
è un numero intero fino a 2048. Il tipo di indice deve essereflat
. Formatta la configurazione dell'indice come segue:{"dimension":"DIMENSION", "flat": "{}"}
.
Creare un indice vettoriale composto
L'esempio seguente crea un indice vettoriale composto per il campo color
e un campo di incorporamento vettoriale.
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=field,vector-config='{"dimension":"1024", "flat": "{}"}' \ --database=database-id
Elenca tutti gli indici vettoriali
gcloud
gcloud alpha firestore indexes composite list --database=database-id
Sostituisci database-id con l'ID del database.
Eliminare un indice vettoriale
gcloud
gcloud alpha firestore indexes composite delete index-id --database=database-id
dove:
- index-id è l'ID dell'indice da eliminare.
Utilizza
indexes composite list
per recuperare l'ID indice. - database-id è l'ID del database.
Descrivere un indice vettoriale
gcloud
gcloud alpha firestore indexes composite describe index-id --database=database-id
dove:
- index-id è l'ID dell'indice da descrivere. Utilizza o
indexes composite list
per recuperare l'ID indice. - database-id è l'ID del database.
Eseguire una query per il vicino più prossimo
Puoi eseguire una ricerca di somiglianza per trovare i vicini più prossimi di un incorporamento vettoriale. Le ricerche di analogie richiedono indici vettoriali. Se non esiste un indice, Firestore suggerisce un indice da creare utilizzando 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();
Distanze vettoriali
Le query per il vicino più vicino supportano le seguenti opzioni per la distanza vettoriale:
EUCLIDEAN
: misura la distanza EUCLIDEAN tra i vettori. Per scoprire di più, vedi Euclidea.COSINE
: confronta i vettori in base all'angolo tra di loro, il che consente di misurare la somiglianza che non si basa sulla grandezza dei vettori. Ti consigliamo di utilizzareDOT_PRODUCT
con vettori normalizzati dell'unità anziché la distanza COSINE, che è matematicamente equivalente con prestazioni migliori. Per saperne di più, consulta Somiglianza tra coseno.DOT_PRODUCT
: simile aCOSINE
, ma è influenzata dalla grandezza dei vettori. Per scoprire di più, vedi Prodotto Dot.
Dati prefiltro
Per prefiltrare i dati prima di trovare i vicini più prossimi, puoi combinare una ricerca di similitudine con altri filtri, ad eccezione dei filtri di disuguaglianza. Sono supportati i filtri composti and
e
or
. Per i filtri di campo, sono supportati i seguenti filtri:
==
uguale ain
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();
Limitazioni
Quando lavori con gli incorporamenti vettoriali, tieni presente le seguenti limitazioni:
- La dimensione di incorporamento massima supportata è 2048. Per archiviare indici più grandi, utilizza la riduzione della dimensionalità.
- Il numero massimo di documenti da restituire da una query al vicino più prossimo è 1000.
- La ricerca vettoriale non supporta i listener di snapshot in tempo reale.
- Non puoi utilizzare i filtri di disuguaglianze per prefiltrare i dati.
- Solo le librerie client Python e Node.js supportano la ricerca vettoriale.
Passaggi successivi
- Leggi le best practice per Firestore.
- Comprendere le letture e le scritture su larga scala