Strona pokazuje, jak używać funkcji Cloud Firestore do wykonywania operacji K w najbliższym czasie wyszukiwanie wektorów sąsiada (KNN) przy użyciu następujących metod:
- 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 jednego z obsługiwanych wektorów miary odległości
Wektory dystrybucyjne sklepów
Możesz tworzyć wartości wektorowe, takie jak wektory dystrybucyjne tekstu Cloud Firestore i przechowuj je w dokumentach Cloud Firestore.
Operacja zapisu z wektorem dystrybucyjnym wektorowym
Na przykładzie poniżej pokazujemy, jak zapisać wektor dystrybucyjny w formacie Dokument Cloud Firestore:
Python
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 za każdym razem, gdy dokument jest aktualizowany lub 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ą, tworzenia indeksów wektorowych i zarządzania nimi.
Utwórz indeks wektorów
Przed utworzeniem indeksu wektorów uaktualnij Google Cloud CLI do najnowszej wersji:
gcloud components update
Aby utworzyć indeks wektorów, użyj funkcji gcloud firestore indexes composite create
:
gcloud
gcloud 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
dane przed wyszukiwaniem najbliższych sąsiadów.
gcloud
gcloud 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 firestore indexes composite list --database=database-id
Zastąp database-id identyfikatorem bazy danych.
Usuń indeks wektorów
gcloud
gcloud 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 firestore indexes composite describe index-id --database=database-id
gdzie:
- index-id to identyfikator indeksu do opisania. Użyj 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 wyszukać podobieństwo, aby znaleźć najbliższych sąsiadów wektorów dystrybucyjnych. Wyszukiwanie podobieństw wymaga indeksów wektorów. Jeśli indeks nie istnieje, Cloud Firestore proponuje indeks do utworzenia przy użyciu funkcji gcloud CLI.
W tym przykładzie znaleziono 10 najbliższych sąsiadów wektora zapytania.
Python
Node.js
import { Firestore, FieldValue, VectorQuery, VectorQuerySnapshot, } from "@google-cloud/firestore"; // Requires a single-field vector index const vectorQuery: VectorQuery = coll.findNearest({ vectorField: 'embedding_field', queryVector: [3.0, 1.0, 2.0], limit: 10, 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 mierz podobieństwo, które nie jest oparte na wielkości wektorów. Zalecamy używanie funkcjiDOT_PRODUCT
z wektorami znormalizowanymi jednostkami zamiast Odległość COSINE, która jest matematycznym odpowiednikiem z lepszym skuteczność reklam. Aby dowiedzieć się więcej, zobacz Podobieństwo cosinusowe, które ma być potrzebne i innych.DOT_PRODUCT
: podobny doCOSINE
, ale podlega wektory dystrybucyjne. Więcej informacji: Iloczyn skalarny.
Wybierz pomiar odległości
W zależności od tego, czy wszystkie wektory dystrybucyjne wektorów są znormalizowane, można wyznaczyć odległość, która będzie używana do pomiaru odległości. Znormalizowany magnituda (długość) wynosi dokładnie 1,0.
Jeśli dodatkowo wiesz, z jakim pomiarem odległości został wytrenowany model, użyj tego miary odległości do obliczenia odległości między wektorem wektory dystrybucyjne.
Znormalizowane dane
Jeśli masz zbiór danych, w którym wszystkie wektory dystrybucyjne wektorów są znormalizowane, to wszystkie trzy
miary odległości dają te same semantyczne wyniki wyszukiwania. W gruncie rzeczy, chociaż każdy
miara odległości zwraca inną wartość, ale wartości są sortowane w ten sam sposób. Kiedy
wektory dystrybucyjne są znormalizowane, przy czym DOT_PRODUCT
jest zwykle najkorzystniejszą metodą obliczeniową
skutecznie, ale w większości przypadków różnica jest nieistotna. Jeśli jednak
aplikacja jest wysoce wrażliwa na wydajność, DOT_PRODUCT
może pomóc w
i optymalizacji wydajności.
Nieznormalizowane dane
Jeśli masz zbiór danych, w którym wektory dystrybucyjne wektorów nie są znormalizowane,
użycie DOT_PRODUCT
jako odległości nie jest prawidłowe matematycznie
ponieważ iloczyn skalarny nie mierzy odległości. W zależności
na temat sposobu generowania wektorów dystrybucyjnych i preferowanego typu wyszukiwania
miara odległości COSINE
lub EUCLIDEAN
daje
które są subiektywnie lepsze niż inne pomiary odległości.
Eksperymenty COSINE
lub EUCLIDEAN
mogą
być konieczne do określenia, która z nich jest najlepsza w Twoim przypadku.
Nie ma pewności, czy dane są znormalizowane czy nieznormalizowane
Jeśli nie masz pewności, czy Twoje dane są znormalizowane, i chcesz użyć
DOT_PRODUCT
, zalecamy używanie zamiast niego COSINE
.
COSINE
jest jak DOT_PRODUCT
z wbudowaną normalizacją.
Odległość mierzona za pomocą funkcji COSINE
w zakresie od 0
do 2
. Wynik
bliski 0
wskazuje, że wektory są bardzo podobne.
Wstępnie filtruj dokumenty
Aby wstępnie przefiltrować dokumenty przed znalezieniem najbliższych sąsiadów, możesz połączyć
podobieństwo z innymi operatorami zapytań. and
i
Obsługiwane są filtry złożone or
. Więcej informacji o obsługiwanych filtrach pól znajdziesz w artykule Operatory zapytań.
Python
Node.js
// Similarity search with pre-filter // Requires composite vector index const preFilteredVectorQuery: VectorQuery = coll .where("color", "==", "red") .findNearest({ vectorField: "embedding_field", queryVector: [3.0, 1.0, 2.0], limit: 5, distanceMeasure: "EUCLIDEAN", }); const vectorQueryResults = await preFilteredVectorQuery.get();
Pobierz obliczoną odległość wektora
Obliczoną odległość wektora można pobrać, przypisując wartość
nazwa właściwości wyjściowej distance_result_field
w zapytaniu FindNearest
,
w tym przykładzie:
Python
Node.js
const vectorQuery: VectorQuery = coll.findNearest( { vectorField: 'embedding_field', queryVector: [3.0, 1.0, 2.0], limit: 10, distanceMeasure: 'EUCLIDEAN', distanceResultField: 'vector_distance' }); const snapshot: VectorQuerySnapshot = await vectorQuery.get(); snapshot.forEach((doc) => { console.log(doc.id, ' Distance: ', doc.get('vector_distance')); });
Jeśli chcesz użyć maski pola do zwrócenia podzbioru pól dokumentu razem z funkcją distanceResultField
, musisz też umieścić w masce pola wartość distanceResultField
, jak pokazano w tym przykładzie:
Python
Node.js
const vectorQuery: VectorQuery = coll .select('color', 'vector_distance') .findNearest({ vectorField: 'embedding_field', queryVector: [3.0, 1.0, 2.0], limit: 10, distanceMeasure: 'EUCLIDEAN', distanceResultField: 'vector_distance' });
Określ próg odległości
Możesz określić próg podobieństwa, który spowoduje zwrócenie tylko dokumentów z i konkretnego progu. Działanie pola progu zależy od miary odległości wybierz:
- Odległość
EUCLIDEAN
iCOSINE
ograniczają próg do dokumentów, w których odległość jest mniejsza od określonego progu lub jej równa. Ta odległość miary maleją, gdy wektory stają się coraz bardziej podobne. - Odległość w polu
DOT_PRODUCT
ogranicza próg do dokumentów, w których odległość wynosi nie przekracza określonego progu. Odległość w formie iloczynu skalarnego rośnie, gdy wektory stają się coraz bardziej podobne.
Poniższy przykład pokazuje, jak określić próg odległości, aby otrzymać maksymalnie 10 najbliższych dokumentów, które są oddalone o maksymalnie 4,5 jednostki przy użyciu wskaźnika odległości EUCLIDEAN
:
Python
Node.js
const vectorQuery: VectorQuery = coll.findNearest({ vectorField: 'embedding_field', queryVector: [3.0, 1.0, 2.0], limit: 10, distanceMeasure: 'EUCLIDEAN', distanceThreshold: 4.5 }); const snapshot: VectorQuerySnapshot = await vectorQuery.get(); snapshot.forEach((doc) => { console.log(doc.id); });
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 funkcji redukcja 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.
- Tylko biblioteki klienta Python i Node.js obsługują wyszukiwanie wektorowe.
Co dalej?
- Zapoznaj się ze sprawdzonymi metodami dotyczącymi domeny Cloud Firestore.
- Dowiedz się więcej o czytaniu i pisaniu na dużą skalę.