Pesquisar embeddings com a pesquisa de vetor

Neste tutorial, mostramos como realizar uma pesquisa de similaridade em embeddings armazenados em tabelas do BigQuery usando a VECTOR_SEARCH função e um índice vetorial.

A pesquisa de vetor é uma técnica para comparar objetos semelhantes usando embeddings, e é usada para impulsionar produtos do Google, incluindo a Pesquisa Google, o YouTube e o Google Play. É possível usar a pesquisa de vetor para realizar pesquisas semânticas em grande escala ou uma pesquisa híbrida que combina uma pesquisa semântica com uma pesquisa lexical (palavra-chave). Ao usar índices vetoriais com a pesquisa de vetor, você pode aproveitar tecnologias fundamentais, como a indexação de arquivo invertido (IVF) e o algoritmo ScaNN.

A pesquisa de vetor é criada com base em embeddings. Os embeddings são vetores numéricos de alta dimensão que representam uma determinada entidade, como um texto ou um arquivo de áudio. Os modelos de machine learning (ML) usam embeddings para codificar semântica sobre essas entidades, facilitando o entendimento delas e sua comparação. Por exemplo, uma operação comum em modelos de clustering, classificação e recomendação é medir a distância entre vetores em um espaço de embedding para encontrar os itens semanticamente mais parecidos.

Objetivos

  • Realizar uma pesquisa de similaridade em embeddings armazenados em tabelas do BigQuery usando a função VECTOR_SEARCH.
  • Usar um índice vetorial para melhorar o desempenho da pesquisa de vetor.
  • Realizar uma pesquisa que usa um índice vetorial e uma pesquisa que não usa um índice.
  • Avaliar o recall comparando os resultados de pesquisas com um índice e pesquisas sem um índice.

Custos

A função VECTOR_SEARCH usa os preços de computação do BigQuery. Você recebe cobranças pela pesquisa de similaridade, usando preços sob demanda ou de edições.

  • Sob demanda: você recebe cobranças pela quantidade de bytes verificados na tabela de base, no índice e na consulta de pesquisa.
  • Preços de edições: você recebe cobranças pelos slots necessários para concluir o job na edição da reserva. Cálculos de similaridade maiores e mais complexos geram mais cobranças.

Para mais informações, consulte preços do BigQuery.

Antes de começar

  1. No Google Cloud console do, na página do seletor de projetos, escolha ou crie um Google Cloud projeto do.

    Funções necessárias para selecionar ou criar um projeto

    • Selecionar um projeto: a seleção de um projeto não exige um papel específico do IAM. Você pode selecionar qualquer projeto em que tenha recebido um papel.
    • Criar um projeto: para criar um projeto, você precisa do papel de criador de projetos (roles/resourcemanager.projectCreator), que contém a resourcemanager.projects.create permissão. Saiba como conceder papéis.

    Acessar o seletor de projetos

  2. Verifique se o faturamento está ativado para o Google Cloud projeto.

  3. Ative a API BigQuery.

    Funções necessárias para ativar APIs

    Para ativar as APIs, é necessário ter a permissão serviceusage.services.enable. Se você criou o projeto, provavelmente já tem essa permissão pelo papel de proprietário (roles/owner). Caso contrário, você pode receber essa permissão pelo papel de administrador de uso do serviço (roles/serviceusage.serviceUsageAdmin). Saiba como conceder papéis.

    Ativar a API

Funções exigidas

Para conseguir as permissões necessárias para concluir o tutorial, peça ao administrador para conceder a você os seguintes papéis do IAM no projeto:

Para mais informações sobre a concessão de papéis, consulte Gerenciar o acesso a projetos, pastas e organizações.

Também é possível conseguir as permissões necessárias com papéis personalizados ou outros papéis predefinidos.

Criar um conjunto de dados

Para criar um conjunto de dados do BigQuery, selecione uma das seguintes opções:

Console

  1. No Google Cloud console, acesse a página BigQuery.

    Acessar o BigQuery

  2. No painel esquerdo, clique em Explorar:

    Botão destacado para o painel "Explorer".

    Se o painel esquerdo não aparecer, clique em Expandir painel esquerdo para abrir o painel.

  3. Em Explorer, expanda o projeto e clique em Conjuntos de dados.

  4. Na página Conjuntos de dados, clique em Criar conjunto de dados.

  5. No painel Criar conjunto de dados, faça o seguinte:

    • Para o código do conjunto de dados, insira bqml_tutorial.

    • Para Local dos dados, selecione EUA.

    Deixe as configurações padrão restantes como estão.

  6. Clique em Criar conjunto de dados.

bq

Para criar um novo conjunto de dados, use o bq mk --dataset comando.

  1. Crie um conjunto de dados chamado bqml_tutorial com o local dos dados definido como US:

    bq mk --dataset \
      --location=US \
      --description "BigQuery ML tutorial dataset." \
      bqml_tutorial
  2. Confirme se o conjunto de dados foi criado:

    bq ls

API

Chame o datasets.insert método com um recurso de conjunto de dados definido:

{
  "datasetReference": {
     "datasetId": "bqml_tutorial"
  }
}

Criar tabelas para armazenar dados e embeddings

Nesta seção, você cria a tabela patents, que contém embeddings de patentes. Os embeddings são baseados em um subconjunto do conjunto de dados público do Google Patentes. Você também cria a tabela patents2, que contém um embedding de patente para encontrar vizinhos mais próximos.

Para criar as tabelas, siga estas etapas:

  1. Para criar a tabela patents, cole o seguinte no editor de consultas e clique em Executar:

    CREATE TABLE bqml_tutorial.patents AS
    SELECT * FROM `patents-public-data.google_patents_research.publications`
    WHERE ARRAY_LENGTH(embedding_v1) > 0
     AND publication_number NOT IN ('KR-20180122872-A')
    LIMIT 1000000;

    Você recebe uma mensagem de confirmação como esta: This statement created a new table named patents.

  2. Para criar a tabela patents2 que contém um embedding de patente para encontrar vizinhos mais próximos, cole o seguinte no editor de consultas e clique em Executar:

    CREATE TABLE bqml_tutorial.patents2 AS
    SELECT * FROM `patents-public-data.google_patents_research.publications`
    WHERE publication_number = 'KR-20180122872-A';

    Você recebe uma mensagem de confirmação como esta: This statement created a new table named patents2.

Criar um índice vetorial

Quando você usa VECTOR_SEARCH com um índice vetorial, VECTOR_SEARCH usa o método do Vizinho aproximado mais perto para melhorar o desempenho da pesquisa de vetor, mas reduzindo o recall e, portanto, retornando resultados mais aproximados. Sem um índice vetorial, VECTOR_SEARCH usa a pesquisa de força bruta para medir a distância de cada registro.

Nesta seção, você cria o índice vetorial my_index na coluna embedding_v1 da tabela patents. Em seguida, verifique se o índice está disponível.

Para criar o índice vetorial, siga estas etapas:

  1. Para criar o índice vetorial my_index na coluna embedding_v1 da patents tabela, cole o seguinte no editor de consultas e clique em Executar:

    CREATE OR REPLACE VECTOR INDEX my_index ON bqml_tutorial.patents(embedding_v1)
    STORING(publication_number, title)
    OPTIONS(distance_type='COSINE', index_type='IVF');

    Você recebe uma mensagem de confirmação como esta: The vector index creation on table bqml_tutorial.patents was initiated. Please query bqml_tutorial.INFORMATION_SCHEMA.VECTOR_INDEXES to check the progress of the index.

  2. Para confirmar se o índice vetorial está pronto, cole o seguinte no editor de consultas e clique em Executar:

    SELECT * FROM bqml_tutorial.INFORMATION_SCHEMA.VECTOR_INDEXES;

    Nos resultados da consulta, verifique se o index_status é ACTIVE e se o valor coverage_percentage é 100. Pode levar vários minutos para que coverage_percentage chegue a 100.

Usar a função VECTOR_SEARCH com um índice

Depois que o índice vetorial for criado e preenchido, use a função VECTOR_SEARCH para encontrar o vizinho mais próximo do embedding na coluna embedding_v1 da tabela patents2. Como essa consulta usa o índice vetorial na pesquisa, então VECTOR_SEARCH usa um método do Vizinho aproximado mais perto para encontrar o vizinho mais próximo do embedding.

Para usar a função VECTOR_SEARCH com um índice, cole o seguinte no editor de consultas e clique em Executar:

SELECT query.publication_number AS query_publication_number,
  query.title AS query_title,
  base.publication_number AS base_publication_number,
  base.title AS base_title,
  distance
FROM
  VECTOR_SEARCH(
    TABLE bqml_tutorial.patents,
    'embedding_v1',
    TABLE bqml_tutorial.patents2,
    top_k => 5,
    distance_type => 'COSINE',
    options => '{"fraction_lists_to_search": 0.005}');

Os resultados são semelhantes aos seguintes:

+--------------------------+-------------------------------------------------------------+-------------------------+--------------------------------------------------------------------------------------------------------------------------+---------------------+
| query_publication_number |                         query_title                         | base_publication_number |                                                        base_title                                                        |      distance       |
+--------------------------+-------------------------------------------------------------+-------------------------+--------------------------------------------------------------------------------------------------------------------------+---------------------+
| KR-20180122872-A         | Rainwater management system based on rainwater keeping unit | CN-106599080-B          | A kind of rapid generation for keeping away big vast transfer figure based on GIS                                        | 0.14471956347590609 |
| KR-20180122872-A         | Rainwater management system based on rainwater keeping unit | CN-114118544-A          | Urban waterlogging detection method and device                                                                           | 0.17472108931171348 |
| KR-20180122872-A         | Rainwater management system based on rainwater keeping unit | KR-20200048143-A        | Method and system for mornitoring dry stream using unmanned aerial vehicle                                               | 0.17561990745619782 |
| KR-20180122872-A         | Rainwater management system based on rainwater keeping unit | KR-101721695-B1         | Urban Climate Impact Assessment method of Reflecting Urban Planning Scenarios and Analysis System using the same         | 0.17696129365559843 |
| KR-20180122872-A         | Rainwater management system based on rainwater keeping unit | CN-109000731-B          | The experimental rig and method that research inlet for stom water chocking-up degree influences water discharged amount | 0.17902723269642917 |
+--------------------------+-------------------------------------------------------------+-------------------------+--------------------------------------------------------------------------------------------------------------------------+---------------------+

Usar a função VECTOR_SEARCH com força bruta

Nesta seção, você usa a função VECTOR_SEARCH para encontrar o vizinho mais próximo do embedding na coluna embedding_v1 da tabela patents2. Essa consulta não usa o índice vetorial na pesquisa. Portanto, VECTOR_SEARCH encontra o vizinho exato mais próximo do embedding.

Para usar VECTOR_SEARCH com força bruta, cole o seguinte no editor de consultas e clique em Executar:

SELECT query.publication_number AS query_publication_number,
  query.title AS query_title,
  base.publication_number AS base_publication_number,
  base.title AS base_title,
  distance
FROM
  VECTOR_SEARCH(
    TABLE bqml_tutorial.patents,
    'embedding_v1',
    TABLE bqml_tutorial.patents2,
    top_k => 5,
    distance_type => 'COSINE',
    options => '{"use_brute_force":true}');

Os resultados são semelhantes aos seguintes:

+--------------------------+-------------------------------------------------------------+-------------------------+--------------------------------------------------------------------------------------------------------------------------+---------------------+
| query_publication_number |                         query_title                         | base_publication_number |                                                        base_title                                                        |      distance       |
+--------------------------+-------------------------------------------------------------+-------------------------+--------------------------------------------------------------------------------------------------------------------------+---------------------+
| KR-20180122872-A         | Rainwater management system based on rainwater keeping unit | CN-106599080-B          | A kind of rapid generation for keeping away big vast transfer figure based on GIS                                        |  0.1447195634759062 |
| KR-20180122872-A         | Rainwater management system based on rainwater keeping unit | CN-114118544-A          | Urban waterlogging detection method and device                                                                           |  0.1747210893117136 |
| KR-20180122872-A         | Rainwater management system based on rainwater keeping unit | KR-20200048143-A        | Method and system for mornitoring dry stream using unmanned aerial vehicle                                               | 0.17561990745619782 |
| KR-20180122872-A         | Rainwater management system based on rainwater keeping unit | KR-101721695-B1         | Urban Climate Impact Assessment method of Reflecting Urban Planning Scenarios and Analysis System using the same         | 0.17696129365559843 |
| KR-20180122872-A         | Rainwater management system based on rainwater keeping unit | CN-109000731-B          | The experimental rig and method that research inlet for stom water chocking-up degree influences water discharged amount | 0.17902723269642928 |
+--------------------------+-------------------------------------------------------------+-------------------------+--------------------------------------------------------------------------------------------------------------------------+---------------------+

Avaliar o recall

Quando você realiza uma pesquisa de vetor com um índice, ela retorna resultados aproximados, mas reduz o recall. É possível calcular o recall comparando os resultados retornados pela pesquisa de vetor com um índice e os resultados retornados pela pesquisa de vetor com força bruta. O valor publication_number identifica exclusivamente uma patente. Portanto, ele é usado para comparação na consulta a seguir.

Para avaliar o recall, cole o seguinte no editor de consultas e clique em Executar:

WITH approx_results AS (
  SELECT query.publication_number AS query_publication_number,
    base.publication_number AS base_publication_number
  FROM
    VECTOR_SEARCH(
      TABLE bqml_tutorial.patents,
      'embedding_v1',
      TABLE bqml_tutorial.patents2,
      top_k => 5,
      distance_type => 'COSINE',
      options => '{"fraction_lists_to_search": 0.005}')
),
  exact_results AS (
  SELECT query.publication_number AS query_publication_number,
    base.publication_number AS base_publication_number
  FROM
    VECTOR_SEARCH(
      TABLE bqml_tutorial.patents,
      'embedding_v1',
      TABLE bqml_tutorial.patents2,
      top_k => 5,
      distance_type => 'COSINE',
      options => '{"use_brute_force":true}')
)

SELECT
  a.query_publication_number,
  SUM(CASE WHEN a.base_publication_number = e.base_publication_number THEN 1 ELSE 0 END) / 5 AS recall
FROM exact_results e LEFT JOIN approx_results a
  ON e.query_publication_number = a.query_publication_number
GROUP BY a.query_publication_number;

Os resultados têm a seguinte aparência:

+--------------------------+--------+
| query_publication_number | recall |
+--------------------------+--------+
| KR-20180122872-A         |    1.0 |
+--------------------------+--------+

Se o recall for menor do que o desejado, será possível aumentar o valor de fraction_lists_to_search, mas você terá uma latência e um uso de recursos potencialmente maiores. Para ajustar a pesquisa de vetor, tente várias execuções de VECTOR_SEARCH com diferentes valores de argumento, salve os resultados em tabelas e depois os compare.

Limpar

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados neste tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.

  1. No Google Cloud console, acesse a página Gerenciar recursos.

    Acessar "Gerenciar recursos"

  2. Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir.
  3. Na caixa de diálogo, digite o ID do projeto e clique em Desativar para excluir o projeto.

Como alternativa, para manter o projeto e excluir os recursos usados neste tutorial, siga estas etapas:

  1. Acesse a página BigQuery.

    Acessar o BigQuery

  2. No painel esquerdo, expanda o projeto e clique em Conjuntos de dados.

  3. Para o conjunto de dados bqml_tutorial, clique em Abrir ações > Excluir.

  4. Na caixa de diálogo Excluir conjunto de dados, clique em Excluir para confirmar.

A seguir