Padrões de pesquisa vetorial e de texto completo híbrida

Nesta página, descrevemos como realizar pesquisas híbridas de texto completo e vetoriais no Spanner. A pesquisa híbrida combina a precisão da correspondência de palavras-chave (pesquisa de texto completo, FTS) com a capacidade de recall da correspondência semântica (pesquisa vetorial) para produzir resultados de pesquisa altamente relevantes.

O Spanner é compatível com os seguintes padrões de pesquisa híbrida, que são divididos em três categorias principais:

Categoria Descrição Objetivo principal
Fusion A fusão recupera e classifica documentos de forma independente usando pesquisa por palavra-chave e vetorial e, em seguida, combina (funde) os resultados. Alcance o recall e a relevância máximos combinando vários indicadores de pontuação.
Filtrado As palavras-chave filtram ou refinam o espaço de pesquisa. Verifique se a correspondência de palavras-chave é um requisito ao aproveitar a relevância semântica.
Reclassificação de ML Um modelo de machine learning refina um conjunto inicial de candidatos para um ranking final mais preciso. Alcançar a maior precisão possível para um pequeno conjunto final de resultados.

A pesquisa por fusão envolve executar a pesquisa de texto completo e a pesquisa vetorial de forma independente no mesmo corpus de dados. Em seguida, ele mescla os resultados para criar uma lista classificada única, unificada e altamente relevante.

Embora seja possível executar consultas independentes no lado do cliente, a pesquisa híbrida no Spanner oferece as seguintes vantagens:

  • Simplifica a lógica do aplicativo gerenciando solicitações paralelas e a fusão de resultados no servidor.
  • Evita transferir para o cliente conjuntos de resultados intermediários potencialmente grandes.

É possível usar o SQL para criar métodos de fusão no Spanner. Esta seção fornece exemplos de fusão de classificação recíproca e fusão de pontuação relativa. No entanto, recomendamos avaliar diferentes estratégias de fusão para determinar qual atende melhor aos requisitos do seu aplicativo.

Fusão baseada em classificação

Use a fusão baseada em classificação quando for difícil comparar ou normalizar as pontuações de relevância de diferentes métodos de recuperação (como pontuações da pesquisa de texto completo e distâncias vetoriais) porque elas são medidas em espaços diferentes. Esse método usa a posição de classificação de cada documento de cada extrator para gerar uma pontuação e uma classificação finais.

A fusão de classificação recíproca (RRF) é uma função de fusão baseada em classificação. A pontuação de RRF de um documento é a soma dos recíprocos das classificações de vários extratores, calculada da seguinte forma:

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

Em que:

  • d é o documento.
  • R é o conjunto de mecanismos de recuperação (FTS e pesquisa vetorial).
  • k é uma constante (geralmente definida como 60) usada para moderar a influência de documentos com classificação muito alta.
  • w é a classificação do documento do recuperador r.

Implementar o RRF em uma consulta do Spanner

As métricas de vetor (como APPROX_DOT_PRODUCT) e as pontuações de pesquisa de texto (como SCORE_NGRAMS) operam em escalas incompatíveis. Para resolver isso, o exemplo a seguir implementa o RRF para normalizar os dados com base na posição no ranking, e não nas pontuações brutas.

A consulta usa UNNEST(ARRAY(...) WITH OFFSET para atribuir uma classificação aos 100 principais candidatos de cada método. Em seguida, ela calcula uma pontuação padronizada usando o inverso desses rankings e agrega os resultados para retornar as cinco principais correspondências.

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;

Fusão baseada em pontuação

A fusão baseada em pontuação é eficaz quando as pontuações de relevância de diferentes métodos são comparáveis ou podem ser normalizadas, o que pode permitir uma classificação mais precisa que incorpora o peso de relevância real de cada método.

A fusão de pontuação relativa (RSF) é um método baseado em pontuação que normaliza as pontuações de diferentes métodos em relação às pontuações mais altas e mais baixas em cada método, geralmente usando as funções MIN() e MAX(). A pontuação RSF de um documento recuperado por um conjunto de extratores é calculada da seguinte forma:

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

Em que:

  • d é o documento.
  • R é o conjunto de mecanismos de recuperação (FTS e pesquisa vetorial).
  • w é o peso atribuído a um extrator específico.

Implementar a RSF em uma consulta do Spanner

Para implementar o RSF, é necessário normalizar as pontuações do vetor e do FTS em uma escala comum. O exemplo a seguir calcula as pontuações mínima e máxima em cláusulas WITH separadas para derivar os fatores de normalização. Em seguida, ele combina os resultados usando um FULL OUTER JOIN, somando as pontuações normalizadas da pesquisa de vizinho aproximado mais próximo (ANN, na sigla em inglês), convertida de cosine_distance, e a 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;

As pesquisas filtradas usam a FTS para criar um filtro que reduz o conjunto de documentos considerados para uma pesquisa de vetor de vizinhos k-mais próximos (KNN). Você também pode usar uma pré-ordenação para limitar o tamanho do conjunto de resultados.

A pesquisa de exemplo nesta seção segue estas etapas para restringir o espaço de pesquisa vetorial ao subconjunto de dados que corresponde às palavras-chave:

  • Usa SEARCH (text_tokens, 'Green') para encontrar linhas em que a coluna text_tokens contém o texto Green. As 1.000 principais linhas são retornadas por uma ordem de classificação definida pelo índice de pesquisa.
  • Usa uma função de vetor, DOT_PRODUCT(@vector, embedding), para calcular a similaridade entre o vetor de consulta (@vector) e o vetor de documento armazenado (embedding). Em seguida, ele classifica os resultados e retorna as 10 principais correspondências finais.
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;

Reclassificação por ML

A reclassificação baseada em ML é uma abordagem computacionalmente intensiva, mas altamente precisa. Ele aplica um modelo de machine learning a um pequeno conjunto de candidatos que foi reduzido pela FTS, pela pesquisa vetorial ou por uma combinação das duas. Para mais informações sobre a integração da Vertex AI com o Spanner, consulte a Visão geral da integração da Vertex AI com o Spanner.

É possível integrar o reordenamento por ML usando a função ML.PREDICT do Spanner com um modelo implantado da Vertex AI.

Implementar a reclassificação baseada em ML

  1. Implante um modelo de reclassificação (como da HuggingFace) em um endpoint da Vertex AI.
  2. Crie um objeto MODEL do Spanner que aponte para o endpoint da Vertex AI. Por exemplo, no seguinte exemplo de modelo Reranker:

    • text ARRAY<string(max)> são os documentos.
    • text_pair ARRAY<string(max)> é o texto da consulta no exemplo.
    • score são as pontuações de relevância atribuídas pelo modelo de ML para os pares de textos de entrada.
    CREATE MODEL Reranker
    INPUT (text ARRAY<string(max)>, text_pair ARRAY<string(max)>)
    OUTPUT (score FLOAT32)
    REMOTE
    OPTIONS (
    endpoint = '...'
    );
    
  3. Use uma subconsulta para extrair os candidatos iniciais (como os 100 principais resultados de uma pesquisa de ANN) e transmita-os para ML.PREDICT. A função retorna uma nova coluna de pontuação para a ordenação final.

    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;
    

A seguir