Adicionar um filtro em uma consulta de vetor na Pesquisa de IA do Azure
Você pode definir uma solicitação de consulta de vetor que inclui uma expressão de filtro para adicionar critérios de inclusão ou exclusão às suas consultas. Neste artigo, aprenda a:
Este artigo usa REST para ilustração. Para obter exemplos de código em outros idiomas, consulte o repositório GitHub azure-search-vector-samples para soluções de ponta a ponta que incluem consultas de vetor.
Você também pode usar o Search Explorer no portal do Azure para consultar o conteúdo do vetor. Se você usar a exibição JSON, poderá adicionar filtros e especificar o modo de filtro.
Como a filtragem funciona em uma consulta de vetor
Os filtros se aplicam a campos não vetoriais filterable
, um campo de cadeia de caracteres ou numérico, para incluir ou excluir documentos de pesquisa com base em critérios de filtro. Embora um campo de vetor não seja filtrado em si, os filtros podem ser aplicados a outros campos no mesmo índice, incluindo ou excluindo os documentos que também contêm campos de vetor.
Os filtros são aplicados antes ou depois da execução da consulta com base no parâmetro vectorFilterMode
.
Definir um filtro
Os filtros determinam o escopo de uma consulta de vetor. Os filtros são definidos e iteram em cadeia de caracteres não vetorial e campos numéricos atribuídos como filterable
no índice, mas o objetivo de um filtro determina o que a consulta de vetor executa: todo o espaço pesquisável ou o conteúdo de um resultado de pesquisa.
Se você não tiver campos de origem com texto ou valores numéricos, verifique se há metadados de documento, como propriedades LastModified ou CreatedBy, que possam ser úteis em um filtro de metadados.
2024-07-01 é a versão estável para essa API. Ele tem:
vectorFilterMode
para os modos de filtragem de pré-filtro (padrão) ou pós-filtro.filter
fornece os critérios.
No exemplo a seguir, o vetor é uma representação dessa cadeia de caracteres de consulta: "quais serviços do Azure dão suporte à pesquisa de texto completo". A consulta tem como destino o campo contentVector
. O vetor real tem 1536 inserções. Portanto, ele é cortado neste exemplo para fins de legibilidade.
Os critérios de filtro são aplicados a um campo de texto filtrado (category
neste exemplo) antes que o mecanismo de pesquisa execute a consulta de vetor.
POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2024-07-01
Content-Type: application/json
api-key: {{admin-api-key}}
{
"count": true,
"select": "title, content, category",
"filter": "category eq 'Databases'",
"vectorFilterMode": "preFilter",
"vectorQueries": [
{
"kind": "vector",
"vector": [
-0.009154141,
0.018708462,
. . .
-0.02178128,
-0.00086512347
],
"exhaustive": true,
"fields": "contentVector",
"k": 5
}
]
}
Definir o vectorFilterMode
O parâmetro de consulta vectorFilterMode determina se o filtro é aplicado antes ou depois da execução da consulta vetor.
Usar o modo de pré-filtro
A pré-filtragem aplica filtros antes da execução da consulta, reduzindo a área da superfície de pesquisa sobre a qual o algoritmo da busca em vetores procura conteúdo semelhante.
Em uma consulta de vetor, preFilter
é o padrão.
Usar o modo pós-filtro
A pós-filtragem aplica filtros após a execução da consulta, restringindo os resultados da pesquisa.
Teste de comparação dos modos de filtro de vetor
Para entender as condições sob as quais um modo de filtro tem um desempenho melhor que o outro, executamos uma série de testes para avaliar os resultados da consulta em índices pequenos, médios e grandes.
- Pequeno (100.000 documentos, índice de 2,5 GB, 1536 dimensões)
- Médio (1 milhão de documentos, índice de 25 GB, 1536 dimensões)
- Grande (1 bilhão de documentos, índice de 1,9 TB, 96 dimensões)
Para as cargas de trabalho pequenas e médias, usamos um serviço Standard 2 (S2) com uma partição e uma réplica. Para a carga de trabalho grande, usamos um serviço Standard 3 (S3) com 12 partições e uma réplica.
Os índices tinham uma construção idêntica: um campo de chave, um campo de vetor, um campo de texto e um campo numérico filtrável. O índice a seguir é definido por meio da sintaxe 2023-11-03.
def get_index_schema(self, index_name, dimensions):
return {
"name": index_name,
"fields": [
{"name": "id", "type": "Edm.String", "key": True, "searchable": True},
{"name": "content_vector", "type": "Collection(Edm.Single)", "dimensions": dimensions,
"searchable": True, "retrievable": True, "filterable": False, "facetable": False, "sortable": False,
"vectorSearchProfile": "defaulthnsw"},
{"name": "text", "type": "Edm.String", "searchable": True, "filterable": False, "retrievable": True,
"sortable": False, "facetable": False},
{"name": "score", "type": "Edm.Double", "searchable": False, "filterable": True,
"retrievable": True, "sortable": True, "facetable": True}
],
"vectorSearch": {
"algorithms": [
{
"name": "defaulthnsw",
"kind": "hnsw",
"hnswParameters": { "metric": "euclidean" }
}
],
"profiles": [
{
"name": "defaulthnsw",
"algorithm": "defaulthnsw"
}
]
}
}
Nas consultas, usamos um filtro idêntico para operações de pré-filtro e pós-filtro. Usamos um filtro simples para garantir que as variações no desempenho fossem devido ao modo de filtragem e não à complexidade do filtro.
Os resultados foram medidos em consultas por segundo (QPS).
Observações
A pré-filtragem é quase sempre mais lenta do que a pós-filtragem, exceto em índices pequenos, nos quais o desempenho é aproximadamente igual.
Em conjuntos de dados maiores, a pré-filtragem é significativamente mais lenta em ordens de magnitude.
Então, por que o pré-filtro é o padrão se é quase sempre mais lento? A pré-filtragem garante que resultados
k
sejam retornados se existirem no índice, onde o viés favorece o recall e a precisão em vez da velocidade.A pós-filtragem é para clientes que:
- priorizam a velocidade sobre a seleção (a pós-filtragem pode retornar menos de
k
resultados) - usar filtros que não são excessivamente seletivos
- têm índices de tamanho suficiente, de modo que o desempenho da pré-filtragem é inaceitável
- priorizam a velocidade sobre a seleção (a pós-filtragem pode retornar menos de
Detalhes
Dado um conjunto de dados com 100.000 vetores em 1536 dimensões:
- Ao filtrar mais de 30% do conjunto de dados, a pré-filtragem e a pós-filtragem eram comparáveis.
- Ao filtrar menos de 0,1% do conjunto de dados, a pré-filtragem era cerca de 50% mais lenta do que a pós-filtragem.
Dado um conjunto de dados com 1 milhão de vetores em 1536 dimensões:
- Ao filtrar mais de 30% do conjunto de dados, a pré-filtragem era cerca de 30% mais lenta.
- Ao filtrar menos de 2% do conjunto de dados, a pré-filtragem era cerca de sete vezes mais lenta.
Dado um conjunto de dados com 1 bilhão de vetores em 96 dimensões:
- Ao filtrar mais de 5% do conjunto de dados, a pré-filtragem era cerca de 50% mais lenta.
- Ao filtrar menos de 10% do conjunto de dados, a pré-filtragem era cerca de sete vezes mais lenta.
O grafo a seguir mostra o QPS relativo do pré-filtro, computado como QPS de pré-filtro dividido pelo QPS do pós-filtro.
O eixo vertical é a QPS de pré-filtragem sobre a QPS de pós-filtragem. Por exemplo, um valor de 0,0 significa que a pré-filtragem é 100% mais lenta; 0,5 no eixo vertical significa que a pré-filtragem é 50% mais lenta; 1,0 significa que a pré-filtragem e a pós-filtragem são equivalentes.
O eixo horizontal representa a taxa de filtragem ou o percentual de documentos candidatos após a aplicação do filtro. Por exemplo, 1.00%
significa que um por cento do corpus de pesquisa foi selecionado pelos critérios do filtro.