Pesquisa difusa para corrigir erros ortográficos e erros de digitação

O Azure AI Search dá suporte para a pesquisa difusa, um tipo de consulta que releva erros de digitação e de grafia na cadeia de caracteres de entrada. A pesquisa difusa verifica se os termos têm uma composição semelhante. A expansão da pesquisa para abranger correspondências próximas tem o efeito de corrigir automaticamente erros de grafia quando a discrepância é de apenas alguns caracteres incorretos.

É um exercício de expansão de consulta que produz uma correspondência em termos que têm uma composição semelhante. Quando uma pesquisa difusa é especificada, o mecanismo de pesquisa cria um grafo (com base na teoria de automação finita determinística) de termos com composição semelhante, para todos os termos na consulta. Por exemplo, se a consulta incluir três termos "university of washington", um grafo será criado para cada termo na consulta search=university~ of~ washington~ (não há remoção de palavras irrelevantes na pesquisa difusa, portanto, "of" obtém um grafo).

O grafo consiste em até 50 expansões, ou permutas, de cada termo, capturando variantes corretas e incorretas no processo. Em seguida, o mecanismo retorna as correspondências mais altas relevantes na resposta.

Para um termo como "universidade", o grafo pode ter "unversty, universty, university, universe, inverse". Todos os documentos que correspondem àqueles no grafo são incluídos nos resultados. Em contraste com outras consultas que analisam o texto para lidar com diferentes formas da mesma palavra ("rato" e "ratos"), as comparações em uma consulta difusa são consideradas literalmente, sem análise linguística no texto. "Universo" e "inverso", que são semanticamente diferentes, serão correspondentes, pois as discrepâncias sintáticas são pequenas.

Uma correspondência será realizada com sucesso se as discrepâncias forem limitadas a duas ou menos edições, que correspondem a inserção, exclusão, substituição ou transposição de caracteres. O algoritmo de correção de cadeia de caracteres que especifica o diferencial é a métrica de distância Damerau-Levenshtein. Ela é descrita como o "número mínimo de operações (inserções, exclusões, substituições ou transposições de dois caracteres adjacentes) necessárias para alterar uma palavra em outra".

No Azure AI Search:

  • A consulta difusa se aplica a termos inteiros. Não há suporte diretamente para frases, mas você pode especificar uma correspondência difusa em cada termo de uma frase de várias partes, como construções AND. Por exemplo, search=dr~ AND cleanin~. Essa expressão de consulta localiza correspondências em "limpeza a seco".

  • A distância padrão de uma edição é 2. O valor ~0 significa sem expansão (somente o termo exato é considerado uma correspondência), mas você pode especificar ~1 para um grau de diferença ou uma edição.

  • Uma consulta difusa pode expandir um termo em até 50 permutações. Esse limite não é configurável, mas você pode reduzir efetivamente o número de expansões diminuindo a distância de edição para 1.

  • As respostas consistem em documentos que contêm uma correspondência relevante (até 50).

Durante o processamento de consulta, as consultas difusas não passam por uma análise léxica. A entrada da consulta é adicionada diretamente à árvore de consulta e expandida para criar um grafo de termos. A única transformação executada é a mudança das letras maiúsculas para minúsculas.

Coletivamente, os grafos são enviados como critérios de correspondência em relação aos tokens no índice. Como você pode imaginar, a pesquisa difusa é inerentemente mais lenta do que outras formas de consulta. O tamanho e a complexidade do índice podem determinar se os benefícios são suficientes para compensar a latência da resposta.

Observação

Como a pesquisa difusa tende a ser lenta, pode valer a pena investigar alternativas como a indexação de n-gram, com sua progressão de sequências de caracteres curtas (duas e três sequências de caracteres para tokens bigramas e trigramas). Dependendo da linguagem e da superfície de consulta, o n-gram pode ter melhor desempenho. A desvantagem é que a indexação de n-gram exige muito armazenamento e gera índices muito maiores.

Outra alternativa, que você pode considerar se deseja lidar apenas com os principais casos, seria um mapa de sinônimos. Por exemplo, mapear "pesquisa" a "pesqiusa, pesuisa, psquisa" ou "recuperar" a "recuprar".

Os campos de cadeia de caracteres atribuídos como "pesquisáveis" são candidatos à pesquisa parcial.

Os analisadores não são usados para criar um grafo de expansão, mas isso não significa que eles devem ser ignorados em cenários de pesquisa difusa. Os analisadores são importantes para a tokenização durante a indexação, em que os tokens nos índices invertidos são usados para correspondência com o grafo.

Como sempre, se as consultas de teste não estiverem produzindo as correspondências esperadas, experimente diferentes analisadores de indexação. Por exemplo, tente um analisador de idiomas para ver se você obtém melhores resultados. Em alguns idiomas, especialmente aqueles com mutações de vogal, pode ser útil usar as formas flexionadas e irregulares de palavras geradas pelos processadores de linguagem natural da Microsoft. Em alguns casos, o uso do analisador de linguagem correto pode fazer diferença na indexação do termo de maneira que seja compatível com o valor fornecido pelo usuário.

As consultas parciais são criadas usando a sintaxe completa da consulta Lucene, invocando o analisador de consulta Lucene completo e acrescentando um caractere de til ~ após cada termo inteiro inserido pelo usuário.

Aqui está um exemplo de uma solicitação de consulta que invoca a pesquisa difusa. Ele inclui quatro termos, dois dos quais estão escritos incorretamente:

POST https://[service name].search.windows.net/indexes/hotels-sample-index/docs/search?api-version=2023-11-01
{
    "search": "seatle~ waterfront~ view~ hotle~",
    "queryType": "full",
    "searchMode": "any",
    "searchFields": "HotelName, Description",
    "select": "HotelName, Description, Address/City,",
    "count": "true"
}
  1. Defina o tipo de consulta como a sintaxe Lucene completa (queryType=full).

  2. Forneça a cadeia de consulta em que cada termo é seguido por um operador de bloco (~) no final de cada termo (search=<string>~). Um grafo de expansão será criado para cada termo na entrada da consulta.

    Inclua um parâmetro opcional, um número entre 0 e 2 (padrão), se você quiser especificar a distância de edição (~1). Por exemplo, "mar~" ou "mar~1" retornaria "mar", "amar" e "maré".

Opcionalmente, você pode melhorar o desempenho da consulta examinando a solicitação para campos específicos. Use o parâmetro searchFields para especificar quais campos pesquisar. Você também pode usar a propriedade select para especificar quais campos são retornados na resposta da consulta.

Para testes simples, recomendamos o Gerenciador de pesquisa ou o Cliente REST para iterar uma expressão de consulta. Ambas as ferramentas são interativas, o que significa que você pode percorrer rapidamente várias variantes de um termo e avaliar as respostas que retornam.

Quando os resultados são ambíguos, o realce de ocorrências ajuda a identificar a correspondência na resposta.

Observação

O uso do realce de ocorrências para identificar correspondências difusas tem limitações e funciona apenas para pesquisa difusa básica. Se o índice tiver perfis de pontuação ou se você adicionar camadas à consulta com sintaxe adicional, talvez o realce de ocorrências não identifique a correspondência.

Exemplo 1: pesquisa difusa com o termo exato

Suponha que a seguinte cadeia de caracteres exista no campo "Description" em um documento de pesquisa: "Test queries with special characters, plus strings for MSFT, SQL and Java."

Comece com uma pesquisa difusa por "especial" e adicione o realce de ocorrências ao campo Descrição:

search=special~&highlight=Description

Na resposta, como você adicionou o realce de ocorrências, a formatação é aplicada a "especial" como o termo correspondente.

"@search.highlights": {
    "Description": [
        "Test queries with <em>special</em> characters, plus strings for MSFT, SQL and Java."
    ]
}

Tente a solicitação novamente, digitando incorretamente "especial" tirando várias letras ("pe"):

search=scial~&highlight=Description

Até agora, nenhuma alteração na resposta. Dado o padrão de 2 graus de distância, a remoção de dois caracteres "pe" de "especial" ainda permite uma correspondência bem-sucedida nesse termo.

"@search.highlights": {
    "Description": [
        "Test queries with <em>special</em> characters, plus strings for MSFT, SQL and Java."
    ]
}

Tentando mais uma solicitação, modifique ainda mais o termo de pesquisa tirando um último caractere para um total de três exclusões (de "especial" para "scal"):

search=scal~&highlight=Description

Observe que a mesma resposta é retornada, mas agora, em vez de corresponder a "especial", a correspondência difusa é "SQL".

"@search.score": 0.4232868,
"@search.highlights": {
    "Description": [
        "Mix of special characters, plus strings for MSFT, <em>SQL</em>, 2019, Linux, Java."
    ]
}

O propósito desse exemplo expandido é ilustrar a clareza que o realce de ocorrências pode trazer a resultados ambíguos. Em todos os casos, o mesmo documento é retornado. Se você usasse IDs de documento para verificar uma correspondência, talvez tivesse ignorado a mudança de "especial" para "SQL".

Confira também