Na tej stronie dowiesz się, jak używać Cloud Firestore do wyszukiwania wektorów KNN przy użyciu następujących technik:
- Zapisz wartości wektorów
- Tworzenie indeksów wektorów KNN i zarządzanie nimi
- Utwórz zapytanie KNN (k-najbliższy sąsiad) przy użyciu jednej z obsługiwanych funkcji odległości wektorowych
Wektory dystrybucyjne sklepów
Wartości wektorowe, takie jak wektory dystrybucyjne tekstu, możesz tworzyć z danych Cloud Firestore i przechowywać je w dokumentach Cloud Firestore.
Operacja zapisu z wektorem dystrybucyjnym wektorowym
Poniższy przykład pokazuje, jak zapisać wektorowy wektor w dokumencie 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]) });
Wektory dystrybucyjne obliczeniowe za pomocą funkcji w Cloud Functions
Aby obliczać i przechowywać wektory dystrybucyjne wektorów dystrybucyjnych za każdym razem, gdy dokument jest aktualizowany lub tworzony, możesz skonfigurować funkcję w 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, }); }
Tworzenie indeksów wektorów i zarządzanie nimi
Zanim będzie można przeprowadzić wyszukiwanie najbliższych sąsiadów z użyciem wektorów dystrybucyjnych wektorowych, musisz utworzyć odpowiedni indeks. Poniższe przykłady pokazują, jak tworzyć indeksy wektorów i nimi zarządzać.
Utwórz indeks wektorów
Aby utworzyć indeks wektorów, użyj polecenia 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
gdzie:
- collection-group to identyfikator grupy kolekcji.
- vector-field to nazwa pola zawierającego wektor dystrybucyjny.
- database-id to identyfikator bazy danych.
- vector-configuration obejmuje wektor
dimension
i typ indeksu.dimension
jest liczbą całkowitą do 2048. Typ indeksu musi być ustawiony naflat
. Sformatuj konfigurację indeksu w ten sposób:{"dimension":"DIMENSION", "flat": "{}"}
.
Poniższy przykład tworzy indeks złożony, w tym indeks wektorów dla pola vector-field
i indeks rosnący dla pola color
. Możesz użyć tego typu indeksu do wstępnego filtrowania danych przed wyszukiwaniem najbliższych sąsiadów.
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
Wyświetl wszystkie indeksy wektorów
gcloud
gcloud alpha firestore indexes composite list --database=database-id
Zastąp database-id identyfikatorem bazy danych.
Usuń indeks wektorów
gcloud
gcloud alpha firestore indexes composite delete index-id --database=database-id
gdzie:
- index-id to identyfikator indeksu do usunięcia.
Użyj narzędzia
indexes composite list
, aby pobrać identyfikator indeksu. - database-id to identyfikator bazy danych.
Opisz indeks wektorów
gcloud
gcloud alpha firestore indexes composite describe index-id --database=database-id
gdzie:
- index-id to identyfikator indeksu do opisania. Użyj kodu lub
indexes composite list
, aby pobrać identyfikator indeksu. - database-id to identyfikator bazy danych.
Utwórz zapytanie o najbliższych sąsiadów
Możesz przeprowadzić wyszukiwanie podobieństwa, aby znaleźć najbliższych sąsiadów wektora dystrybucyjnego wektorowego. Wyszukiwanie podobieństw wymaga indeksów wektorów. Jeśli indeks nie istnieje, Cloud Firestore zaproponuje indeks do utworzenia przy użyciu 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();
Odległości wektorowe
Zapytania o najbliższy sąsiad obsługują następujące opcje odległości wektora:
EUCLIDEAN
: mierzy odległość UECLIDEAN między wektorami. Więcej informacji: euklidesowa.COSINE
: porównuje wektory na podstawie kąta między nimi, co pozwala zmierzyć podobieństwo, które nie jest oparte na wielkości wektorów. Zalecamy używanie funkcjiDOT_PRODUCT
z wektorami znormalizowanymi jednostkami zamiast odległości COSINE, która jest odpowiednikiem matematycznym o większej wydajności. Więcej informacji znajdziesz w sekcji Podobieństwo cosinusowe.DOT_PRODUCT
: podobny doCOSINE
, ale zależy od wielkości wektorów. Więcej informacji znajdziesz w artykule Iloczyn skalarny.
Wstępnie filtruj dane
Aby wstępnie przefiltrować dane przed znalezieniem najbliższych sąsiadów, możesz połączyć wyszukiwanie podobieństw z innymi filtrami oprócz filtrów nierówności. Obsługiwane są filtry złożone and
i or
. W przypadku filtrów pól obsługiwane są te filtry:
==
równa się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();
Ograniczenia
Korzystając z wektorów dystrybucyjnych wektorowych, pamiętaj o następujących ograniczeniach:
- Maksymalny obsługiwany wymiar wektora dystrybucyjnego to 2048. Aby przechowywać większe indeksy, użyj redukcji wymiarów.
- Maksymalna liczba dokumentów do zwrócenia z zapytania o najbliższych sąsiadów to 1000.
- Wyszukiwanie wektorowe nie obsługuje detektorów zrzutów w czasie rzeczywistym.
- Do wstępnego filtrowania danych nie można używać filtrów nierówności.
- Tylko biblioteki klienta Python i Node.js obsługują wyszukiwanie wektorowe.
Co dalej?
- Zapoznaj się ze sprawdzonymi metodami dotyczącymi Cloud Firestore.
- Dowiedz się, jak czytać i pisać na dużą skalę.