Mit Vektoreinbettungen suchen

Auf dieser Seite erfahren Sie, wie Sie Firestore verwenden, um KNN-Vektoren (K-Nearest Nachbarn) mit diesen Techniken zu suchen:

  • Vektorwerte speichern
  • KNN-Vektorindexe erstellen und verwalten
  • Erstellen Sie eine KNN-Abfrage (K-Nearest-Nachbar) mit einer der unterstützten Vektordistanzfunktionen.

Vektoreinbettungen speichern

Sie können Vektorwerte wie Texteinbettungen aus Ihren Firestore-Daten erstellen und in Firestore-Dokumenten speichern.

Schreibvorgang mit einer Vektoreinbettung

Das folgende Beispiel zeigt, wie eine Vektoreinbettung in einem Firestore-Dokument gespeichert wird:

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])
});
    

Vektoreinbettungen mit einer Cloud Function berechnen

Sie können eine Cloud Functions-Funktion einrichten, um Vektoreinbettungen bei jeder Aktualisierung oder Erstellung eines Dokuments zu berechnen und zu speichern:

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,
  });
}
    

Vektorindexe erstellen und verwalten

Bevor Sie mit Ihren Vektoreinbettungen eine Suche nach den nächsten Nachbarn durchführen können, müssen Sie einen entsprechenden Index erstellen. Die folgenden Beispiele veranschaulichen, wie Vektorindexe erstellt und verwaltet werden.

Einzelfeldvektorindex erstellen

Verwenden Sie gcloud alpha firestore indexes composite create, um einen Einzelfeldvektorindex zu erstellen:

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
    

Dabei gilt:

  • collection-group ist die ID der Sammlungsgruppe.
  • vector-field ist der Name des Felds, das die Vektoreinbettung enthält.
  • database-id ist die ID der Datenbank.
  • vector-configuration enthält den Vektor-dimension und den Indextyp. dimension ist eine Ganzzahl bis 2.048. Der Indextyp muss flat sein. Formatieren Sie die Indexkonfiguration so: {"dimension":"DIMENSION", "flat": "{}"}.

Zusammengesetzten Vektorindex erstellen

Im folgenden Beispiel werden ein zusammengesetzter Vektorindex für das Feld color und ein Feld für die Vektoreinbettung erstellt.

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
    

Alle Vektorindexe auflisten

gcloud
gcloud alpha firestore indexes composite list --database=database-id

Ersetzen Sie database-id durch die ID der Datenbank.

Vektorindex löschen

gcloud
gcloud alpha firestore indexes composite delete index-id --database=database-id
    

Dabei gilt:

  • index-id ist die ID des zu löschenden Index. Verwenden Sie indexes composite list, um die Index-ID abzurufen.
  • database-id ist die ID der Datenbank.

Vektorindex beschreiben

gcloud
gcloud alpha firestore indexes composite describe index-id --database=database-id
    

Dabei gilt:

  • index-id ist die ID des zu beschreibenden Index. Verwenden Sie oder indexes composite list, um die Index-ID abzurufen.
  • database-id ist die ID der Datenbank.

Abfrage für den nächsten Nachbarn stellen

Sie können eine Ähnlichkeitssuche durchführen, um die nächsten Nachbarn einer Vektoreinbettung zu ermitteln. Für Ähnlichkeitssuchen sind Vektorindexe erforderlich. Wenn kein Index vorhanden ist, schlägt Firestore einen Index vor, der mit der gcloud CLI erstellt werden kann.

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();
    

Vektorentfernungen

Abfragen für nächste Nachbarn unterstützen die folgenden Optionen für die Vektorentfernung:

  • EUCLIDEAN: Misst die EUCLIDEAN-Abstand zwischen den Vektoren. Weitere Informationen finden Sie unter Euklidisch.
  • COSINE: vergleicht Vektoren anhand des Winkels zwischen ihnen, sodass Sie eine Ähnlichkeit messen können, die nicht auf der Größe der Vektoren basiert. Wir empfehlen die Verwendung von DOT_PRODUCT mit Einheitsnormalisierungsvektoren anstelle der COSINE-Distanz, die mathematisch mit einer besseren Leistung äquivalent ist. Weitere Informationen finden Sie unter Kosinus-Ähnlichkeit.
  • DOT_PRODUCT: Ähnlich wie COSINE, wird aber von der Größe der Vektoren beeinflusst. Weitere Informationen finden Sie unter Dot-Produkt.

Daten vorfiltern

Wenn Sie Daten vor der Suche nach den nächsten Nachbarn filtern möchten, können Sie eine Ähnlichkeitssuche mit anderen Filtern außer Ungleichheitsfiltern kombinieren. Die zusammengesetzten Filter and und or werden unterstützt. Für Feldfilter werden die folgenden Filter unterstützt:

  • == gleich
  • 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();
    

Beschränkungen

Beachten Sie bei der Arbeit mit Vektoreinbettungen die folgenden Einschränkungen:

  • Die maximal unterstützte Einbettungsdimension beträgt 2.048. Verwenden Sie zum Speichern größerer Indexe die Dimensionsreduzierung.
  • Die maximale Anzahl von Dokumenten, die von einer Abfrage des nächsten Nachbarn zurückgegeben werden soll, beträgt 1.000.
  • Die Vektorsuche unterstützt keine Echtzeit-Snapshot-Listener.
  • Sie können keine Ungleichheitsfilter zum Vorfiltern von Daten verwenden.
  • Die Vektorsuche wird nur von den Python- und Node.js-Clientbibliotheken unterstützt.

Nächste Schritte