این صفحه به شما نشان میدهد که چگونه از Cloud Firestore برای انجام جستجوهای برداری K-نزدیکترین همسایه (KNN) با استفاده از تکنیکهای زیر استفاده کنید:
- ذخیره مقادیر برداری
- ایجاد و مدیریت شاخصهای برداری KNN
- با استفاده از یکی از معیارهای فاصله برداری پشتیبانی شده، یک پرس و جوی K-نزدیکترین همسایه (KNN) ایجاد کنید.
قبل از اینکه شروع کنی
قبل از ذخیره جاسازیها در Cloud Firestore ، باید جاسازیهای برداری ایجاد کنید. Cloud Firestore جاسازیها را تولید نمیکند. میتوانید از خدماتی مانند Vertex AI برای ایجاد مقادیر برداری، به عنوان مثال، جاسازیهای متنی از دادههای Cloud Firestore خود استفاده کنید. سپس میتوانید این جاسازیها را دوباره در اسناد Cloud Firestore ذخیره کنید.
برای کسب اطلاعات بیشتر در مورد جاسازیها، به بخش جاسازیها چیست؟ مراجعه کنید.
برای یادگیری نحوه دریافت جاسازی متن با Vertex AI ، به دریافت جاسازی متن مراجعه کنید.
جاسازیهای برداری فروشگاه
مثالهای زیر نحوه ذخیره جاسازیهای برداری در Cloud Firestore را نشان میدهند.
عملیات نوشتن با جاسازی برداری
مثال زیر نحوه ذخیره سازی یک بردار جاسازی شده در یک سند Cloud Firestore را نشان میدهد:
پایتون
نود جی اس
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 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 همسایه نزدیک به بردار جستجو را پیدا میکند.
پایتون
نود جی اس
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 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 پشتیبانی میشوند. برای اطلاعات بیشتر در مورد فیلترهای فیلد پشتیبانیشده، به عملگرهای پرسوجو مراجعه کنید.
پایتون
نود جی اس
// 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 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 بازیابی کنید، همانطور که در مثال زیر نشان داده شده است:
پایتون
نود جی اس
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 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 را نیز در ماسک فیلد قرار دهید، همانطور که در مثال زیر نشان داده شده است:
پایتون
نود جی اس
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 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 فاصله دارند را نشان میدهد:
پایتون
نود جی اس
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 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 و جاوا از جستجوی برداری پشتیبانی میکنند.
قدم بعدی چیست؟
- درباره بهترین شیوههای استفاده از Cloud Firestore مطالعه کنید.
- خواندن و نوشتن در مقیاس بزرگ را درک کنید.