תיאור
מבצע חיפוש וקטורי של השכן הקרוב ביותר בשדה embedding שצוין באמצעות distance_measure המבוקש.
דוגמאות
Node.js
const results = await db.pipeline() .collection("cities") .findNearest({ field: "embedding", vectorValue: [1.5, 2.345], distanceMeasure: "euclidean" }) .execute();
Web
const results = await execute(db.pipeline() .collection("cities") .findNearest({ field: "embedding", vectorValue: [1.5, 2.345], distanceMeasure: "euclidean" }));
Swift
let results = try await db.pipeline() .collection("cities") .findNearest( field: Field("embedding"), vectorValue: VectorValue([1.5, 2.345]), distanceMeasure: .euclidean ) .execute()
Kotlin
val results = db.pipeline() .collection("cities") .findNearest( "embedding", doubleArrayOf(1.5, 2.345), FindNearestStage.DistanceMeasure.EUCLIDEAN ) .execute()
Java
Task<Pipeline.Snapshot> results = db.pipeline() .collection("cities") .findNearest( "embedding", new double[] {1.5, 2.345}, FindNearestStage.DistanceMeasure.EUCLIDEAN ) .execute();
Python
from google.cloud.firestore_v1.vector import Vector from google.cloud.firestore_v1.base_vector_query import DistanceMeasure results = ( client.pipeline() .collection("cities") .find_nearest( field="embedding", vector_value=Vector([1.5, 2.345]), distance_measure=DistanceMeasure.EUCLIDEAN, ) .execute() )
Java
Pipeline.Snapshot results = firestore .pipeline() .collection("cities") .findNearest( "embedding", new double[] {1.5, 2.345}, FindNearest.DistanceMeasure.EUCLIDEAN, new FindNearestOptions()) .execute() .get();
התנהגות
מדידת מרחק
בשלב find_nearest(...) אפשר לבחור מבין האפשרויות הבאות למרחק בין וקטורים:
-
euclidean: מדידתeuclideanהמרחק בין הווקטורים. מידע נוסף זמין במאמר בנושא מרחק אוקלידי. -
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 מצביעה על כך שהווקטורים דומים מאוד.
הגבלת התוצאות
אפשר להגביל את מספר המסמכים שמוחזרים על ידי השאילתה באמצעות הגדרת השדה limit
Node.js
const results = await db.pipeline()
.collection("cities")
.findNearest({
field: "embedding",
vectorValue: vector([1.5, 2.345]),
distanceMeasure: "euclidean",
limit: 10,
})
.execute();
אחזור המרחק הווקטורי המחושב
כדי לאחזר את המרחק הווקטורי המחושב, צריך להקצות שם של מאפיין פלט distance_field בשלב find_nearest(...), כמו בדוגמה הבאה:
לדוגמה, באוסף הבא:
Node.js
await db.collection("cities").doc("SF").set({name: "San Francisco", embedding: vector([1.0, -1.0])});
await db.collection("cities").doc("TO").set({name: "Toronto", embedding: vector([5.0, -10.0])});
await db.collection("cities").doc("AT").set({name: "Atlantis", embedding: vector([2.0, -4.0])});
מבצעים חיפוש וקטורי עם פלט מבוקש distance_field:
Node.js
const results = await db.pipeline()
.collection("cities")
.findNearest({
field: "embedding",
vectorValue: vector([1.3, 2.345]),
distanceMeasure: "euclidean",
distanceField: "computedDistance",
})
.execute();
שמפיק את המסמכים הבאים:
{name: "San Francisco", embedding: vector([1.0, -1.0]), computedDistance: 3.3584259705999178},
{name: "Atlantis", embedding: vector([2.0, -4.0]), computedDistance: 6.383496299051172},
{name: "Toronto", embedding: vector([5.0, -10.0]), computedDistance: 12.887553103673328}
מגבלות
כשעובדים עם הטמעות וקטוריות, חשוב לשים לב להגבלה הבאה:
- המימד המקסימלי של הטמעת נתונים שנתמך הוא 2048. כדי לאחסן אינדקסים גדולים יותר, משתמשים בצמצום ממדים.