इस पेज पर, Cloud Firestore का इस्तेमाल करके, के-निकटतम पड़ोसी (केएनएन) वेक्टर खोज करने का तरीका बताया गया है. इसके लिए, इन तकनीकों का इस्तेमाल किया जाता है:
- स्टोर वेक्टर वैल्यू
- केएनएन वेक्टर इंडेक्स बनाना और मैनेज करना
- वेक्टर के बीच की दूरी मापने के लिए, उपलब्ध किसी एक तरीके का इस्तेमाल करके, K-सबसे-नज़दीकी-पड़ोसी (केएनएन) क्वेरी करना
वेक्टर एम्बेडिंग सेव करना
अपने Cloud Firestore डेटा से, टेक्स्ट एम्बेडिंग जैसी वेक्टर वैल्यू बनाई जा सकती हैं. साथ ही, उन्हें Cloud Firestore दस्तावेज़ों में सेव किया जा सकता है.
वेक्टर एम्बेडिंग के साथ लिखने की कार्रवाई
यहां दिए गए उदाहरण में, Cloud Firestore दस्तावेज़ में वेक्टर एम्बेडिंग को सेव करने का तरीका बताया गया है:
Python
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]) });
शुरू करें
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 फ़ंक्शन की मदद से वेक्टर एम्बेडिंग कंप्यूट करना
जब भी कोई दस्तावेज़ अपडेट या बनाया जाता है, तब वेक्टर एम्बेडिंग को कैलकुलेट और सेव करने के लिए, 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, }); }
शुरू करें
// 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 CLI को नए वर्शन में अपग्रेड करें:
gcloud components update
वेक्टर इंडेक्स बनाने के लिए, gcloud firestore indexes composite create
का इस्तेमाल करें:
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
where:
- collection-group कलेक्शन ग्रुप का आईडी है.
- vector-field उस फ़ील्ड का नाम है जिसमें वेक्टर एम्बेडिंग शामिल है.
- database-id डेटाबेस का आईडी है.
- vector-configuration में वेक्टर
dimension
और इंडेक्स टाइप शामिल होता है.dimension
, 2048 तक का पूर्णांक होता है. इंडेक्स का टाइपflat
होना चाहिए. इंडेक्स कॉन्फ़िगरेशन को इस तरह से फ़ॉर्मैट करें:{"dimension":"DIMENSION", "flat": "{}"}
.
नीचे दिए गए उदाहरण में, एक कंपोज़िट इंडेक्स बनाया गया है. इसमें फ़ील्ड vector-field
के लिए वेक्टर इंडेक्स और फ़ील्ड color
के लिए एसेंडिंग इंडेक्स शामिल है. इस तरह के इंडेक्स का इस्तेमाल, सबसे मिलते-जुलते पड़ोसी की खोज से पहले डेटा को पहले से फ़िल्टर करने के लिए किया जा सकता है.
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
सभी वेक्टर इंडेक्स की सूची बनाना
gcloud
gcloud firestore indexes composite list --database=database-id
database-id की जगह डेटाबेस का आईडी डालें.
वेक्टर इंडेक्स मिटाना
gcloud
gcloud firestore indexes composite delete index-id --database=database-id
where:
- index-id मिटाए जाने वाले इंडेक्स का आईडी है.
इंडेक्स आईडी वापस पाने के लिए,
indexes composite list
का इस्तेमाल करें. - database-id डेटाबेस का आईडी है.
वेक्टर इंडेक्स के बारे में जानकारी
gcloud
gcloud firestore indexes composite describe index-id --database=database-id
where:
- index-id इंडेक्स का आईडी है. इंडेक्स आईडी वापस पाने के लिए,
indexes composite list
का इस्तेमाल करें. - database-id डेटाबेस का आईडी है.
नियरेस्ट-नेबर क्वेरी बनाना
वेक्टर एम्बेडिंग के सबसे मिलते-जुलते पड़ोसी ढूंढने के लिए, मिलती-जुलती खोज की जा सकती है. मिलती-जुलती खोजों के लिए, वेक्टर इंडेक्स ज़रूरी होते हैं. अगर कोई इंडेक्स मौजूद नहीं है, तो Cloud Firestore, gcloud CLI का इस्तेमाल करके इंडेक्स बनाने का सुझाव देता है.
यहां दिए गए उदाहरण में, क्वेरी वेक्टर के सबसे नज़दीक मौजूद 10 वेक्टर ढूंढे गए हैं.
Python
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();
शुरू करें
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
: यह फ़ंक्शन, वेक्टर के बीच की इयूक्लिडियन दूरी को मापता है. ज़्यादा जानने के लिए, यूक्लिडियन देखें.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
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();
शुरू करें
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
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')); });
शुरू करें
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
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' });
शुरू करें
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
दूरी की मेट्रिक का इस्तेमाल करके, ज़्यादा से ज़्यादा 4.5 यूनिट की दूरी पर मौजूद 10 सबसे नज़दीकी दस्तावेज़ों को दिखाने के लिए, दूरी की थ्रेशोल्ड वैल्यू तय करने का तरीका बताया गया है:
Python
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); });
शुरू करें
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 क्लाइंट लाइब्रेरी में वेक्टर सर्च की सुविधा काम करती है.
आगे क्या करना है
- Cloud Firestore के लिए सबसे सही तरीकों के बारे में पढ़ें.
- बड़े पैमाने पर डेटा को पढ़ता और लिखता है.