בדף הזה מוסבר איך לבצע חיפושים היברידיים של טקסט מלא ושל וקטורים ב-Spanner. חיפוש היברידי משלב בין הדיוק של התאמה למילות מפתח (חיפוש טקסט מלא, FTS) לבין ההחזרה של התאמה סמנטית (חיפוש וקטורי) כדי להפיק תוצאות חיפוש רלוונטיות מאוד.
Spanner תומך בתבניות הבאות של חיפוש היברידי, שמחולקות לשלוש קטגוריות עיקריות:
| קטגוריה | תיאור | היעד העיקרי |
| Fusion | Fusion מאחזר ומדרג מסמכים באופן עצמאי באמצעות חיפוש מילות מפתח וחיפוש וקטורי, ואז משלב (מאחד) את התוצאות. | כדי להשיג את רמת ההיזכרות והרלוונטיות המקסימלית, כדאי לשלב כמה אותות ניקוד. |
| מסונן | מילות מפתח מסננות או מצמצמות את מרחב החיפוש. | חשוב לוודא שהתאמה למילות מפתח היא דרישה, תוך שימוש ברלוונטיות סמנטית. |
| דירוג מחדש באמצעות ML | מודל של למידת מכונה משפר קבוצה ראשונית של מועמדים כדי ליצור דירוג סופי ומדויק יותר. | להשיג את רמת הדיוק הגבוהה ביותר האפשרית עבור קבוצה קטנה של תוצאות סופיות. |
חיפוש פיוז'ן
חיפוש משולב כולל הפעלה של FTS וחיפוש וקטורים באופן נפרד באותו מאגר נתונים. לאחר מכן, הוא ממזג את התוצאות כדי ליצור רשימה אחת, מאוחדת ורלוונטית מאוד.
אפשר להריץ שאילתות עצמאיות בצד הלקוח, אבל לחיפוש היברידי ב-Spanner יש את היתרונות הבאים:
- הוא מפשט את הלוגיקה של האפליקציה על ידי ניהול בקשות מקבילות ומיזוג תוצאות בשרת.
- היא מונעת העברה של קבוצות תוצאות ביניים גדולות אל הלקוח.
אפשר להשתמש ב-SQL כדי ליצור שיטות שילוב ב-Spanner. בקטע הזה מופיעות דוגמאות למיזוג של דירוגים הפוכים ולמיזוג של ציונים יחסיים. עם זאת, מומלץ לבחון אסטרטגיות שונות של מיזוג כדי לקבוע איזו מהן מתאימה ביותר לדרישות של האפליקציה שלכם.
מיזוג מבוסס-דירוג
משתמשים במיזוג מבוסס-דירוג כשקשה להשוות או לנרמל את ציוני הרלוונטיות משיטות שונות לאחזור (כמו ציוני FTS ומרחקים וקטוריים) כי הם נמדדים במרחבים שונים. בשיטה הזו נעשה שימוש במיקום בדירוג של כל מסמך מכל כלי לאחזור מידע כדי ליצור ניקוד ודירוג סופיים.
מיזוג דרגות הדדיות (RRF) הוא פונקציית מיזוג שמבוססת על דרגות. הציון RRF של מסמך הוא סכום ההופכיים של הדירוגים שלו ממספר מנגנוני אחזור. החישוב מתבצע באופן הבא:
\[ score\ (d\epsilon D)\ =\ \sum\limits_{r\epsilon R}^{}(1\ /\ (\ 𝑘\ +\ ran{k}_{r}\ (𝑑)\ )\ )\ \]
כאשר:
- d הוא המסמך.
- R היא קבוצת כלי האחזור (חיפוש FTS וחיפוש וקטורי).
- k הוא קבוע (לרוב מוגדר כ-60) שמשמש למיתון ההשפעה של מסמכים עם דירוג גבוה מאוד.
- w הוא הדירוג של המסמך מרכיב המאחזר r.
הטמעה של RRF בשאילתת Spanner
מדדים וקטוריים (כמו APPROX_DOT_PRODUCT) וציוני חיפוש טקסט (כמו SCORE_NGRAMS) פועלים בסולמות לא תואמים. כדי לפתור את הבעיה הזו, בדוגמה הבאה מיושם RRF לנרמול נתונים על סמך מיקום בדירוג ולא על סמך ציונים גולמיים.
השאילתה משתמשת ב-UNNEST(ARRAY(...) WITH OFFSET) כדי להקצות דירוג ל-100 המועמדים המובילים מכל שיטה. לאחר מכן, המערכת מחשבת ציון סטנדרטי באמצעות ההיפוך של הדירוגים האלה, ומצברת את התוצאות כדי להחזיר את חמשת ההתאמות המובילות.
SELECT SUM(1 / (60 + rank)) AS rrf_score, key
FROM (
(
SELECT rank, x AS key
FROM UNNEST(ARRAY(
SELECT key
FROM hybrid_search
WHERE embedding IS NOT NULL
ORDER BY APPROX_DOT_PRODUCT(@vector, embedding,
OPTIONS => JSON '{"num_leaves_to_search": 50}') DESC
LIMIT 100)) AS x WITH OFFSET AS rank
)
UNION ALL
(
SELECT rank, x AS key
FROM UNNEST(ARRAY(
SELECT key
FROM hybrid_search
WHERE SEARCH_NGRAMS(text_tokens_ngrams, 'foo')
ORDER BY SCORE_NGRAMS(text_tokens_ngrams, 'foo') DESC
LIMIT 100)) AS x WITH OFFSET AS rank
)
)
GROUP BY key
ORDER BY rrf_score DESC
LIMIT 5;
שילוב מבוסס-ציון
היתרון של שילוב מבוסס-ניקוד הוא שהוא יעיל כשציוני הרלוונטיות משיטות שונות ניתנים להשוואה או כשניתן לנרמל אותם. כך אפשר לקבל דירוג מדויק יותר שמשלב את משקל הרלוונטיות בפועל של כל שיטה.
שילוב של ציונים יחסיים (RSF) הוא שיטה שמבוססת על ציונים ומנרמלת ציונים משיטות שונות ביחס לציונים הכי גבוהים והכי נמוכים בכל שיטה, בדרך כלל באמצעות הפונקציות MIN() ו-MAX(). ציון ה-RSF של מסמך שאוחזר על ידי קבוצה של מאחזרים מחושב באופן הבא:
\[ score(d\epsilon D)\ =\ \sum\limits_{r\epsilon R}^{}({w}_{r}*(scor{e}_{r}(d)\ -\ mi{n}_{r})\ /\ (ma{x}_{r\ }-mi{n}_{r})\ ) \]
כאשר:
- d הוא המסמך.
- R היא קבוצת כלי האחזור (חיפוש FTS וחיפוש וקטורי).
- w הוא המשקל שמוקצה לרכיב מאחזר ספציפי.
הטמעה של RSF בשאילתת Spanner
כדי להטמיע את RSF, צריך לנרמל את הציונים מהווקטור ומ-FTS לסולם משותף. בדוגמה הבאה מחושבים הציונים המינימליים והמקסימליים בסעיפים נפרדים של WITH כדי לקבל את גורמי הנורמליזציה. לאחר מכן, המערכת משלבת את התוצאות באמצעות FULL OUTER JOIN, ומסכמת את הציונים הנורמליים מחיפוש השכן הקרוב המשוער (ANN) (שהומרו מ-cosine_distance) ומחיפוש FTS.
WITH ann AS (
SELECT key, APPROX_COSINE_DISTANCE(@vector, embedding,
OPTIONS => JSON '{"num_leaves_to_search": 50}') AS cosine_distance,
FROM hybrid_search
WHERE embedding IS NOT NULL
ORDER BY cosine_distance
LIMIT 100
),
fts AS (
SELECT key, SCORE_NGRAMS(text_tokens_ngrams, 'Green') AS score,
FROM hybrid_search
WHERE SEARCH_NGRAMS(text_tokens_ngrams, 'Green')
ORDER BY score DESC
LIMIT 100
),
ann_min AS (
SELECT MIN(1 - cosine_distance) AS min
FROM ann
),
ann_max AS (
SELECT MAX(1 - cosine_distance) AS max
FROM ann
),
fts_min AS (
SELECT MIN(score) AS min
FROM fts
),
fts_max AS (
SELECT MAX(score) AS max
FROM fts
)
SELECT IFNULL(ann.key, fts.key),
IFNULL(((1 - ann.cosine_distance) - ann_min.min) /
(ann_max.max - ann_min.min), 0) +
IFNULL((fts.score - fts_min.min) /
(fts_max.max - fts_min.min), 0) AS score
FROM ann
FULL OUTER JOIN fts
ON ann.key = fts.key
CROSS JOIN ann_min
CROSS JOIN ann_max
CROSS JOIN fts_min
CROSS JOIN fts_max
ORDER BY score DESC
LIMIT 5;
חיפוש מסונן
חיפושים מסוננים משתמשים ב-FTS כדי ליצור מסנן שמצמצם את קבוצת המסמכים שנלקחים בחשבון בחיפוש וקטורי של k-שכנים קרובים (KNN). אפשר גם להשתמש במיון מראש כדי להגביל את גודל מערך התוצאות.
הטמעה של חיפוש עם סינון בשאילתת Spanner
בדוגמה לחיפוש שבסעיף הזה, מתבצעים השלבים הבאים כדי לצמצם את מרחב החיפוש של הווקטורים לקבוצת המשנה של הנתונים שתואמים למילות המפתח:
- הפונקציה
SEARCH (text_tokens, 'Green')משמשת לאיתור שורות שבהן העמודהtext_tokensמכילה את הטקסטGreen. 1,000 השורות העליונות מוחזרות על ידי סדר מיון שמוגדר על ידי אינדקס החיפוש. - הפונקציה הווקטורית
DOT_PRODUCT(@vector, embedding)משמשת לחישוב הדמיון בין וקטור השאילתה (@vector) לבין וקטור המסמך המאוחסן (הטמעה). לאחר מכן, היא ממיינת את התוצאות ומחזירה את 10 ההתאמות הסופיות המובילות.
SELECT key
FROM (
SELECT key, embedding
FROM hybrid_search
WHERE SEARCH (text_tokens, 'Green')
ORDER BY presort
LIMIT 1000)
ORDER BY DOT_PRODUCT(@vector, embedding) DESC
LIMIT 10;
דירוג מחדש באמצעות למידת מכונה
דירוג מחדש שמבוסס על למידת מכונה הוא גישה שדורשת הרבה משאבי מחשוב, אבל היא מאוד מדויקת. היא מפעילה מודל למידת מכונה על קבוצה קטנה של מועמדים שצומצמה על ידי FTS, חיפוש וקטורי או שילוב של שניהם. מידע נוסף על שילוב של Spanner עם Vertex AI זמין במאמר סקירה כללית על שילוב של Spanner עם Vertex AI.
אפשר לשלב דירוג מחדש של ML באמצעות הפונקציה Spanner
ML.PREDICT
עם מודל Vertex AI שנפרס.
הטמעה של דירוג מחדש שמבוסס על למידת מכונה
- פריסת מודל לדירוג מחדש (למשל מ-HuggingFace) לנקודת קצה של Vertex AI.
יוצרים אובייקט Spanner
MODELשמצביע על נקודת הקצה של Vertex AI. לדוגמה, בדוגמה הבאה של מודלReranker:-
text ARRAY<string(max)>הם המסמכים. -
text_pair ARRAY<string(max)>הוא טקסט השאילתה בדוגמה. -
scoreהם ציוני הרלוונטיות שהוקצו על ידי מודל ה-ML לזוגות הקלט של הטקסטים.
CREATE MODEL Reranker INPUT (text ARRAY<string(max)>, text_pair ARRAY<string(max)>) OUTPUT (score FLOAT32) REMOTE OPTIONS ( endpoint = '...' );-
משתמשים בשאילתת משנה כדי לאחזר את המועמדים הראשוניים (למשל, 100 התוצאות המובילות מחיפוש ANN) ומעבירים אותם אל
ML.PREDICT. הפונקציה מחזירה עמודת ניקוד חדשה למיון הסופי.SELECT key FROM ML.PREDICT( MODEL Reranker, ( SELECT key, text, "gift for 8-year-old" AS text_pair FROM hybrid_search WHERE embedding IS NOT NULL ORDER BY APPROX_DOT_PRODUCT(@vector, embedding, options=>JSON '{"num_leaves_to_search": 50}') DESC LIMIT 100) ) ORDER BY score DESC LIMIT 3;