Wyszukiwanie z użyciem wektorów dystrybucyjnych wektorowych

Na stronie znajdziesz informacje o tym, jak użyć Cloud Firestore, aby wykonać najbliższe kroki 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 funkcje odległości

Wektory dystrybucyjne sklepów

Możesz tworzyć wartości wektorowe, takie jak wektory dystrybucyjne tekstu dane Cloud Firestore i przechowywanie ich 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
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 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

Aby utworzyć indeks wektorów, użyj funkcji 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 na flat. 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 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 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 zaproponuje indeks do utworzenia za pomocą 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 mierz podobieństwo, które nie jest oparte na wielkości wektorów. Zalecamy używanie funkcji DOT_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 do COSINE, ale podlega wektory dystrybucyjne. Więcej informacji: 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. and i Obsługiwane są filtry złożone or. W przypadku filtrów pól te wartości obsługiwane 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 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.
  • 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?