Pattern di ricerca vettoriale e a testo intero ibrida

Questa pagina descrive come eseguire ricerche ibride vettoriali e full-text in Spanner. La ricerca ibrida combina la precisione della corrispondenza delle parole chiave (ricerca full-text, FTS) con il richiamo della corrispondenza semantica (ricerca vettoriale) per produrre risultati di ricerca altamente pertinenti.

Spanner supporta i seguenti pattern di ricerca ibrida, suddivisi in tre categorie principali:

Categoria Descrizione Obiettivo principale
Fusion Fusion recupera e classifica i documenti in modo indipendente utilizzando la ricerca per parole chiave e vettoriale, quindi combina (unisce) i risultati. Ottieni il massimo richiamo e la massima pertinenza combinando più segnali di punteggio.
Filtrata Le parole chiave filtrano o perfezionano lo spazio di ricerca. Assicurati che la corrispondenza delle parole chiave sia un requisito sfruttando la pertinenza semantica rilevanza.
Ricalcolo ML Un modello di machine learning perfeziona un insieme iniziale di candidati per una classificazione finale più precisa. Ottieni la massima precisione possibile per un piccolo insieme finale di risultati.

La ricerca Fusion prevede l'esecuzione indipendente di FTS e della ricerca vettoriale sullo stesso corpus di dati. Quindi unisce i risultati per creare un elenco classificato unico, unificato e altamente pertinente.

Sebbene tu possa eseguire query indipendenti sul lato client, la ricerca ibrida in Spanner offre i seguenti vantaggi:

  • Semplifica la logica dell'applicazione gestendo le richieste parallele e l'unione dei risultati sul server.
  • Evita di trasferire al client set di risultati intermedi potenzialmente di grandi dimensioni.

Puoi utilizzare SQL per creare metodi di fusione in Spanner. Questa sezione fornisce esempi di fusione del rango reciproco e fusione del punteggio relativo. Tuttavia, ti consigliamo di valutare diverse strategie di fusione per determinare quella più adatta ai requisiti della tua applicazione.

Fusione basata sul rango

Utilizza la fusione basata sul rango quando i punteggi di pertinenza di diversi metodi di recupero (ad esempio i punteggi FTS e le distanze vettoriali) sono difficili da confrontare o normalizzare perché vengono misurati in spazi diversi. Questo metodo utilizza la posizione del rango di ogni documento di ogni recuperatore per generare un punteggio e una classificazione finali.

Reciprocal Rank Fusion (RRF) è una funzione di fusione basata sul rango. Il punteggio RRF per un documento è la somma dei reciproci dei suoi ranghi di più recuperatori e viene calcolato nel seguente modo:

\[ score\ (d\epsilon D)\ =\ \sum\limits_{r\epsilon R}^{}(1\ /\ (\ 𝑘\ +\ ran{k}_{r}\ (𝑑)\ )\ )\ \]

Dove:

  • d è il documento.
  • R è l'insieme dei recuperatori (FTS e ricerca vettoriale).
  • k è una costante (spesso impostata su 60) utilizzata per moderare l'influenza dei documenti con un rango molto alto.
  • w è il rango del documento del recuperatore r.

Implementare RRF in una query Spanner

Le metriche vettoriali (ad esempio APPROX_DOT_PRODUCT) e i punteggi di ricerca testuale (ad esempio SCORE_NGRAMS) operano su scale incompatibili. Per risolvere questo problema, l'esempio seguente implementa RRF per normalizzare i dati in base alla posizione del rango anziché ai punteggi grezzi.

La query utilizza UNNEST(ARRAY(...) WITH OFFSET) per assegnare un rango ai primi 100 candidati di ogni metodo. Calcola quindi un punteggio standardizzato utilizzando l'inverso di queste classifiche e aggrega i risultati per restituire le prime cinque corrispondenze.

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;

Fusione basata sul punteggio

La fusione basata sul punteggio è efficace quando i punteggi di pertinenza di metodi diversi sono comparabili o possono essere normalizzati, il che potrebbe consentire una classificazione più precisa che incorpora il peso di pertinenza effettivo di ogni metodo.

Relative Score Fusion (RSF) è un metodo basato sul punteggio che normalizza i punteggi di metodi diversi rispetto ai punteggi più alti e più bassi all'interno di ogni metodo, in genere utilizzando le funzioni MIN() e MAX(). Il punteggio RSF di un documento recuperato da un insieme di recuperatori viene calcolato nel seguente modo:

\[ score(d\epsilon D)\ =\ \sum\limits_{r\epsilon R}^{}({w}_{r}*(scor{e}_{r}(d)\ -\ mi{n}_{r})\ /\ (ma{x}_{r\ }-mi{n}_{r})\ ) \]

Dove:

  • d è il documento.
  • R è l'insieme dei recuperatori (FTS e ricerca vettoriale).
  • w è il peso assegnato a un recuperatore specifico.

Implementare RSF in una query Spanner

Per implementare RSF, devi normalizzare i punteggi del vettore e di FTS su una scala comune. L'esempio seguente calcola i punteggi minimi e massimi in clausole WITH separate per derivare i fattori di normalizzazione. Quindi combina i risultati utilizzando un FULL OUTER JOIN, sommando i punteggi normalizzati della ricerca approssimativa del vicino più prossimo (ANN) (convertiti da cosine_distance) e di 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;

Le ricerche filtrate utilizzano FTS per creare un filtro che riduce l'insieme di documenti considerati per una ricerca vettoriale del vicino più prossimo (KNN). Facoltativamente, puoi utilizzare un ordinamento preliminare per limitare le dimensioni del set di risultati.

La ricerca di esempio in questa sezione esegue i seguenti passaggi per restringere lo spazio di ricerca vettoriale al sottoinsieme di dati che corrispondono alle parole chiave:

  • Utilizza SEARCH (text_tokens, 'Green') per trovare le righe in cui la colonna text_tokens contiene il testo Green. Le prime 1000 righe vengono restituite da un ordine di riordinamento definito dall'indice di ricerca.
  • Utilizza una funzione vettoriale, DOT_PRODUCT(@vector, embedding) per calcolare la similarità tra il vettore della query (@vector) e il vettore del documento memorizzato (embedding). Quindi ordina i risultati e restituisce le prime 10 corrispondenze finali.
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;

Ricalcolo ML

Il ricalcolo basato su ML è un approccio computazionalmente intensivo ma altamente preciso. Applica un modello di machine learning a un piccolo insieme di candidati ridotto da FTS, dalla ricerca vettoriale o da una combinazione di entrambi. Per ulteriori informazioni sull'integrazione di Spanner Agent Platform, consulta la panoramica sull'integrazione di Spanner Agent Platform.

Puoi integrare il ricalcolo ML utilizzando la ML.PREDICT funzione di Spanner con un modello di Gemini Enterprise Agent Platform di cui è stato eseguito il deployment.

Implementare il ricalcolo basato su ML

  1. Esegui il deployment di un modello di ricalcolo (ad esempio da HuggingFace) in un endpoint Agent Platform.
  2. Crea un oggetto MODEL di Spanner che rimandi all'endpoint Agent Platform. Ad esempio, nel seguente esempio di modello Reranker:

    • text ARRAY<string(max)> sono i documenti.
    • text_pair ARRAY<string(max)> è il testo della query nell'esempio.
    • score sono i punteggi di pertinenza assegnati dal modello ML per le coppie di testi di input.
    CREATE MODEL Reranker
    INPUT (text ARRAY<string(max)>, text_pair ARRAY<string(max)>)
    OUTPUT (score FLOAT32)
    REMOTE
    OPTIONS (
    endpoint = '...'
    );
    
  3. Utilizza una sottoquery per recuperare i candidati iniziali (ad esempio i primi 100 risultati di una ricerca ANN) e trasmettili a ML.PREDICT. La funzione restituisce una nuova colonna di punteggio per l'ordinamento finale.

    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;
    

Passaggi successivi