Vektör yerleştirilmiş öğeleri kullanarak arama

Sayfada, K-yakınına performans göstermek için Cloud Firestore hizmetinin nasıl kullanılacağı gösterilmektedir Aşağıdaki teknikleri kullanarak komşu (KNN) vektör aramaları:

  • Vektör değerlerini depola
  • KNN vektör dizinlerini oluşturma ve yönetme
  • Desteklenen vektörlerden birini kullanarak K-en yakın-komşu (KNN) sorgusu yapma mesafe ölçümleri

Vektör yerleştirmeleri depolama

Web sayfalarınızdan metin yerleştirmeler gibi vektör değerleri Cloud Firestore verilerini işleyebilir ve bunları Cloud Firestore dokümanda depolayabilirsiniz.

Vektör yerleştirmeyi içeren yazma işlemi

Aşağıdaki örnekte, bir vektör yerleştirmenin nasıl depolanacağını Cloud Firestore doküman:

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

Cloud Functions işleviyle vektör yerleştirmeleri hesaplayın

Bir doküman güncellendiğinde veya bir Cloud Functions işlevi oluşturabilirsiniz:

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

Vektör dizinleri oluşturma ve yönetme

Vektör yerleştirmelerinizi kullanarak en yakın komşu araması yapmadan önce karşılık gelen bir dizin oluşturmanız gerekir. Aşağıdaki örneklerde Vektör dizinleri oluşturmayı ve yönetmeyi öğreneceğiz.

Vektör dizini oluşturma

Bir vektör dizini oluşturmadan önce Google Cloud CLI öğesinin en son sürümüne yükseltme yapın:

gcloud components update

Bir vektör dizini oluşturmak için gcloud firestore indexes composite create işlevini kullanın:

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

Bu örnekte:

  • collection-group, koleksiyon grubunun kimliğidir.
  • vector-field, vektör yerleştirmeyi içeren alanın adıdır.
  • database-id, veritabanının kimliğidir.
  • vector-configuration, dimension vektörünü ve dizin türünü içeriyor. dimension, 2048'e kadar olan bir tam sayıdır. Dizin türü flat olmalıdır. Dizin yapılandırmasını şu şekilde biçimlendirin: {"dimension":"DIMENSION", "flat": "{}"}.

Aşağıdaki örnek, vector-field alanı için bir vektör dizini içeren bileşik bir dizin oluşturur ve color alanı için artan bir dizin. Bu dizin türünü, önceden filtre uygulamak için kullanabilirsiniz verilerini görebilirsiniz.

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

Tüm vektör dizinlerini listeleme

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

database-id değerini veritabanının kimliğiyle değiştirin.

Vektör dizinini silme

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

Bu örnekte:

  • index-id, silinecek dizinin kimliğidir. Dizin kimliğini almak için indexes composite list işlevini kullanın.
  • database-id, veritabanının kimliğidir.

Vektör endeksini açıklama

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

Bu örnekte:

  • index-id, açıklanacak dizin kimliğidir. veya Dizin kimliğini almak için indexes composite list.
  • database-id, veritabanının kimliğidir.

En yakın komşu sorgusu oluşturma

Bir yerin en yakın komşularını bulmak için benzerlik araması yapabilirsiniz. vektör yerleştirme. Benzerlik aramaları için vektör dizinleri gerekir. Bir dizin yoksa Cloud Firestore, oluşturulması gereken bir dizin önerir gcloud CLI kullanarak.

Aşağıdaki örnekte, sorgu vektörünün en yakın 10 komşusu bulunmuştur.

Python
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure
from google.cloud.firestore_v1.vector import Vector

collection = db.collection("coffee-beans")

# Requires a single-field vector index
vector_query = 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 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();

Vektör mesafeleri

En yakın komşu sorgular, vektör mesafesi için aşağıdaki seçenekleri destekler:

  • EUCLIDEAN: Vektörler arasındaki EUCLIDEAN mesafesini ölçer. Daha fazla bilgi edinmek için bkz. Öklid.
  • COSINE: Vektörleri aralarındaki açıya göre karşılaştırır. Bu sayede, Vektörlerin büyüklüğüne dayalı olmayan benzerliği ölçmek yerine, birim normalleştirilmiş vektörlerle DOT_PRODUCT kullanmanızı öneririz Daha iyi ile matematiksel olarak eşdeğer olan COSINE mesafesi bazı yolları da görmüştük. Daha fazla bilgi edinmek için bkz. Öğrenmek için kosinüs benzerliği daha fazla.
  • DOT_PRODUCT: COSINE ile benzerdir ancak vektörleri alır. Daha fazla bilgi edinmek için bkz. Nokta çarpım.

Mesafe ölçüsünü seçin

Tüm vektör yerleştirmelerinizin normalleştirilip normalleştirilmediğine bağlı olarak, mesafe ölçüsünü bulmak için kullanılacak mesafe ölçüsünü belirler. Normalleştirilmiş vektör yerleştirmenin büyüklüğü (uzunluk) tam olarak 1,0'dır.

Ayrıca, modelinizin hangi mesafe ölçümüyle eğitildiğini biliyorsanız vektörünüz arasındaki mesafeyi hesaplamak için bu mesafe ölçüsünü kullanın yerleştirme.

Normalleştirilmiş veriler

Tüm vektör yerleştirmelerin normalleştirildiği bir veri kümeniz varsa, mesafe ölçümleri aynı anlamsal arama sonuçlarını sağlar. Aslında her bir sorun mesafe ölçümü farklı bir değer döndürdüğünde, bu değerler de aynı şekilde sıralanır. Zaman yerleştirilmiş öğeler normalleştirilir; DOT_PRODUCT genellikle en sayısal veri türüdür verimli olsa da aradaki fark çoğu durumda göz ardı edilebilir düzeydedir. Ancak, Uygulama son derece hassas performansa sahip. DOT_PRODUCT size yardımcı olabilir en iyi uygulamaları paylaşacağız.

Normalleştirilmemiş veriler

Vektör yerleştirmelerinin normalleştirilmediği bir veri kümeniz varsa bir uzaklık olarak DOT_PRODUCT kullanmak matematiksel açıdan doğru değildir ölçülemez. Şuna bağlı olarak: yerleştirmelerin nasıl oluşturulduğu ve ne tür bir aramanın tercih edildiği, COSINE veya EUCLIDEAN mesafe ölçüsü şu sonucu verir: diğer mesafe ölçülerinden öznel olarak daha iyi arama sonuçları elde eder. COSINE veya EUCLIDEAN ile yapılan denemeler neyin en iyi olduğunu belirlemek için gereklidir.

Verilerin normalleştirilip normalleştirilmediğinden emin değilim

Verilerinizin normalleştirilip normalleştirilmediğinden emin değilseniz ve DOT_PRODUCT bunun yerine COSINE kullanmanızı öneririz. COSINE, yerleşik normalleştirmeyle DOT_PRODUCT gibidir. COSINE kullanılarak ölçülen mesafe 0 ile 2 arasında değişir. Sonuç 0 değerine yakın olması, vektörlerin çok benzer olduğunu gösterir.

Dokümanları önceden filtrele

En yakın komşuları bulmadan önce dokümanları önceden filtrelemek için sorgu operatörleriyle benzerlik araması yapabilirsiniz. and ve or bileşik filtre destekleniyor. Desteklenen alan filtreleri hakkında daha fazla bilgi edinmek için Sorgu operatörleri bölümüne bakın.

Python
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure
from google.cloud.firestore_v1.vector import Vector

collection = db.collection("coffee-beans")

# Similarity search with pre-filter
# Requires a composite vector index
vector_query = 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({
      vectorField: "embedding_field",
      queryVector: [3.0, 1.0, 2.0],
      limit: 5,
      distanceMeasure: "EUCLIDEAN",
    });

const vectorQueryResults = await preFilteredVectorQuery.get();

Hesaplanan vektör mesafesini alma

Hesaplanan vektör mesafesini, FindNearest sorgusunda, distance_result_field çıkış özelliği adı aşağıdaki örnekte gösterilmektedir:

Python
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure
from google.cloud.firestore_v1.vector import Vector

collection = db.collection("coffee-beans")

vector_query = collection.find_nearest(
    vector_field="embedding_field",
    query_vector=Vector([3.0, 1.0, 2.0]),
    distance_measure=DistanceMeasure.EUCLIDEAN,
    limit=10,
    distance_result_field="vector_distance",
)

docs = vector_query.stream()

for doc in docs:
    print(f"{doc.id}, Distance: {doc.get('vector_distance')}")
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'));
});

distanceResultField ile birlikte doküman alanlarının bir alt kümesini döndürmek için bir alan maskesi kullanmak isterseniz aşağıdaki örnekte gösterildiği gibi alan maskesine distanceResultField değerini de eklemeniz gerekir:

Python
vector_query = collection.select(["color", "vector_distance"]).find_nearest(
    vector_field="embedding_field",
    query_vector=Vector([3.0, 1.0, 2.0]),
    distance_measure=DistanceMeasure.EUCLIDEAN,
    limit=10,
    distance_result_field="vector_distance",
)
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'
    });

Mesafe eşiği belirleyin

Yalnızca şunun içindeki dokümanları döndüren bir benzerlik eşiği belirtebilirsiniz: eşikler. Eşik alanının davranışı, mesafe ölçüsüne bağlıdır birini seçin:

  • EUCLIDEAN ve COSINE mesafeler, eşiğin yalnızca belgede toplandığı belgelerle sınırlıdır. belirtilen eşikten küçük veya eşik değerine eşit. Bu mesafe Vektörler daha benzer hale geldikçe ölçümler azalır.
  • DOT_PRODUCT mesafe, mesafenin şu olduğu belgelerle sınırlıdır: belirtilen eşikten yüksek veya eşikli eşit olmalıdır. Nokta çarpım mesafeleri Vektörler daha benzer hale geldikçe artar.

Aşağıdaki örnekte, EUCLIDEAN mesafe metriği kullanılarak en fazla 4, 5 birim uzaklıktaki en yakın 10 dokümanı döndürmek için mesafe eşiğinin nasıl belirtileceği gösterilmektedir:

Python
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure
from google.cloud.firestore_v1.vector import Vector

collection = db.collection("coffee-beans")

vector_query = collection.find_nearest(
    vector_field="embedding_field",
    query_vector=Vector([3.0, 1.0, 2.0]),
    distance_measure=DistanceMeasure.EUCLIDEAN,
    limit=10,
    distance_threshold=4.5,
)

docs = vector_query.stream()

for doc in docs:
    print(f"{doc.id}")
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);
});

Sınırlamalar

Vektör yerleştirmeleriyle çalışırken aşağıdaki sınırlamaları göz önünde bulundurun:

  • Desteklenen maksimum yerleştirme boyutu 2048'dir. Daha büyük dizinleri depolamak için boyutlandırma azaltma.
  • En yakın komşu sorgudan döndürülecek maksimum doküman sayısı 1.000'dir.
  • Vektör arama, gerçek zamanlı anlık görüntü işleyicileri desteklemez.
  • Vektör aramasını yalnızca Python ve Node.js istemci kitaplıkları destekler.

Sırada ne var?