वेक्टर एम्बेडिंग की मदद से खोजें

इस पेज पर, Cloud Firestore का इस्तेमाल करके, K-सबसे नज़दीकी पड़ोसी (केएनएन) वेक्टर खोज करने का तरीका बताया गया है. इसके लिए, इन तकनीकों का इस्तेमाल किया जाता है:

  • वेक्टर वैल्यू सेव करना
  • केएनएन वेक्टर इंडेक्स बनाना और मैनेज करना
  • इस्तेमाल किए जा सकने वाले वेक्टर दूरी के मेज़रमेंट में से किसी एक का इस्तेमाल करके, के-सबसे नज़दीकी पड़ोसी (केएनएन) क्वेरी करना

शुरू करने से पहले

Cloud Firestore में एंबेडिंग सेव करने से पहले, आपको वेक्टर एंबेडिंग जनरेट करनी होंगी. Cloud Firestore एंबेडिंग जनरेट नहीं करता. वेक्टर वैल्यू बनाने के लिए, Agent Platform जैसी किसी सेवा का इस्तेमाल किया जा सकता है. उदाहरण के लिए, टेक्स्ट एंबेडिंग आपके Cloud Firestore डेटा से. इसके बाद, इन एंबेडिंग को वापस Cloud Firestore दस्तावेज़ों में सेव किया जा सकता है.

एंबेडिंग के बारे में ज़्यादा जानने के लिए, एंबेडिंग क्या होती हैं?

Agent Platform की मदद से टेक्स्ट एंबेडिंग पाने का तरीका जानने के लिए, टेक्स्ट एंबेडिंग पाना लेख पढ़ें.

वेक्टर एंबेडिंग सेव करना

यहां दिए गए उदाहरणों में, वेक्टर एंबेडिंग सेव करने का तरीका बताया गया है Cloud Firestore.

वेक्टर एंबेडिंग के साथ लिखने की कार्रवाई

यहां दिए गए उदाहरण में, 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([0.18332680, 0.24160706, 0.3416704]),
}

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])
});
Go
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
}
Java
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 की मदद से वेक्टर एंबेडिंग कंप्यूट करना

किसी दस्तावेज़ के अपडेट या बनाए जाने पर, वेक्टर एंबेडिंग का हिसाब लगाने और उन्हें सेव करने के लिए, Cloud Function सेट अप किया जा सकता है:

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,
  });
}
Go
  // Not yet supported in the Go client library
Java
  // Not yet supported in the Java client library

वेक्टर इंडेक्स बनाना और मैनेज करना

वेक्टर एंबेडिंग की मदद से, सबसे नज़दीकी पड़ोसी की खोज करने से पहले, आपको उससे जुड़ा इंडेक्स बनाना होगा. यहां दिए गए उदाहरणों में, Google Cloud CLI और कंसोल की मदद से, वेक्टर इंडेक्स बनाने और मैनेज करने का तरीका बताया गया है. Firebase CLI और Terraform की मदद से भी, वेक्टर इंडेक्स मैनेज किए जा सकते हैं.

वेक्टर इंडेक्स बनाना

Google Cloud कंसोल

Google Cloud Console से मैन्युअल तरीके से नया इंडेक्स बनाने के लिए:

  1. Google Cloud Console में, डेटाबेस पेज पर जाएं.

    डेटाबेस पर जाएं

  2. डेटाबेस की सूची में से, ज़रूरी डेटाबेस चुनें.
  3. नेविगेशन मेन्यू में, इंडेक्स पर क्लिक करें. इसके बाद, मैन्युअल टैब पर क्लिक करें.
  4. इंडेक्स बनाएं पर क्लिक करें.

    वेक्टर खोजों के लिए, वेक्टर फ़ील्ड को इंडेक्स करने के लिए, वेक्टर इंडेक्स बनाएं को चुनें.

  5. कलेक्शन आईडी डालें. वेक्टर फ़ील्ड का पाथ और वेक्टर एंबेडिंग डाइमेंशन की संख्या डालें. इंडेक्स किए जाने वाले अन्य फ़ील्ड के नाम और हर फ़ील्ड के लिए इंडेक्स मोड जोड़ें.

    इंडेक्स सेव करें पर क्लिक करें.

आपका नया इंडेक्स, मैन्युअल इंडेक्स की सूची में दिखेगा. साथ ही, Cloud Firestore आपका इंडेक्स बनाना शुरू कर देगा. इंडेक्स बन जाने के बाद, आपको इंडेक्स के बगल में हरे रंग का सही का निशान दिखेगा.

gcloud

वेक्टर इंडेक्स बनाने से पहले, 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 एक पूर्णांक है, जो 2048 तक हो सकता है. इंडेक्स टाइप, 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

सभी वेक्टर इंडेक्स की सूची बनाना

Google Cloud कंसोल

  1. Google Cloud Console में, डेटाबेस पेज पर जाएं.

    डेटाबेस पर जाएं

  2. डेटाबेस की सूची में से, ज़रूरी डेटाबेस चुनें.
  3. नेविगेशन मेन्यू में, इंडेक्स पर क्लिक करें. इसके बाद, मैन्युअल टैब पर क्लिक करें.

    इंडेक्स की टेबल में, डेटाबेस के सभी इंडेक्स की सूची दिखती है. वेक्टर इंडेक्स में, आइकॉन वाला वेक्टर फ़ील्ड शामिल होता है.

gcloud

सभी इंडेक्स की सूची बनाने और इंडेक्स आईडी पाने के लिए:

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

database-id को डेटाबेस के आईडी से बदलें.

किसी इंडेक्स के बारे में ज़्यादा जानकारी देखने के लिए, इंडेक्स आईडी का इस्तेमाल किया जा सकता है:

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

यहां:

  • index-id, उस इंडेक्स का आईडी है जिसके बारे में जानकारी देखनी है.
  • database-id, डेटाबेस का आईडी है.

वेक्टर इंडेक्स मिटाना

Google Cloud कंसोल

  1. Google Cloud Console में, डेटाबेस पेज पर जाएं.

    डेटाबेस पर जाएं

  2. डेटाबेस की सूची में से, ज़रूरी डेटाबेस चुनें.
  3. नेविगेशन मेन्यू में, इंडेक्स पर क्लिक करें. इसके बाद, मैन्युअल टैब पर क्लिक करें.

  4. मैन्युअल इंडेक्स की सूची में, आपको जो इंडेक्स मिटाना है उसके लिए, ज़्यादा बटन पर क्लिक करें. मिटाएं पर क्लिक करें.
  5. चेतावनी में, इंडेक्स मिटाएं पर क्लिक करके, इस इंडेक्स को मिटाने की पुष्टि करें.
gcloud
gcloud firestore indexes composite delete index-id --database=database-id

यहां:

  • index-id, उस इंडेक्स का आईडी है जिसे मिटाना है. इंडेक्स आईडी पाने के लिए, indexes composite list का इस्तेमाल करें.
  • database-id, डेटाबेस का आईडी है.

सबसे नज़दीकी पड़ोसी की क्वेरी करना

वेक्टर एंबेडिंग के सबसे नज़दीकी पड़ोसी ढूंढने के लिए, समानता खोज की जा सकती है. समानता खोज के लिए, वेक्टर इंडेक्स की ज़रूरत होती है. अगर कोई इंडेक्स मौजूद नहीं है, तो Cloud Firestore इंडेक्स बनाने का सुझाव देता है gcloud CLI का इस्तेमाल करके.

यहां दिए गए उदाहरण में, क्वेरी वेक्टर के 10 सबसे नज़दीकी पड़ोसी ढूंढे गए हैं.

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([0.3416704, 0.18332680, 0.24160706]),
    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();
Go
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
}
Java
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: वेक्टर के बीच की EUCLIDEAN दूरी को मापता है. ज़्यादा जानने के लिए, यूक्लिडियन लेख पढ़ें.
  • COSINE: वेक्टर की तुलना, उनके बीच के ऐंगल के आधार पर करता है. इससे, ऐसी समानता को मापा जा सकता है जो वेक्टर के मैग्नीट्यूड पर आधारित नहीं होती. हमारा सुझाव है कि COSINE दूरी के बजाय, यूनिट नॉर्मलाइज़ किए गए वेक्टर के साथ DOT_PRODUCT का इस्तेमाल करें. यह गणित के हिसाब से एक जैसा है और इसकी परफ़ॉर्मेंस बेहतर है. ज़्यादा जानने के लिए, कोसाइन समानता लेख पढ़ें.
  • DOT_PRODUCT: COSINE के जैसा है, लेकिन यह वेक्टर के मैग्नीट्यूड से प्रभावित होता है. ज़्यादा जानने के लिए, डॉट प्रॉडक्ट लेख पढ़ें.

दूरी का मेज़रमेंट चुनना

यह तय किया जा सकता है कि दूरी का मेज़रमेंट ढूंढने के लिए, किस दूरी के मेज़रमेंट का इस्तेमाल करना है. यह इस बात पर निर्भर करता है कि आपकी सभी वेक्टर एंबेडिंग नॉर्मलाइज़ की गई हैं या नहीं. नॉर्मलाइज़ की गई वेक्टर एंबेडिंग का मैग्नीट्यूड (लंबाई) ठीक 1.0 होता है.

इसके अलावा, अगर आपको पता है कि आपके मॉडल को किस दूरी के मेज़रमेंट से ट्रेन किया गया था, तो अपनी वेक्टर एंबेडिंग के बीच की दूरी का हिसाब लगाने के लिए, उसी दूरी के मेज़रमेंट का इस्तेमाल करें.

नॉर्मलाइज़ किया गया डेटा

अगर आपके पास ऐसा डेटासेट है जिसमें सभी वेक्टर एंबेडिंग नॉर्मलाइज़ की गई हैं, तो दूरी के तीनों मेज़रमेंट, सेमैंटिक खोज के एक जैसे नतीजे देते हैं. असल में, दूरी का हर मेज़रमेंट अलग-अलग वैल्यू दिखाता है, लेकिन उन वैल्यू को एक ही तरीके से क्रम में लगाया जाता है. एंबेडिंग के नॉर्मलाइज़ होने पर, आम तौर पर DOT_PRODUCT सबसे ज़्यादा कंप्यूटेशन के हिसाब से कारगर होता है. हालांकि, ज़्यादातर मामलों में यह अंतर न के बराबर होता है. हालांकि, अगर आपका ऐप्लिकेशन परफ़ॉर्मेंस के हिसाब से बहुत संवेदनशील है, तो DOT_PRODUCT परफ़ॉर्मेंस को बेहतर बनाने में मदद कर सकता है.

नॉन-नॉर्मलाइज़ किया गया डेटा

अगर आपके पास ऐसा डेटासेट है जिसमें वेक्टर एंबेडिंग नॉर्मलाइज़ नहीं की गई हैं, तो दूरी के मेज़रमेंट के तौर पर DOT_PRODUCT का इस्तेमाल करना गणित के हिसाब से सही नहीं है, क्योंकि डॉट प्रॉडक्ट, दूरी को नहीं मापता. एंबेडिंग कैसे जनरेट की गई थीं और किस तरह की खोज को प्राथमिकता दी जाती है, इस आधार पर COSINE या EUCLIDEAN दूरी का मेज़रमेंट, खोज के ऐसे नतीजे देता है जो अन्य दूरी के मेज़रमेंट की तुलना में बेहतर होते हैं. यह तय करने के लिए कि आपके इस्तेमाल के उदाहरण के लिए कौनसा बेहतर है, COSINE या EUCLIDEAN के साथ एक्सपेरिमेंट करना ज़रूरी हो सकता है.

यह पक्का नहीं है कि डेटा नॉर्मलाइज़ किया गया है या नहीं

अगर आपको यह पक्का नहीं है कि आपका डेटा नॉर्मलाइज़ किया गया है या नहीं और आपको DOT_PRODUCT का इस्तेमाल करना है, तो हमारा सुझाव है कि इसके बजाय COSINE का इस्तेमाल करें. COSINE, नॉर्मलाइज़ेशन की सुविधा के साथ DOT_PRODUCT जैसा है. COSINE का इस्तेमाल करके मापी गई दूरी, 0 से 2 के बीच होती है. 0 के आस-पास का नतीजा बताता है कि वेक्टर बहुत मिलते-जुलते हैं.

दस्तावेज़ों को प्री-फ़िल्टर करना

सबसे नज़दीकी पड़ोसी ढूंढने से पहले, दस्तावेज़ों को प्री-फ़िल्टर करने के लिए, समानता खोज को अन्य क्वेरी ऑपरेटर के साथ जोड़ा जा सकता है. and और or कंपोज़िट फ़िल्टर इस्तेमाल किए जा सकते हैं. इस्तेमाल किए जा सकने वाले फ़ील्ड फ़िल्टर के बारे में ज़्यादा जानने के लिए, क्वेरी ऑपरेटर लेख पढ़ें.

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([0.3416704, 0.18332680, 0.24160706]),
    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();
Go
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
}
Java
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();

कैलकुलेट की गई वेक्टर दूरी पाना

FindNearest क्वेरी पर, distance_result_field आउटपुट प्रॉपर्टी का नाम असाइन करके, कैलकुलेट की गई वेक्टर दूरी पाई जा सकती है. जैसा कि यहां दिए गए उदाहरण में दिखाया गया है:

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([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')}")
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'));
});
Go
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
}
Java
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 की वैल्यू भी शामिल करनी होगी. जैसा कि यहां दिए गए उदाहरण में दिखाया गया है:

Python
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",
)
Node.js
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'
    });
Go
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
}
Java
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 दूरी, सीमा को उन दस्तावेज़ों तक सीमित करती है जिनकी दूरी, तय की गई सीमा से ज़्यादा या उसके बराबर होती है. वेक्टर के ज़्यादा मिलते-जुलते होने पर, डॉट प्रॉडक्ट की दूरियां बढ़ जाती हैं.

यहां दिए गए उदाहरण में, दूरी की सीमा तय करने का तरीका बताया गया है. इसमें, EUCLIDEAN दूरी की मेट्रिक का इस्तेमाल करके, ज़्यादा से ज़्यादा 10 सबसे नज़दीकी दस्तावेज़ दिखाए जाएंगे. ये दस्तावेज़, ज़्यादा से ज़्यादा 4.5 यूनिट की दूरी पर मौजूद हैं:

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([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}")
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);
});
Go
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
}
Java
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());
}

सीमाएं

वेक्टर एंबेडिंग के साथ काम करते समय, इन सीमाओं का ध्यान रखें:

  • एंबेडिंग का ज़्यादा से ज़्यादा 2048 डाइमेंशन इस्तेमाल किया जा सकता है. बड़े इंडेक्स सेव करने के लिए, डाइमेंशनैलिटी रिडक्शन का इस्तेमाल करें.
  • सबसे नज़दीकी पड़ोसी की क्वेरी से, ज़्यादा से ज़्यादा 1,000 दस्तावेज़ दिखाए जा सकते हैं. यह सीमा सिर्फ़ स्टैंडर्ड एडिशन के लिए है.
  • वेक्टर खोज में, रीयल-टाइम स्नैपशॉट लिसनर की सुविधा काम नहीं करती.
  • वेक्टर खोज की सुविधा, सिर्फ़ Python, Node.js, Go, और Java क्लाइंट लाइब्रेरी में काम करती है.

आगे क्या करना है