جستجو با جاسازی های برداری

این صفحه به شما نشان می‌دهد که چگونه از Cloud Firestore برای انجام جستجوهای برداری K-نزدیکترین همسایه (KNN) با استفاده از تکنیک‌های زیر استفاده کنید:

  • ذخیره مقادیر برداری
  • ایجاد و مدیریت شاخص‌های برداری KNN
  • با استفاده از یکی از معیارهای فاصله برداری پشتیبانی شده، یک پرس و جوی K-نزدیکترین همسایه (KNN) ایجاد کنید.

قبل از اینکه شروع کنی

قبل از ذخیره جاسازی‌ها در Cloud Firestore ، باید جاسازی‌های برداری ایجاد کنید. Cloud Firestore جاسازی‌ها را تولید نمی‌کند. می‌توانید از خدماتی مانند Vertex AI برای ایجاد مقادیر برداری، به عنوان مثال، جاسازی‌های متنی از داده‌های Cloud Firestore خود استفاده کنید. سپس می‌توانید این جاسازی‌ها را دوباره در اسناد Cloud Firestore ذخیره کنید.

برای کسب اطلاعات بیشتر در مورد جاسازی‌ها، به بخش جاسازی‌ها چیست؟ مراجعه کنید.

برای یادگیری نحوه دریافت جاسازی متن با Vertex AI ، به دریافت جاسازی متن مراجعه کنید.

جاسازی‌های برداری فروشگاه

مثال‌های زیر نحوه ذخیره جاسازی‌های برداری در Cloud Firestore را نشان می‌دهند.

عملیات نوشتن با جاسازی برداری

مثال زیر نحوه ذخیره سازی یک بردار جاسازی شده در یک سند Cloud Firestore را نشان می‌دهد:

پایتون
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([0.18332680, 0.24160706, 0.3416704]),
}

collection.add(doc)
نود جی اس
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])
});
برو
import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/firestore"
)

type CoffeeBean struct {
	Name           string             `firestore:"name,omitempty"`
	Description    string             `firestore:"description,omitempty"`
	EmbeddingField firestore.Vector32 `firestore:"embedding_field,omitempty"`
	Color          string             `firestore:"color,omitempty"`
}

func storeVectors(w io.Writer, projectID string) error {
	ctx := context.Background()

	// Create client
	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	// Vector can be represented by Vector32 or Vector64
	doc := CoffeeBean{
		Name:           "Kahawa coffee beans",
		Description:    "Information about the Kahawa coffee beans.",
		EmbeddingField: []float32{1.0, 2.0, 3.0},
		Color:          "red",
	}
	ref := client.Collection("coffee-beans").NewDoc()
	if _, err = ref.Set(ctx, doc); err != nil {
		fmt.Fprintf(w, "failed to upsert: %v", err)
		return err
	}

	return nil
}
جاوا
import com.google.cloud.firestore.CollectionReference;
import com.google.cloud.firestore.DocumentReference;
import com.google.cloud.firestore.FieldValue;
import com.google.cloud.firestore.VectorQuery;

CollectionReference coll = firestore.collection("coffee-beans");

Map<String, Object> docData = new HashMap<>();
docData.put("name", "Kahawa coffee beans");
docData.put("description", "Information about the Kahawa coffee beans.");
docData.put("embedding_field", FieldValue.vector(new double[] {1.0, 2.0, 3.0}));

ApiFuture<DocumentReference> future = coll.add(docData);
DocumentReference documentReference = future.get();

محاسبه‌ی جایگذاری‌های برداری با استفاده از تابع ابری

برای محاسبه و ذخیره جاسازی‌های برداری هر زمان که یک سند به‌روزرسانی یا ایجاد می‌شود، می‌توانید یک تابع ابری (Cloud Function) راه‌اندازی کنید:

پایتون
@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)
نود جی اس
/**
 * 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,
  });
}
برو
  // Not yet supported in the Go client library
جاوا
  // Not yet supported in the Java client library

ایجاد و مدیریت شاخص‌های برداری

قبل از اینکه بتوانید جستجوی نزدیکترین همسایه را با تعبیه‌های برداری خود انجام دهید، باید یک فهرست مربوطه ایجاد کنید. مثال‌های زیر نحوه ایجاد و مدیریت فهرست‌های برداری را با Google Cloud CLI نشان می‌دهند. فهرست‌های برداری را می‌توان با Firebase CLI و Terraform نیز مدیریت کرد .

ایجاد یک اندیس برداری

قبل از ایجاد یک شاخص برداری، به آخرین نسخه Google Cloud CLI ارتقا دهید:

gcloud components update

برای ایجاد یک شاخص برداری، از gcloud firestore indexes composite create استفاده کنید:

جی‌کلاود
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

کجا:

  • collection-group شناسه گروه مجموعه است.
  • vector-field نام میدانی است که شامل جاسازی برداری است.
  • database-id شناسه پایگاه داده است.
  • vector-configuration شامل dimension بردار و نوع شاخص است. dimension یک عدد صحیح تا ۲۰۴۸ است. نوع شاخص باید flat باشد. پیکربندی شاخص را به صورت زیر قالب‌بندی کنید: {"dimension":" DIMENSION ", "flat": "{}"} .

مثال زیر یک شاخص ترکیبی ایجاد می‌کند، که شامل یک شاخص برداری برای فیلد vector-field و یک شاخص صعودی برای color فیلد است. می‌توانید از این نوع شاخص برای پیش‌فیلتر کردن داده‌ها قبل از جستجوی نزدیکترین همسایه استفاده کنید.

جی‌کلاود
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

فهرست کردن تمام اندیس‌های برداری

جی‌کلاود
gcloud firestore indexes composite list --database=database-id

به جای database-id شناسه پایگاه داده را وارد کنید.

حذف یک اندیس برداری

جی‌کلاود
gcloud firestore indexes composite delete index-id --database=database-id

کجا:

  • index-id شناسه‌ی اندیسی است که باید حذف شود. indexes composite list برای بازیابی شناسه‌ی اندیس استفاده کنید.
  • database-id شناسه پایگاه داده است.

یک شاخص برداری را شرح دهید

جی‌کلاود
gcloud firestore indexes composite describe index-id --database=database-id

کجا:

  • index-id شناسه شاخصی است که باید توصیف شود. برای بازیابی شناسه شاخص indexes composite list استفاده کنید.
  • database-id شناسه پایگاه داده است.

ایجاد پرس و جوی نزدیکترین همسایه

شما می‌توانید یک جستجوی شباهت برای یافتن نزدیکترین همسایه‌های یک جاسازی برداری انجام دهید. جستجوهای شباهت نیاز به شاخص‌های برداری دارند. اگر شاخصی وجود نداشته باشد، Cloud Firestore یک شاخص برای ایجاد با استفاده از gcloud CLI پیشنهاد می‌دهد.

مثال زیر 10 همسایه نزدیک به بردار جستجو را پیدا می‌کند.

پایتون
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([0.3416704, 0.18332680, 0.24160706]),
    distance_measure=DistanceMeasure.EUCLIDEAN,
    limit=5,
)
نود جی اس
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();
برو
import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/firestore"
)

func vectorSearchBasic(w io.Writer, projectID string) error {
	ctx := context.Background()

	// Create client
	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	collection := client.Collection("coffee-beans")

	// Requires a vector index
	// https://firebase.google.com/docs/firestore/vector-search#create_and_manage_vector_indexes
	vectorQuery := collection.FindNearest("embedding_field",
		[]float32{3.0, 1.0, 2.0},
		5,
		// More info: https://firebase.google.com/docs/firestore/vector-search#vector_distances
		firestore.DistanceMeasureEuclidean,
		nil)

	docs, err := vectorQuery.Documents(ctx).GetAll()
	if err != nil {
		fmt.Fprintf(w, "failed to get vector query results: %v", err)
		return err
	}

	for _, doc := range docs {
		fmt.Fprintln(w, doc.Data()["name"])
	}
	return nil
}
جاوا
import com.google.cloud.firestore.VectorQuery;
import com.google.cloud.firestore.VectorQuerySnapshot;

VectorQuery vectorQuery = coll.findNearest(
        "embedding_field",
        new double[] {3.0, 1.0, 2.0},
        /* limit */ 10,
        VectorQuery.DistanceMeasure.EUCLIDEAN);

ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();

فواصل برداری

پرس‌وجوهای نزدیکترین همسایه از گزینه‌های زیر برای فاصله برداری پشتیبانی می‌کنند:

  • EUCLIDEAN : فاصله اقلیدسی بین بردارها را اندازه‌گیری می‌کند. برای کسب اطلاعات بیشتر، به اقلیدسی مراجعه کنید.
  • COSINE : بردارها را بر اساس زاویه بین آنها مقایسه می‌کند که به شما امکان می‌دهد شباهتی را که بر اساس بزرگی بردارها نیست، اندازه‌گیری کنید. توصیه می‌کنیم به جای فاصله COSINE از DOT_PRODUCT با بردارهای نرمال شده واحد استفاده کنید، که از نظر ریاضی معادل با عملکرد بهتر است. برای کسب اطلاعات بیشتر، به شباهت کسینوسی مراجعه کنید.
  • DOT_PRODUCT : مشابه COSINE است اما تحت تأثیر بزرگی بردارها قرار می‌گیرد. برای کسب اطلاعات بیشتر، به ضرب نقطه‌ای مراجعه کنید.

انتخاب معیار فاصله

بسته به اینکه آیا همهٔ جاسازی‌های برداری شما نرمال‌سازی شده‌اند یا خیر، می‌توانید تعیین کنید که از کدام معیار فاصله برای یافتن معیار فاصله استفاده کنید. یک جاسازی برداری نرمال‌سازی شده دارای بزرگی (طول) دقیقاً ۱.۰ است.

علاوه بر این، اگر می‌دانید مدل شما با کدام معیار فاصله آموزش دیده است، از آن معیار فاصله برای محاسبه فاصله بین جاسازی‌های برداری خود استفاده کنید.

داده‌های نرمال‌شده

اگر مجموعه داده‌ای دارید که در آن تمام جاسازی‌های برداری نرمال‌سازی شده‌اند، هر سه معیار فاصله نتایج جستجوی معنایی یکسانی را ارائه می‌دهند. در اصل، اگرچه هر معیار فاصله مقدار متفاوتی را برمی‌گرداند، اما آن مقادیر به یک روش مرتب‌سازی می‌شوند. وقتی جاسازی‌ها نرمال‌سازی می‌شوند، DOT_PRODUCT معمولاً از نظر محاسباتی کارآمدترین است، اما در بیشتر موارد تفاوت ناچیز است. با این حال، اگر برنامه شما به عملکرد بسیار حساس است، DOT_PRODUCT ممکن است به تنظیم عملکرد کمک کند.

داده‌های غیر نرمال‌شده

اگر مجموعه داده‌ای دارید که در آن جاسازی‌های برداری نرمال‌سازی نشده‌اند، از نظر ریاضی استفاده DOT_PRODUCT به عنوان معیار فاصله صحیح نیست زیرا ضرب نقطه‌ای فاصله را اندازه‌گیری نمی‌کند. بسته به نحوه ایجاد جاسازی‌ها و نوع جستجوی ترجیحی، معیار فاصله COSINE یا EUCLIDEAN نتایج جستجویی را تولید می‌کند که از نظر ذهنی بهتر از سایر معیارهای فاصله هستند. آزمایش با COSINE یا EUCLIDEAN ممکن است برای تعیین اینکه کدام یک برای مورد استفاده شما بهتر است، ضروری باشد.

مطمئن نیستم که داده‌ها نرمال شده‌اند یا نرمال نشده‌اند

اگر مطمئن نیستید که داده‌های شما نرمال‌سازی شده‌اند یا خیر و می‌خواهید از DOT_PRODUCT استفاده کنید، توصیه می‌کنیم به جای آن COSINE استفاده کنید. COSINE مانند DOT_PRODUCT است که نرمال‌سازی در آن تعبیه شده است. فاصله اندازه‌گیری شده با استفاده از COSINE از 0 تا 2 متغیر است. نتیجه‌ای که نزدیک به 0 باشد نشان می‌دهد که بردارها بسیار شبیه به هم هستند.

پیش فیلتر کردن اسناد

برای پیش‌فیلتر کردن اسناد قبل از یافتن نزدیکترین همسایه‌ها، می‌توانید جستجوی تشابه را با سایر عملگرهای پرس‌وجو ترکیب کنید. فیلترهای مرکب and و or پشتیبانی می‌شوند. برای اطلاعات بیشتر در مورد فیلترهای فیلد پشتیبانی‌شده، به عملگرهای پرس‌وجو مراجعه کنید.

پایتون
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([0.3416704, 0.18332680, 0.24160706]),
    distance_measure=DistanceMeasure.EUCLIDEAN,
    limit=5,
)
نود جی اس
// 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();
برو
import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/firestore"
)

func vectorSearchPrefilter(w io.Writer, projectID string) error {
	ctx := context.Background()

	// Create client
	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	collection := client.Collection("coffee-beans")

	// Similarity search with pre-filter
	// Requires a composite vector index
	vectorQuery := collection.Where("color", "==", "red").
		FindNearest("embedding_field",
			[]float32{3.0, 1.0, 2.0},
			5,
			// More info: https://firebase.google.com/docs/firestore/vector-search#vector_distances
			firestore.DistanceMeasureEuclidean,
			nil)

	docs, err := vectorQuery.Documents(ctx).GetAll()
	if err != nil {
		fmt.Fprintf(w, "failed to get vector query results: %v", err)
		return err
	}

	for _, doc := range docs {
		fmt.Fprintln(w, doc.Data()["name"])
	}
	return nil
}
جاوا
import com.google.cloud.firestore.VectorQuery;
import com.google.cloud.firestore.VectorQuerySnapshot;

VectorQuery preFilteredVectorQuery = coll
        .whereEqualTo("color", "red")
        .findNearest(
                "embedding_field",
                new double[] {3.0, 1.0, 2.0},
                /* limit */ 10,
                VectorQuery.DistanceMeasure.EUCLIDEAN);

ApiFuture<VectorQuerySnapshot> future = preFilteredVectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();

فاصله برداری محاسبه شده را بازیابی کنید

شما می‌توانید فاصله برداری محاسبه شده را با اختصاص نام ویژگی خروجی distance_result_field در کوئری FindNearest بازیابی کنید، همانطور که در مثال زیر نشان داده شده است:

پایتون
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([0.3416704, 0.18332680, 0.24160706]),
    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')}")
نود جی اس
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'));
});
برو
import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/firestore"
)

func vectorSearchDistanceResultField(w io.Writer, projectID string) error {
	ctx := context.Background()

	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	collection := client.Collection("coffee-beans")

	// Requires a vector index
	// https://firebase.google.com/docs/firestore/vector-search#create_and_manage_vector_indexes
	vectorQuery := collection.FindNearest("embedding_field",
		[]float32{3.0, 1.0, 2.0},
		10,
		firestore.DistanceMeasureEuclidean,
		&firestore.FindNearestOptions{
			DistanceResultField: "vector_distance",
		})

	docs, err := vectorQuery.Documents(ctx).GetAll()
	if err != nil {
		fmt.Fprintf(w, "failed to get vector query results: %v", err)
		return err
	}

	for _, doc := range docs {
		fmt.Fprintf(w, "%v, Distance: %v\n", doc.Data()["name"], doc.Data()["vector_distance"])
	}
	return nil
}
جاوا
import com.google.cloud.firestore.VectorQuery;
import com.google.cloud.firestore.VectorQueryOptions;
import com.google.cloud.firestore.VectorQuerySnapshot;

VectorQuery vectorQuery = coll.findNearest(
        "embedding_field",
        new double[] {3.0, 1.0, 2.0},
        /* limit */ 10,
        VectorQuery.DistanceMeasure.EUCLIDEAN,
        VectorQueryOptions.newBuilder().setDistanceResultField("vector_distance").build());

ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();

for (DocumentSnapshot document : vectorQuerySnapshot.getDocuments()) {
    System.out.println(document.getId() + " Distance: " + document.get("vector_distance"));
}

اگر می‌خواهید از یک ماسک فیلد برای برگرداندن زیرمجموعه‌ای از فیلدهای سند به همراه یک distanceResultField استفاده کنید، باید مقدار distanceResultField را نیز در ماسک فیلد قرار دهید، همانطور که در مثال زیر نشان داده شده است:

پایتون
vector_query = collection.select(["color", "vector_distance"]).find_nearest(
    vector_field="embedding_field",
    query_vector=Vector([0.3416704, 0.18332680, 0.24160706]),
    distance_measure=DistanceMeasure.EUCLIDEAN,
    limit=10,
    distance_result_field="vector_distance",
)
نود جی اس
const vectorQuery: VectorQuery = coll
    .select('name', 'description', 'vector_distance')
    .findNearest({
      vectorField: 'embedding_field',
      queryVector: [3.0, 1.0, 2.0],
      limit: 10,
      distanceMeasure: 'EUCLIDEAN',
      distanceResultField: 'vector_distance'
    });
برو
import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/firestore"
)

func vectorSearchDistanceResultFieldMasked(w io.Writer, projectID string) error {
	ctx := context.Background()

	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	collection := client.Collection("coffee-beans")

	// Requires a vector index
	// https://firebase.google.com/docs/firestore/vector-search#create_and_manage_vector_indexes
	vectorQuery := collection.Select("color", "vector_distance").
		FindNearest("embedding_field",
			[]float32{3.0, 1.0, 2.0},
			10,
			firestore.DistanceMeasureEuclidean,
			&firestore.FindNearestOptions{
				DistanceResultField: "vector_distance",
			})

	docs, err := vectorQuery.Documents(ctx).GetAll()
	if err != nil {
		fmt.Fprintf(w, "failed to get vector query results: %v", err)
		return err
	}

	for _, doc := range docs {
		fmt.Fprintf(w, "%v, Distance: %v\n", doc.Data()["color"], doc.Data()["vector_distance"])
	}
	return nil
}
جاوا
import com.google.cloud.firestore.VectorQuery;
import com.google.cloud.firestore.VectorQueryOptions;
import com.google.cloud.firestore.VectorQuerySnapshot;

VectorQuery vectorQuery = coll
        .select("name", "description", "vector_distance")
        .findNearest(
          "embedding_field",
          new double[] {3.0, 1.0, 2.0},
          /* limit */ 10,
          VectorQuery.DistanceMeasure.EUCLIDEAN,
          VectorQueryOptions.newBuilder()
            .setDistanceResultField("vector_distance")
            .build());

ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();

for (DocumentSnapshot document : vectorQuerySnapshot.getDocuments()) {
    System.out.println(document.getId() + " Distance: " + document.get("vector_distance"));
}

تعیین آستانه فاصله

شما می‌توانید یک آستانه‌ی شباهت تعیین کنید که فقط اسناد درون آن آستانه را برگرداند. رفتار فیلد آستانه به معیار فاصله‌ای که انتخاب می‌کنید بستگی دارد:

  • فواصل EUCLIDEAN و COSINE ، آستانه را به اسنادی محدود می‌کنند که فاصله آنها کمتر یا مساوی آستانه مشخص شده است. این معیارهای فاصله با نزدیک‌تر شدن بردارها به هم، کاهش می‌یابند.
  • فاصله‌ی DOT_PRODUCT آستانه را به اسنادی محدود می‌کند که فاصله‌ی آن‌ها بزرگتر یا مساوی آستانه‌ی مشخص شده باشد. فواصل ضرب نقطه‌ای با افزایش شباهت بردارها افزایش می‌یابد.

مثال زیر نحوه تعیین آستانه فاصله برای بازگرداندن حداکثر 10 سند نزدیک که حداکثر 4.5 واحد با استفاده از معیار فاصله EUCLIDEAN فاصله دارند را نشان می‌دهد:

پایتون
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([0.3416704, 0.18332680, 0.24160706]),
    distance_measure=DistanceMeasure.EUCLIDEAN,
    limit=10,
    distance_threshold=4.5,
)

docs = vector_query.stream()

for doc in docs:
    print(f"{doc.id}")
نود جی اس
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);
});
برو
import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/firestore"
)

func vectorSearchDistanceThreshold(w io.Writer, projectID string) error {
	ctx := context.Background()

	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	collection := client.Collection("coffee-beans")

	// Requires a vector index
	// https://firebase.google.com/docs/firestore/vector-search#create_and_manage_vector_indexes
	vectorQuery := collection.FindNearest("embedding_field",
		[]float32{3.0, 1.0, 2.0},
		10,
		firestore.DistanceMeasureEuclidean,
		&firestore.FindNearestOptions{
			DistanceThreshold: firestore.Ptr[float64](4.5),
		})

	docs, err := vectorQuery.Documents(ctx).GetAll()
	if err != nil {
		fmt.Fprintf(w, "failed to get vector query results: %v", err)
		return err
	}

	for _, doc := range docs {
		fmt.Fprintln(w, doc.Data()["name"])
	}
	return nil
}
جاوا
import com.google.cloud.firestore.VectorQuery;
import com.google.cloud.firestore.VectorQueryOptions;
import com.google.cloud.firestore.VectorQuerySnapshot;

VectorQuery vectorQuery = coll.findNearest(
        "embedding_field",
        new double[] {3.0, 1.0, 2.0},
        /* limit */ 10,
        VectorQuery.DistanceMeasure.EUCLIDEAN,
        VectorQueryOptions.newBuilder()
          .setDistanceThreshold(4.5)
          .build());

ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();

for (DocumentSnapshot document : vectorQuerySnapshot.getDocuments()) {
    System.out.println(document.getId());
}

محدودیت‌ها

هنگام کار با جاسازی‌های برداری، به محدودیت‌های زیر توجه کنید:

  • حداکثر بُعد جاسازی پشتیبانی‌شده ۲۰۴۸ است. برای ذخیره شاخص‌های بزرگ‌تر، از کاهش ابعاد استفاده کنید.
  • حداکثر تعداد اسنادی که از یک پرس‌وجوی نزدیکترین همسایه می‌توان برگرداند، ۱۰۰۰ است.
  • جستجوی برداری از شنودگرهای تصویر لحظه‌ای (snapshot listeners) پشتیبانی نمی‌کند.
  • فقط کتابخانه‌های کلاینت پایتون، Node.js، Go و جاوا از جستجوی برداری پشتیبانی می‌کنند.

قدم بعدی چیست؟