<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Relevância - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Relevância - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/pt/search-labs/blog/category/relevance</link>
    </image>
    <link>https://www.elastic.co/pt/search-labs/blog/category/relevance</link>
    <atom:link href="https://www.elastic.co/pt/search-labs/rss/category/relevance.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[pt]]></language>
    <lastBuildDate>Tue, 29 Sep 2026 07:37:05 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Garantindo precisão semântica com pontuação mínima]]></title>
    <description><![CDATA[Melhore a precisão semântica empregando limiares mínimos de pontuação. O artigo inclui exemplos concretos de busca semântica e híbrida. ]]></description>
    <content:encoded><![CDATA[<p>A busca semântica abriu um mundo de oportunidades para a relevância da busca. Modelos esparsos e densos de alta qualidade, como ELSER, E5 e Jina Embedding v4, retornam resultados relevantes com base no significado das palavras, em vez da correspondência de palavras-chave. No entanto, a busca semântica às vezes retorna resultados irrelevantes na cauda final ou para consultas que não apresentam resultados relevantes no índice. Essa propriedade dos modelos esparsos e densos pode confundir os usuários ou desperdiçar tokens preciosos para grandes modelos de linguagem (LLMs).</p><p>Neste artigo, você aprenderá como usar o parâmetro de pontuação mínima para aumentar a precisão dos seus resultados de busca semânticos. Se você quiser testar os exemplos fornecidos neste post do blog, <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/ensuring-semantic-precision-with-minimum-score/ensuring_semantic_precision_with_minimum_score.ipynb">acesse o caderno Jupyter associado</a>.</p><h2>Contexto: Precisão e recall</h2><p>Na relevância da pesquisa, a <em>precisão </em>e a <em>recall </em>são conceitos-chave. Qualquer leitor que ainda não esteja familiarizado é altamente incentivado a pesquisar sobre eles. Segue abaixo um resumo.</p><ul><li><p><strong>Precisão: </strong>a fração dos resultados de busca retornados que são relevantes para o usuário.</p></li><li><p><strong>Recall: </strong>a fração de todos os documentos relevantes no corpus que estão incluídos no conjunto de resultados de busca.</p></li></ul><p>Ou, em outras palavras, a precisão retorna <strong>apenas </strong>resultados relevantes e o recall retorna <strong>todos </strong>os resultados relevantes. Como você pode imaginar, esses são requisitos frequentemente concorrentes. A busca semântica tende a ter uma memória muito alta, mas pode ter dificuldades com precisão. Continue lendo para saber como se locomover por esta propriedade.</p><h2>Apresentando o parâmetro de pontuação mínima</h2><p>O parâmetro ‘min_score’ nos permite melhorar a precisão ao definir uma pontuação mínima, que truncará o conjunto de resultados removendo quaisquer correspondências com uma pontuação inferior ao limite definido. Aqui está um exemplo simples:</p>GET search-movies/_search
{
  "retriever": {
    "linear": {
      "min_score": 4,
      "retrievers": [
        ...
      ]
    }
  }
}<h2>Normalização da pontuação</h2><p>Definir uma pontuação mínima é muito bom; no entanto, nem todos os modelos semânticos retornam uma pontuação adequada para um limite estático. ELSER, por exemplo, retorna uma pontuação que é ilimitada. <a href="https://huggingface.co/intfloat/e5-small#faq">Algumas</a> pontuações de modelos densos estão fortemente agrupadas e só fazem sentido no contexto da consulta específica.</p><p>Para a maioria dos casos de busca semântica, recomendamos usar uma abordagem de normalização antes de aplicar o 'min_score'. A normalização garante que a pontuação do documento esteja dentro de um intervalo definido. Os recuperadores Elasticsearch fornecem dois desses <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/retrievers/linear-retriever#linear-retriever-normalizers">normalizadores</a>, 'l2_norm' e 'minmax'. O mais comumente usado é o 'minmax', pois é fácil de entender e funciona bem em muitos cenários. As principais propriedades do 'minmax' incluem:</p><ul><li><p>As pontuações dos documentos são distribuídas entre 0 e 1.</p></li><li><p>O documento com maior pontuação é sempre pontuado como 1.</p></li><li><p>O documento com menor pontuação sempre é pontuado como 0.</p><ul><li><p>Isso pode torná-lo menos adequado para buscar palavras-chave. Consulte a seção “Busca híbrida” para uma discussão mais aprofundada.</p></li></ul></li></ul><p>A seguir está um exemplo de consulta semântica normalizada com <code>min_score</code>. O tamanho da janela de classificação foi aumentado para 500 para permitir que possamos retornar uma lista maior de resultados de busca, começando em 100.</p>GET search-movies/_search
{
  "size": 100,
  "_source": [
    "title", "overview"
  ],
  "retriever": {
    "linear": {
      "rank_window_size": 500,
      "min_score": 0.25,
      "retrievers": [
        {
          "normalizer": "minmax",
          "retriever": {
            "standard": {
              "query": {
                "semantic": {
                  "field": "overview_vector",
                  "query": "superhero movie"
                }
              }
            }
          }
        }
      ]
    }
  }
}<p>O tamanho foi ajustado para um valor maior do que o normalmente visto na produção. Isso é para que possamos inspecionar a qualidade dos resultados de busca e ajustar os resultados.</p><h2>Busca híbrida usando o recuperador linear</h2><p>Para busca híbrida, a abordagem mais simples é normalizar todas as pontuações, atribuir pesos e aplicar uma pontuação mínima. Note que, ao escolher pesos cuja soma seja 1, você mantém a pontuação total dentro de um intervalo de 0 a 1. Isso facilita entender as pontuações finais e afinar <code>min_score</code>. A seguir está um exemplo:</p>GET search-movies/_search
{
  "size": 100,
  "_source": ["title", "overview","keywords"],
  "retriever": {
    "linear": {
      "rank_window_size": 500,
      "min_score": 0.25,
      "retrievers": [
        {
          "weight": 0.6,
          "normalizer": "minmax",
          "retriever": {
            "standard": {
              "query": {
                "semantic": {
                  "field": "overview_vector",
                  "query": "superhero movie"
                }
              }
            }
          }
        },
        {
          "weight": 0.4,
          "normalizer": "minmax",
          "retriever": {
            "standard": {
              "query": {
                "multi_match": {
                  "query": "superhero movie",
                  "fields": ["overview","keywords", "title"],
                  "type": "cross_fields",
                  "minimum_should_match": "2"
                }
              }
            }
          }
        }
      ]
    }
  }
}<h2>Busca híbrida usando o RRF</h2><p>Com o BM25, muitas vezes controlamos a precisão por outros meios, como usando o operador <code>AND</code> ou <code>minimum_should_match</code>. Além disso, consultas compostas por termos únicos, precisos e raros naturalmente causam resultados de busca com poucos resultados, muitas vezes todos altamente relevantes. Isso pode resultar em:</p><ul><li><p>Os resultados mais distantes na lista recebem uma pontuação normalizada baixa no recuperador BM25, mesmo que a pontuação absoluta do BM25 esteja próxima das pontuações mais altas.</p></li><li><p>Ao adicionar uma pontuação BM25 muito baixa à pontuação semântica, o total pode ser aproximado como a pontuação semântica.</p></li><li><p>A falta de contribuição da pontuação BM25 pode fazer com que o documento seja descartado pelo <code>min_score threshold</code>.</p></li></ul><p>Como solução, podemos usar a fusão de classificação recíproca (RRF) para combinar os resultados BM25 e semânticos. O RRF contorna o desafio de comparar pontuações de diferentes algoritmos de busca focando na posição em cada conjunto de resultados. Nesse cenário, o <code>min_score</code> é aplicado apenas ao recuperador semântico.</p>GET search-movies/_search
{
  "_source": ["title", "overview","keywords"],
  "retriever": {
    "rrf": {
      "rank_window_size": 500,
      "retrievers": [
        {
          "linear": {
            "rank_window_size": 500,
            "min_score": 0.25,
            "retrievers": [
              {
                "normalizer": "minmax",
                "retriever": {
                  "standard": {
                    "query": {
                      "semantic": {
                        "field": "overview_vector",
                        "query": "superhero movie"
                      }
                    }
                  }
                }
              }
            ]
          }
        },
        {
          "standard": {
            "query": {
              "multi_match": {
                "query": "superhero movie",
                "fields": ["overview", "keywords","title"],
                "type": "cross_fields",
                "minimum_should_match": "2"
              }
            }
          }
        }
      ]
    }
  }
}<h2>Conclusão</h2><p>Usando <code>min_score</code>, mostramos como podemos reduzir o número de falsos positivos em nossos conjuntos de resultados causados pela alta recordação de algoritmos de busca semântica. Para saber mais sobre recuperadores, consulte este <a href="https://www.elastic.co/search-labs/blog/elasticsearch-retrievers">post do blog</a> e a <a href="https://www.elastic.co/docs/solutions/search/retrievers-overview">documentação do Elasticsearch</a>.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/semantic-precision-minimum-score</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/semantic-precision-minimum-score</guid>
    <category><![CDATA[Relevância]]></category>
    <category><![CDATA[Busca híbrida]]></category>
    <dc:creator><![CDATA[Mattias Brunnert]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd4a3fba607900049/6a170e0fcdacbf8fe17d2a7a/8b3b5910abfe16d48d309341a0027008b16c4340-720x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Fri, 20 Feb 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Avaliação da relevância de consultas de pesquisa com listas de julgamento]]></title>
    <description><![CDATA[Saiba como criar listas de julgamento para avaliar objetivamente a relevância das consultas de pesquisa e melhorar métricas de desempenho, como recall, para testes de buscas escaláveis no Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>Os desenvolvedores que trabalham em mecanismos de busca frequentemente se deparam com o mesmo problema: a equipe de negócios não está satisfeita com uma busca específica porque os documentos que eles esperam ver na parte de cima dos resultados da busca aparecem em terceiro ou quarto lugar na lista de resultados.</p><p>No entanto, quando você resolve esse problema, acaba com outras consultas porque não pôde testar todos os casos manualmente. Mas como você ou sua equipe de QA podem testar se uma mudança em uma consulta tem efeito dominó em outras? Ou, mais importante ainda, como você pode ter certeza de que suas mudanças realmente melhoraram uma consulta?</p><h2>Rumo a uma avaliação sistemática</h2><p>É aqui que as listas de julgamento se tornam úteis. Em vez de depender de testes manuais e subjetivos toda vez que você faz uma alteração, você pode definir um conjunto fixo de consultas relevantes para seu caso de negócio, juntamente com os resultados relevantes.</p><p>Esse conjunto se torna sua referência. Toda vez que você implementa uma mudança, você a usa para avaliar se você buscou uma melhoria ou não.</p><p>O valor dessa abordagem é:</p><ul><li><p><strong>Elimina a incerteza</strong>: você não precisa mais se perguntar se suas alterações afetam outras consultas; os dados dirão isso a você.</p></li><li><p><strong>Interrompe os testes manuais</strong>: assim que os conjuntos de julgamento são registrados, o teste é automático.</p></li><li><p><strong>Dá suporte à mudanças</strong>: você pode apresentar métricas claras que sustentam os benefícios de uma mudança.</p></li></ul><h2>Como começar a construir sua lista de julgamentos</h2><p>Uma das formas mais fáceis de começar é pegar uma consulta representativa e selecionar manualmente os documentos relevantes. Existem duas maneiras de fazer esta lista:</p><ul><li><p><strong>Julgamentos binários:</strong> cada documento associado a uma consulta recebe uma <strong>marcação simples</strong>: <em>relevante</em> (geralmente com uma pontuação de “1”) e não-relevante (“0”).</p></li><li><p><strong>Julgamentos graduados:</strong> aqui, cada documento recebe uma pontuação com diferentes níveis. Por exemplo: definir uma escala de 0 a 4, semelhante à <a href="https://en.wikipedia.org/wiki/Likert_scale">Escala Likert</a>, onde 0 = "nada relevante" e 4 = "totalmente relevante", com variações como "relevante", "um pouco relevante" etc.</p></li></ul><p>Julgamentos binários funcionam bem quando a intenção de buscar tem limites claros: esse documento deve estar nos resultados ou não?</p><p>Julgamentos graduados são mais úteis quando há áreas cinzentas: alguns resultados são melhores que outros, então você pode ter resultados "muito bons", "bons" e "inúteis" e usar métricas que valorizam a ordem dos resultados e o feedback do usuário. No entanto, as escalas graduadas também introduzem desvantagens: diferentes avaliadores podem usar os níveis de pontuação de maneira diferente, o que torna os julgamentos menos consistentes. E porque as métricas graduadas dão mais peso às pontuações mais altas, mesmo uma pequena mudança (como classificar algo com 3 em vez de 4) pode criar uma mudança muito maior na métrica do que o avaliador pretendia. Essa subjetividade adicional torna os julgamentos graduados mais complicados e difíceis de gerenciar ao longo do tempo.</p><h2>Preciso classificar os documentos eu mesmo?</h2><p>Não necessariamente, pois existem diferentes maneiras de criar sua lista de julgamentos, cada uma com suas próprias vantagens e desvantagens:</p><ul><li><p><strong>Julgamentos explícitos:</strong> aqui, os SMEs analisam cada consulta/documento e decidem manualmente se é relevante e qual a dimensão da relevância. Embora isso ofereça qualidade e controle, tem menos escalabilidade.</p></li><li><p><strong>Julgamentos implícitos:</strong> com esse método, você infere os documentos relevantes com base no comportamento real dos usuários, como cliques, taxa de rejeição e compras, entre outros. Essa abordagem permite coletar dados automaticamente, mas pode ser tendenciosa. Por exemplo, os usuários tendem a clicar mais vezes nos resultados principais, mesmo que não sejam relevantes.</p></li><li><p><strong>Julgamentos gerados por IA:</strong> essa última opção utiliza modelos (como LLMs) para avaliar automaticamente consultas e documentos, chamados <a href="https://en.wikipedia.org/wiki/LLM-as-a-Judge">LLM como juiz</a>. É rápido e fácil de redimensionar, mas a qualidade dos dados depende da qualidade do modelo que você está usando e de como os dados de treinamento do LLM se alinham aos seus <a href="http://interests.as/">interesses</a> comerciais. Assim como acontece com as notas humanas, os LLMs como juiz podem apresentar os próprios preconceitos ou inconsistências, por isso é importante validar o resultado em relação a um conjunto menor de julgamentos confiáveis. Modelos LLM são probabilísticos por natureza, então não é incomum ver um modelo LLM dando diferentes graus ao mesmo resultado, independentemente de definir o parâmetro de <a href="https://www.ibm.com/think/topics/llm-temperature">temperatura</a> como 0.</p></li></ul><p>A seguir, apresentamos algumas recomendações para escolher o melhor método para criar seu conjunto de julgamentos:</p><ul><li><p>Decida a importância de alguns recursos que somente os usuários possam avaliar de forma adequada (como preço, marca, idioma, estilo e detalhes do produto). Se eles forem importantes, você precisará de <strong>julgamentos explícitos</strong> para pelo menos uma parte da sua <em>lista de julgamentos</em>.</p></li><li><p>Use <strong>julgamentos implícitos</strong> quando seu mecanismo de busca já tiver tráfego suficiente para que você possa usar cliques, conversões e métricas de tempo persistentes para detectar tendências de uso. Você ainda deve interpretá-los com cuidado, comparando-os com seus conjuntos de julgamento explícitos para evitar qualquer viés (por exemplo: os usuários tendem a clicar nos resultados mais bem classificados com mais frequência, mesmo que os resultados com classificação inferior sejam mais relevantes)</p></li></ul><p>Para resolver isso, técnicas de posicionamento de debiasing ajustam ou reponderam os dados de cliques para refletir melhor o verdadeiro interesse do usuário. Algumas abordagens incluem:</p><ul><li><p><strong>Reorganização de resultados</strong>: altere a ordem dos resultados de busca para um subconjunto de usuários a fim de estimar como a posição afeta os cliques.</p></li><li><p><strong>Os modelos de clique </strong>incluem<a href="https://wiki.math.uwaterloo.ca/statwiki/index.php?title=a_Dynamic_Bayesian_Network_Click_Model_for_web_search_ranking">Rede bayesiana dinâmica </a><a href="https://wiki.math.uwaterloo.ca/statwiki/index.php?title=a_Dynamic_Bayesian_Network_Click_Model_for_web_search_ranking"><strong>DBN</strong></a>, <a href="https://rsrikant.com/papers/kdd10.pdf">Modelo de Navegação do Usuário </a><a href="https://rsrikant.com/papers/kdd10.pdf"><strong>UBM</strong></a>. Esses modelos estatísticos estimam que a probabilidade de um clique reflete o interesse real em vez de apenas posição, usando padrões como rolagem, tempo de espera, sequência de cliques e retorno à página de resultados.</p></li></ul><h2>Exemplo: app de avaliação de filmes</h2><h3>Pré-requisitos</h3><p>Para executar este exemplo, você precisa de um cluster Elasticsearch 8.x em execução, <a href="https://www.elastic.co/downloads/elasticsearch">localmente</a> ou <a href="https://www.elastic.co/cloud/cloud-trial-overview">no Elastic Cloud</a> (hospedado ou sem servidor), e acesso à <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis">REST API</a> ou ao Kibana.</p><p>Pense em um app no qual os usuários possam carregar as opiniões sobre filmes e também buscar filmes para assistir. Como os textos são escritos pelos próprios usuários, eles podem ter erros de digitação e muitas variações em termos de expressão. Portanto, é fundamental que o mecanismo de busca seja capaz de interpretar essa diversidade e fornecer resultados úteis para os usuários.</p><p>Para poder iterar consultas sem impactar o comportamento geral de busca, a equipe de negócios da sua empresa criou o seguinte conjunto de julgamento binário, baseado nas buscas mais frequentes:</p><p>Consulta</p><p>DocID</p><p>Texto</p><p>Performance de DiCaprio</p><p>doc1</p><p>A atuação de DiCaprio em O Regresso foi de tirar o fôlego.</p><p>Performance de DiCaprio</p><p>doc2</p><p>A Origem mostra Leonardo DiCaprio em um dos papéis mais icônicos que ele já fez.</p><p>Performance de DiCaprio</p><p>doc3</p><p>Brad Pitt entrega uma atuação sólida neste thriller policial.</p><p>Performance de DiCaprio</p><p>doc4</p><p>Uma aventura cheia de ação com efeitos visuais impressionantes.</p><p>filmes tristes que fazem você chorar</p><p>doc5</p><p>Uma história comovente de amor e perda que me fez chorar muito.</p><p>filmes tristes que fazem você chorar</p><p>doc6</p><p>Um dos filmes mais tristes já feitos — traga lenços!</p><p>filmes tristes que fazem você chorar</p><p>doc7</p><p>Uma comédia leve que vai fazer rir</p><p>filmes tristes que fazem você chorar</p><p>doc8</p><p>Uma saga de ficção científica épica repleta de ação e emoção.</p><p>Criando o índice:</p>PUT movies
{
  "mappings": {
    "properties": {
      "text": {
        "type": "text"
      }
    }
  }
}<p>SOLICITAÇÃO em massa:</p>POST /movies/_bulk
{ "index": { "_id": "doc1" } }
{ "text": "DiCaprio performance in The Revenant was breathtaking." }
{ "index": { "_id": "doc2" } }
{ "text": "Inception shows Leonardo DiCaprio in one of his most iconic roles." }
{ "index": { "_id": "doc3" } }
{ "text": "Brad Pitt delivers a solid performance in this crime thriller." }
{ "index": { "_id": "doc4" } }
{ "text": "An action-packed adventure with stunning visual effects." }
{ "index": { "_id": "doc5" } }
{ "text": "A heartbreaking story of love and loss that made me cry for hours." }
{ "index": { "_id": "doc6" } }
{ "text": "One of the saddest movies ever made -- bring tissues!" }
{ "index": { "_id": "doc7" } }
{ "text": "A lighthearted comedy that will make you laugh." }
{ "index": { "_id": "doc8" } }
{ "text": "A science-fiction epic full of action and excitement." }<p>Abaixo está a consulta Elasticsearch que o aplicativo está usando:</p>GET movies/_search
{
 "query": {
   "match": {
     "text": {
       "query": "DiCaprio performance",
       "minimum_should_match": "100%"
     }
   }
 }
}<h3>Do julgamento às métricas</h3><p>Sozinho, as listas de julgamento não fornecem muitas informações; eles são apenas uma expectativa dos resultados das nossas consultas. O momento importante deles é quando os usamos para calcular métricas objetivas para medir nosso desempenho na busca.</p><p>Hoje em dia, a maioria das métricas populares inclui</p><ul><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#k-precision"><strong>Precisão</strong></a><strong>: </strong>mede a proporção de resultados relevantes em todos os resultados de busca.</p></li><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#k-recall"><strong>Recall</strong></a><strong>: </strong>mede a proporção de resultados relevantes que o mecanismo de busca encontrou entre x resultados.</p></li><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#_discounted_cumulative_gain_dcg"><strong>Ganho cumulativo descontado (DCG):</strong></a>mede a qualidade do ranking do resultado, considerando que os resultados mais relevantes devem estar no topo.</p></li><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#_mean_reciprocal_rank"><strong>Classificação Recíproca Média (MRR):</strong></a> mede a posição do primeiro resultado relevante. Quanto mais alto na lista, maior a pontuação.</p></li></ul><p>Usando o mesmo app de avaliação de filmes como exemplo, calcularemos a métrica de recordação para ver se há alguma informação que está sendo omitida em nossas consultas.</p><p>No Elasticsearch, podemos usar as <em>listas de julgamentos</em> para calcular métricas via <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval">API de avaliação de classificação</a>. Essa API recebe como entrada a lista de julgamentos, a consulta e a métrica que você deseja avaliar e retorna um valor, que é uma comparação do resultado da consulta com a lista de julgamentos.</p><p>Vamos executar a lista de julgamento para as duas consultas que temos:</p>POST /movies/_rank_eval
{
 "requests": [
   {
     "id": "dicaprio-performance",
     "request": {
       "query": {
         "match": {
           "text": {
             "query": "DiCaprio performance",
             "minimum_should_match": "100%"
           }
         }
       }
     },
     "ratings": [
       {
         "_index": "movies",
         "_id": "doc1",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc2",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc3",
         "rating": 0
       },
       {
         "_index": "movies",
         "_id": "doc4",
         "rating": 0
       }
     ]
   },
   {
     "id": "sad-movies",
     "request": {
       "query": {
         "match": {
           "text": {
             "query": "sad movies that make you cry",
             "minimum_should_match": "100%"
           }
         }
       }
     },
     "ratings": [
       {
         "_index": "movies",
         "_id": "doc5",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc6",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc7",
         "rating": 0
       },
       {
         "_index": "movies",
         "_id": "doc8",
         "rating": 0
       }
     ]
   }
 ],
 "metric": {
   "recall": {
     "k": 10,
     "relevant_rating_threshold": 1
     }
 }
}<p>Vamos usar dois pedidos para _rank_eval: um para a consulta do DiCaprio e outro para filmes tristes. Cada solicitação inclui uma consulta e a lista de julgamento (avaliações). Não precisamos classificar todos os documentos, pois aqueles que não estão incluídos nas classificações são considerados sem julgamento. Para realizar os cálculos, o sistema considera apenas o "conjunto relevante", ou seja, os documentos que são considerados relevantes na avaliação.</p><p>Nesse caso, a consulta do DiCaprio tem resultado de 1, enquanto os filmes tristes receberam 0 resultados. Isso significa que na primeira consulta, conseguimos obter todos os resultados relevantes, enquanto na segunda consulta, não obtivemos nenhum resultado. Portanto, a média de recall é de 0,5.</p>{
 "metric_score": 0.5,
 "details": {
   "dicaprio-performance": {
     "metric_score": 1,
     "unrated_docs": [],
     "hits": [
       {
         "hit": {
           "_index": "movies",
           "_id": "doc1",
           "_score": 2.4826927
         },
         "rating": 1
       },
       {
         "hit": {
           "_index": "movies",
           "_id": "doc2",
           "_score": 2.0780432
         },
         "rating": 1
       }
     ],
     "metric_details": {
       "recall": {
         "relevant_docs_retrieved": 2,
         "relevant_docs": 2
       }
     }
   },
   "sad-movies": {
     "metric_score": 0,
     "unrated_docs": [],
     "hits": [],
     "metric_details": {
       "recall": {
         "relevant_docs_retrieved": 0,
         "relevant_docs": 2
       }
     }
   }
 },
 "failures": {}
}<p>Talvez estejamos sendo muito rigorosos com o parâmetro <strong>minimum_should_match </strong>, já que ao exigir que 100% das palavras da consulta estejam nos documentos, provavelmente estamos deixando de fora os resultados relevantes. Vamos remover o parâmetro <strong>minimum_should_match</strong> para que um documento seja considerado relevante se apenas uma palavra na consulta seja encontrada nele.</p>POST /movies/_rank_eval
{
 "requests": [
   {
     "id": "dicaprio-performance",
     "request": {
       "query": {
         "match": {
           "text": {
             "query": "DiCaprio performance"
           }
         }
       }
     },
     "ratings": [
       {
         "_index": "movies",
         "_id": "doc1",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc2",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc3",
         "rating": 0
       },
       {
         "_index": "movies",
         "_id": "doc4",
         "rating": 0
       }
     ]
   },
   {
     "id": "sad-movies",
     "request": {
       "query": {
         "match": {
           "text": {
             "query": "sad movies that make you cry"
           }
         }
       }
     },
     "ratings": [
       {
         "_index": "movies",
         "_id": "doc5",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc6",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc7",
         "rating": 0
       },
       {
         "_index": "movies",
         "_id": "doc8",
         "rating": 0
       }
     ]
   }
 ],
 "metric": {
   "recall": {
     "k": 10,
     "relevant_rating_threshold": 1
     }
 }
}<p>Como você pode ver, ao remover o parâmetro <strong>minimum_should_match</strong> em uma das duas consultas, agora obtemos uma taxa de acerto média de 1 em ambas.</p>{
  "metric_score": 1,
  "details": {
    "dicaprio-performance": {
      "metric_score": 1,
      "unrated_docs": [],
      "hits": [
        {
          "hit": {
            "_index": "movies",
            "_id": "doc1",
            "_score": 2.0661702
          },
          "rating": 1
        },
        {
          "hit": {
            "_index": "movies",
            "_id": "doc3",
            "_score": 0.732218
          },
          "rating": 0
        },
        {
          "hit": {
            "_index": "movies",
            "_id": "doc2",
            "_score": 0.6271719
          },
          "rating": 1
        }
      ],
      "metric_details": {
        "recall": {
          "relevant_docs_retrieved": 2,
          "relevant_docs": 2
        }
      }
    },
    "sad-movies": {
      "metric_score": 1,
      "unrated_docs": [],
      "hits": [
        {
          "hit": {
            "_index": "movies",
            "_id": "doc7",
            "_score": 2.1307156
          },
          "rating": 0
        },
        {
          "hit": {
            "_index": "movies",
            "_id": "doc5",
            "_score": 1.3160692
          },
          "rating": 1
        },
        {
          "hit": {
            "_index": "movies",
            "_id": "doc6",
            "_score": 1.190063
          },
          "rating": 1
        }
      ],
      "metric_details": {
        "recall": {
          "relevant_docs_retrieved": 2,
          "relevant_docs": 2
        }
      }
    }
  },
  "failures": {}
}<p>Em resumo, remover a cláusula minimum_should_match: 100% nos permite ter um recall perfeito para ambas as consultas.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltaf4f08a8a2915180/6a170df61949f76cbfe7aaba/24d055da4348c63827ba7046fe8cafb6f47cadd8-546x628.png" alt="" /><p>Conseguimos! Certo?</p><p>Não tão depressa!</p><p>Ao melhorar o recall, abrimos as portas para uma gama maior de resultados. No entanto, cada ajuste implica uma contrapartida. É por isso que definimos casos de teste completos, usando diferentes métricas para avaliar as mudanças.</p><p>Usar listas de julgamento e métricas evita que você fique às cegas ao fazer alterações, pois agora você tem dados para respaldá-las. A validação não é mais manual e repetitiva, e você pode testar as mudanças em mais de um caso de uso. Além disso, o teste A/B permite que você teste ao vivo qual configuração funciona melhor para seus usuários e seu caso de negócios, completando assim as métricas técnicas e as métricas do mundo real.</p><h2>Recomendações finais para o uso de listas de julgamento</h2><p>Trabalhar com listas de julgamento não é apenas medir, mas também criar um framework que permita iterar com confiança. Para atingir isso, você pode seguir estas recomendações:</p><ol><li><p><strong>Comece pequeno, mas comece de algum lugar</strong>. Você não precisa ter 10.000 consultas com 50 listas de julgamento cada. Você só precisa identificar de 5 a 10 consultas mais importantes para seu case de negócios e definir quais documentos espera ver no topo dos resultados. Isso já te dá uma base. Normalmente, você quer começar com as principais consultas mais as que não obtiveram resultados. Você também pode começar a testar com uma métrica fácil de configurar, como Precision, e depois ir aumentando a complexidade.</p></li><li><p><strong>Validar com os usuários.</strong> Complemente os números com testes A/B em produção. Dessa forma, você saberá se mudanças que parecem boas nas métricas também estão gerando um impacto real.</p></li><li><p><strong>Mantenha a lista atualizada.</strong> Seu caso de negócio vai evoluir, assim como suas consultas importantes. Atualize seu julgamento periodicamente para refletir novas necessidades.</p></li><li><p><strong>Faça disso parte do fluxo.</strong> Integre listas de julgamento aos seus pipelines de desenvolvimento. Certifique-se de que cada alteração de configuração, sinônimo ou análise de texto seja automaticamente validada em relação à sua lista base.</p></li><li><p><strong>Conecte conhecimento técnico com estratégia.</strong> Não se limite a medir métricas técnicas como a precisão ou o recall. Use os resultados da sua avaliação para informar os resultados do negócio.</p></li></ol>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/judgment-lists-search-query-relevance-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/judgment-lists-search-query-relevance-elasticsearch</guid>
    <category><![CDATA[Relevância]]></category>
    <category><![CDATA[Na Elastic]]></category>
    <dc:creator><![CDATA[Jhon Guzmán]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcadfd2fb1cc95b4c/6a170df7acf0887798be9bd0/25478d0ffb228afd5d65d82312998ec1c299c565-700x490.png" length="0" type="image/png"/>
    <pubDate>Thu, 11 Dec 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Busca híbrida sem complicações: simplificando a busca híbrida com recuperadores.]]></title>
    <description><![CDATA[Descubra como simplificar a busca híbrida no Elasticsearch com um formato de consulta de múltiplos campos para recuperadores lineares e RRF, e crie consultas sem conhecimento prévio sobre seu índice do Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p><a href="https://www.elastic.co/what-is/hybrid-search">A busca híbrida</a> é amplamente reconhecida como uma abordagem de busca poderosa, combinando a precisão e a velocidade da <a href="https://www.elastic.co/search-labs/blog/lexical-and-semantic-search-with-elasticsearch#lexical-search---sparse-retrieval">busca lexical</a> com os recursos de linguagem natural da <a href="https://www.elastic.co/what-is/semantic-search">busca semântica</a>. No entanto, aplicá-lo na prática pode ser complicado, muitas vezes exigindo conhecimento profundo sobre o índice e a construção de consultas verbosas com configurações complexas. Neste blog, exploraremos como o <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/retrievers#multi-field-query-format">formato de consulta com múltiplos campos para buscadores lineares e RRF</a> torna a busca híbrida mais simples e acessível, eliminando problemas comuns e permitindo que você aproveite todo o seu potencial com maior facilidade. Analisaremos também como o formato de consulta com vários campos permite realizar consultas de pesquisa híbridas sem conhecimento prévio sobre o índice.</p><h2>O problema da amplitude de pontuação</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3521a6558cd477ca/6a17f174445de94d3c4d0225/c8b49153c47d2cdc233c0d2e440db04711d48ca5-1600x1600.jpg" alt="" /><p>Para contextualizar, vamos analisar um dos principais motivos pelos quais a busca híbrida pode ser difícil: a variação nos intervalos de pontuação. Nosso velho amigo <a href="https://www.elastic.co/elasticon/conf/2016/sf/improved-text-scoring-with-bm25">BM25</a> produz pontuações ilimitadas. Em outras palavras, o BM25 pode gerar pontuações que variam de perto de 0 até (teoricamente) o infinito. Em contraste, as consultas aos campos <code>dense_vector</code> produzirão pontuações limitadas entre 0 e 1. Exacerbando este problema, <code>semantic_text</code> ofusca o tipo de campo usado para indexar embeddings, portanto, a menos que você tenha conhecimento detalhado sobre a configuração do seu índice e endpoint de inferência, pode ser difícil dizer qual será o intervalo de pontuação da sua consulta. Isso representa um problema ao tentar intercalar resultados de busca lexical e semântica, já que os resultados lexicais podem ter precedência sobre os semânticos, mesmo que os resultados semânticos sejam mais relevantes. A solução geralmente aceita para esse problema é normalizar as pontuações antes de intercalar os resultados. O Elasticsearch possui duas ferramentas para isso: os recuperadores <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/retrievers/linear-retriever">lineares</a> e <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/retrievers/rrf-retriever">RRF</a> .
</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt09ed6bf3d25066bd/6a17f1750b0bedbd70dd3686/264481268c8b6ac259e3c257b85431b513f16672-1077x586.png" alt="Comparação dos resultados da pesquisa com linear/rrf versus sem linear/rrf." /><p>O recuperador <strong>RRF</strong> aplica o <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/reciprocal-rank-fusion">algoritmo RRF</a>, usando a classificação do documento como medida de relevância e descartando a pontuação. Como a pontuação não é considerada, as discrepâncias na faixa de pontuação não representam um problema.</p><p>O recuperador <strong>linear</strong> utiliza uma combinação linear para determinar a pontuação final de um documento. Isso envolve pegar a pontuação de cada consulta de componente para o documento, normalizá-la e somá-las para gerar a pontuação total. Matematicamente, a operação pode ser expressa como:</p>Total Score = 𝚺(N(Sx))<p>Onde <code>N</code> é a função de normalização e SX é a pontuação para a consulta X. A função de normalização é fundamental aqui, pois transforma a pontuação de cada consulta para usar o mesmo intervalo. Você pode aprender mais sobre o recuperador linear <a href="https://www.elastic.co/search-labs/blog/linear-retriever-hybrid-search">aqui</a>.</p><h2>Analisando detalhadamente</h2><p>Os usuários podem implementar uma busca híbrida eficaz com essas ferramentas, mas isso requer algum conhecimento sobre o seu índice. Vejamos um exemplo com o recuperador linear, onde consultaremos um índice com dois campos:</p>PUT linear_retriever_example
{
  "mappings": {
    "properties": {
      "semantic_text_field": { &lt;1&gt;
        "type": "semantic_text",
        "inference_id": ".multilingual-e5-small-elasticsearch"
      },
      "text_field": { &lt;2&gt;
        "type": "text"
      }
    }
  }
}<p>1. <code>semantic_text_field</code> é um campo <code>semantic_text</code> que usa <a href="https://www.elastic.co/docs/explore-analyze/machine-learning/nlp/ml-nlp-e5">E5</a>, um modelo de incorporação de texto.</p><p>2. <code>text_field</code> é um campo <code>text</code> padrão</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "retrievers": [
        {
          "retriever": {
            "standard": {
              "query": {
                "match": { &lt;1&gt;
                  "semantic_text_field": "foo"
                }
              }
            }
          },
          "normalizer": "minmax"
        },
        {
          "retriever": {
            "standard": {
              "query": {
                "match": {
                  "text_field": "foo"
                }
              }
            }
          },
          "normalizer": "minmax"
        }
      ]
    }
  }
}<p>1. Usamos uma consulta <code>match</code> em nosso campo <code>semantic_text</code> , para o qual <a href="https://www.elastic.co/search-labs/blog/semantic-search-match-knn-sparse-vector#we-made-match-happen-in-semantic-search!">adicionamos suporte no Elasticsearch 8.18/9.0</a></p><p>
Ao construir a consulta, precisamos ter em mente que <code>semantic_text_field</code> usa um modelo de incorporação de texto, portanto, quaisquer consultas sobre ele gerarão uma pontuação entre 0 e 1. Precisamos também saber que <code>text_field</code> é um campo <code>text</code> padrão e, portanto, as consultas nele gerarão uma pontuação ilimitada. Para criar um conjunto de resultados com a relevância adequada, precisamos usar um mecanismo de recuperação que normalize as pontuações das consultas antes de combiná-las. Neste exemplo, usamos o recuperador linear com normalização <code>minmax</code> , que normaliza a pontuação de cada consulta para um valor entre 0 e 1.</p><p>A construção da consulta neste exemplo é bastante simples, pois envolve apenas dois campos. No entanto, a situação pode se complicar rapidamente à medida que mais campos, e de tipos variados, são adicionados. Isso demonstra como escrever uma consulta de pesquisa híbrida eficaz geralmente requer um conhecimento mais profundo do índice consultado, para que as pontuações das consultas componentes sejam devidamente normalizadas antes da combinação. Isso representa uma barreira para a adoção mais ampla da busca híbrida.</p><h3>Agrupamento de consultas</h3><p>Vamos expandir o exemplo: E se quiséssemos consultar um campo <code>text</code> e dois campos <code>semantic_text</code> ? Poderíamos construir uma consulta como esta:</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "retrievers": [
        {
          "retriever": {
            "standard": {
              "query": {
                "semantic": {
                  "field": "semantic_text_field_1",
                  "query": "foo"
                }
              }
            }
          },
          "normalizer": "minmax"
        },
        {
          "retriever": {
            "standard": {
              "query": {
                "semantic": {
                  "field": "semantic_text_field_2",
                  "query": "foo"
                }
              }
            }
          },
          "normalizer": "minmax"
        },
        {
          "retriever": {
            "standard": {
              "query": {
                "match": {
                  "text_field": "foo"
                }
              }
            }
          },
          "normalizer": "minmax"
        }
      ]
    }
  }
}<p>Isso parece bom à primeira vista, mas existe um problema em potencial. Agora, as correspondências do campo <code>semantic_text</code> representam ⅔ da pontuação total:</p>Total Score = N(semantic_text_field_1 score) + N(semantic_text_field_2 score) + N(text_field score)<p>Provavelmente não é isso que você deseja, pois cria uma pontuação desequilibrada. Os efeitos podem não ser tão perceptíveis em um exemplo como este, com apenas 3 campos, mas tornam-se problemáticos quando mais campos são consultados. Por exemplo, a maioria dos índices contém muito mais campos lexicais do que semânticos (ou seja, <code>dense_vector</code>, <code>sparse_vector</code> ou <code>semantic_text</code>). E se estivéssemos consultando um índice com 9 campos lexicais e 1 campo semântico usando o padrão acima? As correspondências lexicais representariam 90% da pontuação, diminuindo a eficácia da busca semântica.</p><p>Uma forma comum de resolver isso é agrupar as consultas em categorias lexicais e semânticas e atribuir pesos iguais a ambas. Isso impede que qualquer uma das categorias domine a pontuação total.</p><p>Vamos colocar isso em prática. Como seria essa abordagem de consultas agrupadas neste exemplo ao usar o recuperador linear?</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "retrievers": [
        {
          "retriever": {
            "linear": {
              "retrievers": [
                {
                  "retriever": {
                    "standard": {
                      "query": {
                        "semantic": {
                          "field": "semantic_text_field_1",
                          "query": "foo"
                        }
                      }
                    }
                  },
                  "normalizer": "minmax"
                },
                {
                  "retriever": {
                    "standard": {
                      "query": {
                        "semantic": {
                          "field": "semantic_text_field_2",
                          "query": "foo"
                        }
                      }
                    }
                  },
                  "normalizer": "minmax"
                }
              ]
            }
          },
          "normalizer": "minmax"
        },
        {
          "retriever": {
            "standard": {
              "query": {
                "match": {
                  "text_field": "foo"
                }
              }
            }
          },
          "normalizer": "minmax"
        }
      ]
    }
  }
}<p>Uau, isso está ficando prolixo! Você pode até ter precisado rolar a página para cima e para baixo várias vezes para examinar toda a consulta! Aqui, utilizamos dois níveis de normalização para criar os grupos de consulta. Matematicamente, pode ser expresso como:</p>Total Score = N(N(semantic_text_field_1 score) + N(semantic_text_field_2 score)) + N(text_field score)<p>Este segundo nível de normalização garante que as consultas aos campos <code>semantic_text</code> e <code>text</code> sejam ponderadas igualmente. Observe que omitimos a normalização de segundo nível para <code>text_field</code> neste exemplo, uma vez que há apenas um campo lexical, poupando-o de <em>ainda mais</em> verbosidade.</p><p>Essa estrutura de consulta já é complexa demais, e estamos consultando apenas três campos. À medida que se consultam mais campos, a tarefa torna-se cada vez mais difícil de gerir, mesmo para profissionais de pesquisa experientes.</p><h2>O formato de consulta com vários campos</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5d9007d279f0da29/6a17f17714d90c39cf79b6f5/dd04e1686076a574b717c1460acfe4eb79299208-1600x1600.jpg" alt="" /><p>Adicionamos o <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/retrievers#multi-field-query-format">formato de consulta com vários campos</a> para os recuperadores lineares e RRF no Elasticsearch 8.19, 9.1 e <a href="https://www.elastic.co/cloud/serverless">serverless</a> para simplificar tudo isso. Agora você pode realizar a mesma consulta acima apenas com:</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "fields": [ "semantic_text_field_1", "semantic_text_field_2", "text_field" ],
      "query": "foo",
      "normalizer": "minmax"
    }
  }
}<p>O que reduz a consulta de 55 linhas para apenas 9! O Elasticsearch usa automaticamente os mapeamentos de índice para:</p><ul><li><p>Determine o tipo de cada campo consultado.</p></li><li><p>Agrupe cada campo em uma categoria lexical ou semântica.</p></li><li><p>Dê o mesmo peso a cada categoria na pontuação final.</p></li></ul><p>Isso permite que qualquer pessoa execute uma consulta de pesquisa híbrida eficaz sem precisar saber detalhes sobre o índice ou os endpoints de inferência utilizados.</p><p>Ao usar o RRF, você pode omitir o <code>normalizer</code>, já que a classificação é usada como um indicador de relevância:</p>GET rrf_retriever_example/_search
{
  "retriever": {
    "rrf": {
      "fields": [ "semantic_text_field_1", "semantic_text_field_2", "text_field" ],
      "query": "foo"
    }
  }
}<h2>Aumento por campo</h2><p>Ao usar o recuperador linear, você pode aplicar um reforço por campo para ajustar a importância das correspondências em determinados campos. Por exemplo, digamos que você esteja consultando quatro campos: dois campos <code>semantic_text</code> e dois campos <code>text</code> :</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "fields": [ "semantic_text_field_1", "semantic_text_field_2", "text_field_1", "text_field_2" ],
      "query": "foo",
      "normalizer": "minmax"
    }
  }
}<p>Por padrão, cada campo tem o mesmo peso em seu grupo (lexical ou semântico). A distribuição da pontuação é a seguinte:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdc6e197e5ff7b68d/6a17f179505ac32834ad8c46/ba31c76189e3a1e5b1638437ccf0528aafec2598-1600x549.png" alt="Comparação de grupos de consulta e pontuações de campo" /><p>Em outras palavras, cada área corresponde a 25% da pontuação total.</p><p>Podemos usar a sintaxe <code>field^boost</code> para adicionar um aumento por campo a qualquer campo. Vamos aplicar um aumento de 2 a <code>semantic_text_field_1</code> e <code>text_field_1</code>:</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "fields": [ "semantic_text_field_1^2", "semantic_text_field_2", "text_field_1^2", "text_field_2" ]
      "query": "foo",
      "normalizer": "minmax"
    }
  }
}<p>Agora a distribuição da pontuação é a seguinte:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltccc9ed7d6e865a5e/6a17f17abe6086a31d004882/de20e555d52f914bf483a048d056f54f4fece757-1600x549.png" alt="Alteração no peso do campo com busca de referência e híbrida" /><p>Cada grupo de consultas ainda tem o mesmo peso, mas agora o peso dos campos dentro dos grupos foi alterado:</p><ul><li><p><code>semantic_text_field_1</code> representa 66% da pontuação do grupo de consultas semânticas e 33% da pontuação total.</p></li><li><p><code>text_field_1</code> representa 66% da pontuação do grupo de consulta lexical e 33% da pontuação total.</p></li></ul><p>ℹ️ Observe que o intervalo de pontuação total não será alterado quando um aumento por campo for aplicado. Este é um efeito colateral intencional da normalização de pontuação, que garante que as pontuações das consultas lexicais e semânticas permaneçam diretamente comparáveis entre si.</p><p>ℹ️ O reforço por campo também pode ser usado com o recuperador RRF no Elasticsearch 9.2+</p><h3>Resolução curinga</h3><p>Você pode usar o caractere curinga <code>*</code> no parâmetro <code>fields</code> para corresponder a vários campos. Continuando o exemplo acima, esta consulta é funcionalmente equivalente a consultar explicitamente s<code>emantic_text_field_1</code>, <code>semantic_text_field_2</code> e <code>text_field_1</code> :</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "fields": [ "semantic_text_field_*", "*_field_1" ],
      "query": "foo",
      "normalizer": "minmax"
    }
  }
}<p>É interessante notar que o padrão <code>*_field_1</code> corresponde tanto <code>text_field_1</code> quanto a <code>semantic_text_field_1</code>. Isso é tratado automaticamente; a consulta será executada como se cada um dos campos tivesse sido consultado explicitamente. Também não há problema em que <code>semantic_text_field_1</code> corresponda a ambos os padrões; todas as correspondências de nomes de campos são desduplicadas antes da execução da consulta.</p><p>Você pode usar o caractere curinga de diversas maneiras:</p><ul><li><p>Correspondência de prefixo (ex: <code>*_text_field</code>)</p></li><li><p>Correspondência em linha (ex: <code>semantic_*_field</code>)</p></li><li><p>Correspondência de sufixo (ex: <code>semantic_text_field_*</code>)</p></li></ul><p>Você também pode usar vários curingas para aplicar uma combinação do acima, como <code>*_text_field_*</code>.</p><h3>Campos de consulta padrão</h3><p>O formato de consulta com vários campos também permite consultar um índice sobre o qual você não sabe nada. Se você omitir o parâmetro <code>fields</code> , a consulta abrangerá todos os campos especificados pela <a href="https://www.elastic.co/docs/reference/elasticsearch/index-settings/index-modules">configuração de índice index.query.default_field</a>:</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "query": "foo",
      "normalizer": "minmax"
    }
  }
}<p>Por padrão, <code>index.query.default_field</code> é definido como <code>*</code>. Este caractere curinga será resolvido para todos os tipos de campo no índice que suportam consultas por termo, que são a maioria. As exceções são:</p><ul><li><p><code>dense_vector</code> campos</p></li><li><p><code>rank_vector</code> campos</p></li><li><p>Campos geométricos: <code>geo_point</code>, <code>shape</code></p></li></ul><p>Essa funcionalidade é especialmente útil quando você deseja realizar uma consulta de pesquisa híbrida em um índice fornecido por terceiros. O formato de consulta com vários campos permite executar uma consulta adequada de forma simples. Basta excluir o parâmetro <code>fields</code> e todos os campos aplicáveis serão consultados.</p><h2>Conclusão</h2><p>O problema do intervalo de pontuação pode tornar a implementação de uma busca híbrida eficaz bastante complexa, especialmente quando há pouca informação sobre o índice consultado ou os endpoints de inferência em uso. O formato de consulta com múltiplos campos para os mecanismos de recuperação linear e RRF atenua esse problema, integrando uma abordagem de busca híbrida automatizada, baseada em agrupamento de consultas, em uma API simples e acessível. Funcionalidades adicionais, como reforço por campo, resolução de curingas e campos de consulta padrão, ampliam a funcionalidade para abranger diversos casos de uso.</p><h2>Experimente o formato de consulta com vários campos hoje mesmo.</h2><p>Você pode conferir os mecanismos de recuperação linear e RRF com o formato de consulta de múltiplos campos em projetos Elasticsearch <a href="https://www.elastic.co/cloud/serverless">Serverless</a> totalmente gerenciados, com um <a href="https://www.elastic.co/docs/deploy-manage/deploy/elastic-cloud/create-serverless-project">período de avaliação gratuito</a>. Também está disponível em versões de pilha a partir das versões 8.19 e 9.1.</p><p>Comece em minutos no seu ambiente local com um único comando:</p>curl -fsSL https://elastic.co/start-local | sh<p></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/hybrid-search-multi-field-query-retrievers-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/hybrid-search-multi-field-query-retrievers-elasticsearch</guid>
    <category><![CDATA[Busca híbrida]]></category>
    <category><![CDATA[Relevância]]></category>
    <dc:creator><![CDATA[Mike Pellegrini]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt89e066372c549595/6a17f17c3e9e457c38ba1583/4494f98ae3958bbdbc6171df9677fc4d65ec5640-1536x1024.png" length="0" type="image/png"/>
    <pubDate>Thu, 27 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Sabe, para contexto - Parte I: A evolução da busca híbrida e da engenharia de contexto]]></title>
    <description><![CDATA[Explore como a busca híbrida e a engenharia de contexto evoluíram a partir de fundamentos lexicais para viabilizar a próxima geração de fluxos de trabalho de IA com agentes.]]></description>
    <content:encoded><![CDATA[<h2>Nosso novíssimo mundo de IA agente</h2><p>Como muitos de nós, me sinto ao mesmo tempo entusiasmado e surpreso com a velocidade com que as capacidades da IA estão evoluindo. Vimos pela primeira vez os grandes modelos de linguagem (LLMs) e a busca vetorial nos lançarem na revolução semântica, onde não precisávamos mais ficar procurando coisas com palavras-chave. Em seguida, os LLMs nos mostraram novas maneiras de interagir com nossos dados, usando interfaces de bate-papo para transformar solicitações em linguagem natural em respostas que destilam vastas bases de conhecimento em resumos facilmente assimiláveis. Nós agora (já!) Possuem os primórdios da lógica automatizada orientada por LLM na forma de fluxos de trabalho de "IA agente" que podem compreender semanticamente uma solicitação recebida, raciocinar sobre as etapas a serem seguidas e, em seguida, escolher entre as ferramentas disponíveis para executar iterativamente ações para atingir esses objetivos.</p><p>A promessa da IA agente está nos forçando a evoluir, deixando de usar principalmente a "engenharia de prompts" para moldar nossas interações generativas de IA, e passando a nos concentrar em como podemos ajudar as ferramentas agentes a obter as informações adicionais mais relevantes e eficientes que o LLM precisa considerar ao gerar suas respostas — a "engenharia de contexto" é a próxima fronteira. A busca híbrida é, de longe, o meio mais poderoso e flexível para revelar contexto relevante, e a plataforma Search AI da Elastic abre uma nova maneira de aproveitar os dados a serviço da engenharia de contexto. Neste artigo, discutiremos como os Modelos de Aprendizagem Baseados em Liderança (LLMs) transformaram o mundo da recuperação de informação sob duas perspectivas e, em seguida, como eles podem trabalhar em conjunto para alcançar melhores resultados. Há muito terreno a percorrer…</p><h2>Parte I: Como os LLMs mudaram a busca</h2><p>Vamos começar pela perspectiva de como os LLMs (mestrados em direito) mudaram a forma como acessamos e recuperamos informações.</p><h3>Nosso legado lexical</h3><p>Há muito tempo que vivemos num mundo de busca lexical um tanto limitado (ou quase, da melhor forma possível). A busca é a primeira ferramenta que utilizamos ao pesquisar ou iniciar um novo projeto e, até recentemente, dependia de nós formular nossas consultas de uma maneira que um mecanismo de busca lexical entendesse. A busca lexical baseia-se na correspondência de algum tipo de termo de consulta com palavras-chave encontradas em um conjunto de documentos — independentemente de o conteúdo ser estruturado ou não estruturado. Para que uma busca lexical retorne um documento como resultado, ele precisa ter correspondido àquela palavra-chave (ou ter um vocabulário controlado, como uma lista de sinônimos ou um dicionário, para fazer a conexão conceitual para nós).</p>POST my-index/_search
{
  "size": 10,
  "query": {
    "semantic": {
      "query": "machine learning applications",
      "field": "semantic-content-field"
    }
  }
}<p><em>Um exemplo de </em><a href="https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-multi-match-query"></a><em> consulta lexical de correspondência múltipla</em></p><p>Ao menos os mecanismos de busca têm a capacidade de retornar resultados com uma pontuação de relevância. Os mecanismos de busca oferecem uma ampla gama de opções de sintaxe de consulta para segmentar dados indexados de forma eficaz, além de algoritmos de relevância integrados que classificam os resultados de acordo com a intenção da sintaxe de consulta do usuário. Os mecanismos de busca se beneficiam de décadas de avanços em algoritmos de classificação por relevância, o que os torna uma plataforma eficiente de recuperação de dados, capaz de fornecer resultados pontuados e classificados de acordo com sua relevância para a consulta. Bancos de dados e outros sistemas que usam SQL como principal método para recuperar dados estão em desvantagem nesse aspecto: não existe o conceito de relevância em uma consulta de banco de dados; o máximo que podem fazer é classificar os resultados alfabeticamente ou numericamente. A boa notícia é que você obterá todos os resultados (recall) com essas palavras-chave, mas eles não estarão necessariamente em uma ordem útil em relação ao <em>motivo pelo qual</em> você os solicitou (precisão). Esse é um ponto importante, como veremos em breve…</p><h3>Entre o dragão (semântico)</h3><p>O potencial das representações vetoriais de informações como alternativa à busca por palavras-chave vem sendo pesquisado há <a href="https://www.elastic.co/search-labs/blog/introduction-to-vector-search">bastante tempo</a>. Os vetores são muito promissores porque nos libertam do modo de correspondência de conteúdo baseado apenas em palavras-chave — como são representações numéricas de termos e pesos, os vetores permitem que os conceitos sejam matematicamente próximos com base na compreensão do modelo de linguagem sobre como os termos se relacionam entre si no domínio de treinamento. A longa demora na busca por vetores de propósito geral se devia ao fato de os modelos serem, em sua maioria, limitados a domínios específicos; eles simplesmente não eram grandes o suficiente para compreender adequadamente os muitos conceitos diferentes que um termo poderia representar em diferentes contextos.</p><p>Foi somente com o surgimento dos Modelos de Linguagem de Grande Porte (LLMs, na sigla em inglês), há alguns anos, e sua capacidade de serem treinados com quantidades muito maiores de dados (usando <a href="https://en.wikipedia.org/wiki/Transformer_(deep_learning_architecture)">transformadores</a> e <a href="https://en.wikipedia.org/wiki/Attention_(machine_learning)">atenção</a>), que a busca vetorial se tornou viável — o tamanho e a profundidade dos LLMs finalmente permitiram que os vetores armazenassem nuances suficientes para, de fato, capturar o significado semântico. Esse aumento repentino na profundidade de compreensão permitiu que os LLMs (Learning Language Machines) passassem a desempenhar diversas funções de processamento de linguagem natural (PLN) que antes estavam bloqueadas, sendo talvez a mais impactante a capacidade de inferir o próximo termo mais provável em uma sequência, dado o contexto do que já estava presente na sequência. A inferência é o processo que confere à IA generativa sua capacidade quase humana de produzir texto. O texto gerado por IA é baseado na compreensão do LLM sobre como os termos se relacionam em seus dados de treinamento e também utiliza a formulação da solicitação para diferenciar os diversos contextos em que os termos podem aparecer.</p><p>Por mais mágica que seja a IA generativa, os LLMs <em>têm</em> limitações que causam erros de qualidade e precisão, comumente chamados de alucinações. As alucinações ocorrem quando o profissional de saúde mental não tem acesso à informação (ou não é guiado ao contexto correto) para basear sua resposta na verdade, então, na tentativa de ser prestativo, ele gera uma resposta confiante e plausível que, na verdade, é inventada. Parte da causa é que, embora os LLMs aprendam o uso da linguagem em grandes domínios de informações diversas, eles precisam interromper o treinamento em um determinado momento, portanto, há um fator de temporalidade em sua compreensão — o que significa que o modelo só pode saber o que era preciso até o momento em que o treinamento foi interrompido. Outro fator que contribui para as alucinações é que o modelo geralmente desconhece dados privados (dados não disponíveis na internet pública), e isso é especialmente significativo quando esses dados contêm termos e nomenclatura específicos.</p><h3>Bancos de dados vetoriais</h3><p>Os LLMs vetorizam o conteúdo para seu espaço de modelo usando uma técnica chamada incorporação de texto, que se refere à <a href="https://www.elastic.co/search-labs/blog/hybrid-search-multiple-embeddings">incorporação</a> ou mapeamento do significado semântico do conteúdo na visão de mundo do modelo com base no treinamento que ele recebeu. Existem algumas etapas envolvidas na preparação e no processamento de conteúdo para incorporação, incluindo <a href="https://www.elastic.co/search-labs/blog/chunking-strategies-elasticsearch">a segmentação</a> e a tokenização (e <a href="https://www.kaggle.com/code/danishmahdi/subword-tokenization-bpe-wordpiece-and-unigram">a tokenização de subpalavras</a>). O resultado é tipicamente um conjunto de vetores densos que representam a compreensão do modelo sobre o significado daquele trecho de conteúdo dentro de seu espaço vetorial. O chunking é um processo impreciso que visa ajustar o conteúdo às limitações de processamento de um modelo para gerar embeddings, tentando também agrupar textos relacionados em um chunk usando construções semânticas como indicadores de sentença e parágrafo.</p><p>A necessidade de fragmentação pode gerar alguma perda semântica em um documento incorporado, porque os fragmentos individuais não estão totalmente associados a outros fragmentos do mesmo documento. A opacidade inerente das redes neurais pode agravar essa perda de informação — um modelo de aprendizagem linear é verdadeiramente uma “caixa preta”, onde as conexões entre termos e conceitos feitas durante o treinamento não são determinísticas e não podem ser interpretadas por humanos. Isso acarreta problemas de explicabilidade, repetibilidade, viés inconsciente e, potencialmente, perda de confiança e precisão. No entanto, a capacidade de conectar ideias semanticamente, de não estar vinculado a palavras-chave específicas ao fazer buscas, é extremamente poderosa:</p>POST my-index/_search 
{
  "size": 10, 
  "query": {
    "semantic": {
      "query": "machine learning applications",
      "field": "semantic-content-field"
    }
  }
} <p><em>Um exemplo </em><a href="https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-semantic-query"><em>de</em></a><em> consulta semântica</em></p><p>Há ainda outra questão a considerar em relação às bases de dados vetoriais: elas não são motores de busca, são bases de dados! Quando uma <a href="https://www.elastic.co/search-labs/blog/introduction-to-vector-search">busca por similaridade vetorial</a> é realizada, os termos da consulta são codificados para encontrar um conjunto de coordenadas (de incorporação) dentro do espaço vetorial do modelo. Essas coordenadas são então usadas como o alvo para encontrar os documentos que são os "vizinhos mais próximos" do alvo — o que significa que a classificação de um documento (ou sua posição nos resultados) é determinada pela <em>distância</em> de similaridade calculada entre as coordenadas desse documento e as coordenadas da consulta. Em que direção a classificação deve ter prioridade? Qual dos contextos possíveis está mais próximo da intenção do usuário? A imagem que me vem à mente é uma cena do filme <a href="https://www.youtube.com/watch?v=x3h7xz558EY&amp;start=3&amp;end=86">Stargate</a>, onde temos os seis pontos de coordenadas que se cruzam para nos indicar o destino (o alvo), mas não conseguimos chegar lá sem conhecer o "sétimo símbolo" - as coordenadas do ponto de partida que representam a intenção subjetiva do usuário. Assim, em vez de a classificação relativa dos vetores ser baseada em uma esfera de similaridade cada vez maior e indiferenciada, ao considerarmos a intenção subjetiva da consulta por meio de sintaxe expressiva e pontuação de relevância, podemos obter algo semelhante a um <em>cilindro</em> de relevância subjetiva graduada.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb49ae330d3de1fc1/6a17053ee8fbce089639fb46/1ddfaae0c1496d08d7d30419e6d2aeaeacfc0ea2-1600x544.png" alt="Um cilindro de relevância subjetiva graduada." /><p>As capacidades de inferência de um LLM podem ajudar a identificar o contexto mais provável <em>para</em> a consulta, mas o problema é que <em>, sem essa ajuda,</em> as coordenadas da consulta recebida <em>só</em> podem ser determinadas pela forma como o modelo foi originalmente treinado.</p><p>De certa forma, pode-se dizer que a similaridade vetorial vai ao extremo oposto da correspondência estrita por palavras-chave — sua força reside na capacidade de superar os problemas de incompatibilidade de termos, mas <a href="https://medium.com/data-science/vector-embeddings-are-lossy-heres-what-to-do-about-it-4f9a8ee58bb7">quase em excesso</a>: os modelos de similaridade de palavras tendem a unificar conceitos relacionados em vez de diferenciá-los. A similaridade vetorial melhora nossa capacidade de combinar conteúdo semanticamente, mas não garante precisão, pois pode ignorar palavras-chave exatas e detalhes específicos que não são suficientemente desambiguados pelo modelo. A busca por similaridade vetorial é poderosa por si só, mas precisamos de maneiras de correlacionar os resultados que obtemos de um banco de dados vetorial com os resultados de outros métodos de recuperação.</p><h3>Técnicas de reclassificação</h3><p>Agora é um bom momento para mencionar uma técnica geral chamada reclassificação, que reavalia ou normaliza os conjuntos de resultados para uma ordem de classificação unificada. A necessidade de reclassificação pode ser devida a resultados de múltiplas fontes ou métodos de recuperação que possuem mecanismos de classificação/pontuação diferentes (ou nenhum, como no caso do SQL!), ou a reclassificação pode ser usada para alinhar semanticamente os resultados de fontes não semânticas à consulta do usuário. A reclassificação é uma operação de segunda etapa, ou seja, um conjunto de resultados que foram coletados por algum método <em>de recuperação inicial</em> (ou seja, Em seguida, os métodos de busca (SQL, busca lexical, busca vetorial) são reordenados com um método de pontuação diferente.</p><p>Existem diversas abordagens disponíveis, incluindo <a href="https://www.elastic.co/docs/solutions/search/ranking/learning-to-rank-ltr">Learning-To-Rank (LTR)</a> e <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/reciprocal-rank-fusion">Reciprocal Rank Fusion (RRF)</a> — o LTR é útil para capturar características dos resultados de pesquisa (curtidas, avaliações, cliques, etc.) e usá-las para pontuar e impulsionar ou influenciar os resultados. O RRF é perfeito para mesclar resultados retornados de diferentes modalidades de consulta (por exemplo, pesquisas lexicais e em bancos de dados vetoriais) juntas em uma única lista de resultados. O Elastic também oferece a flexibilidade de ajustar as pontuações usando métodos <a href="https://www.elastic.co/search-labs/blog/linear-retriever-hybrid-search">de reclassificação linear</a> .</p><p>Uma das técnicas de reclassificação mais eficazes, no entanto, é <a href="https://www.elastic.co/docs/solutions/search/ranking/semantic-reranking">a reclassificação semântica</a>, que utiliza a compreensão semântica de um modelo de aprendizado de máquina para analisar os vetores de incorporação da consulta e dos resultados em conjunto e, em seguida, aplicar a pontuação/repontuação de relevância para determinar a ordem final. A reclassificação semântica requer, obviamente, uma conexão com um modelo de reclassificação, e o Elasticsearch fornece uma <a href="https://www.elastic.co/docs/api/doc/elasticsearch/group/endpoint-inference">API de Inferência</a> que permite criar endpoints <strong>de reclassificação</strong> que utilizam modelos integrados (<a href="https://www.elastic.co/docs/explore-analyze/machine-learning/nlp/ml-nlp-rerank">Elastic Rerank</a>), modelos de terceiros <a href="https://www.elastic.co/docs/reference/elasticsearch/clients/eland/machine-learning">importados</a> ou serviços hospedados externamente, como <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-cohere">Cohere</a> ou <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-googlevertexai">Google Vertex AI</a>. Em seguida, você pode realizar a reclassificação por meio da sintaxe de abstração de consulta <a href="https://www.elastic.co/docs/solutions/search/retrievers-overview">do recuperador</a> :</p>POST my-index/_search 
{
  "size": 10,
  "retriever": {
    "text_similarity_reranker": {
      "retriever": {
        "rrf": {
          "retrievers": [
            {
              "standard": {
                "query": {
                  "multi_match": {
                    "query": "machine learning applications",
                    "fields": ["title", "content"]
                  }
                }
              }
            },
            {
              "knn": {
                "field": "semantic-content-field",
                "k": 10,
                "num_candidates": 100,
                "query_vector_builder": {
                  "text_embedding": {
                    "model_id": "my-text-embedding-model",
                    "model_text": "machine learning applications"
                  }
                }
              }
            }
          ],
          "rank_window_size": 50,
          "rank_constant": 20
        }
      }
    },
    "field": "content",
    "inference_id": "my-reranker",
    "inference_text": "machine learning applications",
    "rank_window_size": 20
  }
}<p><em>Um exemplo de operação de reclassificação de recuperação em múltiplos estágios</em></p><p>Parece ótimo, não é? Podemos realizar uma reclassificação de resultados de fontes distintas e chegar perto de uma compreensão semântica de todos os tipos de conteúdo... A reclassificação semântica pode ser dispendiosa tanto em termos computacionais quanto de tempo de processamento, e por isso, só pode ser feita de forma viável em um número limitado de resultados, o que significa que <em>a forma como</em> esses resultados iniciais são obtidos é importante.</p><h3>O método de recuperação de contexto é importante.</h3><p>A intenção subjetiva é um fator importante para determinar a precisão de um resultado e avaliar sua relevância. Sem a possibilidade de considerar a intenção do usuário ao realizar a consulta (expressa por meio de sintaxe flexível ou por reclassificação em um segundo estágio), só podemos selecionar entre os contextos existentes já codificados no espaço do modelo. Normalmente, lidamos com essa falta de contexto por meio de técnicas como <a href="https://en.wikipedia.org/wiki/Retrieval-augmented_generation">a Geração de Aumento de Recuperação (RAG)</a>. O RAG funciona alterando as coordenadas da consulta ao incluir termos relacionados adicionais retornados de uma pré-consulta para obter dados contextualmente relevantes. Isso torna o mecanismo que fornece esse contexto adicional e <em>seu</em> método inicial de recuperação ainda mais importantes para a precisão do contexto!</p><p>Vamos analisar os diferentes métodos de recuperação de contexto e como eles podem ajudar ou prejudicar uma operação RAG:</p><ul><li><p><strong>A recuperação de pesquisa híbrida sem um mecanismo de busca ainda carece de relevância subjetiva.</strong> Se a plataforma que fornece o RAG for baseada principalmente em SQL (o que inclui a maioria das plataformas de "data lake"), ela não terá pontuação de relevância na fase inicial de recuperação. Muitas plataformas de data lake oferecem sua própria versão de recuperação híbrida (não busca), geralmente combinando técnicas de reclassificação como reclassificação semântica e RRF em seus resultados de recuperação baseados em SQL e em bancos de dados vetoriais. Uma simples ordenação é obviamente insuficiente para uma classificação subjetiva, mas mesmo quando usada como base para uma operação de reclassificação semântica de segundo estágio, o SQL como recuperação de primeiro estágio torna-se um problema quando a reclassificação semântica é realizada apenas nos "k melhores" resultados — sem alguma forma de pontuar os resultados na recuperação, que garantia temos de que os <em>melhores</em> resultados estão realmente entre os primeiros resultados?</p></li><li><p><strong>A similaridade vetorial por si só não é suficiente para o RAG</strong>. Na verdade, isso se deve a uma série de problemas que se acumulam: a perda de dados inerente ao processo de incorporação, juntamente com métodos ingênuos de segmentação, a forma como a similaridade é calculada e a ausência crucial do componente de intenção subjetiva. Um dos principais objetivos do RAG é fundamentar as interações da IA generativa na verdade objetiva, tanto para evitar alucinações quanto para informar o LLM sobre informações privadas que ele desconhecia durante o treinamento. Podemos usar o contexto adicional fornecido pelo RAG para restringir e direcionar os LLMs a considerarem as conexões e os detalhes que sabemos serem mais importantes para responder à questão em análise. Para isso, precisamos usar <em>abordagens</em> semânticas e lexicais.</p></li><li><p><strong>RAG baseado em grep/regex de arquivo.</strong> Há <a href="https://www.nicolasbustamante.com/p/the-rag-obituary-killed-by-agents">setores</a> do universo da IA agente que apontam para o uso de janelas de contexto vastamente ampliadas que acessam arquivos locais via grep e regex para RAG (Random Access Groups - Grupos de Acesso Aleatório) em vez de plataformas de recuperação externas. A ideia é que, com uma janela contextual muito maior disponível, os profissionais de Letras e Literatura (LLMs) poderão fazer conexões conceituais dentro de seu próprio espaço de pensamento, em vez de depender de fragmentos isolados e de múltiplos métodos/plataformas de recuperação de informações para coletar informações relevantes. Embora seja verdade, em teoria, que ter um documento inteiro forneça uma visão mais completa do que segmentos de um documento, isso só funciona em domínios de dados pequenos (ou, por exemplo, ao fornecer arquivos para <a href="https://en.wikipedia.org/wiki/Vibe_coding">vibecoding</a>) e, mesmo assim, o método de recuperação inicial é uma varredura de todos os documentos com correspondência apenas por palavra-chave.</p></li></ul><p><strong>A busca é mais do que a recuperação de informações.</strong></p><p>Os mecanismos de busca são projetados especificamente para tornar as consultas o mais rápidas e flexíveis possível. Internamente, utilizam estruturas de dados especializadas para armazenar e recuperar diferentes tipos de dados de maneiras que atendam às necessidades específicas de cada tipo de dado. O Elasticsearch oferece armazenamento e consulta otimizados para praticamente todos os tipos de dados, incluindo busca lexical em texto completo/não estruturado (correspondência, frase, proximidade, correspondência múltipla), correspondência e filtragem rápidas por palavra-chave (correspondência exata), intervalos numéricos, datas, endereços IP, e é muito flexível na forma como armazena estruturas de documentos (por exemplo, documentos aninhados ou achatados). O Elasticsearch também é um banco de dados vetorial nativo que pode armazenar e consultar tipos de vetores esparsos e densos, e continuamos a explorar maneiras inovadoras (por exemplo, <a href="https://www.elastic.co/search-labs/blog/better-binary-quantization-lucene-elasticsearch">Better Binary Quantization (BBQ)</a> e <a href="https://www.elastic.co/search-labs/blog/diskbbq-elasticsearch-introduction">DiskBBQ</a>) para manter a fidelidade da pesquisa, ao mesmo tempo que melhoramos a velocidade, a escalabilidade e os custos associados ao conteúdo vetorizado. A plataforma Elasticsearch também oferece resiliência de dados e alta disponibilidade integradas, e inclui recursos de gerenciamento do ciclo de vida dos dados, como <a href="https://www.elastic.co/docs/deploy-manage/tools/snapshot-and-restore/searchable-snapshots">Snapshots pesquisáveis</a> , que permitem manter dados acessados com pouca frequência ou com retenção de longo prazo em armazenamento de objetos econômico — mas ainda totalmente pesquisáveis.</p><h3>A busca híbrida oferece o melhor de todos os mundos.</h3><p><a href="https://www.elastic.co/what-is/hybrid-search">Busca híbrida</a> (e não apenas recuperação híbrida!) Combina os pontos fortes da busca lexical tradicional com a compreensão semântica dos Modelos de Aprendizagem Lógica (LLMs) e da busca por similaridade vetorial. Essa sinergia permite direcionar resultados altamente relevantes na fase <em>de recuperação</em> por meio de qualquer uma das opções flexíveis de sintaxe de consulta que um mecanismo de busca oferece: opções de sintaxe orientadas por intenção e pontuação de relevância, recuperação de dados multimodais, filtragem, agregações e direcionamento. Com sintaxes de busca como <a href="https://www.elastic.co/docs/reference/query-languages/esql">ES|QL</a> e <a href="https://www.elastic.co/docs/solutions/search/retrievers-overview">mecanismos de recuperação</a> em múltiplos estágios, podemos combinar de forma flexível a busca tradicional com a busca semântica, filtros e múltiplas técnicas de reclassificação, tudo em uma única requisição.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6ee9512910856ee3/6a17053fcdacbf2ea97d291e/f25180cb430414b99ae553d3b8eb161dbccea4d4-1920x1080.png" alt="Como funciona a busca híbrida" /><p>Uma das maiores vantagens da pesquisa híbrida é que suas consultas podem usar sintaxe especializada para vários tipos de dados diferentes simultaneamente. Essas diferentes sintaxes de consulta podem ser usadas não apenas para <em>encontrar</em> resultados, mas também como filtros ou agregações <em>nos</em> resultados. Por exemplo, um dos tipos de consulta mais comuns que frequentemente é combinado com outras sintaxes é <a href="https://www.elastic.co/docs/explore-analyze/geospatial-analysis">a análise geoespacial</a>. Você pode realizar ações como consultar resultados que possuam coordenadas geográficas dentro de uma distância específica de um ponto, solicitar agregações de seus resultados por região ou ainda agregações para rastrear e alertar sobre movimentos de entrada e saída de uma zona. Com a pesquisa híbrida, você tem a flexibilidade de combinar sintaxes para direcionar os resultados da maneira mais precisa, recuperando o conteúdo mais próximo do seu contexto.</p><h2>Intervalo</h2><p>Esta primeira parte conta a história de como a busca vetorial mudou a forma como conseguimos recuperar dados e prepara o terreno para as mudanças que os Modelos de Aprendizagem Baseados em Lógica (LLMs) trouxeram aos mecanismos de consulta que usamos para interagir com os dados. Vamos fingir que tivemos que dividir isso em várias partes para que os LLMs pudessem entender sem perder o contexto… ;-) Vamos aprender mais sobre <em>por que isso é importante</em> na <a href="https://www.elastic.co/search-labs/blog/context-engineering-llm-evolution-agentic-ai">Parte II: IA Agêntica e a necessidade de engenharia de contexto</a>, e na Parte III, retornaremos à nossa discussão sobre busca híbrida.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/context-engineering-hybrid-search-evolution-agentic-ai</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/context-engineering-hybrid-search-evolution-agentic-ai</guid>
    <category><![CDATA[Busca híbrida]]></category>
    <category><![CDATA[Relevância]]></category>
    <dc:creator><![CDATA[Woody Walton]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc49e39872984c8eb/6a1705410e2e49e42c419fd5/7e59a0671aa9ea32d68188a693936a66ebf48625-1000x628.png" length="0" type="image/png"/>
    <pubDate>Wed, 12 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Busca híbrida revisitada: apresentando o recuperador linear no Elasticsearch!]]></title>
    <description><![CDATA[Descubra como o recuperador linear aprimora a busca híbrida, aproveitando pontuações ponderadas e normalização MinMax para classificações mais precisas e consistentes, e aprenda a usá-lo.]]></description>
    <content:encoded><![CDATA[<p>Em nossa postagem <a href="https://www.elastic.co/pt/search-labs/blog/elasticsearch-retrievers-ga-8.16.0">anterior,</a> apresentamos a estrutura de recuperadores redesenhada do zero, que permite a criação de pipelines de classificação complexos. Também exploramos como o recuperador Reciprocal Rank Fusion (RRF) permite a pesquisa híbrida ao mesclar resultados de diferentes consultas. Embora o RRF seja fácil de implementar, ele tem uma limitação notável: ele se concentra apenas em classificações relativas, ignorando pontuações reais. Isso torna o ajuste fino e a otimização um desafio.</p><h2>Conheça o retriever linear!</h2><p>Nesta postagem, apresentamos o <a href="https://www.elastic.co/pt/docs/solutions/search/retrievers-overview#retrievers-overview-types">recuperador</a> <a href="https://www.elastic.co/pt/docs/solutions/search/retrievers-overview#retrievers-overview-types"><code>linear</code></a> , nossa mais recente adição para oferecer suporte à pesquisa híbrida! Ao contrário de <code>rrf</code>, o recuperador <code>linear</code> calcula uma soma ponderada em todas as consultas que correspondem a um documento. Essa abordagem preserva a importância relativa de cada documento dentro de um conjunto de resultados, ao mesmo tempo que permite controle preciso sobre a influência de cada consulta na pontuação final. Como resultado, ele fornece uma maneira mais intuitiva e flexível de ajustar a pesquisa híbrida.</p><p>Definindo um recuperador linear onde a pontuação final será calculada como:</p><p>É tão simples quanto:</p>GET linear_retriever_blog/_search
{
   "retriever": {
       "linear": {
           "retrievers": [
               {
                   "retriever": {
                       "knn": {
                          ...
                        }
                    },
                   "weight": 5
               },
                  {
                   "retriever": {
                       "standard": {
                          ...
                        }
                    },
                   "weight": 1.5
               },


           ]
        }
     }
}<p>Percebeu como é simples e intuitivo? (e muito parecido com <code>rrf</code>!) Essa configuração permite que você controle precisamente quanto cada tipo de consulta contribui para a classificação final, ao contrário de <code>rrf</code>, que depende apenas de classificações relativas.</p><p>Uma ressalva permanece: as pontuações <code>knn</code> podem ser estritamente limitadas, dependendo da métrica de similaridade usada. Por exemplo, com similaridade de cosseno ou produto escalar de vetores normalizados por unidade, as pontuações sempre estarão dentro do intervalo <code>[0, 1]</code> . Em contraste, as pontuações <code>bm25</code> são menos previsíveis e não têm limites claramente definidos.</p><h2>Escalando as pontuações: kNN vs BM25</h2><p>Um desafio da busca híbrida é que diferentes recuperadores produzem pontuações em escalas diferentes. Considere, por exemplo, o seguinte cenário:</p><p>Pontuações da consulta A:</p><p></p><p>doc1</p><p>doc2</p><p>doc3</p><p>doc4</p><p>knn</p><p>0,347</p><p>0,35</p><p>0,348</p><p>0,346</p><p>bm25</p><p>100</p><p>1,5</p><p>1</p><p>0,5</p><p>Pontuações da consulta B:</p><p></p><p>doc1</p><p>doc2</p><p>doc3</p><p>doc4</p><p>knn</p><p>0,347</p><p>0,35</p><p>0,348</p><p>0,346</p><p>bm25</p><p>0,63</p><p>0,01</p><p>0,3</p><p>0,4</p><p>Você pode ver a disparidade acima: as pontuações <code>kNN</code> variam entre 0 e 1, enquanto as pontuações <code>bm25</code> podem variar muito. Essa diferença dificulta a definição de pesos estáticos ideais para combinar os resultados.</p><h2>Normalização para o resgate: o normalizador MinMax</h2><p>Para resolver isso, introduzimos um normalizador <code>minmax</code> opcional que dimensiona as pontuações, independentemente para cada consulta, para o intervalo <code>[0, 1]</code> usando a seguinte fórmula:</p><p>Isso preserva a importância relativa de cada documento dentro do conjunto de resultados de uma consulta, facilitando a combinação de pontuações de diferentes recuperadores. Com a normalização, as pontuações se tornam:</p><p>Pontuações da consulta A:</p><p></p><p>doc1</p><p>doc2</p><p>doc3</p><p>doc4</p><p>knn</p><p>0,347</p><p>0,35</p><p>0,348</p><p>0,346</p><p>bm25</p><p>1,00</p><p>0,01</p><p>0,005</p><p>0,000</p><p>Pontuações da consulta B:</p><p></p><p>doc1</p><p>doc2</p><p>doc3</p><p>doc4</p><p>knn</p><p>0,347</p><p>0,35</p><p>0,348</p><p>0,346</p><p>bm25</p><p>1,00</p><p>0,000</p><p>0,465</p><p>0,645</p><p>Todas as pontuações agora estão no intervalo <code>[0, 1]</code> e otimizar a soma ponderada é muito mais simples, pois agora capturamos a importância (em relação à consulta) de um resultado em vez de sua pontuação absoluta e mantemos a consistência entre as consultas.</p><h2>Exemplo de recuperador linear </h2><p>Vamos ver um exemplo agora para mostrar a aparência do exemplo acima e como o recuperador <code>linear</code> aborda algumas das deficiências do <code>rrf</code>. O RRF depende somente de classificações relativas e não considera diferenças reais de pontuação. Por exemplo, dadas estas pontuações:</p><p></p><p>doc1</p><p>doc2</p><p>doc3</p><p>doc4</p><p>knn</p><p>0,347</p><p>0,35</p><p>0,348</p><p>0,346</p><p>bm25</p><p>100</p><p>1,5</p><p>1</p><p>0,5</p><p>pontuação rrf</p><p>0,03226</p><p>0,03252</p><p>0,03200</p><p>0,03125</p><p>rrf classificaria os documentos como:</p><p>No entanto, doc1 tem uma pontuação <code>bm25</code> significativamente maior que as outras, o que <code>rrf</code> não consegue capturar porque só analisa classificações relativas. O recuperador <code>linear</code> , combinado com a normalização, contabiliza corretamente as pontuações e suas diferenças, produzindo uma classificação mais significativa:</p><p></p><p>doc1</p><p>doc2</p><p>doc3</p><p>doc4</p><p>knn</p><p>0,347</p><p>0,35</p><p>0,348</p><p>0,346</p><p>bm25</p><p>1</p><p>0,01</p><p>0,005</p><p>0</p><p>Como podemos ver acima, a ótima classificação do doc1 e <code>score</code> para <code>bm25</code> são devidamente contabilizadas e refletidas nas pontuações finais. Além disso, todas as pontuações agora estão no intervalo <code>[0, 1]</code> para que possamos compará-las e combiná-las de uma forma muito mais intuitiva (e até mesmo criar processos de otimização offline).</p><h2>Juntando tudo</h2><p>Para aproveitar ao máximo o recuperador <code>linear</code> com normalização, a solicitação de pesquisa ficaria assim:</p>GET linear_retriever_blog/_search
{
   "retriever": {
       "linear": {
           "retrievers": [
               {
                   "retriever": {
                       "knn": {
                          ...
                        }
                    },
                   "weight": 5
               },
                  {
                   "retriever": {
                       "standard": {
                          ...
                        }
                    },
                   "weight": 1.5,
                   "normalizer": "minmax"
               },


           ]
       }
   }
}<p>Essa abordagem combina o melhor dos dois mundos: ela mantém a flexibilidade e a pontuação intuitiva do recuperador <code>linear</code> , ao mesmo tempo em que garante uma escala de pontuação consistente com a normalização MinMax.</p><p>Assim como todos os nossos recuperadores, o recuperador <code>linear</code> pode ser integrado a qualquer nível de uma árvore hierárquica de recuperadores, com suporte para explicabilidade, destaque de correspondência, recolhimento de campo e muito mais.</p><h2>Quando escolher o retriever linear e por que isso faz a diferença</h2><p>O recuperador <code>linear</code> :</p><ul><li><p>Preserva a importância relativa aproveitando pontuações reais, não apenas classificações.</p></li><li><p>Permite ajustes finos com contribuições ponderadas de diferentes consultas.</p></li><li><p>Melhora a consistência usando a normalização, tornando a pesquisa híbrida mais robusta e previsível.</p></li></ul><h2>Conclusão</h2><p>O recuperador <code>linear</code> já está disponível no Elasticsearch Serverless e nas versões 8.18 e 9.0! Mais exemplos e parâmetros de configuração também podem ser encontrados em nossa documentação. Experimente e veja como ele pode melhorar sua experiência de pesquisa híbrida — aguardamos seu feedback. Boa busca!</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/linear-retriever-hybrid-search</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/linear-retriever-hybrid-search</guid>
    <category><![CDATA[Relevância]]></category>
    <category><![CDATA[Busca híbrida]]></category>
    <dc:creator><![CDATA[Panagiotis Bailis]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte58a751cbcc1153d/6a17e3c76317305c4f585a10/7a07e27e3095463ff93b4cb7f8a0cf3b8e44eab0-1777x1000.png" length="0" type="image/png"/>
    <pubDate>Wed, 28 May 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Criando listas de julgamento com Quepid]]></title>
    <description><![CDATA[Aprenda a criar listas de julgamento no Quepid usando um processo colaborativo de avaliador humano e utilize os benchmarks para ajustar sua relevância.]]></description>
    <content:encoded><![CDATA[<p>A criação de <a href="https://www.elastic.co/search-labs/blog/judgment-lists">listas de julgamento</a> é uma etapa crucial na otimização da qualidade dos resultados de pesquisa, mas pode ser uma tarefa complexa e difícil. Uma lista de julgamento é um conjunto selecionado de consultas de pesquisa combinadas com classificações de relevância para seus respectivos resultados, também conhecida como coleção de teste. As métricas calculadas usando esta lista servem como referência para medir o desempenho de um mecanismo de busca. Para ajudar a agilizar o processo de criação de listas de julgamento, a equipe <a href="https://opensourceconnections.com/">do OpenSource Connections</a> desenvolveu <a href="https://quepidapp.com/">o Quepid</a>. O julgamento pode ser explícito ou baseado em feedback implícito dos usuários. Este blog irá orientá-lo na configuração de um ambiente colaborativo no Quepid para permitir que avaliadores humanos façam julgamentos explícitos de forma eficaz, o que é a base de qualquer lista de julgamentos.</p><p>A Quepid auxilia as equipes de busca no processo de avaliação da qualidade da pesquisa:</p><ul><li><p>Criar conjuntos de consultas</p></li><li><p>Criar listas de julgamento</p></li><li><p>Calcular métricas de qualidade de pesquisa</p></li><li><p>Compare diferentes algoritmos/classificadores de busca com base em métricas de qualidade de busca calculadas.</p></li></ul><p>Para o nosso blog, vamos supor que administramos uma locadora de filmes e que nosso objetivo é melhorar a qualidade dos nossos resultados de busca.</p><h2>Pré-requisitos</h2><p>Este blog utiliza os dados e os mapeamentos do <a href="https://github.com/o19s/es-tmdb">repositório es-tmdb</a>. Os dados são do <a href="https://www.themoviedb.org/">The Movie Database</a>. Para acompanhar, crie um índice chamado tmdb com os mapeamentos e indexe os dados. Não importa se você configurar uma instância local ou usar uma implantação do Elastic Cloud para isso - qualquer uma funciona bem. Para este blog, pressupomos uma implementação no Elastic Cloud. Você pode encontrar informações sobre como indexar os dados no <a href="https://github.com/o19s/es-tmdb/blob/master/README.md">arquivo README do repositório es-tmdb</a>.</p><p>Faça uma consulta de correspondência simples no campo de título para <code>rocky</code> para confirmar que você tem dados para pesquisar:</p>GET tmdb/_search
{
 "query": {
   "match": {
     "title": "rocky"
   }
 }
}<p>Você deverá ver 8 resultados.</p>{
 "took": 2,
 "timed_out": false,
 "_shards": {
   "total": 1,
   "successful": 1,
   "skipped": 0,
   "failed": 0
 },
 "hits": {
   "total": {
     "value": 8,
     "relation": "eq"
   }
…
}<h2>Faça login no Quepid</h2><p><a href="https://github.com/o19s/quepid">O Quepid</a> é uma ferramenta que permite aos usuários medir a qualidade dos resultados de pesquisa e executar experimentos offline para melhorá-la.</p><p>Você pode usar o Quepid de duas maneiras: usando a versão gratuita e disponível publicamente em <a href="https://app.quepid.com">https://app.quepid.com</a>, ou instale o Quepid em uma máquina à qual você tenha acesso. Este post pressupõe que você esteja usando a versão gratuita hospedada. Se você deseja configurar uma instância do Quepid em seu ambiente, siga o <a href="https://github.com/o19s/quepid/wiki/Installation-Guide">Guia de Instalação</a>.</p><p>Independentemente da configuração escolhida, você precisará criar uma conta, caso ainda não tenha uma.</p><h2>Como configurar um caso do Quepid</h2><p>O Quepid é organizado em torno de "Casos". Um Case armazena consultas juntamente com configurações de ajuste de relevância e instruções sobre como estabelecer uma conexão com seu mecanismo de busca.</p><ul><li><p>Para usuários iniciantes, selecione <strong>Criar seu primeiro caso de relevância</strong>.</p></li><li><p>Usuários recorrentes podem selecionar <strong>Casos de Relevância</strong> no menu principal e clicar em <strong>+ Criar um caso</strong>.</p></li></ul><p>Dê um nome descritivo ao seu caso, por exemplo, "Linha de Base da Busca de Filmes", pois queremos começar a medir e aprimorar nossa busca de referência.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte2913d344c42cd24/6a17e6477b54f906b48b38bd/8f9e480d9aae0d706cfc5371e41f19c706dd452a-594x251.png" alt="Configurando um caso Quepid" /><p>Confirme o nome selecionando <strong>Continuar</strong>.</p><p>Em seguida, estabelecemos uma conexão do Quepid com o mecanismo de busca. O Quepid pode se conectar a uma variedade de mecanismos de busca, incluindo o Elasticsearch.</p><p>A configuração irá variar dependendo da sua instalação do Elasticsearch e do Quepid. Para conectar o Quepid a uma implementação do Elastic Cloud, precisamos habilitar e configurar o CORS para nossa implementação do Elastic Cloud e ter uma chave de API pronta. Instruções detalhadas estão disponíveis no <a href="https://quepid-docs.dev.o19s.com/2/quepid/49/how-to-connect-quepid-to-elastic-cloud">guia correspondente na documentação do Quepid</a>.</p><p>Insira as informações do seu endpoint Elasticsearch (<code>https://YOUR_ES_HOST:PORT/tmdb/_search</code>) e quaisquer informações adicionais necessárias para conectar (a chave da API no caso de uma implantação do Elastic Cloud nas opções de configuração <strong>avançadas</strong> ), teste a conexão clicando em <strong>ping</strong> e selecione <strong>Continuar</strong> para ir para a próxima etapa.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcc068309bdc094ae/6a17e6480b0bed14cddd356a/267339dfaecae2740eb2ee2739bdc971608bdb5f-588x1169.png" alt="Configurando um endpoint do Elasticsearch com o Quepid." /><p>Agora definimos quais campos queremos que sejam exibidos no caso. Selecione todas as opções que ajudarão nossos avaliadores humanos a avaliar posteriormente a relevância de um documento para uma determinada consulta.</p><p>Defina <code>title</code> como o <em>Campo de Título</em>, deixe <code>_id</code> como o <em>Campo de ID</em> e adicione <code>overview, tagline, cast, vote_average, thumb:poster_path</code> como <em>Campos de Exibição Adicionais</em>. A última entrada exibe pequenas imagens em miniatura dos filmes em nossos resultados para nos guiar visualmente, assim como aos avaliadores humanos.</p><p>Confirme as configurações de exibição selecionando o botão <strong>Continuar</strong> .</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc910bdf5aa7680b3/6a17e64ae8fbce710b3a1906/02c58aae8c2ebb6d31f538b27462b4c65428fdc3-594x493.png" alt="Definindo quais campos queremos ver exibidos no caso para avaliadores humanos do Quepid." /><p>O último passo é adicionar consultas de pesquisa ao caso. Adicione as três consultas <em>star wars</em>, <em>harrison ford</em> e <em>best action movie</em> uma de cada vez através do campo de entrada e <strong>clique em Continuar</strong>.</p><p>Idealmente, um caso contém consultas que representam consultas reais de usuários e ilustram diferentes tipos de consultas. Por ora, podemos imaginar <em>"Star Wars"</em> como uma consulta que representa todas as buscas por títulos de filmes, <em>"Harrison Ford" como</em> uma consulta que representa todas as buscas por membros do elenco e <em>"Melhor Filme de Ação"</em> como uma consulta que representa todas as buscas por filmes de um gênero específico. Isso geralmente é chamado de conjunto de consultas.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt46122bb45e1063e4/6a17e64b505ac36510ad8af8/baccfe96766319aa7255e9bff08913ac87d1517f-595x326.png" alt="Adicionando consultas de busca a um caso do Quepid" /><p>Em um cenário de produção, amostraríamos consultas de dados de rastreamento de eventos aplicando técnicas estatísticas como <a href="https://opensourceconnections.com/blog/2022/10/13/how-to-succeed-with-explicit-relevance-evaluation-using-probability-proportional-to-size-sampling/">a amostragem de Probabilidade Proporcional ao Tamanho</a> e importaríamos essas consultas amostradas para o Quepid para incluir consultas do início (consultas frequentes) e da cauda (consultas infrequentes) em relação à sua frequência, o que significa que damos preferência a consultas mais frequentes sem excluir as raras.</p><p>Por fim, selecione <strong>Concluir</strong> e você será redirecionado para a interface do caso, onde verá as três consultas definidas.</p><h2>Consultas e necessidades de informação</h2><p>Para atingirmos nosso objetivo principal de criar uma lista de julgamentos, avaliadores humanos precisarão julgar um resultado de busca (normalmente um documento) para uma determinada consulta. Isso é chamado de par consulta/documento.</p><p>Às vezes, parece fácil saber o que um usuário queria ao analisar a consulta. A intenção por trás da consulta <code>harrison ford</code> é encontrar filmes estrelados por Harrison Ford, o ator. E quanto à consulta <code>action</code>? Sei que eu teria a tentação de dizer que a intenção do usuário é encontrar filmes do gênero ação. Mas quais? Os mais recentes, os mais populares, os melhores de acordo com as avaliações dos usuários? Ou será que o usuário quer encontrar todos os filmes que se chamam "Ação"? <a href="https://www.themoviedb.org/search/movie?query=Action">Existem pelo menos 12 (!) filmes chamados “Action” no The Movie Database</a> e seus nomes diferem principalmente no número de pontos de exclamação no título.</p><p>Dois avaliadores humanos podem divergir na interpretação de uma pergunta cuja intenção não seja clara. Entenda a Necessidade de Informação: Uma <a href="https://en.wikipedia.org/wiki/Information_needs">Necessidade de Informação</a> é um desejo consciente ou inconsciente por informação. Definir uma necessidade de informação ajuda os avaliadores humanos a julgarem os documentos em relação a uma consulta, desempenhando, portanto, um papel importante no processo de elaboração de listas de julgamento. Usuários experientes ou especialistas no assunto são bons candidatos para especificar as necessidades de informação. É uma boa prática definir as necessidades de informação a partir da perspectiva do usuário, pois são essas necessidades que os resultados da busca devem satisfazer.</p><p>Necessidades de informação para as consultas do nosso caso de “Linha de Base de Pesquisa de Filmes”:</p><ol><li><p><strong>Star Wars</strong>: O usuário deseja encontrar filmes ou séries da franquia Star Wars. Documentários sobre Star Wars podem ser relevantes.</p></li><li><p><strong>Harrison Ford</strong>: O usuário deseja encontrar filmes estrelados pelo ator Harrison Ford. Filmes em que Harrison Ford desempenha um papel diferente, como o de narrador, podem ser relevantes.</p></li><li><p><strong>Melhor filme de ação</strong>: O usuário deseja encontrar filmes de ação, de preferência aqueles com alta média de votos dos usuários.</p></li></ol><h2>Como definir necessidades de informação no Quepid</h2><p>Para definir uma necessidade de informação no Quepid, acesse a interface do caso:</p><p>1. Abra uma pesquisa (por exemplo, <em>star wars</em>) e selecione <em>Alternar notas.</em></p><p>2. Insira a necessidade de informação no primeiro campo e quaisquer observações adicionais no segundo campo:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte57395f64f6e5fab/6a17e64d6864a40fd6b68771/e01d3d5242a350d8797faa665eb3170039f5dfa2-1483x559.png" alt="Definindo necessidades de informação e consulta no Quepid." /><p>3. Clique em <strong>Salvar</strong>.</p><p>Para um pequeno número de consultas, esse processo funciona bem. No entanto, ao expandir seu caso de três para 100 consultas (os casos do Quepid geralmente variam de 50 a 100 consultas), você pode querer definir as necessidades de informação fora do Quepid (por exemplo, em uma planilha) e, em seguida, carregá-las por meio da <strong>opção Importar</strong> e selecionar <strong>Necessidades de Informação</strong>.</p><h2>Criar uma equipe no Quepid e compartilhar seu caso</h2><p>Julgamentos colaborativos melhoram a qualidade das avaliações de relevância. Para formar uma equipe:</p><p>1. Navegue até <strong>"Equipes"</strong> no menu principal.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt45c51d1a0e05a80d/6a17e64fe8fbcede793a190f/797706e8d130b474a95d30b6fa22ecaf36f98c03-613x58.png" alt="Criando uma equipe no Quepid." /><p>2. Clique em <strong>+ Adicionar novo</strong>, insira um nome para a equipe (por exemplo, "Avaliadores de relevância de pesquisa") e clique em <strong>Criar</strong>.</p><p>3. Adicione membros digitando seus endereços de e-mail e clicando em <strong>Adicionar Usuário</strong>.</p><p>4. Na interface do caso, selecione <strong>Compartilhar caso</strong>.</p><p>5. Selecione a equipe apropriada e confirme.</p><h2>Criar um livro de julgamentos no Quepid</h2><p>Um livro no Quepid permite que vários avaliadores avaliem pares de consulta/documento de forma sistemática. Para criar um:</p><p>1. Na interface do processo, acesse <strong>Julgamentos</strong> e clique em <strong>+ Criar um Livro</strong>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3543c00e0b834b3f/6a17e650e9ea87f57fa9c598/6a077f26225961150b7414463d7db04f090b68d6-896x365.png" alt="Criando um livro de julgamentos no Quepid." /><p>2. Configure o livro com um nome descritivo, atribua-o à sua equipe, selecione um método de pontuação (por exemplo, DCG@10) e defina a estratégia de seleção (avaliadores únicos ou múltiplos). Utilize as seguintes configurações para o livro:</p><ul><li><p><strong>Nome</strong>: “Pesquisa de Filmes em Escala de 0 a 3”</p></li><li><p><strong>Equipes com as quais você deseja compartilhar este livro</strong>: Marque a caixa da equipe que você criou.</p></li><li><p><strong>Marcador</strong>: DCG@10</p></li></ul><p>3. Clique em <strong>Criar livro.</strong></p><p>O nome é descritivo e contém informações sobre o que é pesquisado em (“Filmes”) e também a escala das avaliações (“0-3”). O Scorer DCG@10 selecionado define a forma como a métrica de pesquisa será calculada. “DCG” é a abreviação de <a href="https://en.wikipedia.org/wiki/Discounted_cumulative_gain">Ganho Cumulativo Descontado</a> e “@10” é o número de resultados do topo considerados no cálculo da métrica.</p><p>Neste caso, estamos usando uma métrica que mede o ganho de informação e o combina com a ponderação posicional. Pode haver outras métricas de pesquisa mais adequadas ao seu caso de uso, e <a href="https://opensourceconnections.com/blog/2020/02/28/choosing-your-search-relevance-metric">escolher a correta é um desafio por si só</a>.</p><h2>Preencha o livro com pares de consulta/documento</h2><p>Para adicionar pares de consulta/documento para avaliação de relevância, siga estes passos:</p><p>1. Na interface do processo, navegue até "Sentenças".</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0e98583138535cc3/6a17e6520b0bed4f51dd3571/d717c5b06ae6cb42ed2b9e771486a12f738a9890-1041x218.png" alt="Preencha o livro com pares de consulta/documento no Quepid." /><p>2. Selecione o livro que você criou.</p><p>3. Clique em "Preencher Livro" e confirme selecionando "Atualizar Pares de Consulta/Documento para o Livro".</p><p>Esta ação gera pares com base nos principais resultados de pesquisa para cada consulta, prontos para avaliação pela sua equipe.</p><h2>Deixar sua equipe de avaliadores humanos julgar </h2><p>Até o momento, as etapas concluídas foram de natureza bastante técnica e administrativa. Agora que essa preparação necessária foi concluída, podemos deixar nossa equipe de juízes fazer seu trabalho. Em essência, a função do juiz é avaliar a relevância de um determinado documento para uma questão específica. O resultado desse processo é a lista de julgamentos, que contém todos os rótulos de relevância para os pares de documentos de consulta avaliados. A seguir, esse processo e sua interface serão explicados com mais detalhes.</p><h3>Visão geral da interface Human Rating</h3><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt553afb07d8080421/6a17e654505ac30514ad8afc/be3016091b49655dab3354d84e6dc638f3468390-1283x664.png" alt="Como avaliadores humanos do Quepid fazem interface com informações de julgamento em documentos e consultas." /><p>A interface de Avaliação Humana do Quepid foi projetada para avaliações eficientes:</p><ul><li><p><strong>Consulta:</strong> Exibe o termo de pesquisa.</p></li><li><p><strong>Necessidade de informação:</strong> Mostra a intenção do usuário.</p></li><li><p><strong>Diretrizes de pontuação:</strong> Fornece instruções para avaliações consistentes.</p></li><li><p><strong>Metadados do documento:</strong> Apresentam detalhes relevantes sobre o documento.</p></li><li><p><strong>Botões de avaliação:</strong> Permitem que os avaliadores atribuam julgamentos com os respectivos atalhos de teclado.</p></li></ul><h3>Usando a interface de Human Rating</h3><p>Como avaliador humano, acesso a interface através da visão geral do livro:</p><p>1. Navegue até a interface do caso e clique em <strong>Julgamentos</strong>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0e98583138535cc3/6a17e6520b0bed4f51dd3571/d717c5b06ae6cb42ed2b9e771486a12f738a9890-1041x218.png" alt="Usando a interface de Human Rating do Quepid " /><p>2. Clique em <strong>Mais avaliações são necessárias!</strong></p><p>O sistema apresentará um par consulta/documento que ainda não foi avaliado e que requer julgamentos adicionais. Isso é determinado pela estratégia de seleção do livro:</p><ul><li><p><em>Avaliador único</em>: Um único julgamento por par consulta/documento.</p></li><li><p><em>Avaliadores Múltiplos</em>: Até três avaliações por par consulta/documento.</p></li></ul><h3>Avaliando pares de consulta/documento</h3><p>Vamos analisar alguns exemplos. Ao seguir este guia, você provavelmente se deparará com diferentes filmes. No entanto, os princípios de classificação permanecem os mesmos.</p><p>Nosso primeiro exemplo é o filme “Heroes” para a consulta <em>harrison ford</em>:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta248e787b5e0a670/6a17e656ec0f89612d5a65ee/c1e14b0d8b04dd579471932dbe4ff72ae5692a02-981x571.png" alt="Como preencher um livro no Quepid com pares de consulta/documento." /><p>Primeiro analisamos a consulta, depois a necessidade de informação e, em seguida, avaliamos o filme com base nos metadados fornecidos.</p><p>Este filme é um resultado relevante para nossa pesquisa, já que Harrison Ford faz parte do elenco. Podemos considerar os filmes mais recentes como subjetivamente mais relevantes, mas isso não faz parte da nossa necessidade de informação. Assim, classificamos este documento como "Perfeito", o que corresponde a um 3 em nossa escala de notas.</p><p>Nosso próximo exemplo é o filme “Ford vs Ferrari” para a pesquisa <em>“Harrison Ford”</em>:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf5d86aac918a1e96/6a17e657414c64833e945152/052af7894506d7a765af156ba8e26ceec3559973-981x789.png" alt="Um exemplo do filme &quot;Ford vs. Ferrari&quot; para a consulta harrison ford no Quepid." /><p>Seguindo a mesma prática, avaliamos esta consulta/documento analisando a consulta, a necessidade de informação e, em seguida, o quão bem os metadados do documento correspondem à necessidade de informação.</p><p>Este é um resultado ruim. Provavelmente vemos esse resultado porque um dos nossos termos de pesquisa, "ford", corresponde ao título. Mas Harrison Ford não desempenha nenhum papel neste filme, nem em nenhum outro. Assim, classificamos este documento como "Ruim", o que corresponde a 0 em nossa escala de notas.</p><p>Nosso terceiro exemplo é o filme “Action Jackson” para a busca <em>“melhor filme de ação</em>”:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2cee335ddd1e6a92/6a17e6596df731d1f40a0ed7/247ab862fbc7435537709f8c96619cb331133d09-985x606.png" alt="Um exemplo do filme &quot;Action Jackson&quot; para a consulta melhor filme de ação:" /><p>Parece um filme de ação, então a necessidade de informação está pelo menos parcialmente satisfeita. No entanto, a média dos votos é de 5,4 em 10. E isso faz com que este filme provavelmente não seja o melhor filme de ação da nossa coleção. Isso me levaria, como juiz, a classificar este documento como "Razoável", o que corresponde a 1 em nossa escala de classificação.</p><p>Esses exemplos ilustram o processo de avaliação de pares de consulta/documento com o Quepid, em particular, em um nível mais alto e também em geral.</p><h2>Práticas recomendadas para avaliadores humanos</h2><p>Os exemplos apresentados podem dar a impressão de que é fácil chegar a julgamentos explícitos. Mas criar um programa confiável de avaliação humana não é tarefa fácil. É um processo repleto de desafios que podem facilmente comprometer a qualidade dos seus dados:</p><ul><li><p>Os avaliadores humanos podem ficar fatigados devido a tarefas repetitivas.</p></li><li><p>Preferências pessoais podem distorcer julgamentos.</p></li><li><p>O nível de conhecimento especializado varia de juiz para juiz.</p></li><li><p>Os avaliadores frequentemente precisam conciliar múltiplas responsabilidades.</p></li><li><p>A relevância percebida de um documento pode não corresponder à sua real relevância para uma consulta.</p></li></ul><p>Esses fatores podem resultar em julgamentos inconsistentes e de baixa qualidade. Mas não se preocupe – existem práticas recomendadas comprovadas que podem ajudá-lo a minimizar esses problemas e a construir um processo de avaliação mais robusto e confiável:</p><ul><li><p><strong>Avaliação consistente:</strong> Analise a consulta, a necessidade de informação e os metadados do documento em ordem.</p></li><li><p><strong>Consulte as diretrizes:</strong> Utilize as diretrizes de pontuação para manter a consistência. As diretrizes de avaliação podem conter exemplos de quando aplicar cada nota, ilustrando o processo de julgamento. Realizar uma consulta com avaliadores humanos após o primeiro lote de julgamentos provou ser uma boa prática para identificar casos extremos desafiadores e onde é necessário suporte adicional.</p></li><li><p><strong>Utilize as opções:</strong> Em caso de dúvida, use "Vou avaliar depois" ou "Não sei dizer", fornecendo explicações quando necessário.</p></li><li><p><strong>Faça pausas:</strong> Pausas regulares ajudam a manter a qualidade do julgamento. O Quepid ajuda nas pausas regulares, lançando confetes sempre que um avaliador humano termina um lote de julgamentos.</p></li></ul><p>Seguindo esses passos, você estabelece uma abordagem estruturada e colaborativa para a criação de listas de julgamento no Quepid, aumentando a eficácia dos seus esforços de otimização da relevância da busca.</p><h2>Próximas etapas</h2><p>Para onde ir a partir daqui? As listas de julgamento são apenas um passo fundamental para melhorar a qualidade dos resultados de pesquisa. Eis os próximos passos:</p><h3>Calcule métricas e comece a experimentar</h3><p>Uma vez que as listas de avaliações estejam disponíveis, aproveitar essas avaliações e calcular <a href="https://opensourceconnections.com/blog/2020/02/28/choosing-your-search-relevance-metric/">as métricas de qualidade da busca</a> é uma progressão natural. O Quepid calcula automaticamente a métrica configurada para o caso atual quando os julgamentos estão disponíveis. As métricas são implementadas como "Pontuadores" e você pode fornecer as suas próprias caso as opções suportadas não incluam a sua favorita!</p><p>Acesse a interface do caso, navegue até <strong>Selecionar Avaliador</strong>, escolha <em>DCG@10</em> e confirme clicando em <strong>Selecionar Avaliador</strong>. O Quepid agora calculará o DCG@10 por consulta e também a média geral das consultas para quantificar a qualidade dos resultados da pesquisa para o seu caso.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0d059c959b842139/6a17e65be8fbceb29b3a1913/0ff3b9918342071744d681a43d542102e927abd3-1163x551.png" alt="Como quantificar a qualidade dos resultados de busca no Quepid. " /><p>Agora que a qualidade dos seus resultados de pesquisa foi quantificada, você pode executar os primeiros experimentos. A experimentação começa com a geração de hipóteses. Ao analisar as três consultas na captura de tela após classificá-las, fica evidente que elas apresentam desempenhos muito diferentes em termos de qualidade de busca: <em>"Star Wars"</em> tem um desempenho bastante bom, <em>"Harrison Ford"</em> parece razoável, mas o maior potencial reside em <em>"Melhor Filme de Ação"</em>.</p><p>Expandindo essa consulta, vemos seus resultados e podemos mergulhar nos detalhes minuciosos, explorando por que os documentos corresponderam e o que influencia suas pontuações:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt35227761f4524a1e/6a17e65cb1e11325c579f25a/c45c6cae085a492198c0f8b7060a1a7204e3724e-1131x691.png" alt="Experimentando diferentes consultas para ver o desempenho delas em diferentes métricas de busca no Quepid." /><p>Ao clicar em “Explicar consulta” e acessar a guia “Análise”, vemos que a consulta é uma DisjunctionMaxxQuery que pesquisa em três campos: <em>cast</em>, <em>overview</em> e <em>title</em>:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0966653b9ab3cc9c/6a17e65efaa913171f93c84c/4a1e1bb2a9cd28e9c48e0ba16357d17ed9d3a5cf-894x557.png" alt="Explicando o parsing de consultas" /><p>Normalmente, como engenheiros de busca, conhecemos alguns detalhes específicos do domínio da nossa plataforma de busca. Nesse caso, podemos saber que temos um campo <em>de gêneros</em> . Vamos adicionar isso à consulta e ver se a qualidade da pesquisa melhora.</p><p>Usamos o <strong>ambiente de testes de consulta (Query Sandbox)</strong> que é aberto ao selecionar <strong>"Ajustar Relevância"</strong> na interface do caso. Explore esta opção adicionando o campo <em>de gêneros</em> que você pesquisou:</p>{
  "query": {
    "multi_match": {
      "query": "#$query##",
      "type": "best_fields",
      "fields": [
        "title^10",
        "overview",
        "cast",
        "genres"
      ]
    }
  }
}<p>Clique em "Executar minhas pesquisas novamente"! E veja os resultados. Será que mudaram? Infelizmente não. Agora temos muitas opções para explorar, basicamente todas as opções de consulta que o Elasticsearch oferece:</p><ul><li><p>Poderíamos aumentar o peso do campo de gêneros.</p></li><li><p>Poderíamos adicionar uma função que aumentasse a relevância dos documentos com base na média de votos.</p></li><li><p>Poderíamos criar uma consulta mais complexa que priorizasse documentos com base na média de votos apenas se houvesse uma forte correspondência de gêneros.</p></li><li><p>…</p></li></ul><p>A melhor coisa de ter todas essas opções e explorá-las no Quepid é que temos uma maneira de quantificar os efeitos não apenas na consulta específica que estamos tentando melhorar, mas em todas as consultas que temos em nosso caso. Isso nos impede de melhorar uma consulta com baixo desempenho sacrificando a qualidade dos resultados de pesquisa em outras consultas. Podemos iterar de forma rápida e barata e validar o valor de nossa hipótese sem qualquer risco, tornando a experimentação offline uma capacidade fundamental de todas as equipes de busca.</p><h3>Medir a confiabilidade entre avaliadores</h3><p>Mesmo com descrições de tarefas, necessidades de informação e uma interface de avaliação humana como a que a Quepid oferece, os avaliadores humanos podem discordar.</p><p>A discordância em si não é algo ruim, muito pelo contrário: medir a discordância pode revelar problemas que você talvez queira abordar. A relevância pode ser subjetiva, as consultas podem ser ambíguas e os dados podem estar incompletos ou incorretos. <a href="https://en.wikipedia.org/wiki/Fleiss%27_kappa">O coeficiente Kappa de Fleiss</a> é uma medida estatística de concordância entre avaliadores, e existe um exemplo de planilha no Quepid que você pode usar. Para encontrá-lo, selecione <strong>Notebooks</strong> na navegação de nível superior e selecione o notebook <strong>Fleiss Kappa.ipynb</strong> na pasta <strong>examples</strong> .</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt92d52b30f1fb19c1/6a17e660abe0f2224bdfe9bb/f0669ae96371368ef4d84bb28669560ef09d755c-624x61.png" alt="Como encontrar a medida estatística kappa de Fleiss para a concordância entre avaliadores no Quepid." /><h2>Conclusão</h2><p>O Quepid permite que você enfrente até mesmo os desafios mais complexos de relevância de pesquisa e continua a evoluir: <a href="https://github.com/o19s/quepid/blob/main/CHANGELOG.md#800----2024-02-14">a partir da versão 8, o Quepid oferece suporte a julgamentos gerados por IA</a>, o que é particularmente útil para equipes que desejam dimensionar seu processo de geração de julgamentos.</p><p>Os fluxos de trabalho do Quepid permitem criar listas de julgamento escaláveis de forma eficiente, o que resulta em resultados de pesquisa que realmente atendem às necessidades do usuário. Com as listas de critérios de avaliação estabelecidas, você terá uma base sólida para medir a relevância da pesquisa, implementar melhorias e proporcionar melhores experiências ao usuário.</p><p>Ao prosseguir, lembre-se de que o ajuste de relevância é um processo contínuo. Listas de avaliação permitem que você avalie seu progresso de forma sistemática, mas são mais eficazes quando combinadas com experimentação, análise de métricas e melhorias iterativas.</p><h2>Para ler mais</h2><ul><li><p>Documentação Quepid:</p><ul><li><p><a href="https://quepid-docs.dev.o19s.com/2/quepid/32/relevancy-is-a-team-sport">Relevância é um esporte coletivo</a></p></li><li><p><a href="https://quepid-docs.dev.o19s.com/2/quepid/18/quepid-for-human-raters">Quépid para avaliadores humanos</a></p></li><li><p><a href="https://quepid-docs.dev.o19s.com/2/quepid/49/how-to-connect-quepid-to-elastic-cloud">Como conectar o Quepid ao Elastic Cloud</a></p></li></ul></li><li><p><a href="https://github.com/o19s/quepid">Repositório Quepid no Github</a></p></li><li><p><a href="https://opensourceconnections.com/blog/2020/07/07/meet-pete-the-e-commerce-search-product-manager/">Conheça Pete, uma série de posts no blog sobre como melhorar a busca em e-commerce.</a></p></li><li><p><a href="https://opensourceconnections.com/slack">Slack de Relevância</a>: entre no canal #quepid</p></li></ul><p><strong>Faça parceria com </strong><a href="https://opensourceconnections.com/"><strong>a Open Source Connections</strong></a> para transformar suas capacidades de busca e IA e capacitar sua equipe a evoluí-las continuamente. Nosso histórico comprovado abrange o mundo todo, com clientes alcançando consistentemente melhorias significativas na qualidade da busca, na capacidade da equipe e no desempenho dos negócios. <a href="https://opensourceconnections.com/contact/">Entre em contato conosco hoje mesmo</a> para saber mais.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/quepid-judgement-lists</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/quepid-judgement-lists</guid>
    <category><![CDATA[Relevância]]></category>
    <dc:creator><![CDATA[Daniel Wrigley]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte6779c72c7a42a5a/6a17e6623e9e45acf0ba146b/307c1774bd31f92bb4aa7b69e1a6796240465100-1600x914.png" length="0" type="image/png"/>
    <pubDate>Mon, 26 May 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Geração de filtros e facetas usando aprendizado de máquina.]]></title>
    <description><![CDATA[Explorando as vantagens e desvantagens de automatizar a criação de filtros e facetas em uma experiência de busca usando modelos de aprendizado de máquina versus a abordagem clássica de codificação fixa.]]></description>
    <content:encoded><![CDATA[<p>Filtros e facetas são mecanismos usados para refinar os resultados da pesquisa, ajudando os usuários a encontrar conteúdo ou produtos relevantes mais rapidamente. Na abordagem clássica, as regras são definidas manualmente. Por exemplo, em um catálogo de filmes, atributos como gênero são predefinidos para uso em filtros e facetas. Por outro lado, com modelos de IA, novos atributos podem ser extraídos automaticamente das características dos filmes, tornando o processo mais dinâmico e personalizado. Neste blog, exploramos as vantagens e desvantagens de cada método, destacando suas aplicações e desafios.</p><h2>Filtros vs facetas</h2><p>Antes de começarmos, vamos definir o que são filtros e facetas. <strong>Os filtros</strong> são atributos predefinidos usados para restringir um conjunto de resultados. Em um mercado online, por exemplo, os filtros estão disponíveis mesmo antes de uma busca ser realizada. O usuário pode selecionar uma categoria, como <strong>"Videogames"</strong>, antes de pesquisar por <strong>"PS5"</strong>, refinando a busca para um subconjunto mais específico em vez de toda a base de dados. Isso aumenta significativamente as chances de se obter resultados mais relevantes.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0a77b38aae238938/6a170b821949f72a52e7aa51/5ed8868fa5017d034e1273e35c884a5430afdf3c-1600x937.png" alt="Filtros" /><p><strong>Os facets</strong> funcionam de forma semelhante aos filtros, mas só ficam disponíveis após a realização da pesquisa. Em outras palavras, a pesquisa retorna resultados e, com base neles, é gerada uma nova lista de opções de refinamento. Por exemplo, ao pesquisar um console PS5, características como <strong>capacidade</strong> de armazenamento, <strong>custo de envio</strong> e <strong>cor</strong> podem ser exibidas para ajudar os usuários a escolher o produto ideal.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt166e356b80d423ef/6a170b840e2e494ca341a10f/c5633fcc5b6fbb916110faf32144d8d43572e33a-1600x937.png" alt="Facetas " /><p>Agora que definimos filtros e facetas, vamos discutir o impacto das abordagens clássicas e baseadas em Aprendizado de Máquina (ML) em sua implementação e uso. Cada método possui vantagens e desafios que influenciam a eficiência da busca.</p><h2>Abordagem clássica de filtros e facetas</h2><p>Nessa abordagem, os filtros e as facetas são definidos manualmente com base em regras predefinidas. Isso significa que os atributos disponíveis para refinar a busca são fixos e planejados antecipadamente, levando em consideração a estrutura do catálogo e as necessidades do usuário.</p><p>Por exemplo, em um marketplace, categorias como "Eletrônicos" ou "Moda" podem ter filtros específicos como marca, formato e faixa de preço. Essas regras são criadas estaticamente, garantindo consistência na experiência de busca, mas exigindo ajustes manuais sempre que novos produtos ou categorias surgirem.</p><p>Embora essa abordagem proporcione previsibilidade e controle sobre os filtros e facetas exibidos, ela pode ser limitada quando surgem novas tendências que exigem refinamento dinâmico.</p><p><strong>Prós:</strong></p><ul><li><p><strong>Previsibilidade e controle:</strong> Como os filtros e as facetas são definidos manualmente, o gerenciamento torna-se mais fácil.</p></li><li><p><strong>Baixa complexidade:</strong> Não há necessidade de treinar modelos.</p></li><li><p><strong>Facilidade de manutenção:</strong> Como as regras são predefinidas, ajustes e correções podem ser feitos rapidamente.</p></li></ul><p><strong>Contras</strong>:</p><ul><li><p><strong>Reindexação necessária para novos filtros:</strong> Sempre que um novo atributo precisar ser usado como filtro, todo o conjunto de dados deverá ser reindexado para garantir que os documentos contenham essa informação.</p></li><li><p><strong>Falta de adaptação dinâmica:</strong> os filtros são estáticos e não se ajustam automaticamente às mudanças no comportamento do usuário.</p></li></ul><h3>Implementação de filtros/facetas – Abordagem clássica</h3><p>Nas <strong>Ferramentas de Desenvolvimento, Kibana</strong>, criaremos uma demonstração de filtros/facetas usando a <strong>abordagem clássica</strong>.</p><p>Primeiro, definimos o mapeamento para estruturar o índice:</p>PUT videogames
{
  "mappings": {
    "properties": {
      "name": { "type": "text" },
      "brand": { "type": "keyword" },
      "storage": { "type": "keyword" },
      "price": { "type": "float" },
      "description": { "type": "text" }
    }
  }
}<p>Os campos <strong>de marca</strong> e <strong>armazenamento</strong> são definidos como <strong>palavras-chave</strong>, permitindo que sejam usados diretamente em agregações (<strong>facetas</strong>). O campo <strong>de preço</strong> é do tipo <strong>float</strong>, permitindo a criação de <strong>intervalos de preço</strong>.</p><p>Na próxima etapa, os dados do produto serão indexados:</p>POST videogames/_bulk
{ "index": { "_id": 1 } }
{ "name": "Play Station 5", "brand": "Sony", "storage": "1TB", "price": 499.99, "description": "Stunning Gaming: Marvel at stunning graphics and experience the features of the new PS5. Breathtaking Immersion: Discover a deeper gaming experience with support for haptic feedback, adaptive triggers, and 3D Audio technology. Slim Design: With the PS5 Digital Edition, gamers get powerful gaming technology in a sleek, compact design. 1TB of Storage: Have your favorite games ready and waiting for you to play with 1TB of built-in SSD storage. Backward Compatibility and Game Boost: The PS5 console can play over 4,000 PS4 games. With Game Boost, you can even enjoy faster, smoother frame rates in some of the best PS4 console games." }
{ "index": { "_id": 2 } }
{ "name": "Xbox Series X", "brand": "Microsoft", "storage": "1TB", "price": 499.99, "description": "Fastest, most powerful Xbox console ever. Play thousands of titles: Every game looks and plays better on Xbox Series X. At the heart of Series X is the Xbox Velocity. Architecture, which combines a custom SSD and built-in software to significantly reduce load times in and out of game. Switch between multiple games in an instant with Quick Resume. Explore new worlds and experience the action like never before with an unparalleled 12 teraflops of graphics processing power. Enjoy 4K gaming at up to 120 frames per second, premium advanced 3D sound, and more. 4K at 120 FPS: requires compatible content and display X version - with disc drive" }
{ "index": { "_id": 3 } }
{ "name": "Nintendo Switch", "brand": "Nintendo", "storage": "512GB", "price": 299.99, "description": "SHARPER, VIBRANT VISUALS. The new 7-inch screen on the Nintendo Switch OLED takes your gaming to the next level: vibrant colors with sharp contrasts for every moment. INTEGRATED GAMEPLAY. Enjoy the console's many multiplayer modes and connect with other players. Online or locally, the fun on the Nintendo Switch is guaranteed. ENJOY IMMERSION FOR LONGER. In addition to delivering an unparalleled experience, thanks to its improved audio, the Nintendo Switch has a rechargeable battery while you play. From 4.5 hours to 9 hours of battery life. INCLUDES SUPER MARIO BROS. WONDER. Transform your world with the phenomenal flowers in this new Mario game, full of amazing adventures, power-ups and new abilities. NINTENDO SWITCH ONLINE SUBSCRIPTION. Access online games, play with friends and enjoy the exclusive benefits of the Nintendo Switch Online subscription." }
{ "index": { "_id": 4 } }
{ "name": "Steam Deck", "brand": "Valve", "storage": "512GB", "price": 399.99, "description": "You can save games, apps, photos and videos without worrying about space. High-Level Performance: The 4-core processor and graphics ensure a dynamic experience and fast responses. High-Definition Images: Smooth transitions and sharp images provide complete immersion in the game. Wireless Connectivity: Wi-Fi technology allows you to play wherever you want, without wires or cables limiting your fun" }
{ "index": { "_id": 5 } }
{ "name": "Nintendo Switch Lite", "brand": "Nintendo", "storage": "512GB", "price": 299.99, "description": "MADE TO BE PORTABLE. Nintendo Switch Lite is designed specifically for portable gaming. The console lets you jump into your favorite games wherever you are. COMPACT AND LIGHTWEIGHT. With its sleek, lightweight design, this console is ready to hit the road wherever you are. COMPATIBLE GAMES. The Nintendo Switch Lite system plays the library of Nintendo Switch games that work in handheld mode. A WORLD OF COLOR TO CHOOSE FROM. Available in a variety of vibrant and unique colors, Nintendo Switch Lite lets you bring even more personality wherever you go." }<p>Agora, vamos recuperar as características clássicas agrupando os resultados por marca, armazenamento e faixa de preço. Na consulta, foi definido o tamanho:0. Nesse cenário, o objetivo é recuperar apenas os resultados da agregação, sem incluir os documentos correspondentes à consulta.</p>POST videogames/_search
{
  "size": 0,
  "aggs": {
    "brands": {
      "terms": { "field": "brand" }
    },
    "storage_sizes": {
      "terms": { "field": "storage" }
    },
    "price_ranges": {
      "range": {
        "field": "price",
        "ranges": [
          { "to": 300 },   
          { "from": 300, "to": 500 },  
          { "from": 500 }  
        ]
      }
    }
  }
}<p>A resposta incluirá contagens para <strong>Marca</strong>, <strong>Armazenamento</strong> e <strong>Preço</strong>, ajudando a criar filtros e segmentações.</p>"aggregations": {
   "brands": {
     "doc_count_error_upper_bound": 0,
     "sum_other_doc_count": 0,
     "buckets": [
       {
         "key": "Microsoft",
         "doc_count": 1
       },
       {
         "key": "Nintendo",
         "doc_count": 1
       },
       {
         "key": "Sony",
         "doc_count": 1
       },
       {
         "key": "Valve",
         "doc_count": 1
       }
     ]
   },
   "storage_sizes": {
     "doc_count_error_upper_bound": 0,
     "sum_other_doc_count": 0,
     "buckets": [
       {
         "key": "1TB",
         "doc_count": 2
       },
       {
         "key": "512GB",
         "doc_count": 2
       }
     ]
   },
   "price_ranges": {
     "buckets": [
       {
         "key": "*-300.0",
         "to": 300,
         "doc_count": 1
       },
       {
         "key": "300.0-500.0",
         "from": 300,
         "to": 500,
         "doc_count": 3
       },
       {
         "key": "500.0-*",
         "from": 500,
         "doc_count": 0
       }
     ]
   }
 }<h2>Abordagem baseada em machine learning/IA para filtros e facetas</h2><p>Nessa abordagem, modelos de Aprendizado de Máquina (ML), incluindo técnicas de Inteligência Artificial (IA), analisam atributos de dados para gerar filtros e facetas relevantes. Em vez de depender de regras predefinidas, o aprendizado de máquina/inteligência artificial aproveita as características dos dados indexados. Isso possibilita a descoberta dinâmica de novas facetas e filtros.</p><p><strong>Prós</strong>:</p><ul><li><p><strong>Atualizações automáticas:</strong> Novos filtros e facetas são gerados automaticamente, sem a necessidade de ajustes manuais.</p></li><li><p><strong>Descoberta de novos atributos:</strong> Pode identificar características de dados <strong>anteriormente não consideradas </strong>como filtros, enriquecendo a experiência de busca.</p></li><li><p><strong>Redução do esforço manual:</strong> a equipe não precisa definir e atualizar constantemente as regras de filtragem, pois a IA aprende com os dados disponíveis.</p></li></ul><p><strong>Contras:</strong></p><ul><li><p><strong>Complexidade de manutenção:</strong> O uso de modelos pode exigir pré-validação para garantir a consistência dos filtros gerados.</p></li><li><p><strong>Requer experiência em aprendizado de máquina e inteligência artificial:</strong> A solução exige profissionais qualificados para ajustar e monitorar o desempenho do modelo.</p></li><li><p><strong>Risco de filtros irrelevantes:</strong> Se o modelo não estiver bem calibrado, poderá gerar facetas que não sejam úteis para os usuários.</p></li><li><p><strong>Custo:</strong> O uso de aprendizado de máquina e inteligência artificial pode exigir serviços de terceiros, aumentando os custos operacionais.</p></li></ul><p>Vale ressaltar que, mesmo com um modelo bem calibrado e um prompt bem elaborado, as facetas geradas ainda devem passar por uma etapa de revisão. Essa validação pode ser manual ou baseada em regras de moderação, garantindo que o conteúdo seja apropriado e seguro. Embora não seja necessariamente uma desvantagem, é importante considerar a qualidade e a adequação dos recursos antes que sejam disponibilizados aos usuários.</p><h3>Implementação de filtros/facetas – abordagem de IA</h3><p>Nesta demonstração, utilizaremos um modelo de IA para analisar automaticamente as características do produto e sugerir atributos relevantes. Com um prompt bem estruturado, extraímos informações do catálogo e as transformamos em filtros e facetas. A seguir, apresentamos cada etapa do processo.</p><p>Inicialmente, usaremos a <strong>API de Inferência</strong> para registrar um endpoint para integração com um serviço de aprendizado de máquina. Abaixo, segue um exemplo de integração com <strong>o serviço da OpenAI</strong>.</p>PUT _inference/completion/generate_filter_ia
{
   "service": "openai",
   "service_settings": {
       "api_key": "your-key",
       "model_id": "gpt-4o-mini"
   }
}<p>Agora, definimos o pipeline para executar o prompt e obter os novos filtros gerados pelo modelo.</p>PUT /_ingest/pipeline/generate_filter_ai
{
   "processors": [
     {
       "script": {
         "source": """ctx.prompt = "You are an expert in data organization for search and product categorization. Your task is to analyze the following product and identify the best dynamic facets that can be used in an e-commerce search experience. Product: " + ctx.name + "description: " + ctx.description + "Instructions: - Analyze the product name and description. - Extract only the dynamic facets (technological features or product characteristics that can be inferred from the description, try to create max 3 facets by characteristics found). Put the values into an array. Using key and value, e.g. dynamic_facets: [{ \"name\": \"Gaming Experience\", \"value\": \"Haptic Feedback\" },{ \"name\": \"Gaming Experience\", \"value\": \"Adaptive Triggers\" } - Return only a JSON."
         """
       }
     },
     {
       "inference": {
         "model_id": "generate_filter_ia",
         "input_output": {
           "input_field": "prompt",
           "output_field": "result"
         }
       }
     },
     {
       "gsub": {
         "field": "result",
         "pattern": "```json",
         "replacement": ""
       }
     },
     {
       "json" : {
         "field" : "result",
         "strict_json_parsing": false,
         "add_to_root" : true
       }
     },
     {
       "remove": {
         "field": "result"
       }
     },
     {
       "remove": {
         "field": "prompt"
       }
     }
   ]
}<p>Executando uma simulação desse pipeline para o produto "PlayStation 5", com a seguinte descrição:</p><p><em>Jogabilidade impressionante: Maravilhe-se com gráficos deslumbrantes e experimente os recursos do novo PS5.</em></p><p><em>Imersão de tirar o fôlego: Descubra uma experiência de jogo mais profunda com suporte para feedback tátil, gatilhos adaptáveis e tecnologia de áudio 3D.</em></p><p><em>Design fino: Com o PS5 Digital Edition, os jogadores têm acesso a uma poderosa tecnologia de jogos em um design elegante e compacto.</em></p><p><em>1 TB de armazenamento: Tenha seus jogos favoritos prontos para jogar com 1 TB de armazenamento SSD integrado.</em></p><p><em>Compatibilidade com versões anteriores e Game Boost: O console PS5 pode rodar mais de 4.000 jogos de PS4. Com o Game Boost, você pode desfrutar de taxas de quadros mais rápidas e suaves até mesmo em alguns dos melhores jogos para PS4.</em></p><p>Vamos observar a saída de comando gerada por esta simulação.</p>{
 "docs": [
   {
     "doc": {
       "_index": "index",
       "_version": "-3",
       "_id": "1",
       "_source": {
         "name": "Play Station 5",
         "result": """```json
{
 "dynamic_facets": [
   { "name": "Storage Capacity", "value": "1TB SSD" },
   { "name": "Graphics Technology", "value": "Stunning Graphics" },
   { "name": "Audio Technology", "value": "3D Audio" }
 ]
}
```""",
         "description": "Stunning Gaming: Marvel at stunning graphics and experience the features of the new PS5. Breathtaking Immersion: Discover a deeper gaming experience with support for haptic feedback, adaptive triggers, and 3D Audio technology. Slim Design: With the PS5 Digital Edition, gamers get powerful gaming technology in a sleek, compact design. 1TB of Storage: Have your favorite games ready and waiting for you to play with 1TB of built-in SSD storage. Backward Compatibility and Game Boost: The PS5 console can play over 4,000 PS4 games. With Game Boost, you can even enjoy faster, smoother frame rates in some of the best PS4 console games.",
         "model_id": "generate_filter_ia",
         "prompt": """You are an expert in data organization for search and product categorization. Your task is to analyze the following product and identify the best dynamic facets that can be used in an e-commerce search experience. Product: Play Station 5description: Stunning Gaming: Marvel at stunning graphics and experience the features of the new PS5. Breathtaking Immersion: Discover a deeper gaming experience with support for haptic feedback, adaptive triggers, and 3D Audio technology. Slim Design: With the PS5 Digital Edition, gamers get powerful gaming technology in a sleek, compact design. 1TB of Storage: Have your favorite games ready and waiting for you to play with 1TB of built-in SSD storage. Backward Compatibility and Game Boost: The PS5 console can play over 4,000 PS4 games. With Game Boost, you can even enjoy faster, smoother frame rates in some of the best PS4 console games.Instructions: - Analyze the product name and description. - Extract only the dynamic facets (technological features or product characteristics that can be inferred from the description, try create max 3 facets by characteristics found). Put the values like arrays. Using key and value, e.g. dynamic_facets: [{ "name": "Gaming Experience", "value": "Haptic Feedback" },{ "name": "Gaming Experience", "value": "Adaptive Triggers" } - Return only a JSON."""
       },
       "_ingest": {
         "timestamp": "2025-03-19T22:14:32.0161803Z"
       }
     }
   }
 ]
}<p>Agora, um novo campo, <strong>dynamic_facets</strong>, será adicionado ao novo índice para armazenar as facetas geradas pela IA.</p>PUT videogames_1
{
 "mappings": {
   "properties": {
     "name": { "type": "text" },
     "brand": { "type": "keyword" },
     "storage": { "type": "keyword" },
     "price": { "type": "float" },
     "description": { "type": "text" },
     "dynamic_facets": { "type": "nested",
     "properties": { "name": { "type": "keyword" },
                     "value": { "type": "keyword" } } }
   }
 }
}<p>Utilizando a <strong>API Reindex</strong>, vamos reindexar o índice <strong>de videogames</strong> para <strong>videogames_1</strong>, aplicando o pipeline <strong>generate_filter_ai</strong> durante o processo. Este pipeline irá gerar automaticamente facetas dinâmicas durante a indexação.</p>POST _reindex?wait_for_completion=false
{
 "source": {
   "index": "videogames"
 },
 "dest": {
   "index": "videogames_1",
   "pipeline": "generate_filter_ai"
 }
}<p>Agora, vamos executar uma pesquisa e obter os novos filtros:</p>GET videogames_1/_search
{
 "size": 0,
 "query": {
   "match": {
     "name": "nintendo"
   }
 },
 "aggs": {
   "dynamic_facets": {
     "nested": {
       "path": "dynamic_facets"
     },
     "aggs": {
       "facets": {
         "terms": {
           "field": "dynamic_facets.name"
         },
         "aggs": {
           "facets": {
             "terms": {
               "field": "dynamic_facets.value"
             }
           }
         }
       }
     }
   }
 }
}<p>Resultados:</p>"aggregations": {
   "dynamic_facets": {
     "doc_count": 3,
     "facets": {
       "doc_count_error_upper_bound": 0,
       "sum_other_doc_count": 0,
       "buckets": [
         {
           "key": "Frame Rate",
           "doc_count": 1,
           "facets": {
             "doc_count_error_upper_bound": 0,
             "sum_other_doc_count": 0,
             "buckets": [
               {
                 "key": "120 FPS",
                 "doc_count": 1
               }
             ]
           }
         },
         {
           "key": "Gaming Resolution",
           "doc_count": 1,
           "facets": {
             "doc_count_error_upper_bound": 0,
             "sum_other_doc_count": 0,
             "buckets": [
               {
                 "key": "4K",
                 "doc_count": 1
               }
             ]
           }
         },
         {
           "key": "Graphics Processing Power",
           "doc_count": 1,
           "facets": {
             "doc_count_error_upper_bound": 0,
             "sum_other_doc_count": 0,
             "buckets": [
               {
                 "key": "12 Teraflops",
                 "doc_count": 1
               }
             ]
           }
         }
       ]
     }
   }
 }<p>Para simbolizar a implementação das facetas, segue abaixo um exemplo simples de interface:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb0d6aa40caf7a91a/6a170b86ab7f0839afdb9eb6/12b6d9d4f4d0985848d92841545fd22b7253ae6d-1600x1288.png" alt="implementação das facetas" /><p>O código da interface do usuário apresentado está <a href="https://gist.github.com/andreluiz1987/06d9ec1b381e942e9def0e969bd811a0">aqui</a>.</p><h2>Conclusão</h2><p>Ambas as abordagens para a criação de filtros e facetas têm seus benefícios e pontos de atenção. A abordagem clássica, baseada em regras manuais, oferece controle e custos mais baixos, mas requer atualizações constantes e não se adapta dinamicamente a novos produtos ou recursos.</p><p>Por outro lado, a abordagem baseada em IA e Aprendizado de Máquina automatiza a extração de facetas, tornando a busca mais flexível e permitindo a descoberta de novos atributos sem intervenção manual. No entanto, essa abordagem pode ser mais complexa de implementar e manter, exigindo calibração para garantir resultados consistentes.</p><p>A escolha entre as abordagens clássicas e as baseadas em IA depende das necessidades e da complexidade do negócio. Para cenários mais simples, onde os atributos dos dados são estáveis e previsíveis, a abordagem clássica pode ser mais eficiente e fácil de manter, evitando custos desnecessários com infraestrutura e modelos de IA. Por outro lado, o uso de aprendizado de máquina/inteligência artificial para extrair facetas pode agregar valor significativo, melhorando a experiência de busca e tornando a filtragem mais inteligente.</p><p>O importante é avaliar se a automação justifica o investimento ou se uma solução mais tradicional já atende às necessidades do negócio de forma eficaz.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/filters-facets-using-ml</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/filters-facets-using-ml</guid>
    <category><![CDATA[Relevância]]></category>
    <category><![CDATA[Pesquisa de aprendizado de máquina]]></category>
    <dc:creator><![CDATA[Andre Luiz]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4084864dcdaa25d3/6a170b880c485781f901aaa9/6f196643d573614fe5124705c7e4db9bfce004b0-1200x628.png" length="0" type="image/png"/>
    <pubDate>Thu, 03 Apr 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Como automatizar a busca e o upload de sinônimos usando nossa API de Sinônimos.]]></title>
    <description><![CDATA[Descubra como os LLMs podem ser usados para identificar e gerar sinônimos automaticamente, permitindo que os termos sejam carregados programaticamente na API de sinônimos do Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>Melhorar a qualidade dos resultados de pesquisa é essencial para proporcionar uma experiência de usuário eficiente. Uma forma de otimizar as buscas é expandindo automaticamente os termos pesquisados por meio de sinônimos. Isso permite que as consultas sejam interpretadas de forma mais abrangente, abrangendo variações de idioma e, assim, melhorando a correspondência dos resultados.</p><p>Este blog explora como grandes modelos de linguagem (LLMs) podem ser usados para identificar e gerar sinônimos automaticamente, permitindo que esses termos sejam carregados programaticamente na API de sinônimos do Elasticsearch.</p><h2>Quando usar sinônimos?</h2><p>O uso de sinônimos pode ser uma solução mais rápida e econômica em comparação com a busca vetorial. Sua implementação é mais simples, pois não requer conhecimento profundo de embeddings ou um processo complexo de ingestão de vetores.</p><p>Além disso, o consumo de recursos é menor, uma vez que a busca vetorial exige maior capacidade de armazenamento e memória para indexação e recuperação de dados.</p><p>Outro aspecto importante é a regionalização da busca. Com sinônimos, é possível adaptar os termos de acordo com o idioma e os costumes locais. Isso é útil em situações em que os embeddings podem não corresponder a expressões regionais ou termos específicos de cada país. Por exemplo, algumas palavras ou siglas podem ter significados diferentes dependendo da região, mas são naturalmente tratadas como sinônimos pelos usuários locais. No Brasil, isso é bastante comum. "Abacaxi" e "ananás" são a mesma fruta (abacaxi), mas o segundo termo é mais comumente usado em algumas regiões do Nordeste. Da mesma forma, o conhecido "pão francês" no Sudeste pode ser conhecido como "pão careca" no Nordeste.</p><h2>Como usar LLMs para gerar sinônimos?</h2><p>Para obter sinônimos automaticamente, podemos usar Modelos de Aprendizagem Baseados em Lógica (LLMs), que analisam o contexto de um termo e sugerem variações apropriadas. Essa abordagem permite a expansão dinâmica de sinônimos, garantindo uma busca mais ampla e precisa sem depender de um dicionário fixo.</p><p>Nesta demonstração, usaremos um modelo de linguagem natural (LLM) para gerar sinônimos para produtos de comércio eletrônico. Muitas pesquisas retornam poucos ou nenhum resultado devido a variações nos termos pesquisados. Com sinônimos, podemos resolver esse problema. Por exemplo, uma busca por "smartphone" pode abranger diferentes modelos de celulares, garantindo que os usuários encontrem os produtos que procuram.</p><h3>Pré-requisitos</h3><p>Antes de começarmos, precisamos configurar o ambiente e definir as dependências necessárias. Utilizaremos a solução fornecida pela Elastic para <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/run-elasticsearch-locally.html">executar o Elasticsearch e o Kibana localmente em um contêiner Docker</a>. O código será escrito em Python, versão 3.9.6, com as seguintes dependências:</p>pip install openai==1.59.8 elasticsearch==8.15.1<h3>Criando o índice de produtos</h3><p>Inicialmente, criaremos um índice de produtos sem suporte a sinônimos. Isso nos permitirá validar as consultas e compará-las com um índice que inclui sinônimos.</p><p>Para criar o índice, carregamos em massa um conjunto de dados de produtos usando o seguinte comando no Kibana DevTools:</p>POST _bulk
{"index": {"_index": "products", "_id": 10001}}
{"category": "Electronics", "name": "iPhone 14 Pro"}
{"index": {"_index": "products", "_id": 10007}}
{"category": "Electronics", "name": "MacBook Pro 16-inch"}
{"index": {"_index": "products", "_id": 10013}}
{"category": "Electronics", "name": "Samsung Galaxy Tab S8"}
{"index": {"_index": "products", "_id": 10037}}
{"category": "Electronics", "name": "Apple Watch Series 8"}
{"index": {"_index": "products", "_id": 10049}}
{"category": "Electronics", "name": "Kindle Paperwhite"}
{"index": {"_index": "products", "_id": 10067}}
{"category": "Electronics", "name": "Samsung QLED 4K TV"}
{"index": {"_index": "products", "_id": 10073}}
{"category": "Electronics", "name": "HP Spectre x360 Laptop"}
{"index": {"_index": "products", "_id": 10079}}
{"category": "Electronics", "name": "Apple AirPods Pro"}
{"index": {"_index": "products", "_id": 10115}}
{"category": "Electronics", "name": "Amazon Echo Show 10"}
{"index": {"_index": "products", "_id": 10121}}
{"category": "Electronics", "name": "Apple iPad Air"}
{"index": {"_index": "products", "_id": 10127}}
{"category": "Electronics", "name": "Apple AirPods Max"}
{"index": {"_index": "products", "_id": 10151}}
{"category": "Electronics", "name": "Sony WH-1000XM4 Headphones"}
{"index": {"_index": "products", "_id": 10157}}
{"category": "Electronics", "name": "Google Pixel 6 Pro"}
{"index": {"_index": "products", "_id": 10163}}
{"category": "Electronics", "name": "Apple MacBook Air"}
{"index": {"_index": "products", "_id": 10181}}
{"category": "Electronics", "name": "Google Pixelbook Go"}
{"index": {"_index": "products", "_id": 10187}}
{"category": "Electronics", "name": "Sonos Beam Soundbar"}
{"index": {"_index": "products", "_id": 10199}}
{"category": "Electronics", "name": "Apple TV 4K"}
{"index": {"_index": "products", "_id": 10205}}
{"category": "Electronics", "name": "Samsung Galaxy Watch 4"}
{"index": {"_index": "products", "_id": 10211}}
{"category": "Electronics", "name": "Apple MacBook Pro 16-inch"}
{"index": {"_index": "products", "_id": 10223}}
{"category": "Electronics", "name": "Amazon Echo Dot (4th Gen)"}<h3>Gerando sinônimos com LLM</h3><p>Nesta etapa, utilizaremos um modelo de lógica latente (LLM) para gerar sinônimos dinamicamente. Para atingir esse objetivo, integraremos a API da OpenAI, definindo um modelo e um prompt adequados. O LLM receberá a categoria e o nome do produto, garantindo que os sinônimos sejam contextualmente relevantes.</p>import json
import logging

from openai import OpenAI

def call_gpt(prompt, model):
    try:
        logging.info("generate synonyms by llm...")
        response = client.chat.completions.create(
            model=model,
            messages=[{"role": "user", "content": prompt}],
            temperature=0.7,
            max_tokens=1000
        )
        content = response.choices[0].message.content.strip()
        return content
    except Exception as e:
        logging.error(f"Failed to use model: {e}")
        return None

def generate_synonyms(category, products):
   synonyms = {}

   for product in products:
       prompt = f"You are an expert in generating synonyms for products. Based on the category and product name provided, generate synonyms or related terms. Follow these rules:\n"
       prompt += "1. **Format**: The first word should be the main item (part of the product name, excluding the brand), followed by up to 3 synonyms separated by commas.\n"
       prompt += "2. **Exclude the brand**: Do not include the brand name in the synonyms.\n"
       prompt += "3. **Maximum synonyms**: Generate a maximum of 3 synonyms per product.\n\n"
       prompt += f"The category is: **{category}**, and the product is: **{product}**. Return only the synonyms in the requested format, without additional explanations."

       response = call_gpt(prompt, "gpt-4o")
       synonyms[product] = response

   return synonyms<p>A partir do índice de produtos criado, recuperaremos todos os itens da categoria "Eletrônicos" e enviaremos seus nomes para o LLM. O resultado esperado será algo como:</p>{
  "iPhone 14 Pro": ["iPhone", "smartphone", "mobile", "handset"],
  "MacBook Pro 16-inch": ["MacBook", "Laptop", "Notebook", "Ultrabook"],
  "Samsung Galaxy Tab S8": ["Tab", "Tablet", "Slate", "Pad"],
  "Bose QuietComfort 35 Headphones": ["Headphones", "earphones", "earbuds", "headset"]
}<p>Com os sinônimos gerados, podemos registrá-los no Elasticsearch usando a API de Sinônimos.</p><h3>Gerenciando sinônimos com a API de Sinônimos</h3><p>A API de Sinônimos oferece uma maneira eficiente de gerenciar conjuntos de sinônimos diretamente dentro do sistema. Cada conjunto de sinônimos consiste em regras de sinonímia, onde um grupo de palavras é tratado como equivalente nas buscas.</p><p><strong>Exemplo de criação de um conjunto de sinônimos</strong></p>PUT _synonyms/my-synonyms-set
{
  "synonyms_set": [
    {
      "id": "rule-1",
      "synonyms": "hello, hi"
    },
    {
      "synonyms": "bye, goodbye"
    }
  ]
}<p>
Isso cria um conjunto chamado "meu-conjunto-de-sinônimos", onde "olá" e "oi" são tratados como equivalentes, assim como "tchau" e "adeus".</p><h2>Implementação da criação de sinônimos para o catálogo de produtos.</h2><p>A seguir, está o método responsável por construir um conjunto de sinônimos e inseri-lo no Elasticsearch. As regras de sinônimos são geradas com base no mapeamento de sinônimos sugerido pelo LLM. Cada regra possui um ID, correspondente ao nome do produto no formato slug, e a lista de sinônimos calculada pelo LLM.</p>import json
import logging

from elasticsearch import Elasticsearch
from slugify import slugify

es = Elasticsearch(
    "http://localhost:9200",
    api_key="your_api_key"
)

def mount_synonyms(results):
   synonyms_set = [{"id": slugify(product), "synonyms": synonyms} for product, synonyms in
                   results.items()]

   try:
       response = es.synonyms.put_synonym(id="products-synonyms-set",
                                                 synonyms_set=synonyms_set)

       logging.info(json.dumps(response.body, indent=4))
       return response.body
   except Exception as e:
       logging.error(f"Error create synonyms: {str(e)}")
       return None<p>A seguir, está a carga útil da solicitação para criar o conjunto de sinônimos:</p>{
   "synonyms_set":[
      {
         "id": "iphone-14-pro",
         "synonyms": "iPhone, smartphone, mobile, handset"
      },
      {
         "id": "macbook-pro-16-inch",
         "synonyms": "MacBook, Laptop, Notebook, Computer"
      },
      {
         "id": "samsung-galaxy-tab-s8",
         "synonyms": "Tablet, Slate, Pad, Device"
      },
      {
         "id": "garmin-forerunner-945",
         "synonyms": "Forerunner, smartwatch, fitness watch, GPS watch"
      },
      {
         "id": "bose-quietcomfort-35-headphones",
         "synonyms": "Headphones, Earphones, Headset, Cans"
      }
   ]
}<p>Com o conjunto de sinônimos criado no cluster, podemos prosseguir para a próxima etapa, que é a criação de um novo índice com suporte a sinônimos usando o conjunto definido.</p><p>O código Python completo, com os sinônimos gerados pelo LLM e a criação do conjunto de sinônimos definida pela API de Sinônimos, encontra-se abaixo:</p>import json
import logging

from elasticsearch import Elasticsearch
from openai import OpenAI
from slugify import slugify

logging.basicConfig(level=logging.INFO)

client = OpenAI(
   api_key="your-key",
)

es = Elasticsearch(
    "http://localhost:9200",
    api_key="your_api_key"
)


def call_gpt(prompt, model):
   try:
       logging.info("generate synonyms by llm...")
       response = client.chat.completions.create(
           model=model,
           messages=[{"role": "user", "content": prompt}],
           temperature=0.7,
           max_tokens=1000
       )
       content = response.choices[0].message.content.strip()
       return content
   except Exception as e:
       logging.error(f"Failed to use model: {e}")
       return None


def generate_synonyms(category, products):
   synonyms = {}

   for product in products:
       prompt = f"You are an expert in generating synonyms for products. Based on the category and product name provided, generate synonyms or related terms. Follow these rules:\n"
       prompt += "1. **Format**: The first word should be the main item (part of the product name, excluding the brand), followed by up to 3 synonyms separated by commas.\n"
       prompt += "2. **Exclude the brand**: Do not include the brand name in the synonyms.\n"
       prompt += "3. **Maximum synonyms**: Generate a maximum of 3 synonyms per product.\n\n"
       prompt += f"The category is: **{category}**, and the product is: **{product}**. Return only the synonyms in the requested format, without additional explanations."

       response = call_gpt(prompt, "gpt-4o")
       synonyms[product] = response

   return synonyms


def get_products(category):
   query = {
       "size": 50,
       "_source": ["name"],
       "query": {
           "bool": {
               "filter": [
                   {
                       "term": {
                           "category.keyword": category
                       }
                   }
               ]
           }
       }
   }
   response = es.search(index="products", body=query)

   if response["hits"]["total"]["value"] &gt; 0:
       product_names = [hit["_source"]["name"] for hit in response["hits"]["hits"]]
       return product_names
   else:
       return []


def mount_synonyms(results):
   synonyms_set = [{"id": slugify(product), "synonyms": synonyms} for product, synonyms in
                   results.items()]

   try:
       es_client = get_client_es()
       response = es_client.synonyms.put_synonym(id="products-synonyms-set",
                                                 synonyms_set=synonyms_set)

       logging.info(json.dumps(response.body, indent=4))
       return response.body
   except Exception as e:
       logging.error(f"Erro update synonyms: {str(e)}")
       return None


if __name__ == '__main__':
   category = "Electronics"
   products = get_products("Electronics")
   llm_synonyms = generate_synonyms(category, products)
   mount_synonyms(llm_synonyms)<h3>Criando um índice com suporte a sinônimos</h3><p>Um novo índice será criado onde todos os dados do índice <code>products</code> serão reindexados. Este índice usará o <code>synonyms_filter</code>, que aplica o <code>products-synonyms-set</code> criado anteriormente.</p><p>A seguir, o mapeamento de índice configurado para usar sinônimos:</p>PUT products_02
{
  "settings": {
    "analysis": {
      "filter": {
        "synonyms_filter": {
          "type": "synonym",
          "synonyms_set": "products-synonyms-set",
          "updateable": true
        }
      },
      "analyzer": {
        "synonyms_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "synonyms_filter"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "ID": {
        "type": "long"
      },
      "category": {
        "type": "keyword"
      },
      "name": {
        "type": "text",
        "analyzer": "standard",
        "search_analyzer": "synonyms_analyzer"
      }
    }
  }
}<h3>Reindexando o índice <code>products</code></h3><p>Agora, usaremos a <strong>API Reindex</strong> para migrar os dados do índice <code>products</code> para o novo índice <code>products_02</code> , que inclui suporte a sinônimos. O seguinte código foi executado no Kibana DevTools:
</p>POST _reindex
{
  "source": {
    "index": "products"
  },
  "dest": {
    "index": "products_02"
  }
}<p>Após a migração, o índice <code>products_02</code> será preenchido e estará pronto para validar pesquisas usando o conjunto de sinônimos configurado.</p><h3>Validação da pesquisa com sinônimos</h3><p>Vamos comparar os resultados da pesquisa entre os dois índices. Executaremos a mesma consulta em ambos os índices e validaremos se os sinônimos estão sendo usados para recuperar os resultados.</p><h4>Pesquisar no índice <code>products</code> (sem sinônimos)</h4><p>Usaremos o Kibana para realizar buscas e analisar os resultados. No menu Analytics &gt; Discovery, criaremos uma visualização de dados para visualizar os dados dos índices que criamos.</p><p>Dentro do Discovery, clique em Visualização de Dados e defina um nome e um padrão de índice. Para o índice "<strong>produtos</strong>", usaremos o padrão "<strong>produtos</strong> ". Em seguida, repetiremos o processo para criar uma nova visualização de dados para o índice "<strong>products_02</strong>", usando o padrão "<strong>products_02"</strong> .</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte826fd932cfeb9df/6a17fdffec0f8912aa5a6841/3ad4a6891a3905e96532a312932fdf3a8216aec2-1600x599.png" alt="" /><p>Com as visualizações de dados configuradas, podemos retornar a Analytics &gt; Discovery e iniciar as validações.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltba3729c60068e8a0/6a17fe01e9ea87ba2aa9c82a/422c4b2b51abae6580cad25085d1b8a365fc6b9e-1294x850.png" alt="" /><p>Aqui, após selecionar os produtos DataView e pesquisar pelo termo "tablet", não obtemos resultados, embora saibamos que existem produtos como "Kindle Paperwhite" e "Apple iPad Air".</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2c6a383dd4cb0157/6a17fe02577262671d1bce0c/e4ae3a785fdd93f48d7c7d204185ded149126f2c-1600x862.png" alt="" /><h4>Pesquisar no índice <code>products_02</code> (suporta sinônimos)</h4><p>Ao executar a mesma consulta na visualização de dados "<strong>products_synonyms</strong>", que suporta sinônimos, os produtos foram recuperados com sucesso. Isso demonstra que o conjunto de sinônimos configurado está funcionando corretamente, garantindo que diferentes variações dos termos pesquisados retornem os resultados esperados.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt986b4706e2f70014/6a17fe043e9e454edbba16d3/e609749c39e90d5c82fa846af6124679dd62bcb8-1600x526.png" alt="" /><p>Podemos obter o mesmo resultado executando a mesma consulta diretamente no Kibana DevTools. Basta pesquisar o índice products_02 usando a API de pesquisa do Elasticsearch:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbe829a3c4d7aac60/6a17fe05e8fbce03d73a1bd7/504d0d1f96dcfbceb309063dc0716bcee64ad2f8-1600x870.png" alt="" /><h2>Conclusão</h2><p>A implementação de sinônimos no Elasticsearch melhorou a precisão e a abrangência das buscas no catálogo de produtos. O principal diferencial foi o uso de um <strong>LLM (</strong> Language-Level Model), que gerou sinônimos automaticamente e contextualmente, eliminando a necessidade de listas predefinidas. O modelo analisou nomes e categorias de produtos, garantindo sinônimos relevantes para o comércio eletrônico.</p><p>Além disso, a <strong>API de Sinônimos</strong> simplificou o gerenciamento de dicionários, permitindo que os conjuntos de sinônimos fossem modificados dinamicamente. Com essa abordagem, a busca tornou-se mais flexível e adaptável a diferentes padrões de consulta do usuário.</p><p>Esse processo pode ser continuamente aprimorado com novos dados e ajustes de modelo, garantindo uma experiência de pesquisa cada vez mais eficiente.</p><h2>Referências</h2><p><strong>Executar o Elasticsearch localmente</strong></p><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/run-elasticsearch-locally.html">https://www.elastic.co/guide/en/elasticsearch/reference/current/run-elasticsearch-locally.html</a></p><p><strong>API de sinônimos</strong></p><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/synonyms-apis.html">https://www.elastic.co/guide/en/elasticsearch/reference/current/synonyms-apis.html</a></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elasticsearch-synonyms-automate</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elasticsearch-synonyms-automate</guid>
    <category><![CDATA[Relevância]]></category>
    <category><![CDATA[Noções básicas]]></category>
    <dc:creator><![CDATA[Andre Luiz]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0f0247b9bc1d1ccd/6a17fe07ec0f891c745a6845/05a3cfeaa387561d5334ca3f1609035ddfff7481-1200x628.png" length="0" type="image/png"/>
    <pubDate>Thu, 27 Mar 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Redimensionamento de modelos de interação tardia no Elasticsearch - parte 2]]></title>
    <description><![CDATA[Este artigo explora técnicas para redimensionar vetores de interação tardia para cargas de trabalho de produção em grande escala, como a redução do uso de espaço em disco e a melhoria da eficiência computacional.]]></description>
    <content:encoded><![CDATA[<p>Em nosso <a href="https://www.elastic.co/search-labs/blog/elastiacsearch-colpali-document-search">blog anterior sobre o ColPali</a>, exploramos como criar aplicações de busca visual com o Elasticsearch. O foco principal foi o valor que modelos como o ColPali agregam às aplicações, mas eles apresentam desvantagens de performance em comparação com a busca vetorial usando bi-encoders, como o E5.</p><p>Partindo dos exemplos da <a href="https://www.elastic.co/search-labs/blog/elastiacsearch-colpali-document-search">parte 1</a>, este post explora como usar diferentes técnicas e o conjunto avançado de ferramentas de busca vetorial do Elasticsearch para preparar vetores de interação tardia para cargas de trabalho de produção em grande escala.</p><p>Os exemplos completos de código estão disponíveis no <a href="https://github.com/elastic/elasticsearch-labs/tree/main/supporting-blog-content/colpali">GitHub.</a></p><h2>Desafios dos modelos de interação tardia</h2><p>O ColPali cria mais de 1.000 vetores por página para os documentos do nosso índice.</p><p>Isso resulta em dois desafios ao trabalhar com vetores de interação tardia:</p><ol><li><p>Espaço em disco: salvar todos esses vetores em disco gera um volume significativo de armazenamento, o que se torna caro em ambientes de grande escala.</p></li><li><p>Computação: ao classificar documentos usando a comparação <code>maxSimDotProduct()</code>, precisamos comparar todos esses vetores de cada documento com os N vetores da consulta.</p></li></ol><p>Vamos analisar algumas técnicas para lidar com esses desafios.</p><h2>Técnicas para otimizar modelos de interação tardia</h2><h3>Vetores de bits</h3><p>Para reduzir o espaço em disco, podemos comprimir as imagens em vetores de bits. Podemos usar uma função simples em Python para transformar nossos multivetores em vetores de bits:</p>def to_bit_vectors(embeddings: list) -&gt; list:
    return [
        np.packbits(np.where(np.array(embedding) &gt; 0, 1, 0))
        .astype(np.int8)
        .tobytes()
        .hex()
        for embedding in embeddings
    ]<p>O conceito central da função é simples: valores acima de 0 se tornam 1, e valores abaixo de 0 se tornam 0. Isso resulta em uma matriz de 0s e 1s, que depois transformamos em uma string hexadecimal que representa nosso vetor de bits.</p><p>Para o mapeamento de índice, configuramos o parâmetro <code>element_type</code> para <code>bit</code>:</p>mappings = {
    "mappings": {
        "properties": {
            "col_pali_vectors": {
                "type": "rank_vectors",
                "element_type": "bit"
            }
        }
    }
}

es.indices.create(index=INDEX_NAME, body=mappings)<p>Depois de gravar todos os novos vetores de bits no índice, podemos ranquear nossos vetores de bits usando o código a seguir:</p>query = "What do companies use for recruiting?"
query_vector = to_bit_vectors(create_col_pali_query_vectors(query))
es_query = {
    "_source": False,
    "query": {
        "script_score": {
            "query": {
                "match_all": {}
            },
            "script": {
                "source": "maxSimInvHamming(params.query_vector, 'col_pali_vectors')",
                "params": {
                    "query_vector": query_vector
                }
            }
        }
    },
    "size": 5
}<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcaf0c8f999d68701/6a17f46696142a6f46eb1c56/51b989446e4099745971e1eac27d147a78d13e0a-1600x480.png" alt="" /><p>Ao abrir mão de um pouco de precisão, isso nos permite usar a distância de Hamming (<code>maxSimInvHamming(...)</code>), que consegue explorar otimizações como bit masks, SIMD, entre outras. Saiba mais sobre <a href="https://www.elastic.co/search-labs/blog/bit-vectors-in-elasticsearch">vetores de bits e distância de Hamming em nosso blog</a>.</p><p>Como alternativa, podemos não converter o vetor de consulta em vetores de bits e realizar a busca usando o vetor de interação tardia com fidelidade total:</p>query = "What do companies use for recruiting?"
query_vector = create_col_pali_query_vectors(query)
es_query = {
    "_source": False,
    "query": {
        "script_score": {
            "query": {
                "match_all": {}
            },
            "script": {
                "source": "maxSimDotProduct(params.query_vector, 'col_pali_vectors')",
                "params": {
                    "query_vector": query_vector
                }
            }
        }
    },
    "size": 5
}<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2fa6c89fb451b6e0/6a17f468af47b65da9cde0d9/89f3c795c6dc44b2f7d46801320288316b47e1b2-1600x488.png" alt="Resultados do uso de vetores de bits para otimizar modelos de interação tardia" /><p>Nesse caso, os vetores são comparados usando uma função de similaridade assimétrica.</p><p></p><p>Vamos considerar uma distância de Hamming padrão entre dois vetores de bits. Suponha que temos um vetor de documento <em>D:</em></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd4b6ece1ec4dedac/6a17f4694b055d248143234e/366a70a23e37d403788327b7aefc873fd4482f5e-1235x86.png" alt="" /><p>E um vetor de consulta <em>Q:</em></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7721df9c8f0d84f1/6a17f46b3e03d77cf54f2dcb/978ec31e0afbc0eaebf548a015b628c0cad84625-1247x84.png" alt="" /><p></p><p>A quantização binária simples transforma o vetor <em>D</em> em <code>10101101</code> e o vetor <em>Q</em> em <code>11111011</code>. Para calcular a distância de Hamming, precisamos apenas de operações diretas em bits, algo extremamente rápido. Nesse caso, a distância de Hamming é <code>01010110</code>, que possui uma contagem de bits igual a 4.Assim, a pontuação passa a ser o inverso dessa distância de Hamming. Lembre-se de que vetores mais semelhantes têm uma distância de Hamming MENOR, portanto inverter esse valor permite que vetores mais semelhantes recebam pontuações mais altas. Especificamente aqui, a pontuação seria 1/4 = <code>0.25</code>.</p><p>No entanto, observe que perdemos a magnitude de cada dimensão. Um <code>1</code> é um <code>1</code>. Assim, para <em>Q</em>, a diferença entre <code>0.01</code> e <code>0.79</code> desaparece. Como estamos simplesmente quantizando de acordo com <code>&gt;0</code>, podemos aplicar um pequeno truque em que o vetor Q não é quantizado. Isso não permite a matemática bit a bit extremamente rápida, mas mantém o custo de armazenamento baixo, já que D continua quantizado.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blted50315518e2d599/6a17f46c414c6463709452d3/508e8498ba969534d2a0131d431c75735fc27cb9-1399x611.png" alt="" /><p>Em resumo, essa abordagem preserva as informações contidas em <em>Q</em>, aumentando a qualidade da estimativa de distância e mantendo baixo o custo de armazenamento.</p><p>O uso de vetores de bits permite economizar significativamente espaço em disco e reduzir a carga computacional no momento da consulta. Mas ainda há mais que podemos fazer.</p><h3>Vetores médios</h3><p>Para redimensionar a busca para centenas de milhares de documentos, mesmo os ganhos de desempenho proporcionados pelos vetores de bits não serão suficientes. Para dar conta desse tipo de carga, será necessário aproveitar a estrutura de índice HNSW do Elasticsearch para busca vetorial.</p><p>O ColPali gera cerca de 1.000 vetores por documento, o que é excessivo para adicionar ao grafo HNSW. Portanto, precisamos reduzir a quantidade de vetores. Para isso, podemos criar uma única representação do significado do documento calculando a média de todos os vetores do documento produzidos pelo ColPali quando incorporamos a imagem.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc053425fbfcf8de8/6a17f46f148009faf1b488aa/7c3b4dffb70bd95f67deb35f8c01e73c5286c2ab-1476x1102.png" alt="Vetor médio considerando todos os vetores de interação tardia" /><p>No momento, isso não é possível diretamente no Elastic, sendo necessário pré-processar os vetores antes de ingeri-los no Elasticsearch. </p><p>Isso pode ser feito com o Logstash ou com pipelines de ingestão, mas aqui usaremos uma função simples em Python:</p>def to_avg_vector(vectors):
    vectors_array = np.array(vectors)
    
    avg_vector = np.mean(vectors_array, axis=0)
    
    norm = np.linalg.norm(avg_vector)
    if norm &gt; 0:
        normalized_avg_vector = avg_vector / norm
    else:
        normalized_avg_vector = avg_vector

    return normalized_avg_vector.tolist()<p>Também normalizamos o vetor para que possamos usar a similaridade por produto escalar.</p><p>Depois de transformar todos os vetores do ColPali em vetores médios, podemos indexá-los no campo dense_vector:</p>mappings = {
    "mappings": {
        "properties": {
            "avg_vector": {
                "type": "dense_vector",
                "dims": 128,
                "index": True,
                "similarity": "dot_product"
            },
            "col_pali_vectors": {
                "type": "rank_vectors",
                "element_type": "bit"
            }
        }
    }
}

es.indices.create(index=INDEX_NAME, body=mappings)<p>Precisamos considerar que isso aumentará o uso total de disco, pois estamos salvando mais informações junto com nossos vetores de interação tardia. Além disso, usaremos RAM adicional para manter o grafo HNSW, o que nos permite redimensionar a busca para bilhões de vetores. Para reduzir o uso de RAM, podemos recorrer ao nosso conhecido <a href="https://www.elastic.co/search-labs/blog/optimized-scalar-quantization-elasticsearch">recurso BBQ</a>. Com isso, obtemos resultados de busca rápidos em conjuntos de dados massivos que, de outra forma, não seriam viáveis.</p><p>Agora, simplesmente fazemos a busca com a consulta knn para encontrar os documentos mais relevantes.</p>query = "What do companies use for recruiting?"
query_vector = to_avg_vector(create_col_pali_query_vectors(query))
es_query = {
    "_source": False,
    "knn": {
        "field": "avg_vector",
        "query_vector": query_vector,
        "k": 10,
        "num_candidates": 100
    },
    "size": 5
}<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf4ac6b7fd444f935/6a17f471a29299d76ad02dc0/a500f9907020f032c3b1c7a48ed8c759dc2a1dd4-1600x498.png" alt="" /><p>O que antes era a melhor correspondência acabou caindo para a 3ª posição.</p><p>Para corrigir esse problema, podemos usar uma recuperação em vários estágios. No primeiro estágio, usamos a consulta knn para buscar os melhores candidatos para a consulta em meio a milhões de documentos. No segundo estágio, fazemos a reclassificação apenas dos top k (neste caso, 10) usando a maior fidelidade dos vetores de interação tardia do ColPali. </p>query = "What do companies use for recruiting?"
col_pali_vector = create_col_pali_query_vectors(query)
avg_vector = to_avg_vector(col_pali_vector)
es_query = {
  "_source": False,
  "retriever": {
    "rescorer": {
      "retriever": {
        "knn": {
          "field": "avg_vector",
          "query_vector": avg_vector,
          "k": 10,
          "num_candidates": 100
        }
      },
      "rescore": {
        "window_size": 10,
        "query": {
          "rescore_query": {
            "script_score": {
              "query": {
                "match_all": {}
              },
              "script": {
                "source": "maxSimDotProduct(params.query_vector, 'col_pali_vectors')",
                "params": {
                  "query_vector": col_pali_vector
                }
              }
            }
          }
        }
      }
    }
  },
  "size": 5
}<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt265edd5f37be40b7/6a17f4733e9e45583dba15e6/797f490860af87fcf29f34668a5c4511419c6fd0-1600x501.png" alt="Resultados do uso de vetores médios para otimizar modelos de interação tardia" /><p>Aqui, estamos usando o <a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.18/retriever.html#rescorer-retriever">rescore retriever,</a> introduzido na versão 8.18, para reclassificar nossos resultados. Após a reclassificação, vemos que a melhor correspondência volta a ocupar a primeira posição. </p><p>Observação: em uma aplicação de produção, podemos usar um valor de k muito maior que 10, já que a função max sim ainda é relativamente eficiente em termos de performance.</p><h3>Agrupamento de tokens</h3><p>O agrupamento de tokens reduz o comprimento da sequência de embeddings multivetoriais ao agrupar informações redundantes, como regiões de fundo branco. Essa técnica diminui o número de embeddings ao mesmo tempo que preserva a maior parte do sinal da página.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3d643e6ac908f640/6a17f4754b055d3783432352/09eae0b768f4b450e555d7e53e57561bd52de2c0-1412x1056.png" alt="Agrupamento de tokens para otimizar modelos de interação tardia" /><p>O agrupamento de tokens funciona reunindo embeddings de tokens semelhantes dentro de um documento em clusters, usando um algoritmo de clusterização. Em seguida, calcula-se a média dos vetores em cada cluster para criar uma única representação agregada. Esse vetor agregado substitui os tokens originais do grupo, reduzindo o número total de vetores sem perda significativa do sinal do documento.</p><p>O artigo do ColPali propõe um valor inicial de agrupamento factor igual a 3 para a maioria dos conjuntos de dados, mantendo 97,8% da performance original ao mesmo tempo que reduz o número total de vetores em 66,7%. </p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2d78a15c6944a1ea/6a17f477414c64a2929452d9/343cc9eaf54af8c7a125d4115838f3c7d5659de0-1600x1007.png" alt="Fator de agrupamento para otimizar modelos de interação tardia" /><p>Mas é preciso cautela: o conjunto de dados Shift, que contém documentos muito densos e com grande volume de texto e pouco espaço em branco, apresenta uma queda rápida de desempenho conforme o fator de agrupamento aumenta.</p><p>Para criar os vetores agrupados, podemos usar a biblioteca colpali_engine:</p>from colpali_engine.compression.token_pooling import HierarchicalTokenPooler

pooler = HierarchicalTokenPooler(pool_factor=3) # test on your data for a good pool_factor

def pool_vectors(embedding: list) -&gt; list:
    tensor = torch.tensor(embedding).unsqueeze(0)
    pooled = pooler.pool_embeddings(tensor)
    return pooled.squeeze(0).tolist()<p>Agora temos um vetor que teve suas dimensões reduzidas em cerca de 66,7%. Nós o indexamos normalmente e conseguimos realizar buscas usando nossa função <code>maxSimDotProduct()</code>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc460c14031814ede/6a17f4794202292bf629f72d/2412c5db7d79a590b96d42fe01f140c42f010612-1600x481.png" alt="Resultados dos modelos de interação tardia" /><p>Conseguimos obter bons resultados de busca ao custo de uma leve perda de precisão nos resultados.</p><p>Dica: com um pool_factor mais alto (100-200), também é possível encontrar um meio-termo entre a solução de vetor médio e a abordagem discutida aqui. Com cerca de 5 a 10 vetores por documento, torna-se viável indexá-los em um campo aninhado para aproveitar o índice HNSW.</p><h2>Cross-encoder vs. interação tardia vs. bi-encoder</h2><p>Com tudo o que aprendemos até aqui, onde isso posiciona os modelos de interação tardia, como ColPali ou ColBERT, em comparação com outras técnicas de recuperação baseadas em IA?</p><p>Embora a função max sim seja mais barata do que o uso de cross-encoders, ela ainda exige muito mais comparações e processamento do que a busca vetorial com bi-encoders, em que comparamos apenas dois vetores para cada par consulta-documento. </p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbfd97f3bba3e5b17/6a17f47be31791b0052d5943/75e1fc9e601aa7a6e88f137565c1919166c7a71c-1480x458.png" alt="Cross-encoder vs. modelos de interação tardia vs. bi-encoder" /><p>Por isso, nossa recomendação para modelos de interação tardia é, em geral, usá-los apenas para reclassificação dos primeiros k resultados de busca. Também refletimos isso no nome do tipo de campo: rank_vectors.</p><p>Mas e o cross-encoder? Modelos de interação tardia são melhores por serem mais baratos de executar no momento da consulta? Como acontece com frequência, a resposta é: depende. Os cross-encoders normalmente produzem resultados de maior qualidade, mas exigem muito processamento, já que cada par consulta-documento precisa passar completamente pelo modelo transformer. Eles também se beneficiam do fato de não exigirem indexação de vetores e poderem operar de forma stateless. Isso resulta em:</p><ul><li><p>Menor uso de espaço em disco</p></li><li><p>Um sistema mais simples</p></li><li><p>Maior qualidade nos resultados de busca</p></li><li><p>Maior latência, o que limita a profundidade da reclassificação</p></li></ul><p>Por outro lado, os modelos de interação tardia podem deslocar parte desse custo computacional para o momento da indexação, tornando a consulta mais barata. O preço a pagar é a necessidade de indexar vetores, o que torna os pipelines de indexação mais complexos e exige mais espaço em disco para armazená-los.</p><p>No caso específico do ColPali, a análise de informações provenientes de imagens é muito custosa, já que elas contêm grandes volumes de dados. Nesse cenário, o equilíbrio pende a favor do uso de um modelo de interação tardia como o ColPali, pois avaliar essas informações no momento da consulta seria lento demais e exigiria muitos recursos. </p><p>Já para um modelo de interação tardia como o ColBERT, que trabalha com dados textuais, assim como a maioria dos cross-encoders, por exemplo o elastic-rerank-v1, a decisão pode favorecer o uso do cross-encoder, aproveitando a economia de disco e a maior simplicidade operacional.</p><p>Recomendamos que você avalie esses prós e contras no seu caso de uso e experimente as diferentes ferramentas que o Elasticsearch oferece para criar as melhores aplicações de busca.</p><h2>Conclusão</h2><p>Neste blog, exploramos várias técnicas para otimizar modelos de interação tardia, como o ColPali, para busca vetorial em grande escala no Elasticsearch. Embora esses modelos ofereçam um forte equilíbrio entre eficiência de recuperação e qualidade de classificação, eles também introduzem desafios relacionados a armazenamento e computação.</p><p>Para enfrentar esses desafios, analisamos diferentes abordagens e técnicas:</p><ul><li><p><strong>Vetores de bits</strong> para reduzir significativamente o uso de espaço em disco, ao mesmo tempo que aproveitam computações de similaridade eficientes, como a distância de Hamming ou a similaridade máxima assimétrica.</p></li><li><p><strong>Vetores médios</strong> para comprimir múltiplos embeddings em uma única representação densa, permitindo recuperação eficiente com indexação HNSW.</p></li><li><p><strong>Agrupamento de tokens</strong> para unir embeddings redundantes de forma inteligente, mantendo a integridade semântica e reduzindo a sobrecarga computacional no momento da consulta.</p></li></ul><p>O Elasticsearch oferece um conjunto poderoso de ferramentas para personalizar e otimizar aplicações de busca de acordo com suas necessidades. Seja priorizando velocidade de recuperação, qualidade de ranqueamento ou eficiência de armazenamento, essas técnicas permitem equilibrar desempenho e qualidade conforme as exigências de aplicações do mundo real.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/late-interaction-model-colpali-scale</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/late-interaction-model-colpali-scale</guid>
    <category><![CDATA[Relevância]]></category>
    <category><![CDATA[Banco de dados vetorial]]></category>
    <dc:creator><![CDATA[Peter Straßer,Benjamin Trent]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt97a536033e6b0a56/6a17f47dfbc5f88c86491c0d/c780b78a07573f2df1cfef8b29a7109f839b0ab3-1200x628.png" length="0" type="image/png"/>
    <pubDate>Thu, 20 Mar 2025 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>