ভেক্টর এম্বেডিংয়ের মাধ্যমে সার্চ করা

এই পৃষ্ঠায় দেখানো হয়েছে কীভাবে Cloud Firestore ব্যবহার করে K-nearest neighbor (KNN) ভেক্টর সার্চ পারফর্ম করা যায়, এর জন্য নিম্নলিখিত টেকনিক ব্যবহার করা হয়:

  • ভেক্টর ভ্যালু স্টোর করো
  • KNN ভেক্টর ইন্ডেক্স তৈরি ও ম্যানেজ করা
  • কাজ করে এমন ভেক্টর দূরত্ব পরিমাপের একটি ব্যবহার করে K-নিকটতম-প্রতিবেশী (KNN) কোয়েরি তৈরি করো

শুরু করার আগে

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
}
জাভা
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
জাভা
  // Not yet supported in the Java client library

ভেক্টর ইন্ডেক্স তৈরি ও ম্যানেজ করা

আপনার ভেক্টর এম্বেডিংয়ের মাধ্যমে নিকটতম প্রতিবেশী সার্চ করার আগে, আপনাকে অবশ্যই একটি সংশ্লিষ্ট ইন্ডেক্স তৈরি করতে হবে। নিম্নলিখিত উদাহরণগুলি দেখায় কীভাবে Google Cloud CLI এবং কনসোল ব্যবহার করে ভেক্টর ইনডেক্স তৈরি এবং ম্যানেজ করতে হয়। এছাড়াও, আপনি Firebase CLI ও Terraform-এর মাধ্যমে ভেক্টর ইন্ডেক্স ম্যানেজ করতে পারবেন।

ভেক্টর ইন্ডেক্স তৈরি করুন

Google Cloud কনসোল

Google Cloud কনসোল থেকে ম্যানুয়ালি নতুন ইন্ডেক্স তৈরি করতে:

  1. Google Cloud কনসোলে, ডেটাবেস পৃষ্ঠায় যান।

    ডেটাবেসে যান

  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 হল ২০৪৮ পর্যন্ত একটি পূর্ণসংখ্যা। ইনডেক্সের ধরন অবশ্যই 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 কনসোলে, ডেটাবেস পৃষ্ঠায় যান।

    ডেটাবেসে যান

  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 কনসোলে, ডেটাবেস পৃষ্ঠায় যান।

    ডেটাবেসে যান

  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 ব্যবহার করে তৈরি করার জন্য একটি ইন্ডেক্স সাজেস্ট করে।

নিম্নলিখিত উদাহরণটি কোয়েরি ভেক্টরের সবচেয়ে কাছাকাছি থাকা ১০টি প্রতিবেশী খুঁজে বের করে।

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
}
জাভা
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-এর মতো কিন্তু ভেক্টরের ম্যাগনিটিউড দ্বারা প্রভাবিত হয়। আরও জানতে, ডট প্রোডাক্ট দেখুন।

দূরত্ব পরিমাপের একক বেছে নিন

আপনার সব ভেক্টর এম্বেডিং নরমালাইজ করা হয়েছে কিনা তার উপর নির্ভর করে, আপনি কোন দূরত্ব পরিমাপ ব্যবহার করবেন তা নির্ধারণ করতে পারবেন। একটি নরমালাইজড ভেক্টর এম্বেডিংয়ের ম্যাগনিটিউড (দৈর্ঘ্য) ঠিক ১.০ হয়।

এছাড়াও, আপনার মডেল কোন দূরত্ব পরিমাপের সাথে প্রশিক্ষিত হয়েছে তা যদি আপনি জানেন, আপনার ভেক্টর এম্বেডিংয়ের মধ্যে দূরত্ব গণনা করতে সেই দূরত্ব পরিমাপ ব্যবহার করুন।

নর্মালাইজ করা ডেটা

আপনার কাছে এমন ডেটাসেট থাকলে যেখানে সব ভেক্টর এম্বেডিং নর্ম্যালাইজ করা আছে, তাহলে তিনটি ডিসট্যান্স পরিমাপই একই সেম্যান্টিক সার্চ ফলাফল প্রদান করে। মূলত, প্রতিটি দূরত্ব পরিমাপক আলাদা ভ্যালু দেখালেও, সেই ভ্যালুগুলি একই উপায়ে সাজানো হয়। এম্বেডিং নরমালাইজ করা হলে, 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
}
জাভা
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
}
জাভা
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
}
জাভা
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 দূরত্ব মেট্রিক ব্যবহার করে, সর্বাধিক ৪.৫ ইউনিট দূরে থাকা, সবচেয়ে কাছের ১০টি ডকুমেন্ট পর্যন্ত ফিরিয়ে আনার জন্য কীভাবে দূরত্বের থ্রেশহোল্ড নির্দিষ্ট করতে হয় তা নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

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
}
জাভা
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());
}

সীমাবদ্ধতা

ভেক্টর এম্বেডিং নিয়ে কাজ করার সময় নিম্নলিখিত সীমাবদ্ধতাগুলি মনে রাখবেন:

  • সর্বাধিক অনুমোদিত এম্বেডিং ডাইমেনশন হল ২০৪৮। আরও বড় ইনডেক্স স্টোর করতে, ডাইমেনশনালিটি রিডাকশন ব্যবহার করুন।
  • একটি নিকটতম-প্রতিবেশী কোয়েরি থেকে ফেরত দেওয়ার জন্য সর্বাধিক সংখ্যক ডকুমেন্ট হল ১০০০ (শুধুমাত্র Standard সংস্করণের সীমাবদ্ধতা)।
  • ভেক্টর সার্চে রিয়েল-টাইম স্ন্যাপশট লিসেনার কাজ করে না।
  • শুধুমাত্র Python, Node.js, Go এবং Java ক্লায়েন্ট লাইব্রেরি ভেক্টর সার্চ সাপোর্ট করে।

এর পরে কী করতে হবে