Gerenciar índices vetoriais
Para enviar feedback ou solicitar suporte para esse recurso, envie um e-mail para bq-vector-search@google.com.
Neste documento, descrevemos como criar e gerenciar índices vetoriais.
Um índice vetorial é uma estrutura de dados projetada para permitir que a função VECTOR_SEARCH
execute uma pesquisa vetorial mais eficiente de embeddings. Quando VECTOR_SEARCH
pode usar um índice vetorial, a função usa a técnica de pesquisa do Vizinho aproximado mais perto para melhorar o desempenho da pesquisa, mas reduzindo o recall e, portanto, retornando resultados mais aproximados.
Papéis e permissões
Para criar um índice vetorial, é necessário ter a permissão bigquery.tables.createIndex
do IAM na tabela em que você está criando o índice. Para remover um índice vetorial, é necessário ter a permissão bigquery.tables.deleteIndex
. Cada um dos papéis do IAM predefinidos a seguir inclui as permissões necessárias para trabalhar com índices vetoriais:
- Proprietário de dados do BigQuery (
roles/bigquery.dataOwner
) - Editor de dados do BigQuery (
roles/bigquery.dataEditor
)
Criar um índice vetorial
Para criar um índice de vetor, use a
instrução de linguagem de definição de dados (DDL, na sigla em inglês)
CREATE VECTOR INDEX
:
Acessar a página do BigQuery.
No editor de consultas, execute a seguinte instrução SQL:
CREATE [ OR REPLACE ] VECTOR INDEX [ IF NOT EXISTS ] INDEX_NAME ON DATASET_NAME.TABLE_NAME(COLUMN_NAME) STORING(STORED_COLUMN_NAME [, ...]) OPTIONS(index_type = INDEX_TYPE, distance_type = DISTANCE_TYPE, ivf_options = '{"num_lists":NUM_LISTS}')
Substitua:
INDEX_NAME
: o nome do índice vetorial que você está criando. Como o índice é sempre criado no mesmo projeto e conjunto de dados da tabela base, não é necessário especificá-los no nome.DATASET_NAME
: o nome do conjunto de dados que contém a tabela.TABLE_NAME
: o nome da tabela que contém a coluna com dados de embeddings.COLUMN_NAME
: o nome de uma coluna que contém os dados de embeddings. A coluna precisa ter um tipo deARRAY<FLOAT64>
. A coluna não pode ter campos filhos. Todos os elementos na matriz precisam ser diferentes deNULL
, e todos os valores na coluna precisam ter as mesmas dimensões da matriz.STORED_COLUMN_NAME
: o nome de uma coluna de nível superior na tabela a ser armazenada no índice de vetor. O tipo de coluna não pode serRANGE
. As colunas armazenadas não serão usadas se a tabela tiver uma política de acesso no nível da linha ou se a coluna tiver uma tag de política. Para informações sobre como ativar colunas armazenadas, consulte Armazenar colunas e pré-filtrar.INDEX_TYPE
: o algoritmo a ser usado para criar o índice vetorial.IVF
é o único valor compatível. EspecificarIVF
cria o índice vetorial como índice de arquivo invertido (IVF, na sigla em inglês). Um IVF usa um algoritmo k-means para agrupar em clusters os dados vetoriais e, em seguida, particiona esses dados com base nesses clusters. Quando você usa a funçãoVECTOR_SEARCH
para pesquisar os dados vetoriais, ela pode usar essas partições para reduzir a quantidade de dados que precisa ler a fim de determinar um resultado.DISTANCE_TYPE
: especifica o tipo de distância padrão a ser usado na pesquisa de vetor com esse índice. Os valores compatíveis sãoEUCLIDEAN
eCOSINE
. O padrão éEUCLIDEAN
.A criação do índice sempre usa a distância
EUCLIDEAN
para o treinamento, mas a distância usada na funçãoVECTOR_SEARCH
pode ser diferente.Se você especificar um valor para o argumento
distance_type
da funçãoVECTOR_SEARCH
, esse valor será usado no lugar deDISTANCE_TYPE
.NUM_LISTS
: um valor deINT64
menor ou igual a 5.000 que determina quantas listas o algoritmo de IVF cria. O algoritmo de IVF divide todo o espaço de dados em um número de listas igual aNUM_LISTS
. Assim, os pontos de dados mais próximos uns dos outros têm mais chances de serem colocados na mesma lista. SeNUM_LISTS
for pequeno, você terá menos listas com mais pontos de dados, enquanto um valor maior criará mais listas com menos pontos de dados.É possível usar
NUM_LISTS
em combinação com o argumentofraction_lists_to_search
na funçãoVECTOR_SEARCH
para criar uma pesquisa de vetor eficiente. Se você tiver dados distribuídos em muitos grupos pequenos no espaço de embedding, especifique umNUM_LISTS
alto para criar um índice com mais listas e especifique um valorfraction_lists_to_search
menor para verificar menos listas na pesquisa de vetor. Use um valorNUM_LISTS
menor e um valorfraction_lists_to_search
maior quando seus dados forem distribuídos em menos grupos maiores. Usar um valornum_lists
alto pode fazer com que o índice vetorial demore mais para ser criado.Se você não especificar
NUM_LISTS
, o BigQuery calculará um valor apropriado.
O exemplo a seguir cria um índice vetorial na coluna embedding
de my_table
:
CREATE TABLE my_dataset.my_table(embedding ARRAY<FLOAT64>); CREATE VECTOR INDEX my_index ON my_dataset.my_table(embedding) OPTIONS(index_type = 'IVF');
O exemplo a seguir cria um índice vetorial na coluna embedding
de my_table
e especifica o tipo de distância a ser usado e as opções de IVF:
CREATE TABLE my_dataset.my_table(embedding ARRAY<FLOAT64>); CREATE VECTOR INDEX my_index ON my_dataset.my_table(embedding) OPTIONS(index_type = 'IVF', distance_type = 'COSINE', ivf_options = '{"num_lists": 2500}')
Armazenar colunas e pré-filtrar
Para melhorar ainda mais a eficiência do seu índice de vetor, especifique colunas da sua tabela base para armazenar no índice de vetor. O uso de colunas armazenadas pode otimizar consultas que chamam a função VECTOR_SEARCH
das seguintes maneiras:
A função
VECTOR_SEARCH
gera uma estrutura chamadabase
que contém todas as colunas da tabela base. Sem colunas armazenadas, uma mesclagem potencialmente cara é necessária para recuperar as colunas armazenadas embase
. Se a consulta selecionar apenas colunas armazenadas debase
, o BigQuery otimizará a consulta para eliminar essa junção.Em vez de pesquisar uma tabela inteira, você pode chamar a função
VECTOR_SEARCH
em uma instrução de consulta que pré-filtre a tabela base com uma cláusulaWHERE
. Se a tabela tiver um índice e você filtrar apenas as colunas armazenadas, o BigQuery otimizará a consulta filtrando os dados antes da pesquisa e usando o índice para pesquisar o conjunto de resultados menor. Se você filtrar colunas que não são armazenadas, o BigQuery aplicará o filtro após a pesquisa da tabela ou pós-filtros.A pós-filtragem é menos eficiente e pode causar menos de
top_k
correspondências no conjunto de resultados. Em alguns casos, a pré-filtragem também pode reduzir o tamanho do conjunto de resultados. Se isso acontecer, tente aumentar o valor defraction_lists_to_search
na chamada paraVECTOR_SEARCH
.
Para armazenar colunas, liste-as na cláusula STORING
da
instrução DDL CREATE VECTOR INDEX
.
Armazenar colunas aumenta o tamanho do índice vetorial. Por isso, é melhor armazenar apenas as colunas mais usadas ou filtradas.
O exemplo a seguir cria um índice de vetor com colunas armazenadas e, em seguida, explica o comportamento de diferentes tipos de pesquisas de vetor:
-- Create a table that contains an embedding. CREATE TABLE my_dataset.my_table(embedding ARRAY<FLOAT64>, type STRING, creation_time DATETIME, id INT64); -- Create a query table that contains an embedding. CREATE TABLE my_dataset.my_testdata(embedding ARRAY<FLOAT64>, test_id INT64); -- Create a vector index with stored columns. CREATE VECTOR INDEX my_index ON my_dataset.my_table(embedding) STORING (type, creation_time) OPTIONS (index_type = 'IVF'); -- Select only stored columns from a vector search to avoid an expensive join. SELECT query, base.type, distance FROM VECTOR_SEARCH( TABLE my_dataset.my_table, 'embedding' TABLE my_dataset.my_testdata); -- Pre-filter on a stored column. The index speeds up the query. SELECT * FROM VECTOR_SEARCH( (SELECT * FROM my_dataset.my_table WHERE type = 'animal'), 'embedding', TABLE my_dataset.my_testdata); -- Filter on a column that isn't stored. The index is used to search the -- entire table, and then the results are post-filtered. You might see fewer -- than 5 matches returned for some embeddings. SELECT query.test_id, base.type, distance FROM VECTOR_SEARCH( (SELECT * FROM my_dataset.my_table WHERE id = 123), 'embedding', TABLE my_dataset.my_testdata, top_k => 5); -- Use post-filters. The index is used, but the entire table is searched and -- the post-filtering might reduce the number of results. SELECT query.test_id, base.type, distance FROM VECTOR_SEARCH( TABLE my_dataset.my_table, 'embedding', TABLE my_dataset.my_testdata, top_k => 5) WHERE base.type = 'animal'; -- Use pre-filters with brute force. The data is filtered and then searched -- with brute force for exact results. SELECT query.test_id, base.type, distance FROM VECTOR_SEARCH( (SELECT * FROM my_dataset.my_table WHERE id = 123), 'embedding', TABLE my_dataset.my_testdata, options => '{"use_brute_force":true}');
Limitações
- Não aplique pré-filtros à coluna de incorporação da tabela base.
- Não é possível usar visualizações lógicas no seu pré-filtro.
- Se o pré-filtro tiver uma subconsulta, ela poderá interferir no uso do índice.
- Se você atualizar o esquema de colunas armazenadas do tipo
STRUCT
, o índice de vetor poderá ser inutilizável. - Se você selecionar uma coluna do tipo
STRUCT
na saídaquery
de uma consultaVECTOR_SEARCH
em uma tabela que tenha um índice com colunas armazenadas, a consulta inteira poderá falhar.
A atualização do índice
Os índices vetoriais são totalmente gerenciados pelo BigQuery e atualizados automaticamente quando a tabela indexada é alterada. Se você excluir a coluna indexada de uma tabela ou renomear essa tabela, o índice vetorial será excluído automaticamente.
Se você criar um índice vetorial em uma tabela com menos de 10 MB, ele não será preenchido. Da mesma forma, se você excluir dados de uma tabela indexada e o tamanho dela ficar abaixo de 10 MB, o índice vetorial será desativado temporariamente. Nesse caso, as consultas de pesquisa de vetor não usam o índice, e o código indexUnusedReasons
na seção vectorSearchStatistics
do recurso Job
é BASE_TABLE_TOO_SMALL
. Sem o índice, VECTOR_SEARCH
volta automaticamente a usar força bruta para encontrar os vizinhos de embeddings mais perto.
As consultas que usam a função
VECTOR_SEARCH
sempre retornam resultados corretos, mesmo que parte dos dados ainda não tenha sido indexada.
Encontrar informações sobre índices vetoriais
É possível verificar a existência e a prontidão de um índice vetorial consultando INFORMATION_SCHEMA
. As visualizações a seguir contêm metadados sobre índices vetoriais:
A visualização
INFORMATION_SCHEMA.VECTOR_INDEXES
tem informações sobre os índices vetoriais em um conjunto de dados.Depois que a instrução
CREATE VECTOR INDEX
for concluída, o índice ainda precisará ser preenchido antes de ser usado. É possível usar as colunaslast_refresh_time
ecoverage_percentage
para verificar a prontidão de um índice vetorial. Se o índice vetorial não estiver pronto, ainda será possível usar a funçãoVECTOR_SEARCH
em uma tabela. Talvez ela seja executada mais lentamente sem o índice.A visualização
INFORMATION_SCHEMA.VECTOR_INDEX_COLUMNS
tem informações sobre as colunas indexadas por vetor de todas as tabelas em um conjunto de dados.A visualização
INFORMATION_SCHEMA.VECTOR_INDEX_OPTIONS
tem informações sobre as opções usadas pelos índices vetoriais em um conjunto de dados.
Exemplos de índice vetorial
O exemplo a seguir mostra todos os índices vetoriais ativos das tabelas no conjunto de dados my_dataset
, localizado no projeto my_project
. Isso inclui os nomes, as instruções DDL usadas para criá-los e a porcentagem de cobertura. Se uma tabela base indexada for menor que 10 MB, o índice não será preenchido. Nesse caso, o valor de coverage_percentage
será 0.
SELECT table_name, index_name, ddl, coverage_percentage FROM my_project.my_dataset.INFORMATION_SCHEMA.VECTOR_INDEXES WHERE index_status = 'ACTIVE';
O resultado será semelhante ao seguinte:
+-------------+-------------+-----------------------------------------------------------------------------------------------+---------------------+ | table_name | index_name | ddl | coverage_percentage | +-------------+-------------+-----------------------------------------------------------------------------------------------+---------------------+ | small_table | myindex1 | CREATE VECTOR INDEX `myindex1` ON `my_project.my_dataset.small_table`(embeddings) | 100 | | | | OPTIONS (distance_type = 'EUCLIDEAN', index_type = 'IVF', ivf_options = '{"numLists": 3}') | | +-------------+-------------+-----------------------------------------------------------------------------------------------+---------------------+ | large_table | myindex2 | CREATE VECTOR INDEX `myindex2` ON `my_project.my_dataset.large_table`(vectors) | 42 | | | | OPTIONS (distance_type = 'EUCLIDEAN', index_type = 'IVF', ivf_options = '{"numLists": 12}') | | +-------------+-------------+-----------------------------------------------------------------------------------------------+---------------------+
Exemplos de colunas de índice vetorial
A consulta a seguir extrai informações de colunas que têm índices vetoriais:
SELECT table_name, index_name, index_column_name, index_field_path FROM my_project.dataset.INFORMATION_SCHEMA.VECTOR_INDEX_COLUMNS;
O resultado será semelhante ao seguinte:
+------------+------------+-------------------+------------------+ | table_name | index_name | index_column_name | index_field_path | +------------+------------+-------------------+------------------+ | table1 | indexa | a | a | | table2 | indexb | b | b | | table3 | indexc | c | c | +------------+------------+-------------------+------------------+
Exemplos de opções de índice vetorial
A consulta a seguir extrai informações de opções de índice vetorial:
SELECT table_name, index_name, option_name, option_type, option_value FROM my_project.dataset.INFORMATION_SCHEMA.VECTOR_INDEX_OPTIONS;
O resultado será semelhante ao seguinte:
+------------+------------+------------------+------------------+--------------------+ | table_name | index_name | option_name | option_type | option_value | +------------+------------+------------------+------------------+--------------------+ | table1 | indexa | distance_type | STRING | EUCLIDEAN | | table1 | indexa | index_type | STRING | IVF | | table2 | indexb | ivf_options | STRING | {"num_lists": 100} | | table2 | indexb | index_type | STRING | IVF | +------------+------------+------------------+------------------+--------------------+
Uso do índice vetorial
As informações sobre o uso do índice vetorial estão disponíveis nos metadados do job que executou a consulta de pesquisa de vetor. Para ver os metadados do job, use o console do Google Cloud, a ferramenta de linha de comando bq, a API BigQuery ou as bibliotecas de cliente.
Ao usar o console do Google Cloud, é possível encontrar informações sobre o uso do índice vetorial nos campos Modo de uso do índice vetorial e Motivos da não utilização do índice vetorial.
Ao usar a ferramenta bq ou a API BigQuery, você encontra informações sobre o uso do índice vetorial na seção VectorSearchStatistics
do recurso Job
.
O modo de uso do índice indica se um índice vetorial foi usado fornecendo um dos seguintes valores:
UNUSED
: nenhum índice vetorial foi usado.PARTIALLY_USED
: algumas funçõesVECTOR_SEARCH
na consulta usaram índices vetoriais e outras não.FULLY_USED
: cada funçãoVECTOR_SEARCH
na consulta usou um índice vetorial.
Quando o valor do modo de uso do índice é UNUSED
ou PARTIALLY_USED
, os motivos da não utilização do índice indicam por que os índices vetoriais não foram usados na consulta.
Por exemplo, os resultados a seguir retornados por bq show --format=prettyjson -j my_job_id
mostram que o índice não foi usado porque a opção use_brute_force
foi especificada na função VECTOR_SEARCH
:
"vectorSearchStatistics": { "indexUnusedReasons": [ { "baseTable": { "datasetId": "my_dataset", "projectId": "my_project", "tableId": "my_table" }, "code": "INDEX_SUPPRESSED_BY_FUNCTION_OPTION", "message": "No vector index was used for the base table `my_project:my_dataset.my_table` because use_brute_force option has been specified." } ], "indexUsageMode": "UNUSED" }
Opções de gerenciamento de índice
Para criar índices vetoriais e fazer o BigQuery mantê-los, há duas opções:
- Use o pool de slots compartilhado padrão: quando os dados que você planeja indexar estiverem abaixo do limite por organização, será possível usar o pool de slots compartilhado para gerenciamento de índices.
- Use sua própria reserva: para atingir um progresso de indexação mais previsível e consistente em cargas de trabalho de produção maiores, use suas próprias reservas para o gerenciamento de índices.
Usar slots compartilhados
Se você não tiver configurado o projeto para usar uma reserva dedicada para indexação, o gerenciamento de índices será processado no pool de slots compartilhado e sem custos financeiros, sujeito às restrições a seguir.
Se você adicionar dados a uma tabela base que faça com que o tamanho total das tabelas
indexadas excedam o limite da sua organização,
o BigQuery pausará o gerenciamento de índice
em todas as tabelas indexadas. Quando isso acontece, o campo index_status
na visualização INFORMATION_SCHEMA.VECTOR_INDEXES
exibe PENDING DISABLEMENT
e o índice é colocado em fila para exclusão. Embora o índice esteja com a desativação pendente, ele ainda é usado nas consultas e há cobrança pelo armazenamento do índice.
Depois que um índice é excluído, o campo index_status
mostra o índice como TEMPORARILY DISABLED
. Nesse estado, as consultas não usam o índice e não há cobrança pelo armazenamento dele. Nesse caso, o
código IndexUnusedReason
é BASE_TABLE_TOO_LARGE
.
Se você excluir os dados da tabela base e o tamanho total das tabelas base indexadas
estiver abaixo do limite por organização, o gerenciamento de índice será retomado para
todas as tabelas base indexadas. O campo index_status
na visualização INFORMATION_SCHEMA.VECTOR_INDEXES
é ACTIVE
, as consultas podem usar o índice e há cobrança pelo armazenamento do índice.
O BigQuery não oferece garantias sobre a capacidade disponível do pool compartilhado ou a capacidade de indexação que você vê. Para aplicativos de produção, convém usar slots dedicados para o processamento de índice.
Usar sua própria reserva
Em vez de usar o pool de slots compartilhado padrão, é possível designar sua própria reserva para indexar as tabelas. Usar sua própria reserva garante um desempenho previsível e consistente de jobs de gerenciamento de índice, como criação, atualização e otimizações em segundo plano.
- Não há limites de tamanho de tabela quando um job de indexação for executado na reserva.
- O uso da sua própria reserva oferece flexibilidade no gerenciamento do índice. Se você precisar criar um índice muito grande ou fazer uma grande atualização para uma tabela indexada, adicione temporariamente mais slots à atribuição.
Para indexar as tabelas em um projeto com uma reserva designada, crie uma reserva na região onde as tabelas base estão localizadas. Em seguida, atribua o projeto à reserva com o job_type
definido como BACKGROUND
:
SQL
Use a
instrução DDL CREATE ASSIGNMENT
.
No Console do Google Cloud, acesse a página BigQuery.
No editor de consultas, digite a seguinte instrução:
CREATE ASSIGNMENT `ADMIN_PROJECT_ID.region-LOCATION.RESERVATION_NAME.ASSIGNMENT_ID` OPTIONS ( assignee = 'projects/PROJECT_ID', job_type = 'BACKGROUND');
Substitua:
ADMIN_PROJECT_ID
: o ID do projeto de administração que é proprietário do recurso de reserva.LOCATION
: o local da reservaRESERVATION_NAME
: o nome da reservaASSIGNMENT_ID
: o ID da atribuição.Ele precisa ser exclusivo do projeto e do local, começar e terminar com uma letra minúscula ou um número e conter apenas letras minúsculas, números e traços.
PROJECT_ID
: o ID do projeto que contém as tabelas a serem indexadas. Este projeto está atribuído à reserva.
Clique em
Executar.
Para mais informações sobre como executar consultas, acesse Executar uma consulta interativa.
bq
Use o comando bq mk
:
bq mk \ --project_id=ADMIN_PROJECT_ID \ --location=LOCATION \ --reservation_assignment \ --reservation_id=RESERVATION_NAME \ --assignee_id=PROJECT_ID \ --job_type=BACKGROUND \ --assignee_type=PROJECT
Substitua:
ADMIN_PROJECT_ID
: o ID do projeto de administração que é proprietário do recurso de reserva.LOCATION
: o local da reservaRESERVATION_NAME
: o nome da reservaPROJECT_ID
: o ID do projeto a ser atribuído a essa reserva.
Veja seus jobs de indexação
Um novo job de indexação é criado sempre que um índice é criado ou atualizado em uma única tabela. Para ver informações sobre o job, consulte as visualizações INFORMATION_SCHEMA.JOBS*
. É possível filtrar por jobs de indexação definindo job_type IS NULL AND SEARCH(job_id, '`search_index`')
na cláusula WHERE
da sua consulta. O exemplo a seguir lista os cinco jobs de indexação mais recentes no projeto my_project
:
SELECT * FROM region-us.INFORMATION_SCHEMA.JOBS WHERE project_id = 'my_project' AND job_type IS NULL AND SEARCH(job_id, '`search_index`') ORDER BY creation_time DESC LIMIT 5;
Escolha o tamanho da reserva
Para escolher o número certo de slots para sua reserva, considere quando os jobs de gerenciamento de índice são executados, quantos slots eles usam e como é o uso ao longo do tempo. O BigQuery aciona um job de gerenciamento de índice nas seguintes situações:
- Você cria um índice em uma tabela.
- Os dados são modificados em uma tabela indexada.
- O esquema de uma tabela muda, e isso afeta as colunas que são indexadas.
- Os dados e metadados do índice são otimizados ou atualizados periodicamente.
O número de slots necessários para um job de gerenciamento de índice em uma tabela depende dos seguintes fatores:
- o tamanho da tabela
- a taxa de ingestão de dados para a tabela
- a taxa de instruções DML aplicadas à tabela
- o atraso aceitável para a criação e manutenção do índice
- A complexidade do índice, normalmente determinada por atributos dos dados, como o número de termos duplicados
Monitore o uso e o progresso
A melhor maneira de avaliar o número de slots necessários para executar com eficiência os jobs de gerenciamento de índice é monitorar a utilização deles e ajustar o tamanho da reserva adequadamente. A consulta a seguir produz o uso diário de slots para jobs de gerenciamento de índice. Somente os últimos 30 dias são incluídos na região us-west1
:
SELECT TIMESTAMP_TRUNC(job.creation_time, DAY) AS usage_date, -- Aggregate total_slots_ms used for index-management jobs in a day and divide -- by the number of milliseconds in a day. This value is most accurate for -- days with consistent slot usage. SAFE_DIVIDE(SUM(job.total_slot_ms), (1000 * 60 * 60 * 24)) AS average_daily_slot_usage FROM `region-us-west1`.INFORMATION_SCHEMA.JOBS job WHERE project_id = 'my_project' AND job_type IS NULL AND SEARCH(job_id, '`search_index`') GROUP BY usage_date ORDER BY usage_date DESC limit 30;
Quando não há slots suficientes para executar jobs de gerenciamento de índice, um índice pode ficar dessincronizado com a tabela, e os jobs de indexação poderão falhar. Nesse caso, o BigQuery recria o índice do zero. Para evitar um índice não sincronizado, verifique se você tem slots suficientes para oferecer suporte a atualizações de índice da ingestão e da otimização de dados. Para mais informações sobre o monitoramento do uso do slot, consulte gráficos de recursos de administrador.
Excluir um índice vetorial
Quando você não precisar mais de um índice vetorial ou quiser alterar qual coluna será indexada em uma tabela, exclua o índice dessa tabela usando a instrução DDL DROP VECTOR INDEX
.
Exemplo:
DROP VECTOR INDEX my_index ON my_dataset.indexed_table;
Se uma tabela indexada for excluída, o índice dela será excluído automaticamente.
A seguir
- Para uma visão geral dos casos de uso, preços e limitações dos índices vetoriais, consulte Introdução à pesquisa de vetor.
- Siga o tutorial Pesquisar embeddings com a pesquisa de vetor.