Encontrar vizinhos aproximados mais próximos (ANN) e embeddings de vetor de consulta

Esta página descreve como encontrar vizinhos mais próximos aproximados (ANN) e consultar embeddings de vetor usando as funções de distância de ANN.

Quando um conjunto de dados é pequeno, você pode usar K-vizinhos mais próximos (KNN) para encontrar os vetores k-mais próximos exatos. No entanto, à medida que o conjunto de dados cresce, a latência e o custo de uma pesquisa de KNN também aumentam. É possível usar o ANN para encontrar os k-vizinhos mais próximos aproximados com latência e custo significativamente reduzidos.

Em uma pesquisa de ANN, os vetores k retornados não são os k vizinhos mais próximos verdadeiros porque a pesquisa de ANN calcula distâncias aproximadas e pode não analisar todos os vetores no conjunto de dados. Às vezes, alguns vetores que não estão entre os k vizinhos mais próximos são retornados. Isso é conhecido como perda de recall. A quantidade de perda de recall aceitável depende do caso de uso, mas, na maioria das vezes, perder um pouco de recall em troca de um desempenho aprimorado do banco de dados é uma compensação aceitável.

Para mais detalhes sobre as funções de distância aproximada compatíveis com o Spanner, consulte as seguintes páginas de referência para seu dialeto de banco de dados:

Consultar embeddings de vetor

O Spanner acelera as pesquisas de vetor de vizinho mais próximo aproximado (ANN) usando um índice de vetor. É possível usar um índice de vetor para consultar embeddings de vetor. Para consultar embeddings de vetor, primeiro crie um índice de vetor. Em seguida, use uma das três funções de distância aproximada para encontrar o ANN.

As restrições ao usar as funções de distância aproximada incluem:

  • A função de distância aproximada precisa calcular a distância entre uma coluna de incorporação e uma expressão constante (por exemplo, um parâmetro ou um literal).
  • A saída da função de distância aproximada precisa ser usada em uma cláusula ORDER BY como a única chave de classificação, e um LIMIT precisa ser especificado após o ORDER BY.
  • A consulta precisa filtrar explicitamente as linhas que não estão indexadas. Na maioria dos casos, isso significa que a consulta precisa incluir uma cláusula WHERE <column_name> IS NOT NULL que corresponda à definição do índice de vetor, a menos que a coluna já esteja marcada como NOT NULL na definição da tabela.

Para uma lista detalhada de limitações, consulte a página de referência da função de distância aproximada.

Exemplos

Considere uma tabela Documents com uma coluna DocEmbedding de incorporações de texto pré-calculadas da coluna de bytes DocContents e uma coluna NullableDocEmbedding preenchida de outras fontes que podem ser nulas.

GoogleSQL

CREATE TABLE Documents (
  UserId       INT64 NOT NULL,
  DocId        INT64 NOT NULL,
  Author       STRING(1024),
  DocContents  BYTES(MAX),
  DocEmbedding ARRAY<FLOAT32> NOT NULL,
  NullableDocEmbedding ARRAY<FLOAT32>,
  WordCount    INT64
) PRIMARY KEY (UserId, DocId);

PostgreSQL

CREATE TABLE documents (
  user_id      bigint not null,
  doc_id       bigint not null,
  author       varchar(1024),
  doc_contents bytea,
  doc_embedding float4[] not null,
  nullable_doc_embedding float4[],
  word_count   bigint,
  PRIMARY KEY (user_id, doc_id)
);

Para pesquisar os 100 vetores mais próximos de [1.0, 2.0, 3.0]:

GoogleSQL

SELECT DocId
FROM Documents
WHERE WordCount > 1000
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
  ARRAY<FLOAT32>[1.0, 2.0, 3.0], DocEmbedding,
  options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100

PostgreSQL

SELECT doc_id
FROM documents
WHERE word_count > 1000
ORDER BY spanner.approx_euclidean_distance(
  ARRAY[1.0, 2.0, 3.0]::float4[], doc_embedding,
  options=>jsonb'{"num_leaves_to_search": 10}'
)
LIMIT 100;

Se a coluna de incorporação for anulável:

GoogleSQL

SELECT DocId
FROM Documents
WHERE NullableDocEmbedding IS NOT NULL AND WordCount > 1000
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
  ARRAY<FLOAT32>[1.0, 2.0, 3.0], NullableDocEmbedding,
  options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100

PostgreSQL

SELECT doc_id
FROM documents
WHERE nullable_doc_embedding IS NOT NULL AND word_count > 1000
ORDER BY spanner.approx_euclidean_distance(
  ARRAY[1.0, 2.0, 3.0]::float4[], nullable_doc_embedding,
  options=>jsonb'{"num_leaves_to_search": 10}'
)
LIMIT 100;

A seguir