Pattern di ricerca vettoriale e a testo intero ibrida

Questa pagina descrive come eseguire ricerche ibride vettoriali e a testo intero 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 in modo indipendente i documenti utilizzando la ricerca per parole chiave e vettoriale, quindi combina (unisce) i risultati. Ottieni il massimo richiamo e la massima pertinenza combinando più indicatori di punteggio.
Filtrato I filtri per parole chiave consentono di perfezionare lo spazio di ricerca. Assicurati che la corrispondenza delle parole chiave sia un requisito sfruttando la pertinenza semantica.
Riorganizzazione basata sul machine learning Un modello di machine learning perfeziona un insieme iniziale di candidati per una classifica finale più precisa. Ottenere la massima precisione possibile per un piccolo insieme finale di risultati.

La ricerca ibrida prevede l'esecuzione della ricerca full-text e della ricerca vettoriale in modo indipendente sullo stesso corpus di dati. Quindi, unisce i risultati per creare un unico elenco classificato, 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 di fusione del punteggio relativo�. Tuttavia, ti consigliamo di valutare diverse strategie di fusione per determinare quella più adatta ai requisiti della tua applicazione.

Unione basata sul ranking

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

La Reciprocal Rank Fusion (RRF) è una funzione di fusione basata sul ranking. Il punteggio RRF per un documento è la somma dei reciproci dei suoi ranking 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 retriever (ricerca full-text e vettoriale).
  • k è una costante (spesso impostata su 60) utilizzata per moderare l'influenza dei documenti con un ranking molto alto.
  • w è il ranking del documento dal recuperatore r.

Implementa RRF in una query Spanner

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

La query utilizza UNNEST(ARRAY(...) WITH OFFSET) per assegnare un ranking 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 ottenuti con metodi diversi sono comparabili o quando è possibile normalizzarli, il che potrebbe consentire una classificazione più precisa che incorpora il peso effettivo della pertinenza di ogni metodo.

La fusione del punteggio relativo (RSF) è un metodo basato sul punteggio che normalizza i punteggi di metodi diversi rispetto ai punteggi più alti e più bassi all'interno di ciascun metodo, in genere utilizzando le funzioni MIN() e MAX(). Il punteggio RSF di un documento recuperato da un insieme di retriever viene calcolato come segue:

\[ 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 retriever (ricerca full-text e vettoriale).
  • w è il peso assegnato a un recuperatore specifico.

Implementa RSF in una query Spanner

Per implementare RSF, devi normalizzare i punteggi del vettore e della ricerca full-text in una scala comune. L'esempio seguente calcola i punteggi minimo e massimo in clausole WITH separate per derivare i fattori di normalizzazione. Poi 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 della ricerca full-text.

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 presi in considerazione per una ricerca vettoriale K-Nearest Neighbor (KNN). Se vuoi, puoi utilizzare un preordinamento 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 di query (@vector) e il vettore del documento memorizzato (embedding). Poi ordina i risultati e restituisce le prime 10 partite 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;

Riorganizzazione basata su ML

Il ranking basato sul machine learning è un approccio computazionalmente intensivo, ma molto preciso. Applica un modello di machine learning a un piccolo insieme di candidati che è stato ridotto tramite la ricerca full-text, la ricerca vettoriale o una combinazione di entrambe. Per ulteriori informazioni sull'integrazione di Spanner Vertex AI, consulta la Panoramica dell'integrazione di Spanner Vertex AI.

Puoi integrare il ranking ML utilizzando la funzione Spanner ML.PREDICT con un modello Vertex AI di cui è stato eseguito il deployment.

Implementare il ranking basato sull'ML

  1. Esegui il deployment di un modello di ranking (ad esempio da HuggingFace) a un endpoint Vertex AI.
  2. Crea un oggetto MODEL Spanner che punta all'endpoint Vertex AI. 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 trasmetterli a ML.PREDICT. La funzione restituisce una nuova colonna del 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