דפוסי חיפוש היברידיים של טקסט מלא ושל וקטורים

בדף הזה מוסבר איך לבצע חיפושים היברידיים של טקסט מלא ושל וקטורים ב-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). אפשר גם להשתמש במיון מראש כדי להגביל את גודל מערך התוצאות.

בדוגמה לחיפוש שבסעיף הזה, מתבצעים השלבים הבאים כדי לצמצם את מרחב החיפוש של הווקטורים לקבוצת המשנה של הנתונים שתואמים למילות המפתח:

  • הפונקציה 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 שנפרס.

הטמעה של דירוג מחדש שמבוסס על למידת מכונה

  1. פריסת מודל לדירוג מחדש (למשל מ-HuggingFace) לנקודת קצה של Vertex AI.
  2. יוצרים אובייקט 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 = '...'
    );
    
  3. משתמשים בשאילתת משנה כדי לאחזר את המועמדים הראשוניים (למשל, 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;
    

המאמרים הבאים