<?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[Relevancia - 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[Relevancia - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/es/search-labs/blog/category/relevance</link>
    </image>
    <link>https://www.elastic.co/es/search-labs/blog/category/relevance</link>
    <atom:link href="https://www.elastic.co/es/search-labs/rss/category/relevance.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[es]]></language>
    <lastBuildDate>Tue, 29 Sep 2026 10:08:51 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Garantizar la precisión semántica con una puntuación mínima]]></title>
    <description><![CDATA[Mejora la precisión semántica con umbrales de puntuación mínima. El artículo incluye ejemplos concretos de búsqueda semántica e híbrida. ]]></description>
    <content:encoded><![CDATA[<p>La búsqueda semántica ha abierto un mundo de oportunidades para la relevancia en la búsqueda. Los modelos dispersos y densos de alta calidad, como ELSER, E5 y Jina Embedding v4, devuelven resultados relevantes basados en el significado de las palabras, en lugar de la coincidencia de palabras clave. Sin embargo, la búsqueda semántica a veces devuelve resultados irrelevantes al final o para búsquedas que carecen de resultados relevantes en el índice. Esta propiedad de los modelos dispersos y densos puede confundir a los usuarios o desperdiciar valiosos tokens para los modelos de lenguaje grandes (LLM).</p><p>En este artículo, aprenderás cómo puedes utilizar el parámetro de puntuación mínima para aumentar la precisión de tus resultados de búsqueda semántica. Si deseas probar los ejemplos en esta publicación de blog, ve al <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">cuaderno de Jupyter asociado</a>.</p><h2>Antecedentes: Precisión y recuperación</h2><p>En la búsqueda, la relevancia, la <em>precisión </em>y la<em> recuperación </em>son conceptos clave. Se recomienda encarecidamente a todo lector que no esté familiarizado que se interiorice sobre estos conceptos. A continuación se presenta un resumen.</p><ul><li><p><strong>Precisión: </strong>La fracción de resultados de búsqueda devueltos que son relevantes para el usuario.</p></li><li><p><strong>Recuerda: </strong>La fracción de todos los documentos relevantes del corpus que se incluyen en el conjunto de resultados de búsqueda.</p></li></ul><p>O, en otras palabras, la precisión está devolviendo <strong>solo </strong>resultados relevantes; y la recuperación está devolviendo <strong>todos </strong>los resultados relevantes. Como puedes imaginar, estos son, a menudo, requisitos contradictorios. La búsqueda semántica tiende a tener una recuperación muy alta, pero puede tener dificultades con la precisión. Continúa leyendo para saber cómo moverte por esta propiedad.</p><h2>Introducción del parámetro de puntaje mínimo</h2><p>El parámetro "min_score" nos permite mejorar la precisión al establecer una puntuación mínima, lo que truncará el conjunto de resultados y eliminará cualquier coincidencia con una puntuación inferior al umbral definido. A continuación se muestra un ejemplo sencillo:</p>GET search-movies/_search
{
  "retriever": {
    "linear": {
      "min_score": 4,
      "retrievers": [
        ...
      ]
    }
  }
}<h2>Normalizando la puntuación.</h2><p>Establecer una puntuación mínima está bien; sin embargo, no todos los modelos semánticos devuelven una puntuación adecuada para un umbral estático. ELSER, por ejemplo, devuelve una puntuación que no tiene límite. <a href="https://huggingface.co/intfloat/e5-small#faq">Algunas</a> puntuaciones de un modelo denso están estrechamente agrupadas y solo tienen sentido en el contexto de la consulta específica.</p><p>Para la mayoría de los casos de búsqueda semántica, recomendamos usar un enfoque de normalización antes de aplicar el "min_score". La normalización garantiza que la puntuación del documento esté dentro de un intervalo definido. Elasticsearch ofrece dos <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/retrievers/linear-retriever#linear-retriever-normalizers">normalizadores</a>, "l2_norm" y "minmax". El más comúnmente usado es "minmax", ya que es fácil de entender y funciona bien en muchos escenarios. Las propiedades clave de "minmax" incluyen:</p><ul><li><p>Las puntuaciones de los documentos se distribuyen entre 0 y 1.</p></li><li><p>El documento con la puntuación más alta siempre tiene una puntuación de 1.</p></li><li><p>El documento con la puntuación más baja siempre tiene una puntuación de 0.</p><ul><li><p>Esto puede hacer que sea menos adecuado para la búsqueda por palabras clave. Consulta la sección “Búsqueda híbrida” para más información.</p></li></ul></li></ul><p>A continuación se muestra un ejemplo de una consulta semántica normalizada con <code>min_score</code>. El tamaño de la ventana de clasificación se ha aumentado a 500 para permitirnos devolver una lista más larga de resultados de búsqueda, comenzando en 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>El tamaño se ha establecido en un valor más alto de lo que normalmente se ve en producción. Esto es para que podamos inspeccionar la calidad de los resultados de búsqueda y ajustar los resultados.</p><h2>Búsqueda híbrida usando el retriever lineal</h2><p>Para la búsqueda híbrida, el enfoque más sencillo es normalizar todos las puntuaciones, asignar ponderaciones y aplicar una puntuación mínima. Ten en cuenta que al elegir ponderaciones con una suma de 1, mantienes la puntuación total dentro de un rango de 0–1. Esto hace que sea más fácil entender las puntuaciones finales y afinar <code>min_score</code>. A continuación se muestra un ejemplo:</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>Búsqueda híbrida usando RRF.</h2><p>Con BM25, a menudo controlamos la precisión por otros medios, usando, por ejemplo, el operador de <code>AND</code> o <code>minimum_should_match</code>. Además, las consultas que consisten en términos únicos, precisos y poco frecuentes naturalmente generarán resultados con pocos resultados de búsqueda, a menudo todos muy relevantes. Esto puede llevar a:</p><ul><li><p>Los resultados más lejanos en el resultado reciben una puntuación normalizada baja en el recuperador BM25, incluso si la puntuación absoluta de BM25 está cerca de las puntuaciones más altas.</p></li><li><p>Al agregar una puntuación BM25 muy baja a la puntuación semántica, el total puede aproximarse a la puntuación semántica.</p></li><li><p>La falta de contribución de la puntuación BM25 puede hacer que el documento sea descartado por el <code>min_score threshold</code>.</p></li></ul><p>Como solución, podemos utilizar la fusión de rangos recíprocos (RRF) para combinar BM25 y los resultados semánticos. RRF consigue sortear el desafío de comparar puntuaciones de diferentes algoritmos de búsqueda al colocar el foco en la posición en cada conjunto de resultados. En este escenario, la <code>min_score</code> solo se aplica al 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>Conclusión</h2><p>Al usar <code>min_score</code>, hemos demostrado cómo podemos reducir el número de falsos positivos en nuestros conjuntos de resultados causados por la alta recuperación de algoritmos de búsqueda semántica. Para saber más sobre los recuperadores, consulta esta <a href="https://www.elastic.co/search-labs/blog/elasticsearch-retrievers">publicación de blog</a> y la <a href="https://www.elastic.co/docs/solutions/search/retrievers-overview">documentación de 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[Relevancia]]></category>
    <category><![CDATA[Búsqueda 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[Evaluación de la relevancia de las consultas de búsqueda con listas de evaluaciones]]></title>
    <description><![CDATA[Explora cómo crear listas de evaluación para evaluar objetivamente la relevancia de las consultas de búsqueda y mejorar métricas de rendimiento como la recuperación, para pruebas de búsqueda escalables en Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>Los desarrolladores que trabajan en motores de búsqueda a menudo se encuentran con el mismo problema: el equipo empresarial no está satisfecho con una búsqueda concreta porque los documentos que esperan que estén en la parte superior de los resultados de búsqueda aparecen en tercer o cuarto lugar en la lista de resultados.</p><p>Sin embargo, cuando solucionas este problema, accidentalmente rompes otras consultas porque no pudiste probar todos los casos manualmente. Pero, ¿cómo puedes tú o tu equipo de control de calidad comprobar si un cambio en una consulta tiene un efecto dominó en otras consultas? O aún más importante, ¿cómo puedes estar seguro de que tus cambios realmente mejoraron una consulta?</p><h2>Hacia una evaluación sistemática</h2><p>Aquí es donde las listas de evaluación resultan útiles. En lugar de depender de pruebas manuales y subjetivas cada vez que realices un cambio, puedes definir un conjunto fijo de búsquedas que sean relevantes para tu caso de negocio, junto con sus resultados relevantes.</p><p>Este conjunto se convierte en tu referencia. Cada vez que implementas un cambio, lo utilizas para evaluar si tu búsqueda realmente mejoró o no.</p><p>El valor de este enfoque radica en que:</p><ul><li><p><strong>Elimina la incertidumbre</strong>: ya no necesitas preguntarte si tus cambios afectan a otras consultas; los datos te lo dirán.</p></li><li><p><strong>Detiene las pruebas manuales</strong>: una vez que se registran los conjuntos de evaluación, la prueba es automática.</p></li><li><p><strong>Soporta cambios</strong>: puedes mostrar métricas claras que respaldan los beneficios de un cambio.</p></li></ul><h2>Cómo empezar a crear tu lista de evaluaciones</h2><p>Una de las maneras más fáciles de comenzar es tomar una búsqueda representativa y seleccionar manualmente los documentos relevantes. Hay dos formas de hacer esta lista:</p><ul><li><p><strong>Evaluaciones binarias:</strong> cada documento asociado con una búsqueda recibe una <strong>etiqueta simple</strong>: <em>relevante</em> (generalmente con una puntuación de “1”) y no relevante (“0”).</p></li><li><p><strong>Evaluaciones graduadas:</strong> aquí, cada documento obtiene una puntuación con diferentes niveles. Por ejemplo: establecer un escala de 0 a 4, similar a un <a href="https://en.wikipedia.org/wiki/Likert_scale">escala Likert</a>, donde 0 = “nada relevante” y 4 = “totalmente relevante”, con variaciones como “relevante”, “algo relevante”, etc.</p></li></ul><p>Los juicios binarios funcionan bien cuando la intención de búsqueda tiene límites claros: ¿Debería este documento estar en los resultados o no?</p><p>Las evaluaciones graduadas son más útiles cuando hay áreas grises: algunos resultados son mejores que otros, así que puedes obtener resultados “muy buenos”, “buenos” e “inútiles” y usar métricas que valoren el orden de los resultados y los comentarios del usuario. Sin embargo, las escalas graduadas también presentan inconvenientes: diferentes revisores pueden usar los niveles de puntuación de manera diferente, lo que hace que las evaluaciones sean menos consistentes. Y debido a que las métricas graduadas dan más peso a las puntuaciones más altas, incluso un pequeño cambio (como calificar algo con un 3 en lugar de un 4) puede crear un cambio mucho mayor en la métrica de lo que el revisor pretendía. Esta subjetividad añadida hace que las evaluaciones graduadas sean más complicadas y difíciles de manejar con el tiempo.</p><h2>¿Necesito clasificar los documentos por mi cuenta?</h2><p>No necesariamente, ya que hay diferentes formas de crear tu lista de evaluaciones, cada una con sus propias ventajas y desventajas:</p><ul><li><p><strong>Evaluaciones explícitas:</strong> aquí, los expertos revisan cada búsqueda/documento y deciden manualmente si es relevante (o qué tan relevante es). Si bien esto proporciona calidad y control, tiene menos escalabilidad.</p></li><li><p><strong>Evaluaciones implícitas:</strong> con este método, infieres los documentos relevantes en función del comportamiento real del usuario, como clics, tasa de rebote y compras, entre otros. Este enfoque te permite recopilar datos automáticamente, aunque puede estar sesgado. Por ejemplo, los usuarios tienden a hacer clic en los primeros resultados con más frecuencia, incluso si no son relevantes.</p></li><li><p><strong>Evaluaciones generadas por IA:</strong> esta última opción utiliza modelos (como LLM) para evaluar automáticamente consultas y documentos, a menudo referidos como <a href="https://en.wikipedia.org/wiki/LLM-as-a-Judge">jurados de LLM</a>. Es rápido y fácil de escalar, pero la calidad de los datos depende de la calidad del modelo que estés utilizando y de qué tan bien los datos de entrenamiento de LLM se alinean con tus <a href="http://interests.as/">intereses</a> comerciales. Al igual que con las calificaciones humanas, los jurados LLM pueden introducir sus propios sesgos o inconsistencias, por lo que es importante validar su salida contra un conjunto más pequeño de evaluaciones confiables. Los modelos LLM son probabilísticos por naturaleza, por lo que no es raro ver un modelo LLM dando diferentes calificaciones al mismo resultado independientemente de que el parámetro de <a href="https://www.ibm.com/think/topics/llm-temperature">temperatura</a> sea 0.</p></li></ul><p>A continuación, se incluyen algunas recomendaciones para elegir el mejor método para crear tu conjunto de evaluaciones:</p><ul><li><p>Decide cuán importantes son para ti algunas características que solo los usuarios puedan juzgar correctamente (como precio, marca, idioma, estilo y detalles del producto). Si esos son críticos, necesitas <strong>evaluaciones explícitas</strong> para al menos alguna parte de tu <em>lista de evaluaciones</em>.</p></li><li><p>Usa <strong>evaluaciones implícitas</strong> cuando tu motor de búsqueda ya tenga suficiente tráfico para que puedas usar clics, conversiones y métricas de tiempo persistente para detectar tendencias de uso. Aun así, deberías interpretarlos con cuidado, contrastándolos con tus evaluaciones explícitas para prevenir sesgos (por ejemplo: los usuarios tienden a hacer clic más a menudo en los resultados mejor clasificados, incluso si los de menor rango son más relevantes)</p></li></ul><p>Para abordar esto, las técnicas de eliminación del sesgo de posición ajustan o reponderan los datos de clics para reflejar mejor el verdadero interés del usuario. Algunos enfoques incluyen:</p><ul><li><p><strong>Reordenación de resultados</strong>: cambia el orden de los resultados de búsqueda para un subconjunto de usuarios con el fin de estimar cómo afecta la posición a los clics.</p></li><li><p>Los <strong>modelos de clics</strong> incluyen<a href="https://wiki.math.uwaterloo.ca/statwiki/index.php?title=a_Dynamic_Bayesian_Network_Click_Model_for_web_search_ranking">la red 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> y el <a href="https://rsrikant.com/papers/kdd10.pdf">modelo de navegación del usuario (</a><a href="https://rsrikant.com/papers/kdd10.pdf"><strong>UBM).</strong></a> Estos modelos estadísticos estiman la probabilidad de que un clic refleje un interés real en lugar de solo la posición, utilizando patrones como el desplazamiento, el tiempo de permanencia, la secuencia de clics y el retorno a la página de resultados.</p></li></ul><h2>Ejemplo: app de valoración de películas</h2><h3>Requisitos previos</h3><p>Para ejecutar este ejemplo, necesitas un cluster Elasticsearch 8.x en funcionamiento, <a href="https://www.elastic.co/downloads/elasticsearch">localmente</a> o <a href="https://www.elastic.co/cloud/cloud-trial-overview">Elastic Cloud Hosted</a> (alojado o sin servidor), y acceso a la <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis">API REST</a> o Kibana.</p><p>Imagina una app en la que los usuarios puedan realizar el monitoreo de tiempo de actividad de sus opiniones sobre películas y también hacer una búsqueda de películas para ver. Como los textos son escritos por los propios usuarios, pueden contener errores tipográficos y muchas variaciones en cuanto a la expresión. Por eso es fundamental que el motor de búsqueda sea capaz de interpretar esa diversidad y ofrecer resultados útiles para los usuarios.</p><p>Para poder repetir consultas sin afectar el comportamiento general de búsqueda, el equipo de negocios de tu empresa creó el siguiente conjunto de evaluaciones binarias, basado en las búsquedas más frecuentes:</p><p>Búsqueda</p><p>DocID</p><p>Texto</p><p>Actuación de DiCaprio</p><p>doc1</p><p>La actuación de DiCaprio en El renacido fue impresionante.</p><p>Actuación de DiCaprio</p><p>doc2</p><p>El origen muestra a Leonardo DiCaprio en uno de sus papeles más icónicos.</p><p>Actuación de DiCaprio</p><p>doc3</p><p>Brad Pitt ofrece una actuación estable en este thriller policial.</p><p>Actuación de DiCaprio</p><p>doc4</p><p>Una aventura llena de acción con impresionantes efectos visuales.</p><p>películas tristes que te hacen llorar</p><p>doc5</p><p>Una historia desgarradora de amor y pérdida que me hizo llorar durante horas.</p><p>películas tristes que te hacen llorar</p><p>doc6</p><p>Una de las películas más tristes de todos los tiempos: ¡trae pañuelos!</p><p>películas tristes que te hacen llorar</p><p>doc7</p><p>Una comedia ligera que te hará reír</p><p>películas tristes que te hacen llorar</p><p>doc8</p><p>Una epopeya de ciencia ficción llena de acción y emoción.</p><p>Creación del índice:</p>PUT movies
{
  "mappings": {
    "properties": {
      "text": {
        "type": "text"
      }
    }
  }
}<p>Solicitud en masa:</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>A continuación se muestra la consulta Elasticsearch que emplea la app:</p>GET movies/_search
{
 "query": {
   "match": {
     "text": {
       "query": "DiCaprio performance",
       "minimum_should_match": "100%"
     }
   }
 }
}<h3>De juicio a métricas</h3><p>Por sí solas, las listas de evaluaciones no proporcionan mucha información; son solo una expectativa de los resultados de nuestras consultas. Donde realmente destacan es cuando los usamos para calcular métricas objetivo que midan nuestro rendimiento en búsqueda.</p><p>Actualmente, la mayoría de las métricas populares incluyen</p><ul><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#k-precision"><strong>Precisión</strong></a><strong>: </strong>mide la proporción de resultados que son realmente relevantes dentro de todos los resultados de búsqueda.</p></li><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#k-recall"><strong>Recuperación</strong></a><strong>: </strong>mide la proporción de resultados relevantes que el motor de búsqueda encontró 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>Ganancia acumulada descontada (DCG):</strong></a>mide la calidad de la clasificación del resultado, considerando que los resultados más relevantes deben estar en la parte superior.</p></li><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#_mean_reciprocal_rank"><strong>Rango recíproco medio (MRR):</strong></a> mide la posición del primer resultado relevante. Cuanto más alto estés en la lista, mayor será tu puntuación.</p></li></ul><p>Usando la misma app de clasificación de películas como ejemplo, calcularemos la métrica de recuperación para ver si hay alguna información que se esté excluyendo de nuestras consultas.</p><p>En Elasticsearch, podemos usar las <em>listas de evaluaciones</em> para calcular métricas mediante la <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval">API de Evaluación de Rankings</a>. Esta API recibe como entrada la lista de evaluaciones, la consulta y la métrica que deseas evaluar, y devuelve un valor, que es una comparación del resultado de la consulta con la lista de evaluaciones.</p><p>Vamos a ejecutar la lista de evaluaciones para las dos consultas que tenemos:</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>Usaremos dos solicitudes para _rank_eval: una para la búsqueda de DiCaprio y otra para películas tristes. Cada solicitud incluye una búsqueda y su lista de evaluaciones (calificaciones). No necesitamos calificar todos los documentos ya que los que no se incluyen en las calificaciones se consideran sin evaluación. Para realizar los cálculos, recuerda que la recuperación solo considera “el conjunto relevante”, los documentos que se consideran relevantes en la clasificación.</p><p>En este caso, la búsqueda de DiCaprio tiene una recuperación de 1, mientras que las películas tristes obtuvieron 0. Esto significa que para la primera búsqueda, pudimos obtener todos los resultados relevantes, mientras que en la segunda búsqueda, no obtuvimos ninguno. Por tanto, la recuperación medio es 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>Tal vez estamos siendo demasiado estrictos con el parámetro <strong>minimum_should_match </strong>ya que al exigir que el 100 % de las palabras en la consulta se encuentren en los documentos, probablemente estamos excluyendo resultados relevantes. Eliminemos el parámetro <strong>minimum_should_match</strong> para que un documento se considere relevante si solo se encuentra una palabra de la consulta en él.</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 puedes ver, al eliminar el parámetro <strong>minimum_should_match</strong> en una de las dos consultas, ahora obtenemos una recuperación promedio de 1 en 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>En resumen, al eliminar la cláusula minimum_should_match: 100%, podemos obtener una recuperación perfecta para ambas búsquedas.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltaf4f08a8a2915180/6a170df61949f76cbfe7aaba/24d055da4348c63827ba7046fe8cafb6f47cadd8-546x628.png" alt="" /><p>¡Lo logramos! ¿Cierto?</p><p>¡No tan rápido!</p><p>Al mejorar la memoria, abrimos la puerta a un rango más amplio de resultados. Sin embargo, cada ajuste implica una compensación. Por esto es importante definir casos de prueba completos, utilizando diferentes métricas para evaluar los cambios.</p><p>El uso de listas de evaluaciones y métricas previene que hagas cambios a ciegas, ya que ahora tienes datos para respaldarlos. La validación ya no es manual y repetitiva, y puedes probar tus cambios en más de un caso de uso. Además, las pruebas A/B te permiten probar en tiempo real qué configuración funciona mejor para tus usuarios y tu caso de negocio, cerrando así la brecha entre métricas técnicas y métricas reales.</p><h2>Recomendaciones finales para el uso de listas de evaluaciones</h2><p>Trabajar con listas de evaluaciones no solo consiste en medir, sino también en crear un marco de trabajo que te permita iterar con confianza. Para lograr esto, puedes seguir estas recomendaciones:</p><ol><li><p><strong>Empieza poco a poco, pero empieza</strong>. No es necesario que tengas 10 000 consultas con 50 listas de evaluaciones cada una. Solo necesitas identificar las 5 a 10 consultas más críticas para tu caso de negocio y definir qué documentos esperas ver en la parte superior de los resultados. Esto ya te da una base. Por lo general, te conviene comenzar con las consultas principales y las consultas sin resultados. También puedes comenzar a probar con una métrica fácil de configurar como Precisión y luego ir aumentando la complejidad.</p></li><li><p><strong>Valida con los usuarios.</strong> Complementa los números con pruebas A/B en producción. De esta manera, sabrás si los cambios que se ven bien en las métricas también están generando un impacto real.</p></li><li><p><strong>Haz un mantenimiento de la lista.</strong> Tu caso de negocio evolucionará, y también lo harán tus consultas críticas. Actualiza tu evaluación de forma periódica para reflejar las necesidades nuevas.</p></li><li><p><strong>Haz que sea parte del flujo.</strong> Integra listas de evaluaciones en tus pipelines de desarrollo. Asegúrate de que cada cambio de configuración, sinónimo o análisis de texto se valide automáticamente contra tu lista base.</p></li><li><p><strong>Conecta conocimientos técnicos con estrategia.</strong> No te limites a medir parámetros técnicos como la precisión o la recuperación. Usa tus resultados de la evaluación para influir en los resultados comerciales.</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[Relevancia]]></category>
    <category><![CDATA[Dentro de 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[Búsqueda híbrida sin dolores de cabeza: simplificando la búsqueda híbrida con retrievers]]></title>
    <description><![CDATA[Explora cómo simplificar la búsqueda híbrida en Elasticsearch con un formato de consulta multicampo para retrievers lineales y RRF, y crea consultas sin conocimientos previos sobre tu índice de Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p><a href="https://www.elastic.co/what-is/hybrid-search">La búsqueda híbrida</a> es ampliamente reconocida como un enfoque de búsqueda poderosa, que combina la precisión y rapidez de la <a href="https://www.elastic.co/search-labs/blog/lexical-and-semantic-search-with-elasticsearch#lexical-search---sparse-retrieval">búsqueda léxica</a> con las capacidades de lenguaje natural de <a href="https://www.elastic.co/what-is/semantic-search">la búsqueda semántica</a>. Sin embargo, aplicarlo en la práctica puede ser complicado, ya que a menudo requiere un conocimiento profundo del índice y la construcción de consultas extensas con configuraciones no triviales. En este blog, exploraremos cómo el <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/retrievers#multi-field-query-format">formato de consulta multicampo para retrievers lineales y RRF</a> hace que la búsqueda híbrida sea más sencilla y accesible, eliminando los dolores de cabeza comunes y permitiéndote aprovechar todo su poder con mayor facilidad. También revisaremos cómo el formato de consulta multicampo te permite realizar consultas de búsqueda híbridas sin conocimiento previo de tu índice.</p><h2>El problema del rango de puntaje</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3521a6558cd477ca/6a17f174445de94d3c4d0225/c8b49153c47d2cdc233c0d2e440db04711d48ca5-1600x1600.jpg" alt="" /><p>Para contextualizar, repasemos una de las principales razones por las que la búsqueda híbrida puede ser difícil: los rangos de puntaje variables. Nuestro viejo <a href="https://www.elastic.co/elasticon/conf/2016/sf/improved-text-scoring-with-bm25">amigo BM25</a> produce puntajes ilimitados. En otras palabras, BM25 puede generar puntajes que van desde cerca de 0 hasta (teóricamente) infinitas. En cambio, las consultas contra <code>dense_vector</code> campos producirán puntajes acotados entre 0 y 1. Para empeorar este problema, <code>semantic_text</code> ofusca el tipo de campo empleado para indexar incrustaciones, así que a menos que tengas un conocimiento detallado sobre tu configuración de índices y endpoints de inferencia, puede ser difícil saber cuál será el rango de puntaje de tu consulta. Esto presenta un problema al intentar entrecalar resultados de búsqueda léxica y semántica, ya que los resultados léxicos pueden tener prioridad sobre los semánticos incluso si los resultados semánticos son más relevantes. La solución generalmente aceptada para este problema es normalizar los puntajes antes de entrelazar los resultados. Elasticsearch dispone de dos herramientas para esto: los <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/retrievers/linear-retriever">retrievers lineales</a> y <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="Comparación de resultados de búsqueda con lineales/rrf vs. sin" /><p>El <strong>recuperador RRF</strong> aplica el <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/reciprocal-rank-fusion">algoritmo RRF</a>, usando el rango del documento como medida de relevancia y descartando el puntaje. Como el puntaje no se tiene en cuenta, las discrepancias en el rango de puntaje no son un problema.</p><p>El <strong>retriever lineal</strong> emplea una combinación lineal para determinar el puntaje final de un documento. Esto implica tomar el puntaje de cada consulta componente para el documento, normalizarla y sumarla para generar el puntaje total. Matemáticamente, la operación puede expresar como:</p>Total Score = 𝚺(N(Sx))<p>Donde <code>N</code> es la función de normalización, y SX es el puntaje para la consulta X. La función de normalización es clave aquí, ya que transforma el puntaje de cada consulta para usar el mismo rango. Puedes aprender más sobre el retriever <a href="https://www.elastic.co/search-labs/blog/linear-retriever-hybrid-search">lineal aquí</a>.</p><h2>Desglosándolo</h2><p>Los usuarios pueden implementar una búsqueda híbrida eficaz con estas herramientas, pero requiere cierto conocimiento sobre tu índice. Veamos un ejemplo con el retriever lineal, donde consultaremos un índice con dos 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> es un campo <code>semantic_text</code> que emplea <a href="https://www.elastic.co/docs/explore-analyze/machine-learning/nlp/ml-nlp-e5">E5</a>, un modelo de incrustación de texto</p><p>2. <code>text_field</code> es un campo estándar de <code>text</code></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 una consulta <code>match</code> en nuestro campo <code>semantic_text</code> , para la que <a href="https://www.elastic.co/search-labs/blog/semantic-search-match-knn-sparse-vector#we-made-match-happen-in-semantic-search!">agregamos soporte en Elasticsearch 8.18/9.0</a></p><p>
Al construir la consulta, debemos tener en cuenta que <code>semantic_text_field</code> emplea un modelo de incrustación de texto, por lo que cualquier consulta generará un puntaje entre 0 y 1. También necesitamos saber que <code>text_field</code> es un campo de <code>text</code> estándar y, por tanto, las consultas sobre él generarán un puntaje no acotada. Para crear un conjunto de resultados con la relevancia adecuada, necesitamos usar un retriever que normalice los puntajes de consulta antes de combinarlas. En este ejemplo, usamos el retriever lineal con <code>minmax</code> normalización, que normaliza el puntaje de cada consulta a un valor entre 0 y 1.</p><p>La construcción de la consulta en este ejemplo es bastante sencilla porque solo están involucrados dos campos. Sin embargo, puede complicar muy rápido a medida que se agregan más campos, y de diferentes tipos. Esto demuestra cómo escribir una consulta híbrida eficaz suele requerir un conocimiento más profundo del índice que se consulta, de modo que los puntajes de los componentes se normalicen correctamente antes de la combinación. Esto supone una barrera para la adopción más amplia de la búsqueda híbrida.</p><h3>Agrupación de consultas</h3><p>Ampliemos el ejemplo: ¿Y si quisiéramos consultar un campo <code>text</code> y dos campos <code>semantic_text</code> ? Podríamos construir una consulta así:</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>Eso parece bueno a simple vista, pero hay un posible problema. Ahora los <code>semantic_text</code> partidos de campo representan dos tercios del total del puntaje:</p>Total Score = N(semantic_text_field_1 score) + N(semantic_text_field_2 score) + N(text_field score)<p>Probablemente esto no es lo que buscas porque crea un puntaje desequilibrado. Los efectos pueden no ser tan evidentes en un ejemplo como este con solo 3 campos, pero se vuelve problemático cuando se consultan más campos. Por ejemplo, la mayoría de los índices contienen muchos más cuerpos léxicos que la semántica (es decir, <code>dense_vector</code>, <code>sparse_vector</code>, o <code>semantic_text</code>). ¿Y si consultáramos un índice con 9 campos léxicos y 1 campo semántico usando el patrón anterior? Las coincidencias léxicas representarían el 90% del puntaje, lo que reduce la efectividad de la búsqueda semántica.</p><p>Una forma común de abordar esto es agrupar las consultas en categorías léxicas y semánticas y ponderar ambas de forma uniforme. Esto impide que cualquiera de las dos categorías domine el puntaje total.</p><p>Pongámoslo en práctica. ¿Cómo sería este enfoque de consultas agrupadas en este ejemplo al usar el retriever lineal?</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>¡Vaya, esto se está poniendo muy extenso! ¡Puede que incluso tuviste que desplazarte arriba y abajo varias veces para revisar toda la consulta! Aquí, usamos dos niveles de normalización para crear los grupos de consultas. Matemáticamente, puede expresar como:</p>Total Score = N(N(semantic_text_field_1 score) + N(semantic_text_field_2 score)) + N(text_field score)<p>Este segundo nivel de normalización garantiza que las consultas contra los campos <code>semantic_text</code> y <code>text</code> campo tengan un peso uniforme. Ten en cuenta que en este ejemplo omitimos la normalización de segundo nivel para <code>text_field</code> ya que solo hay un cuerpo léxico, lo que te ahorra <em>aún más</em> verbosidad.</p><p>Esta estructura de consulta ya es engorrosa y solo estamos consultando tres campos. Se vuelve cada vez más inmanejable, incluso para los profesionales experimentados en búsqueda, a medida que consultas más campos.</p><h2>El formato de consulta multicampo</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5d9007d279f0da29/6a17f17714d90c39cf79b6f5/dd04e1686076a574b717c1460acfe4eb79299208-1600x1600.jpg" alt="" /><p>Agregamos el <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/retrievers#multi-field-query-format">formato de consulta multicampo</a> para los retrievers lineales y RRF en Elasticsearch 8.19, 9.1 y <a href="https://www.elastic.co/cloud/serverless">serverless</a> para simplificar todo esto. Ahora puedes realizar la misma consulta que antes con simplemente:</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "fields": [ "semantic_text_field_1", "semantic_text_field_2", "text_field" ],
      "query": "foo",
      "normalizer": "minmax"
    }
  }
}<p>¡Lo que reduce la consulta de 55 líneas a solo 9! Elasticsearch emplea automáticamente los mapeos de índice para:</p><ul><li><p>Determinar el tipo de cada campo consultado</p></li><li><p>Agrupa cada cuerpo en una categoría léxica o semántica</p></li><li><p>Pondera cada categoría de forma equitativa en el puntaje final</p></li></ul><p>Esto permite a cualquiera ejecutar una consulta híbrida eficaz sin necesidad de conocer detalles sobre el índice o los endpoints de inferencia empleados.</p><p>Al usar RRF, puedes omitir la <code>normalizer</code>, ya que rango se usa como indicador de relevancia:</p>GET rrf_retriever_example/_search
{
  "retriever": {
    "rrf": {
      "fields": [ "semantic_text_field_1", "semantic_text_field_2", "text_field" ],
      "query": "foo"
    }
  }
}<h2>Impulso por campo</h2><p>Al usar el retriever lineal, puedes aplicar un aumento por campo para ajustar la importancia de los combates en ciertos campos. Por ejemplo, supongamos que consultas cuatro campos: dos campos <code>semantic_text</code> y dos 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 defecto, cada cuerpo tiene un peso igual en su grupo (léxico o semántico). El desglose del puntaje es el siguiente:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdc6e197e5ff7b68d/6a17f179505ac32834ad8c46/ba31c76189e3a1e5b1638437ccf0528aafec2598-1600x549.png" alt="Comparación de grupos de consulta y puntajes de campo" /><p>En otras palabras, cada campo representa el 25% del puntaje total.</p><p>Podemos usar la sintaxis <code>field^boost</code> para agregar un impulso por campo a cualquier campo. Vamos a aplicar un aumento de 2 a <code>semantic_text_field_1</code> y <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>Ahora el desglose del puntaje es así:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltccc9ed7d6e865a5e/6a17f17abe6086a31d004882/de20e555d52f914bf483a048d056f54f4fece757-1600x549.png" alt="Cambio en el peso del campo con referencia y búsqueda híbrida" /><p>Cada grupo de consulta sigue teniendo un peso igual, pero ahora el peso del campo dentro de los grupos cambió:</p><ul><li><p><code>semantic_text_field_1</code> es el 66% del puntaje del grupo de consultas semánticas, 33% del puntaje total</p></li><li><p><code>text_field_1</code> es el 66% del puntaje del grupo de consultas léxicas, 33% del puntaje total</p></li></ul><p>i️ Ten en cuenta que el rango total de puntaje no cambiará cuando se aplica un aumento por campo. Este es un efecto secundario previsto de la normalización de puntajes, que garantiza que los puntajes de consulta léxica y semántica sigan siendo directamente comparables entre sí.</p><p>i️ El aumento por campo también puede usar con el recuperador RRF en Elasticsearch 9.2+</p><h3>Resolución comodín</h3><p>Puedes usar el comodín <code>*</code> en el parámetro <code>fields</code> para que coincida con varios campos. Continuando con el ejemplo anterior, esta consulta es funcionalmente equivalente a consultar s<code>emantic_text_field_1</code>, <code>semantic_text_field_2</code>, y <code>text_field_1</code> explícitamente:</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "fields": [ "semantic_text_field_*", "*_field_1" ],
      "query": "foo",
      "normalizer": "minmax"
    }
  }
}<p>Es interesante notar que el patrón de <code>*_field_1</code> coincide tanto con <code>text_field_1</code> como con <code>semantic_text_field_1</code>. Esto se gestiona automáticamente; La consulta se ejecutará como si cada uno de los campos fuera consultado explícitamente. También está bien que el <code>semantic_text_field_1</code> coincida con ambos patrones; Todas las coincidencias de nombres de campo se deduplican antes de la ejecución de la consulta.</p><p>Puedes usar el comodín de varias maneras:</p><ul><li><p>Coincidencia de prefijos (ej: <code>*_text_field</code>)</p></li><li><p>Emparejamiento en línea (ej: <code>semantic_*_field</code>)</p></li><li><p>Coincidencia de sufijos (ej: <code>semantic_text_field_*</code>)</p></li></ul><p>También puedes usar varios comodines para aplicar una combinación de lo anterior, como <code>*_text_field_*</code>.</p><h3>Campos de consulta predeterminados</h3><p>El formato de consulta multicampo también te permite consultar un índice del que no sabes nada. Si omites el parámetro <code>fields</code> , consultará todos los campos especificados por la <a href="https://www.elastic.co/docs/reference/elasticsearch/index-settings/index-modules">configuración de índice index.query.default_field</a>:</p>GET linear_retriever_example/_search
{
  "retriever": {
    "linear": {
      "query": "foo",
      "normalizer": "minmax"
    }
  }
}<p>Por defecto, <code>index.query.default_field</code> está configurado como <code>*</code>. Este comodín se resolverá a todos los tipos de campo del índice que admitan consultas de término, que es la mayoría. Las excepciones son:</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>Esta funcionalidad es especialmente útil cuando se quiere realizar una consulta de búsqueda híbrida sobre un índice proporcionado por un tercero. El formato de consulta multicampo permite ejecutar una consulta adecuada de forma sencilla. Simplemente excluye el parámetro <code>fields</code> y se consultarán todos los campos aplicables.</p><h2>Conclusión</h2><p>El problema del rango de puntaje puede hacer que la búsqueda híbrida efectiva sea un dolor de cabeza de implementar, especialmente cuando hay poca comprensión del índice que se consulta o de los endpoints de inferencia empleados. El formato de consulta multicampo para los retrievers lineales y RRF alivia este problema al empaquetar un enfoque automatizado de búsqueda híbrida basado en agrupación de consultas en una API simple y accesible. Funcionalidades adicionales, como el aumento por campo, la resolución de comodines y los campos de consulta por defecto, amplían la funcionalidad para cubrir muchos casos de uso.</p><h2>Prueba hoy el formato de consulta multicampo</h2><p>Puedes consultar los retrievers lineales y RRF con el formato de consulta multicampo en proyectos <a href="https://www.elastic.co/cloud/serverless">Serverless</a> totalmente gestionados de Elasticsearch con <a href="https://www.elastic.co/docs/deploy-manage/deploy/elastic-cloud/create-serverless-project">una prueba gratis</a>. También está disponible en versiones de pila a partir de la 8.19 y 9.1.</p><p>Empieza en minutos en tu entorno local con un solo 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[Búsqueda híbrida]]></category>
    <category><![CDATA[Relevancia]]></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[Para contexto, Parte I: La evolución de la búsqueda híbrida y la ingeniería del contexto]]></title>
    <description><![CDATA[Explora cómo la búsqueda híbrida y la ingeniería contextual evolucionaron desde fundamentos léxicos hasta permitir la próxima generación de flujos de trabajo de IA agente.]]></description>
    <content:encoded><![CDATA[<h2>Nuestro nuevo mundo de IA agente</h2><p>Como muchos de nosotros, me siento a la vez eufórico y asombrado por el ritmo al que evolucionan las capacidades de la IA. Primero vimos cómo los grandes modelos de lenguaje (LLMs) y la búsqueda vectorial nos lanzaron a la revolución semántica, donde ya no buscábamos ni explorábamos palabras clave para encontrar cosas. Después, los LLMs nos mostraron nuevas formas de interactuar con nuestros datos, usando interfaces de chat para transformar solicitudes en lenguaje natural en respuestas que destilan vastas bases de conocimiento en resúmenes fáciles de consumir. Ya sabemos (¡ya!) tienen los inicios de la lógica automatizada impulsada por LLM en forma de flujos de trabajo de "IA agente" que pueden entender semánticamente una petición entrante, razonar los pasos a seguir y luego elegir entre las herramientas disponibles para ejecutar iterativamente acciones y alcanzar esos objetivos.</p><p>La promesa de la IA agente nos está obligando a evolucionar desde el uso principal de 'ingeniería de prompts' para moldear nuestras interacciones generativas con IA, hasta centrarnos en cómo podemos ayudar a las herramientas agenticas a obtener la información adicional más relevante y eficiente que el LLM debe tener en cuenta al generar sus respuestas — la 'ingeniería de contexto' es la próxima frontera. La búsqueda híbrida es, con diferencia, el medio más poderoso y flexible para sacar a la luz el contexto relevante, y la plataforma de Search AI de Elastic abre una nueva vía para aprovechar los datos en servicio de la ingeniería contextual. En este artículo, vamos a hablar de cómo los LLM cambiaron el mundo de la recuperación de información desde dos ángulos, y luego de cómo pueden trabajar juntos para obtener mejores resultados. Hay bastante terreno que cubrir...</p><h2>Parte I: Cómo cambiaron los LLM la búsqueda</h2><p>Empecemos desde el ángulo de cómo los LLM cambiaron la forma en que accedemos y recuperamos información.</p><h3>Nuestro legado léxico</h3><p>Todos vivimos en el mundo de la búsqueda léxica algo limitado (bastante bien, en la medida de lo posible) durante mucho tiempo. La búsqueda es la primera herramienta a la que recurrimos cuando investigamos o empezamos un nuevo proyecto, y hasta hace poco, nos correspondía formular nuestras consultas de una manera que un motor de búsqueda léxico comprenda. La búsqueda léxica se basa en asociar algún tipo de término de consulta con palabras clave que se encuentran en un corpus documental — independientemente de si el contenido es no estructurado o no estructurado. Para que una búsqueda léxica devuelva un documento como resultado, debe coincidir con esa palabra clave (o tener un vocabulario controlado como una lista de sinónimos o diccionario para establecer la conexión conceptual para nosotros).</p>POST my-index/_search
{
  "size": 10,
  "query": {
    "semantic": {
      "query": "machine learning applications",
      "field": "semantic-content-field"
    }
  }
}<p><em>Un ejemplo de consulta léxica </em><a href="https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-multi-match-query"><em>multi-match</em></a></p><p>Al menos los motores de búsqueda tienen la capacidad de devolver resultados con un puntaje de relevancia. Los motores de búsqueda ofrecen una gran variedad de opciones de sintaxis de consulta para dirigir eficazmente los datos indexados y algoritmos de relevancia incorporados que puntuan los resultados en función de la intención de la sintaxis de consulta del usuario. Los motores de búsqueda se benefician de décadas de avances en algoritmos de clasificación de relevancia, y eso los convierte en una plataforma eficiente de recuperación de datos capaz de ofrecer resultados puntuados y ordenados según su relevancia para la consulta. Las bases de datos y otros sistemas que emplean SQL como su método principal para recuperar datos están en desventaja aquí: no existe un concepto de relevancia en una consulta de base de datos; Lo mejor que pueden hacer es ordenar los resultados alfabéticamente o numéricamente. La buena noticia es que obtendrás todos los resultados (recordación) con esas palabras clave, pero no necesariamente están en un orden útil respecto <em>al motivo por el</em> que las pediste (precisión). Es un punto importante, como veremos en breve...</p><h3>Entra en escena el dragón (semántico)</h3><p>El potencial de las representaciones vectoriales de la información como alternativa a la búsqueda por palabras clave se investigó durante <a href="https://www.elastic.co/search-labs/blog/introduction-to-vector-search">bastante tiempo</a>. Los vectores tienen mucho potencial porque nos sacan del modo de emparejamiento de contenido basado solo en palabras clave — al ser representaciones numéricas de términos y pesos, los vectores permiten que los conceptos sean matemáticamente cercanos según la comprensión que tiene un modelo de lenguaje sobre cómo se relacionan los términos entre sí en el ámbito de entrenamiento. El largo retraso en la búsqueda vectorial de propósito general se debió a que los modelos estaban mayormente limitados a dominios específicos, simplemente no eran lo suficientemente grandes para comprender suficientemente los muchos conceptos diferentes que un término podría representar en distintos contextos.</p><p>No fue hasta que los Grandes Modelos de Lenguaje (LLMs) aparecieron hace unos años, con su capacidad de capacitar con cantidades mucho mayores de datos (usando <a href="https://en.wikipedia.org/wiki/Transformer_(deep_learning_architecture)">transformadores</a> y <a href="https://en.wikipedia.org/wiki/Attention_(machine_learning)">atención</a>), que la búsqueda vectorial se volvió práctica: el tamaño y la profundidad de los LLMs finalmente permitieron que los vectores almacenaran suficiente matiz para captar realmente el significado semántico. Ese aumento repentino en la profundidad de comprensión permitió que los LLMs ahora sirvieran a un gran número de funciones de procesamiento del lenguaje natural (PLN) que antes estaban bloqueadas, siendo quizás la más impactante la capacidad de inferir el siguiente término más probable de una secuencia dado el contexto de lo que hay en la secuencia hasta ese momento. La inferencia es el proceso que otorga a la IA generativa su capacidad casi humana para producir texto. El texto generado por IA se basa en la comprensión que tiene el LLM sobre cómo se relacionan los términos dentro de sus datos de entrenamiento y también emplea la redacción de la petición para desambiguar entre diferentes contextos en los que los términos pueden aparecer.</p><p>Por mágica que sea la IA generativa <em>, existen</em> limitaciones en los LLM que causan errores de calidad y precisión, comúnmente llamados alucinaciones. Las alucinaciones ocurren cuando el LLM no tiene acceso a la información (o no es guiado al contexto correcto) para basar su respuesta en la verdad, por lo que, siendo útil, generará en su lugar una respuesta segura y plausible que es inventada. Parte de la causa es que, aunque los LLMs aprenden el uso del lenguaje dentro de grandes dominios de información diversa, tienen que dejar de capacitar en un momento determinado, por lo que su comprensión tiene un factor de puntualidad — es decir, que el modelo solo puede saber qué era preciso hasta el momento en que dejó de capacitar. Otro factor para las alucinaciones es que el modelo normalmente no conoce datos privados (datos no disponibles en Internet público), y eso es especialmente significativo cuando esos datos contienen términos y nomenclatura específicos.</p><h3>Bases de datos vectoriales</h3><p>Los LLM vectorizan el contenido a su espacio de modelo empleando una técnica llamada incrustación de texto, que se refiere a <a href="https://www.elastic.co/search-labs/blog/hybrid-search-multiple-embeddings">incrustar</a> o mapear el significado semántico del contenido dentro de la visión del mundo del modelo en función del entrenamiento recibido. Hay varios pasos para preparar y procesar contenido para incrustar, incluyendo <a href="https://www.elastic.co/search-labs/blog/chunking-strategies-elasticsearch">el chunking</a> y la tokenización (y <a href="https://www.kaggle.com/code/danishmahdi/subword-tokenization-bpe-wordpiece-and-unigram">tokenización de subpalabras</a>). El resultado suele ser un conjunto de vectores densos que representan la comprensión del modelo sobre el significado de ese fragmento de contenido dentro de su espacio vectorial. El chunking es un proceso inexacto que pretende encajar el contenido en las limitaciones de las restricciones de procesamiento de un modelo para generar incrustaciones, mientras intenta agrupar texto relacionado en un bloque usando construcciones semánticas como indicadores de oraciones y párrafos.</p><p>La necesidad de hacer chunks puede crear cierta flexibilidad semántica en un documento incrustado porque los chunks individuales no están completamente asociados con otros chunks del mismo documento. La opacidad inherente de las redes neuronales puede empeorar esta flexibilidad: un LLM es realmente una "caja negra" donde las conexiones entre términos y conceptos establecidas durante el entrenamiento no son deterministas y no pueden interpretar para los humanos. Esto genera problemas de explicabilidad, repetibilidad, sesgos inconscientes y, potencialmente, pérdida de confianza y precisión. Aun así, la capacidad de conectar ideas semánticamente, sin estar atado a palabras clave específicas al enviar consultas, es extremadamente poderosa:</p>POST my-index/_search 
{
  "size": 10, 
  "query": {
    "semantic": {
      "query": "machine learning applications",
      "field": "semantic-content-field"
    }
  }
} <p><em>Un ejemplo </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>Hay un aspecto más a considerar para las bases de datos vectoriales: ¡no son motores de búsqueda, son bases de datos! Cuando se realiza una <a href="https://www.elastic.co/search-labs/blog/introduction-to-vector-search">búsqueda de similitud vectorial</a> , los términos de consulta se codifican para encontrar un conjunto de coordenadas (incrustadas) dentro del espacio vectorial del modelo. Esas coordenadas se emplean entonces como el centro para encontrar los documentos que son los "vecinos más cercanos" al centro — es decir, el rango (o la posición en los resultados) de un documento se determina por la <em>distancia</em> de similitud calculada de las coordenadas de ese documento respecto a las coordenadas de la consulta. ¿En qué dirección debe prevalecer el ranking, cuál de los posibles contextos está más cerca de la intención del usuario? La imagen con la que la comparo es una escena de la película <a href="https://www.youtube.com/watch?v=x3h7xz558EY&amp;start=3&amp;end=86">Stargate</a>, donde tenemos los seis puntos de coordenada que se cruzan para indicarnos el destino (el centro), pero no podemos llegar sin conocer el "séptimo símbolo" — las coordenadas del punto de partida que representan la intención subjetiva del usuario. Así que, en lugar de que la clasificación relativa de los vectores se base en una esfera de similitud en constante expansión e indiferenciada, al considerar la intención subjetiva de la consulta mediante la sintaxis expresiva y el puntaje de relevancia, podemos obtener algo que se asemeje a un <em>cilindro</em> de relevancia subjetiva graduada.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb49ae330d3de1fc1/6a17053ee8fbce089639fb46/1ddfaae0c1496d08d7d30419e6d2aeaeacfc0ea2-1600x544.png" alt="Un cilindro de relevancia subjetiva graduada." /><p>Las capacidades de inferencia de un LLM podrían ayudar a identificar el contexto más probable <em>que tiene</em> para la consulta, pero el problema es que <em>sin ayuda,</em> las coordenadas de la consulta entrante <em>solo</em> pueden determinar por cómo se capacitó originalmente el modelo.</p><p>En cierto modo, se podría decir que la similitud vectorial va al extremo opuesto a una coincidencia estricta de palabras clave — su fortaleza radica en su capacidad para superar los problemas de desajuste de términos, pero <a href="https://medium.com/data-science/vector-embeddings-are-lossy-heres-what-to-do-about-it-4f9a8ee58bb7">casi en exceso</a>: los LLM tienden a unificar conceptos relacionados en lugar de diferenciarlos. La similitud vectorial mejora nuestra capacidad para emparejar contenido semánticamente, pero no garantiza precisión porque puede pasar por alto palabras clave exactas y detalles específicos que el modelo no desambiguó lo suficiente. La búsqueda por similitud vectorial es poderosa en sí misma, pero necesitamos formas de correlacionar los resultados que recuperamos de una base de datos vectorial con los resultados de otros métodos de recuperación.</p><h3>Técnicas de reclasificación</h3><p>Ahora es un buen momento para mencionar una técnica general llamada reclasificación, que vuelve a puntuar o normalizar conjuntos de resultados a un orden de rangos unificado. La necesidad de reclasificar podría deber a que los resultados de múltiples fuentes o métodos de recuperación tengan mecanismos de clasificación/puntaje diferentes (¡o ninguno, SQL!), o bien se podría usar la reclasificación para alinear semánticamente los resultados de fuentes no semánticas con la consulta del usuario. La reclasificación es una operación de segunda etapa, es decir, un conjunto de resultados que fueron recogidos mediante algún método <em>inicial de recuperación</em> (es decir, SQL, búsqueda léxica, búsqueda vectorial) se reordenan con un método de puntaje diferente.</p><p>Existen varios enfoques disponibles, incluyendo <a href="https://www.elastic.co/docs/solutions/search/ranking/learning-to-rank-ltr">Learning-To-Rank (LTR)</a> y <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/reciprocal-rank-fusion">Reciprocal Rank Fusion (RRF)</a> — LTR es útil para capturar características de los resultados de búsqueda (me gusta, valoraciones, clics, etc.) y usarlas para puntuar y potenciar o sesgar resultados. RRF es perfecto para fusionar resultados retornados de diferentes modalidades de consulta (por ejemplo, búsquedas en bases de datos léxicas y vectoriales) juntas en una única lista de resultados. Elastic también ofrece la flexibilidad de ajustar los puntajes mediante métodos <a href="https://www.elastic.co/search-labs/blog/linear-retriever-hybrid-search">de reclasificación lineal</a> .</p><p>Sin embargo, una de las técnicas de reclasificación más efectivas es la <a href="https://www.elastic.co/docs/solutions/search/ranking/semantic-reranking">reclasificación semántica</a>, que emplea la comprensión semántica de un LLM para analizar las incrustaciones vectoriales tanto de la consulta como de los resultados juntos, y luego aplicar el puntaje/repuntuación de relevancia para determinar el orden final. El reranking semántico requiere, por supuesto, una conexión a un modelo de reclasificación, y Elasticsearch proporciona una <a href="https://www.elastic.co/docs/api/doc/elasticsearch/group/endpoint-inference">API de inferencia</a> que permite crear endpoints <strong>de reclasificación</strong> que aprovechan modelos integrados (<a href="https://www.elastic.co/docs/explore-analyze/machine-learning/nlp/ml-nlp-rerank">Elastic Rerank</a>), modelos <a href="https://www.elastic.co/docs/reference/elasticsearch/clients/eland/machine-learning">importados</a> de terceros o servicios alojados externamente como <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-cohere">Cohere</a> o <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-googlevertexai">Google Vertex AI</a>. Luego puedes realizar un reordenamiento mediante la sintaxis de abstracción <a href="https://www.elastic.co/docs/solutions/search/retrievers-overview">de la consulta del retriever</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>Un ejemplo de operación de reclasificación de recuperadores en varias etapas</em></p><p>Suena genial, ¿verdad? Podemos realizar reclasificaciones con resultados de fuentes dispares y acercarnos a una comprensión semántica de todo tipo de contenido... La reclasificación semántica puede ser costosa tanto computacionalmente como en el tiempo de procesamiento requerido, y por ello, la reclasificación semántica solo puede hacer con un número limitado de resultados, lo que significa <em>que la forma</em> en que se recuperan esos resultados iniciales es importante.</p><h3>El método de recuperación del contexto es importante</h3><p>La intención subjetiva es un factor importante para determinar la precisión de un resultado y para valorar su relevancia. Sin la capacidad de considerar la intención del usuario para realizar la consulta (expresada mediante sintaxis flexible, o mediante reclasificación en la segunda etapa), solo podemos seleccionar de los contextos existentes ya codificados dentro del espacio del modelo. La forma en que normalmente abordamos esta falta de contexto es mediante técnicas como <a href="https://en.wikipedia.org/wiki/Retrieval-augmented_generation">la Generación de Aumentos por Recuperación (RAG).</a> El funcionamiento de RAG es que desplaza efectivamente las coordenadas de la consulta al incluir términos relacionados adicionales devueltos de una consulta previa para datos contextualmente relevantes. ¡Eso hace que el motor que proporciona ese contexto adicional y <em>su</em> método inicial para realizar la recuperación sean aún más importantes para la precisión del contexto!</p><p>Repasemos los diferentes métodos de recuperación de contexto y cómo pueden ayudar o perjudicar a una operación RAG:</p><ul><li><p><strong>La recuperación de búsqueda híbrida sin motor de búsqueda sigue careciendo de relevancia subjetiva.</strong> Si la plataforma que proporciona RAG es principalmente SQL (lo que incluye la mayoría de las plataformas "data lake"), carece de puntaje de relevancia en la fase inicial de recuperación. Muchas plataformas de data lake ofrecen su propia versión de recuperación híbrida (no de búsqueda), normalmente combinando técnicas de reclasificación como la reclasificación semántica y la RRF en sus resultados de recuperación basada en SQL y bases de datos vectoriales. Un ordenamiento simple es obviamente insuficiente para la clasificación subjetiva, pero incluso cuando se usa como base para una operación de reclasificación semántica de segunda etapa, SQL como recuperación de primera etapa se convierte en un problema cuando el reclasificación semántica se realiza solo en los "k primeros resultados" — sin alguna forma de puntuar resultados en la recuperación, ¿qué garantía tenemos de que los <em>mejores</em> resultados estén realmente en los primeros resultados?</p></li><li><p><strong>La similitud vectorial por sí sola no es suficiente para RAGs</strong>. Realmente se debe a un conjunto de problemas que se acumulan: es la rapidez del embedding, junto con métodos ingenuos de fragmentación, cómo se calcula la similitud y el componente crucial que falta de la intención subjetiva. Uno de los principales objetivos de RAG es fundamentar las interacciones generativas de IA en la verdad objetiva, tanto para prevenir alucinaciones como para informar al LLM sobre la información privada que no conocía durante el entrenamiento. Podemos emplear el contexto adicional proporcionado por RAG para restringir y dirigir a los LLMs a considerar las conexiones y detalles que sabemos que son más importantes para responder a la pregunta que nos planteamos. Para ello, necesitamos usar <em>tanto</em> enfoques semánticos como léxicos.</p></li><li><p><strong>RAG grep/regex basado en archivos.</strong> Hay algunos <a href="https://www.nicolasbustamante.com/p/the-rag-obituary-killed-by-agents">sectores</a> del universo de IA agente que apuntan al uso de ventanas de contexto enormemente ampliadas que acceden a archivos locales mediante grep y regex para RAG en lugar de plataformas externas de recuperación. La idea es que, con una ventana de contexto mucho más amplia disponible, los LLMs podrán establecer conexiones conceptuales dentro de su propio espacio de pensamiento en lugar de depender de fragmentos y múltiples métodos/plataformas de recuperación para recopilar información relevante. Aunque en teoría es cierto que tener un documento completo ofrece una imagen más completa que los segmentos del documento, esto solo puede funcionar en pequeños dominios de datos (o, por ejemplo, al suministrar archivos para <a href="https://en.wikipedia.org/wiki/Vibe_coding">vibecoding</a>), y aun así, el método inicial de recuperación es un escaneo de todos los documentos con una coincidencia solo por palabra clave.</p></li></ul><p><strong>La búsqueda es más que una recuperación</strong></p><p>Los motores de búsqueda están diseñados específicamente para hacer que las consultas sean lo más rápidas y flexibles posible. Internamente, emplean estructuras de datos especializadas para almacenar y recuperar diferentes tipos de datos de manera que se adapten a esos tipos de datos. Elasticsearch proporciona almacenamiento y consulta optimizados de prácticamente todo tipo de datos, incluyendo búsqueda léxica no estructurada/texto completo (coincidencia, frase, proximidad, multi-coincidencia), coincidencia y filtrado rápido de palabras clave (coincidencia exacta), rangos numéricos, fechas, direcciones IP, y es muy flexible en cómo almacena las estructuras de documentos (por ejemplo, Docs anidados o aplanados). Elasticsearch es también una base de datos vectorial nativa que puede almacenar y consultar tanto tipos vectoriales dispersos como densos, y seguimos explorando formas innovadoras (por ejemplo, <a href="https://www.elastic.co/search-labs/blog/better-binary-quantization-lucene-elasticsearch">Better Binary Quantization (BBQ)</a> y <a href="https://www.elastic.co/search-labs/blog/diskbbq-elasticsearch-introduction">DiskBBQ</a>) para mantener la fidelidad de búsqueda mientras mejoramos la velocidad, escalabilidad y costos asociados al contenido vectorizado. La plataforma Elasticsearch también proporciona resiliencia y alta disponibilidad de datos integradas, e incluye capacidades de gestión del ciclo de vida de los datos como <a href="https://www.elastic.co/docs/deploy-manage/tools/snapshot-and-restore/searchable-snapshots">Searchable Snapshots</a> que permiten mantener datos de poca frecuencia o de retención a largo plazo en un almacenamiento de objetos rentable, pero aún totalmente buscables.</p><h3>La búsqueda híbrida es lo mejor de todos los mundos</h3><p><a href="https://www.elastic.co/what-is/hybrid-search">Búsqueda híbrida</a> (¡no solo recuperación híbrida!) combina las fortalezas de la búsqueda léxica tradicional con la comprensión semántica de los LLMs y la búsqueda por similitud vectorial. Esta sinergia permite dirigir resultados altamente relevantes en la fase <em>de recuperación</em> mediante cualquiera de las opciones flexibles de sintaxis de consulta que ofrece un motor de búsqueda: opciones de sintaxis impulsadas por intención y puntaje de relevancia, recuperación de datos multimodales, filtrado, agregaciones y sesgos. Con sintaxis de búsqueda como <a href="https://www.elastic.co/docs/reference/query-languages/esql">ES|QL</a> y <a href="https://www.elastic.co/docs/solutions/search/retrievers-overview">recuperadores</a> de varias etapas, podemos combinar de forma flexible la búsqueda tradicional con búsqueda semántica, filtros y múltiples técnicas de reclasificación, todo en una sola petición.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6ee9512910856ee3/6a17053fcdacbf2ea97d291e/f25180cb430414b99ae553d3b8eb161dbccea4d4-1920x1080.png" alt="Cómo funciona la búsqueda híbrida" /><p>Uno de los mayores beneficios de la búsqueda híbrida es que tus consultas pueden usar sintaxis especializada para múltiples tipos de datos diferentes simultáneamente. Esas diferentes sintaxis de consulta pueden usar no solo para <em>encontrar</em> resultados, sino también como filtros o agregaciones <em>en</em> los resultados. Por ejemplo, uno de los tipos de consulta más comunes que frecuentemente se combina con otra sintaxis es el <a href="https://www.elastic.co/docs/explore-analyze/geospatial-analysis">análisis geoespacial</a>. Puedes hacer cosas como consultar resultados que tengan coordenadas geográficas dentro de una distancia especificada de un punto, o aplicar agregaciones de tus resultados por región, o agregaciones para rastrear y alertar sobre movimientos dentro o fuera de una zona. Con la búsqueda híbrida tienes la flexibilidad de combinar sintaxis para dirigir los resultados de la manera más precisa, para recuperar el contenido más cercano a tu contexto.</p><h2>Entreacto</h2><p>Esta primera parte cuenta la historia de cómo la búsqueda vectorial cambió la forma en que podemos recuperar datos y sienta el terreno para los cambios que los LLMs trajeron a los mecanismos de consulta que empleamos para interactuar con los datos. Vamos a fingir que tuvimos que descomponer esto en varias partes para que los LLM pudieran entenderlo sin perder el contexto... ;-) Aprendamos más <em>sobre por qué esto es importante</em> en <a href="https://www.elastic.co/search-labs/blog/context-engineering-llm-evolution-agentic-ai">la Parte II: IA Agente y la necesidad de ingeniería de contexto</a>, y en la Parte III volveremos a nuestra discusión sobre la búsqueda 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[Búsqueda híbrida]]></category>
    <category><![CDATA[Relevancia]]></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[Búsqueda híbrida revisitada: ¡presentando el retriever lineal en Elasticsearch!]]></title>
    <description><![CDATA[Descubre cómo el retriever lineal mejora la búsqueda híbrida aprovechando puntajes ponderados y la normalización MinMax para clasificaciones más precisas y consistentes, y aprende a usarlo.]]></description>
    <content:encoded><![CDATA[<p>En nuestra publicación <a href="https://www.elastic.co/es/search-labs/blog/elasticsearch-retrievers-ga-8.16.0">de blog anterior</a> , presentamos el marco de recuperadores rediseñado desde cero, que permite la creación de canalizaciones de clasificación complejas. También exploramos cómo el recuperador Reciprocal Rank Fusion (RRF) permite la búsqueda híbrida al fusionar resultados de diferentes consultas. Si bien RRF es fácil de implementar, tiene una limitación notable: se enfoca puramente en rangos relativos, ignorando los puntajes reales. Esto hace que el ajuste y la optimización sean un desafío.</p><h2>¡Conoce al retriever lineal!</h2><p>En esta publicación, presentamos el <a href="https://www.elastic.co/es/docs/solutions/search/retrievers-overview#retrievers-overview-types"> linear</a> retriever, ¡nuestra última incorporación para apoyar la búsqueda híbrida! A diferencia de <code>rrf</code>, el recuperador de <code>linear</code> calcula una suma ponderada en todas las consultas que coinciden con un documento. Este enfoque conserva la importancia relativa de cada documento dentro de un conjunto de resultados al tiempo que permite un control preciso sobre la influencia de cada consulta en el puntaje final. Como resultado, proporciona una forma más intuitiva y flexible de ajustar la búsqueda híbrida.</p><p>Definición de un recuperador lineal donde el puntaje final se calculará como:</p><p>Es tan simple como:</p>GET linear_retriever_blog/_search
{
   "retriever": {
       "linear": {
           "retrievers": [
               {
                   "retriever": {
                       "knn": {
                          ...
                        }
                    },
                   "weight": 5
               },
                  {
                   "retriever": {
                       "standard": {
                          ...
                        }
                    },
                   "weight": 1.5
               },


           ]
        }
     }
}<p>¿Notas lo simple e intuitivo que es? (¡y muy similar a <code>rrf</code>!) Esta configuración le permite controlar con precisión cuánto contribuye cada tipo de consulta a la clasificación final, a diferencia de <code>rrf</code>, que se basa únicamente en clasificaciones relativas.</p><p>Queda una advertencia: <code>knn</code> puntajes pueden estar estrictamente limitados, dependiendo de la métrica de similitud empleada. Por ejemplo, con la similitud del coseno o el producto punto de los vectores estandarizados por unidades, los puntajes siempre estarán dentro del rango <code>[0, 1]</code> . Por el contrario, <code>bm25</code> puntajes son menos previsibles y no tienen límites claramente definidos.</p><h2>Escalando los puntajes: kNN vs BM25</h2><p>Un desafío de la búsqueda híbrida es que diferentes recuperadores producen puntajes en diferentes escalas. Considere, por ejemplo, el siguiente escenario:</p><p>Puntajes de la 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>Puntajes de la 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>Puede ver la disparidad arriba: <code>kNN</code> puntajes oscilan entre 0 y 1, mientras que <code>bm25</code> puntajes pueden variar enormemente. Esta diferencia hace que sea difícil establecer pesos óptimos estáticos para combinar los resultados.</p><h2>Normalización al rescate: el normalizador MinMax</h2><p>Para solucionar esto, introdujimos un normalizador de <code>minmax</code> opcional que escala los puntajes, de forma independiente para cada consulta, al rango de <code>[0, 1]</code> mediante la siguiente fórmula:</p><p>Esto conserva la importancia relativa de cada documento dentro del conjunto de resultados de una consulta, lo que facilita la combinación de puntajes de diferentes recuperadores. Con la normalización, los puntajes se convierten en:</p><p>Puntajes de la 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>Puntajes de la 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>Todos los puntajes ahora se encuentran en el rango de <code>[0, 1]</code> y optimizar la suma ponderada es mucho más sencillo, ya que ahora capturamos la importancia (relativa a la consulta) de un resultado en lugar de su puntaje absoluto y mantenemos la coherencia entre las consultas.</p><h2>Ejemplo de recuperador lineal </h2><p>Veamos un ejemplo ahora para mostrar cómo se ve lo anterior y cómo el <code>linear</code> retriever aborda algunas de las deficiencias de <code>rrf</code>. RRF se basa únicamente en rangos relativos y no considera las diferencias de puntaje reales. Por ejemplo, dadas estos puntajes:</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>puntaje de la fuerza de avance</p><p>0.03226</p><p>0.03252</p><p>0.03200</p><p>0.03125</p><p>RRF clasificaría los documentos como:</p><p>Sin embargo, doc1 tiene un puntaje de <code>bm25</code> significativamente más alta que los demás, que <code>rrf</code> no logra capturar porque solo analiza los rangos relativos. El recuperador de <code>linear</code> , combinado con la normalización, explica correctamente tanto los puntajes como sus diferencias, produciendo una clasificación más 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 en lo anterior, la gran clasificación y <code>score</code> de doc1 para <code>bm25</code> se contabiliza adecuadamente y se refleja en los puntajes finales. Además de eso, todos los puntajes se encuentran ahora en el rango <code>[0, 1]</code> para que podamos compararlas y combinarlas de una manera mucho más intuitiva (e incluso construir procesos de optimización offline).</p><h2>Poniéndolo todo junto</h2><p>Para aprovechar al máximo el recuperador de <code>linear</code> con normalización, la solicitud de búsqueda tendría el siguiente aspecto:</p>GET linear_retriever_blog/_search
{
   "retriever": {
       "linear": {
           "retrievers": [
               {
                   "retriever": {
                       "knn": {
                          ...
                        }
                    },
                   "weight": 5
               },
                  {
                   "retriever": {
                       "standard": {
                          ...
                        }
                    },
                   "weight": 1.5,
                   "normalizer": "minmax"
               },


           ]
       }
   }
}<p>Este enfoque combina lo mejor de ambos mundos: conserva la flexibilidad y el puntaje intuitivo del recuperador de <code>linear</code> , al tiempo que garantiza una escala de puntaje consistente con la normalización MinMax.</p><p>Al igual que con todos nuestros retrievers, el <code>linear</code> retriever se puede integrar en cualquier nivel de un árbol jerárquico de retriever, con soporte para explicabilidad, resaltado de coincidencias, colapso de campo y más.</p><h2>Cuándo elegir el retriever lineal y por qué marca la diferencia</h2><p>El <code>linear</code> retriever:</p><ul><li><p>Preserva la importancia relativa al aprovechar los puntajes reales, no solo los rangos.</p></li><li><p>Permite el ajuste fino con contribuciones ponderadas de diferentes consultas.</p></li><li><p>Mejora la coherencia mediante la normalización, lo que hace que la búsqueda híbrida sea más estable y previsible.</p></li></ul><h2>Conclusión</h2><p>El recuperador de <code>linear</code> ya está disponible en Elasticsearch Serverless y en las versiones 8.18 y 9.0. También se pueden encontrar más ejemplos y parámetros de configuración en nuestra documentación. Pruébelo y vea cómo puede mejorar su experiencia de búsqueda híbrida: esperamos sus comentarios. ¡Feliz búsqueda!</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[Relevancia]]></category>
    <category><![CDATA[Búsqueda 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[Creación de listas de evaluación con Quepid]]></title>
    <description><![CDATA[Aprende cómo crear listas de evaluación en Quepid utilizando un proceso colaborativo de calificadores humanos y usa los puntos de referencia para ajustar la relevancia.]]></description>
    <content:encoded><![CDATA[<p>La creación de <a href="https://www.elastic.co/search-labs/blog/judgment-lists">listas de juicio</a> es un paso crucial para optimizar la calidad de los resultados de búsqueda, pero puede ser una tarea complicada y difícil. Una lista de juicios es un conjunto seleccionado de consultas de búsqueda combinadas con valoraciones de relevancia para sus resultados correspondientes, también conocida como colección de prueba. Las métricas calculadas mediante esta lista actúan como referencia para medir el rendimiento de un motor de búsqueda. Para agilizar el proceso de creación de listas de juicio, el equipo <a href="https://opensourceconnections.com/">de OpenSource Connections</a> desarrolló <a href="https://quepidapp.com/">Quepid</a>. El juicio puede ser explícito o basar en la retroalimentación implícita de los usuarios. Este blog te guiará para establecer un entorno colaborativo en Quepid que permita eficazmente a los evaluadores humanos hacer juicios explícitos, que es la base de cada lista de juicios.</p><p>Quepid apoya a los equipos de búsqueda en el proceso de evaluación de la calidad de búsqueda:</p><ul><li><p>Construcción de conjuntos de consultas</p></li><li><p>Crear listas de juicios</p></li><li><p>Calcular métricas de calidad de búsqueda</p></li><li><p>Compara diferentes algoritmos/rankingers de búsqueda basándote en métricas calculadas de calidad de búsqueda</p></li></ul><p>Para nuestro blog, supongamos que gestionamos una tienda de alquiler de películas y que tenemos como objetivo mejorar la calidad de los resultados de búsqueda.</p><h2>Prerrequisitos</h2><p>Este blog emplea los datos y los mapeos del <a href="https://github.com/o19s/es-tmdb">repositorio es-tmdb</a>. Los datos provienen <a href="https://www.themoviedb.org/">de The Movie Database</a>. Para seguir el ritmo, configura un índice llamado tmdb con los mapeos e indexa los datos. No importa si configuras una instancia local o usas un despliegue de Elastic Cloud para esto: cualquiera de las dos funciona bien. Asumimos un despliegue de Elastic Cloud para este blog. Puedes encontrar información sobre cómo indexar los datos en el <a href="https://github.com/o19s/es-tmdb/blob/master/README.md">README del repositorio es-tmdb</a>.</p><p>Haz una consulta sencilla de coincidencias en el campo del título para <code>rocky</code> confirmar que tienes datos para buscar:</p>GET tmdb/_search
{
 "query": {
   "match": {
     "title": "rocky"
   }
 }
}<p>Deberías 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>Iniciar sesión en Quepid</h2><p><a href="https://github.com/o19s/quepid">Quepid</a> es una herramienta que permite a los usuarios medir la calidad de los resultados de búsqueda y ejecutar experimentos offline para mejorarla.</p><p>Puedes usar Quepid de dos maneras: o bien usar la versión gratis y disponible públicamente alojada en <a href="https://app.quepid.com">https://app.quepid.com</a>, o configura Quepid en una máquina a la que tengas acceso. Esta publicación asume que estás usando la versión alojada gratis. Si quieres configurar una instancia de Quepid en tu entorno, sigue la <a href="https://github.com/o19s/quepid/wiki/Installation-Guide">Guía de Instalación</a>.</p><p>Sea cual sea la configuración que elijas, tendrás que crear una cuenta si aún no tienes una.</p><h2>Cómo configurar un caso de Quepid</h2><p>Quepid está organizado en torno a los "Casos". Un caso almacena consultas junto con ajustes de relevancia y cómo establecer una conexión con tu motor de búsqueda.</p><ul><li><p>Para usuarios primerizos, selecciona <strong>Crear tu primer caso de relevancia</strong>.</p></li><li><p>Los usuarios que regresan pueden seleccionar <strong>Casos de Relevancia</strong> desde el menú superior y hacer clic <strong>en + Crear un caso</strong>.</p></li></ul><p>Nombra tu caso de forma descriptiva, por ejemplo, "Línea base de búsqueda de películas", ya que queremos empezar a medir y mejorar nuestra búsqueda de referencia.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte2913d344c42cd24/6a17e6477b54f906b48b38bd/8f9e480d9aae0d706cfc5371e41f19c706dd452a-594x251.png" alt="Establecimiento de un caso Quepid" /><p>Confirma el nombre <strong>seleccionando Continuar</strong>.</p><p>A continuación, establecemos una conexión de Quepid con el motor de búsqueda. Quepid puede conectarse a una variedad de motores de búsqueda, incluido Elasticsearch.</p><p>La configuración variará según tu configuración de Elasticsearch y Quepid. Para conectar Quepid a un despliegue de Elastic Cloud, necesitamos habilitar y configurar CORS para nuestro despliegue de Elastic Cloud y tener lista una clave de API. Las instrucciones detalladas están en el tutorial correspondiente <a href="https://quepid-docs.dev.o19s.com/2/quepid/49/how-to-connect-quepid-to-elastic-cloud">en la documentación de Quepid</a>.</p><p>Introduce la información de tu endpoint de Elasticsearch (<code>https://YOUR_ES_HOST:PORT/tmdb/_search</code>) y cualquier información adicional necesaria para conectarte (la clave API en caso de un despliegue de Elastic Cloud en las opciones <strong>de configuración avanzada</strong> ), prueba la conexión haciendo <strong>clic en ping y</strong> <strong>selecciona Continuar</strong> para pasar al siguiente paso.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcc068309bdc094ae/6a17e6480b0bed14cddd356a/267339dfaecae2740eb2ee2739bdc971608bdb5f-588x1169.png" alt="Configuración de un endpoint de Elasticsearch con Quepid" /><p>Ahora definimos qué campos queremos que se muestren en el caso. Selecciona todos los que ayuden a nuestros evaluadores humanos a evaluar posteriormente la relevancia de un documento para una consulta determinada.</p><p>Establece <code>title</code> como <em>Campo de Título</em>, deja <code>_id</code> como <em>Campo ID</em> y agrega <code>overview, tagline, cast, vote_average, thumb:poster_path</code> como <em>Campos de Visualización Adicionales</em>. La última entrada muestra pequeñas imágenes en miniatura de las películas en nuestros resultados para guiarnos visualmente a nosotros y a los evaluadores humanos.</p><p>Confirma la configuración de pantalla seleccionando el botón <strong>Continuar</strong> .</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc910bdf5aa7680b3/6a17e64ae8fbce710b3a1906/02c58aae8c2ebb6d31f538b27462b4c65428fdc3-594x493.png" alt="Definición de los campos que queremos que se muestren en el caso de los evaluadores humanos de Quepid." /><p>El último paso es agregar consultas de búsqueda al caso. Agrega las tres consultas <em>Star Wars</em>, <em>Harrison Ford</em> y <em>la mejor película de acción</em> una por una a través del campo de entrada y <strong>Continúa</strong>.</p><p>Idealmente, un caso contiene consultas que representan consultas reales de usuarios e ilustran diferentes tipos de consultas. Por ahora, podemos <em>imaginar que Star Wars</em> es una consulta que representa todas las consultas de títulos de películas, <em>Harrison Ford</em> una consulta que representa todas las consultas de los miembros del reparto, y <em>Best Action Movie</em> una consulta que representa todas las consultas que buscan películas de un género específico. Esto se denomina típicamente conjunto de consultas.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt46122bb45e1063e4/6a17e64b505ac36510ad8af8/baccfe96766319aa7255e9bff08913ac87d1517f-595x326.png" alt="Agregar consultas de búsqueda a un caso de Quepid" /><p>En un escenario de producción, muestrearíamos consultas de datos de seguimiento de eventos aplicando técnicas estadísticas como <a href="https://opensourceconnections.com/blog/2022/10/13/how-to-succeed-with-explicit-relevance-evaluation-using-probability-proportional-to-size-sampling/">ejemplificación de probabilidad proporcional al tamaño</a> e importaríamos estas consultas muestreadas a Quepid para incluir consultas desde la cabeza (consultas frecuentes) y cola (consultas poco frecuentes) en relación con su frecuencia, lo que significa que tendemos a optar por consultas más frecuentes sin excluir las raras.</p><p>Finalmente, selecciona <strong>Terminar</strong> y serás redirigido a la interfaz de casos donde verás las tres consultas definidas.</p><h2>Búsquedas y necesidades de información</h2><p>Para llegar a nuestro objetivo general de una lista de juicios, los evaluadores humanos deberán juzgar un resultado de búsqueda (normalmente un documento) para una consulta determinada. Esto se llama par consulta/documento.</p><p>A veces, parece fácil saber qué quería un usuario al revisar la consulta. La intención detrás de la <code>harrison ford</code> es encontrar películas protagonizadas por Harrison Ford, el actor. ¿Y qué pasa con la <code>action</code>de la consulta? Sé que me tentaría decir que la intención del usuario es encontrar películas del género de acción. ¿Pero cuáles? ¿Los más recientes, los más populares, los mejores según las valoraciones de los usuarios? ¿O quizá el usuario quiere encontrar todas las películas que se llaman "Acción"? <a href="https://www.themoviedb.org/search/movie?query=Action">Hay al menos 12 (!) películas llamadas "Acción" en The Movie Database</a> y sus nombres difieren principalmente en el número de signos de exclamación en el título.</p><p>Dos evaluadores humanos pueden diferir en la interpretación de una consulta cuando la intención no está clara. Entra en escena la necesidad de información: Una <a href="https://en.wikipedia.org/wiki/Information_needs">necesidad de información</a> es un deseo consciente o inconsciente de información. Definir una necesidad de información ayuda a los evaluadores humanos a juzgar documentos para una consulta, por lo que desempeñan un papel importante en el proceso de elaboración de listas de juicio. Los usuarios expertos o expertos en la materia son buenos candidatos para especificar necesidades de información. Es buena práctica definir las necesidades de información desde la perspectiva del usuario, ya que es su necesidad la que los resultados de búsqueda deben satisfacer.</p><p>Necesidades de información para las consultas de nuestro caso "Línea de Base de Búsqueda de Películas":</p><ol><li><p><strong>Star Wars</strong>: El usuario quiere encontrar películas o seriales de la franquicia Star Wars. Potencialmente relevantes son los documentales sobre Star Wars.</p></li><li><p><strong>Harrison Ford</strong>: El usuario quiere encontrar películas protagonizadas por el actor Harrison Ford. Potencialmente relevantes son las películas en las que Harrison Ford tiene un papel diferente, como el de narrador.</p></li><li><p><strong>mejor película de acción</strong>: El usuario quiere encontrar películas de acción, preferiblemente aquellas con votos medios altos.</p></li></ol><h2>Cómo definir las necesidades de información en Quepid</h2><p>Para definir una necesidad de información en Quepid, accede a la interfaz de casos:</p><p>1. Abre una consulta (por ejemplo,<em>s tar wars</em>) y selecciona <em>Alternar Notas.</em></p><p>2. Introduce la Necesidad de Información en el primer campo y cualquier nota adicional en el segundo campo:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte57395f64f6e5fab/6a17e64d6864a40fd6b68771/e01d3d5242a350d8797faa665eb3170039f5dfa2-1483x559.png" alt="Definir información y necesidades de consulta en Quepid" /><p>3. Haz clic <strong>en almacenar</strong>.</p><p>Para un puñado de consultas, este proceso está bien. Sin embargo, cuando amplías tu caso de tres a 100 consultas (los casos de Quepid suelen estar en el rango de 50 a 100 consultas), puede que quieras definir necesidades de información fuera de Quepid (por ejemplo, en una hoja de cálculo) y luego subirlas mediante <strong>Importar</strong> y seleccionar <strong>Necesidades de Información</strong>.</p><h2>Crea un equipo en Quepid y comparte tu caso</h2><p>Los juicios colaborativos mejoran la calidad de las evaluaciones de relevancia. Para formar un equipo:</p><p>1. Navega a <strong>Teams</strong> en el menú superior.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt45c51d1a0e05a80d/6a17e64fe8fbcede793a190f/797706e8d130b474a95d30b6fa22ecaf36f98c03-613x58.png" alt="Crear un equipo en Quepid" /><p>2. Haz clic <strong>+ Agregar Nuevo</strong>, introduce el nombre de un equipo (por ejemplo, "Search Relevance Raters") y haz clic <strong>en Crear</strong>.</p><p>3. Agregar miembros escribiendo sus direcciones de email y haciendo clic <strong>en Agregar usuario</strong>.</p><p>4. En la interfaz de casos, selecciona <strong>Compartir Caso.</strong></p><p>5. Elegir el equipo adecuado y confirmarlo.</p><h2>Crea un libro de evaluaciones en Quepid</h2><p>Un libro en Quepid permite a varios evaluadores evaluar sistemáticamente los pares consulta/documento. Para crear uno:</p><p>1. Ve a <strong>Sentencias</strong> en la interfaz del caso y haz <strong>clic + Crear un libro</strong>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3543c00e0b834b3f/6a17e650e9ea87f57fa9c598/6a077f26225961150b7414463d7db04f090b68d6-896x365.png" alt="Crear un libro de evaluaciones en Quepid." /><p>2. Configura el libro con un nombre descriptivo, asigna el libro a tu equipo, selecciona un método de puntaje (por ejemplo, DCG@10) y establece la estrategia de selección (uno o varios evaluadores). Emplea los siguientes ajustes para el libro:</p><ul><li><p><strong>Nombre</strong>: "Búsqueda de películas a escala 0-3"</p></li><li><p><strong>Equipos con los que compartir este libro</strong>: Marca la casilla con el equipo que creaste</p></li><li><p><strong>Goleador</strong>: DCG@10</p></li></ul><p>3. Haz clic <strong>en Crear libro.</strong></p><p>El nombre es descriptivo y contiene información sobre lo que se busca en ("Películas") y también la escala de las sentencias ("0-3"). El DCG@10 seleccionado de Scorer define la forma en que se calculará la métrica de búsqueda. "DCG" es la abreviatura de <a href="https://en.wikipedia.org/wiki/Discounted_cumulative_gain">Ganancia Acumulada Descontada</a> y "@10" es el número de resultados desde la parte superior que se tiene en cuenta al calcular la métrica.</p><p>En este caso, estamos usando una métrica que mide la ganancia de información y la combina con ponderación posicional. Puede que haya otras métricas de búsqueda más adecuadas para tu caso de uso y <a href="https://opensourceconnections.com/blog/2020/02/28/choosing-your-search-relevance-metric">elegir la adecuada es un desafío en sí</a> mismo.</p><h2>Llena el libro con pares de búsqueda/documento</h2><p>Para agregar pares de consulta/documento para la evaluación de relevancia, sigue estos pasos:</p><p>1. En la interfaz del caso, navega a "Sentencias".</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0e98583138535cc3/6a17e6520b0bed4f51dd3571/d717c5b06ae6cb42ed2b9e771486a12f738a9890-1041x218.png" alt="Llena el libro con pares de búsqueda/documento en Quepid." /><p>2. Selecciona tu libro creado.</p><p>3. Haz clic en "Poblar libro" y confirma seleccionando "Actualizar pares de consulta/documentos para libro."</p><p>Esta acción genera pares basados en los principales resultados de búsqueda de cada consulta, listos para su evaluación por parte de su equipo.</p><h2>Deja que tu equipo de evaluadores humanos juzgue </h2><p>Hasta ahora, los pasos completados fueron bastante técnicos y administrativos. Ahora que esta preparación necesaria está hecha, podemos dejar que nuestro equipo de jueces haga su trabajo. En esencia, el trabajo del juez es valorar la relevancia de un documento concreto para una consulta determinada. El resultado de este proceso es la lista de juicios que contiene todas las etiquetas de relevancia para los pares de documentos de consulta evaluados. A continuación, se explica este proceso y la interfaz para él con más detalle.</p><h3>Visión general de la interfaz de calificación humana</h3><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt553afb07d8080421/6a17e654505ac30514ad8afc/be3016091b49655dab3354d84e6dc638f3468390-1283x664.png" alt="Cómo los evaluadores humanos de Quepid juzgan la información contenida en documentos y consultas." /><p>La interfaz de calificación humana de Quepid está diseñada para evaluaciones eficientes:</p><ul><li><p><strong>Consulta:</strong> Muestra el término de búsqueda.</p></li><li><p><strong>Necesidad de información:</strong> Muestra la intención del usuario.</p></li><li><p><strong>Directrices de puntaje:</strong> Proporciona instrucciones para evaluaciones consistentes.</p></li><li><p><strong>Metadatos del documento:</strong> Presenta detalles relevantes sobre el documento.</p></li><li><p><strong>Botones de valoración:</strong> Permite a los evaluadores asignar juicios con los atajos de teclado correspondientes.</p></li></ul><h3>Uso de la interfaz de calificación humana</h3><p>Como evaluador humano, accedo a la interfaz a través de la visión general del libro:</p><p>1. Navega a la interfaz del caso y haz clic <strong>en Sentencias</strong>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0e98583138535cc3/6a17e6520b0bed4f51dd3571/d717c5b06ae6cb42ed2b9e771486a12f738a9890-1041x218.png" alt="Usando la interfaz de calificación humana de Quepid " /><p>2. <strong>¡Haz clic en Más Juicios Se Necesitan!</strong></p><p>El sistema presentará un par de consulta/documento que aún no fue valorado y que requiere juicios adicionales. Esto está determinado por la estrategia de selección del Libro:</p><ul><li><p><em>Evaluador único</em>: Un único juicio por par de consulta/documento.</p></li><li><p><em>Evaluadores múltiples</em>: hasta tres juicios por par de consulta/documento.</p></li></ul><h3>Calificación de pares de búsqueda/documento</h3><p>Vamos a repasar un par de ejemplos. Al seguir esta guía, lo más probable es que te presenten diferentes películas. Sin embargo, los principios de clasificación se mantienen igual.</p><p>Nuestro primer ejemplo es la película "Heroes" para la consulta <em>de Harrison Ford</em>:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta248e787b5e0a670/6a17e656ec0f89612d5a65ee/c1e14b0d8b04dd579471932dbe4ff72ae5692a02-981x571.png" alt="Cómo llenar un libro en Quepid con pares de búsqueda/documento" /><p>Primero analizamos la consulta, seguida de la necesidad de información y después juzgamos la película en función de los metadatos proporcionados.</p><p>Esta película es un resultado relevante para nuestra consulta, ya que Harridson Ford forma parte del reparto. Puede que consideremos las películas más recientes como más relevantes subjetivamente, pero esto no forma parte de nuestra necesidad informativa. Así que calificamos este documento con "Perfecto", que es un 3 en nuestra escala de calificación.</p><p>Nuestro siguiente ejemplo es la película "Ford v Ferrari" para la consulta <em>Harrison Ford</em>:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf5d86aac918a1e96/6a17e657414c64833e945152/052af7894506d7a765af156ba8e26ceec3559973-981x789.png" alt="Un ejemplo de la película “Ford vs. Ferrari” para la búsqueda harrison ford en Quepid." /><p>Siguiendo la misma práctica, juzgamos esta consulta/documento analizando la consulta, la necesidad de información y luego cuán bien los metadatos del documento coinciden con la necesidad de información.</p><p>Este es un resultado pobre. Probablemente veamos este resultado como uno de nuestros términos de consulta, "ford", coincide en el título. Pero Harrison Ford no tiene ningún papel en esta película, ni en ningún otro. Así que calificamos este documento como "Pobre", que es un 0 en nuestra escala de calificación.</p><p>Nuestro tercer ejemplo es la película "Action Jackson" para la <em>mejor película de acción</em> que se pregunta:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2cee335ddd1e6a92/6a17e6596df731d1f40a0ed7/247ab862fbc7435537709f8c96619cb331133d09-985x606.png" alt="Un ejemplo de la película “Action Jackson” para la búsqueda de mejor película de acción:" /><p>Esto parece una película de acción, así que la necesidad de información está al menos parcialmente cubierta. Sin embargo, la media de votos es de 5,4 sobre 10. Y eso hace que esta película probablemente no sea la mejor de acción de nuestra colección. Esto me llevaría, como juez, a calificar este documento como "Justo", que es un 1 en nuestra escala de calificación.</p><p>Estos ejemplos ilustran el proceso de valorar pares de consulta/documento con Quepid en individua, tanto a nivel general como en general.</p><h2>Mejores prácticas para evaluadores humanos</h2><p>Los ejemplos mostrados pueden hacer que parezca fácil llegar a juicios explícitos. Pero establecer un programa fiable de valoración humana no es tarea fácil. Es un proceso lleno de desafíos que pueden comprometer fácilmente la calidad de tus datos:</p><ul><li><p>Los evaluadores humanos pueden fatigar por tareas repetitivas.</p></li><li><p>Las preferencias personales pueden sesgar los juicios.</p></li><li><p>Los niveles de experiencia en el sector varían de un juez a otro.</p></li><li><p>Los evaluadores suelen compaginar múltiples responsabilidades.</p></li><li><p>La relevancia percibida de un documento puede no coincidir con su verdadera relevancia para una consulta.</p></li></ul><p>Estos factores pueden dar lugar a juicios inconsistentes y de baja calidad. Pero no te preocupes: existen buenas prácticas probadas que pueden ayudarte a minimizar estos problemas y construir un proceso de evaluación más estable y fiable:</p><ul><li><p><strong>Evaluación constante:</strong> Revisa la consulta, la necesidad de información y los metadatos del documento en orden.</p></li><li><p><strong>Consulte las Directrices:</strong> Emplea directrices de puntaje para mantener la consistencia. Las directrices de puntaje pueden incluir ejemplos de cuándo aplicar cada nota, lo que ilustra el proceso de evaluación. Tener una consulta con evaluadores humanos tras la primera tanda de sentencias resultó ser una buena práctica para aprender sobre casos límite difíciles y dónde se necesita apoyo adicional.</p></li><li><p><strong>Aprovecha las opciones:</strong> Si tienes dudas, emplea "Juzgaré más tarde" o "No puedo saberlo", proporcionando explicaciones cuando sea necesario.</p></li><li><p><strong>Toma descansos:</strong> Las pausas regulares ayudan a mantener la calidad del juicio. Quepid ayuda con los descansos regulares haciendo estallar confeti cada vez que un evaluador humano termina un serial de juicios.</p></li></ul><p>Siguiendo estos pasos, estableces un enfoque estructurado y colaborativo para crear listas de juicios en Quepid, mejorando la eficacia de tus esfuerzos de optimización de relevancia en búsqueda.</p><h2>Pasos siguientes</h2><p>¿A dónde ir a partir de aquí? Las listas de juicio son solo un paso fundamental para mejorar la calidad de los resultados de búsqueda. Aquí están los siguientes pasos:</p><h3>Calcula métricas y comienza a experimentar</h3><p>Una vez que hay listas de juicios disponibles, aprovechar dichos juicios y calcular <a href="https://opensourceconnections.com/blog/2020/02/28/choosing-your-search-relevance-metric/">métricas de calidad de búsqueda</a> es una progresión natural. Quepid calcula automáticamente la métrica configurada para el caso actual cuando hay sentencias disponibles. Las métricas se implementan como "Puntuadores" y puedes proporcionar las tuyas propias cuando las compatibles no incluyen a tu favorito.</p><p>Ve a la interfaz del caso, navega hasta <strong>Seleccionar Anotador</strong>, <em>elige DCG@10</em> y confirma haciendo clic en <strong>Seleccionar Anotador</strong>. Quepid ahora calculará DCG@10 por consulta y también promediará el número total de consultas para cuantificar la calidad de los resultados de búsqueda de tu caso.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0d059c959b842139/6a17e65be8fbceb29b3a1913/0ff3b9918342071744d681a43d542102e927abd3-1163x551.png" alt="Cómo cuantificar la calidad de los resultados de búsqueda en Quepid " /><p>Ahora que la calidad de los resultados de búsqueda está cuantificada, puedes realizar los primeros experimentos. La experimentación comienza generando hipótesis. Mirar las tres consultas en la captura de pantalla tras hacer algunas valoraciones queda claro que las tres consultas rinden de forma muy diferente en cuanto a la métrica de calidad de búsqueda: <em>Star Wars</em> funciona bastante bien, <em>Harrison Ford</em> parece aceptable pero el mayor potencial está en <em>la mejor película de acción</em>.</p><p>Ampliando esta consulta, vemos sus resultados y podemos profundizar en los detalles más minuciosos y explorar por qué los documentos coincidieron y qué influye en sus puntajes:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt35227761f4524a1e/6a17e65cb1e11325c579f25a/c45c6cae085a492198c0f8b7060a1a7204e3724e-1131x691.png" alt="Experimentar con diferentes consultas para ver cómo funcionan con diferentes métricas de búsqueda en Quepid" /><p>Al hacer clic en "Explicar la consulta" y entrar en la pestaña "Análisis sintáctico" vemos que la consulta es una búsqueda de DisjunctionMaxxQuery en tres campos: <em>cast</em>, <em>resumen</em> y <em>título</em>:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0966653b9ab3cc9c/6a17e65efaa913171f93c84c/4a1e1bb2a9cd28e9c48e0ba16357d17ed9d3a5cf-894x557.png" alt="Explicación del análisis de consultas" /><p>Normalmente, como ingenieros de búsqueda, conocemos algunos detalles específicos de nuestro dominio sobre nuestra plataforma de búsqueda. En este caso, puede que sepamos que tenemos un campo <em>de géneros</em> . Vamos a agregar eso a la consulta y ver si la calidad de búsqueda mejora.</p><p>Usamos el <strong>Sandbox de Consultas</strong> que se abre al seleccionar <strong>Relevancia de Ajuste</strong> en la interfaz de casos. Adelante, explora esto agregando el campo <em>de géneros</em> en el que busques:</p>{
  "query": {
    "multi_match": {
      "query": "#$query##",
      "type": "best_fields",
      "fields": [
        "title^10",
        "overview",
        "cast",
        "genres"
      ]
    }
  }
}<p>¡Haz clic en Volver a Ejecutar Mis Búsquedas! Y mira los resultados. ¿Cambiaron? Desgraciadamente no. Ahora tenemos muchas opciones para explorar, básicamente todas las opciones de consulta que ofrece Elasticsearch:</p><ul><li><p>Podríamos aumentar el peso del campo en el campo de géneros.</p></li><li><p>Podríamos agregar una función que aumente los documentos por su media de votos.</p></li><li><p>Podríamos crear una consulta más compleja que solo mejore los documentos por su promedio de votos si hay una coincidencia fuerte de géneros.</p></li><li><p>…</p></li></ul><p>Lo mejor de tener todas estas opciones y explorarlas en Quepid es que tenemos una forma de cuantificar los efectos no solo en la única consulta que intentamos mejorar, sino en todas las consultas que tenemos en nuestro caso. Eso nos impide mejorar una consulta que no rinde sacrificando la calidad de los resultados de búsqueda para otras. Podemos iterar rápida y barata y validar el valor de nuestra hipótesis sin ningún riesgo, haciendo de la experimentación offline una capacidad fundamental de todos los equipos de búsqueda.</p><h3>Mide la confiabilidad entre evaluadores</h3><p>Incluso con descripciones de tareas, necesidades de información y una interfaz de evaluador humano como la que ofrece Quepid, los evaluadores humanos pueden discrepar.</p><p>El desacuerdo en sí mismo no es algo malo, todo lo contrario: medir el desacuerdo puede sacar a la luz cuestiones que quizá quieras abordar. La relevancia puede ser subjetiva, las consultas pueden ser ambiguas y los datos pueden ser incompletos o incorrectos. <a href="https://en.wikipedia.org/wiki/Fleiss%27_kappa">El Kappa de Fleiss</a> es una medida estadística del acuerdo entre evaluadores y hay un cuaderno de ejemplo en Quepid que puedes usar. Para encontrarlo, selecciona <strong>Cuadernos</strong> en la navegación superior y selecciona el cuaderno <strong>Fleiss Kappa.ipynb</strong> en la carpeta <strong>de ejemplos</strong> .</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt92d52b30f1fb19c1/6a17e660abe0f2224bdfe9bb/f0669ae96371368ef4d84bb28669560ef09d755c-624x61.png" alt="Cómo encontrar la medida estadística de Fleiss’ Kappa para el acuerdo entre evaluadores en el cuaderno de Quepid" /><h2>Conclusión</h2><p>Quepid te permite afrontar incluso los retos de relevancia en búsquedas más complejos y sigue evolucionando: <a href="https://github.com/o19s/quepid/blob/main/CHANGELOG.md#800----2024-02-14">desde la versión 8, Quepid soporta juicios generados por IA</a>, lo cual es especialmente útil para equipos que quieren escalar su proceso de generación de juicios.</p><p>Los flujos de trabajo quepid te permiten crear listas de juicios escalables de forma eficiente, lo que finalmente resulta en resultados de búsqueda que realmente satisfacen las necesidades de los usuarios. Con listas de juicios establecidas, tienes una base estable para medir la relevancia en las búsquedas, iterar mejoras y mejorar la experiencia de usuario.</p><p>A medida que avanzas, recuerda que la afinación de la relevancia es un proceso continuo. Las listas de juicio te permiten evaluar sistemáticamente tu progreso, pero son más poderosos cuando se combinan con experimentación, análisis métrico y mejoras iterativas.</p><h2>Lecturas adicionales</h2><ul><li><p>Documentos de Quepid:</p><ul><li><p><a href="https://quepid-docs.dev.o19s.com/2/quepid/32/relevancy-is-a-team-sport">La relevancia es un deporte de equipo</a></p></li><li><p><a href="https://quepid-docs.dev.o19s.com/2/quepid/18/quepid-for-human-raters">Quepid para evaluadores humanos</a></p></li><li><p><a href="https://quepid-docs.dev.o19s.com/2/quepid/49/how-to-connect-quepid-to-elastic-cloud">Cómo conectar Quepid a Elastic Cloud</a></p></li></ul></li><li><p><a href="https://github.com/o19s/quepid">Repositorio de Quepid en Github</a></p></li><li><p><a href="https://opensourceconnections.com/blog/2020/07/07/meet-pete-the-e-commerce-search-product-manager/">Conoce a Pete, un serial de blogs sobre cómo mejorar la búsqueda en comercio electrónico</a></p></li><li><p><a href="https://opensourceconnections.com/slack">Relevance Slack</a>: únete al canal #quepid</p></li></ul><p><strong>Colabora con </strong><a href="https://opensourceconnections.com/"><strong>Open Source Connections</strong></a> para transformar tus capacidades de búsqueda e inteligencia artificial y empoderar a tu equipo para que las evolucione continuamente. Nuestro historial probado abarca todo el mundo, con clientes que logran de forma constante mejoras notables en la calidad de búsqueda, la capacidad del equipo y el rendimiento empresarial. <a href="https://opensourceconnections.com/contact/">Contacta con nosotros hoy</a> mismo para obtener más información.</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[Relevancia]]></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[Generación de filtros y facetas usando ML]]></title>
    <description><![CDATA[Explorando los pros y contras de automatizar la creación de filtros y facetas en una experiencia de búsqueda usando modelos de aprendizaje automático frente al enfoque tradicional codificado de forma dura.]]></description>
    <content:encoded><![CDATA[<p>Los filtros y facetas son mecanismos empleados para refinar los resultados de búsqueda, ayudando a los usuarios a encontrar contenido o productos relevantes más rápidamente. En el enfoque tradicional, las reglas se definen manualmente. Por ejemplo, en un catálogo de películas, atributos como el género están predefinidos para su uso en filtros y facetas. Por otro lado, con los modelos de IA, se pueden extraer automáticamente nuevos atributos de las características de las películas, haciendo el proceso más dinámico y personalizado. En este blog, exploramos los pros y los contras de cada método, destacando sus aplicaciones y desafíos.</p><h2>Filtros vs facetas</h2><p>Antes de empezar, definamos qué son los filtros y las facetas. <strong>Los filtros</strong> son atributos predefinidos que se emplean para restringir un conjunto de resultados. En un mercado, por ejemplo, los filtros están disponibles incluso antes de que se realice una búsqueda. El usuario puede seleccionar una categoría, como <strong>"Juegos de video",</strong> antes de buscar <strong>"PS5",</strong> refinando la búsqueda a un subconjunto más específico en lugar de a toda la base de datos. Esto aumenta significativamente las posibilidades de obtener resultados más relevantes.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0a77b38aae238938/6a170b821949f72a52e7aa51/5ed8868fa5017d034e1273e35c884a5430afdf3c-1600x937.png" alt="Filtros" /><p><strong>Las facetas</strong> funcionan de forma similar a los filtros, pero solo están disponibles luego de realizar la búsqueda. En otras palabras, la búsqueda devuelve resultados y, a partir de ellos, se genera una nueva lista de opciones de refinamiento. Por ejemplo, al buscar una consola PS5, pueden mostrar aspectos como <strong>la capacidad</strong> de almacenamiento, <strong>el costo de envío</strong> y <strong>el color</strong> para ayudar a los usuarios a elegir el producto ideal.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt166e356b80d423ef/6a170b840e2e494ca341a10f/c5633fcc5b6fbb916110faf32144d8d43572e33a-1600x937.png" alt="Facetas " /><p>Ahora que definimos filtros y facetas, hablemos del impacto de los enfoques tradicionales y basados en Aprendizaje Automático (ML) en su implementación y uso. Cada método tiene beneficios y desafíos que influyen en la eficiencia de búsqueda.</p><h2>Enfoque tradicional de filtros y facetas</h2><p>En este enfoque, los filtros y facetas se definen manualmente basar en reglas predefinidas. Esto significa que los atributos disponibles para perfeccionar la búsqueda están fijos y planeados con antelación, teniendo en cuenta la estructura del catálogo y las necesidades del usuario.</p><p>Por ejemplo, en un mercado, categorías como "Electrónica" o "Moda" pueden tener filtros específicos como marca, formato y rango de precio. Estas reglas se crean de forma estática, garantizando la coherencia en la experiencia de búsqueda pero requiriendo ajustes manuales cada vez que surgen nuevos productos o categorías.</p><p>Aunque este enfoque proporciona previsibilidad y control sobre los filtros y facetas mostrados, puede ver limitado cuando surgen nuevas tendencias que exigen refinamiento dinámico.</p><p><strong>Pros:</strong></p><ul><li><p><strong>Previsibilidad y control:</strong> Como los filtros y facetas se definen manualmente, la gestión se vuelve más sencilla.</p></li><li><p><strong>Baja complejidad:</strong> No hace falta capacitar modelos.</p></li><li><p><strong>Facilidad de mantenimiento:</strong> Como las reglas están predefinidas, se pueden hacer ajustes y correcciones rápidamente.</p></li></ul><p><strong>Contras</strong>:</p><ul><li><p><strong>Reindexación necesaria para nuevos filtros:</strong> Cada vez que un nuevo atributo necesita usar como filtro, todo el conjunto de datos debe reindexar para cerciorar que los documentos contengan esta información.</p></li><li><p><strong>Falta de adaptación dinámica:</strong> Los filtros son estáticos y no se ajustan automáticamente a los cambios en el comportamiento del usuario.</p></li></ul><h3>Implementación de filtros/facetas – Enfoque tradicional</h3><p>En <strong>Dev Tools, Kibana</strong>, crearemos una demostración de filtros/facetas usando el <strong>enfoque tradicional</strong>.</p><p>Primero, definimos la asignación para estructurar el índice:</p>PUT videogames
{
  "mappings": {
    "properties": {
      "name": { "type": "text" },
      "brand": { "type": "keyword" },
      "storage": { "type": "keyword" },
      "price": { "type": "float" },
      "description": { "type": "text" }
    }
  }
}<p>Los campos <strong>de marca</strong> y <strong>almacenamiento</strong> se establecen como <strong>palabra clave</strong>, lo que permite usarlos directamente en agregaciones (<strong>facetas</strong>). El campo <strong>de precios</strong> es de tipo <strong>float</strong>, lo que permite la creación de <strong>rangos de precio</strong>.</p><p>En el siguiente paso, los datos del producto se indexarán:</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>Ahora, recuperemos los aspectos tradicionales agrupando los resultados por marca, almacenamiento y rango de precio. En la consulta, se definió size:0. En este escenario, el objetivo es recuperar solo los resultados de la agregación sin incluir los documentos correspondientes a la 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>La respuesta incluirá recuentos para <strong>Marca</strong>, <strong>Almacenamiento</strong> y <strong>Precio</strong>, ayudando a crear filtros y facetas.</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>Machine learning y enfoque basado en IA para filtros y facetas</h2><p>En este enfoque, los modelos de Aprendizaje Automático (ML), incluidas las técnicas de Inteligencia Artificial (IA), analizan atributos de datos para generar filtros y facetas relevantes. En lugar de depender de reglas predefinidas, ML/IA aprovecha características de datos indexados. Esto permite el descubrimiento dinámico de nuevas facetas y filtros.</p><p><strong>Beneficios</strong>:</p><ul><li><p><strong>Actualizaciones automáticas:</strong> Se generan automáticamente nuevos filtros y facetas, sin necesidad de ajustes manuales.</p></li><li><p><strong>Descubrimiento de nuevos atributos:</strong> Puede identificar características de datos <strong>previamente no consideradas </strong>como filtros, enriqueciendo la experiencia de búsqueda.</p></li><li><p><strong>Reducción del esfuerzo manual:</strong> El equipo no necesita definir y actualizar constantemente las reglas de filtrado mientras la IA aprende de los datos disponibles.</p></li></ul><p><strong>Contras:</strong></p><ul><li><p><strong>Complejidad del mantenimiento:</strong> El uso de modelos puede requerir una pre-validación para cerciorar la consistencia de los filtros generados.</p></li><li><p><strong>Requiere conocimientos en ML e IA:</strong> La solución requiere profesionales cualificados para afinar y monitorizar el rendimiento del modelo.</p></li><li><p><strong>Riesgo de filtros irrelevantes:</strong> Si el modelo no está bien calibrado, puede generar facetas que no son útiles para los usuarios.</p></li><li><p><strong>Costar:</strong> El uso de aprendizaje automático e inteligencia artificial puede requerir servicios de terceros, aumentando los costos operativos.</p></li></ul><p>Cabe destacar que, incluso con un modelo bien calibrado y un prompt bien elaborado, los aspectos generados deberían pasar por un paso de revisión. Esta validación puede ser manual o basar en normas de moderación, cerciorando que el contenido sea adecuado y seguro. Aunque no necesariamente supone un inconveniente, es importante cerciorar la calidad e idoneidad de los aspectos antes de que estén disponibles para los usuarios.</p><h3>Implementación de filtros/facetas – enfoque de IA</h3><p>En esta demostración, emplearemos un modelo de IA para analizar automáticamente las características del producto y sugerir atributos relevantes. Con un prompt bien estructurado, extraemos información del catálogo y la transformamos en filtros y facetas. A continuación, presentamos cada paso del proceso.</p><p>Inicialmente, emplearemos la <strong>API de Inferencia</strong> para registrar un endpoint para su integración con un servicio de ML. A continuación se muestra un ejemplo de integración con <strong>el servicio de OpenAI</strong>.</p>PUT _inference/completion/generate_filter_ia
{
   "service": "openai",
   "service_settings": {
       "api_key": "your-key",
       "model_id": "gpt-4o-mini"
   }
}<p>Ahora, definimos la tubería para ejecutar el prompt y obtener los nuevos filtros generados por el 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>Ejecutando una simulación de esta tubería para el producto "PlayStation 5", con la siguiente descripción:</p><p><em>Juegos impresionantes: Maravíllate con unos gráficos impresionantes y disfruta de las características de la nueva PS5.</em></p><p><em>Inmersión impresionante: Descubre una experiencia de juego más profunda con soporte para retroalimentación háptica, disparadores adaptativos y tecnología de audio 3D.</em></p><p><em>Diseño Slim: Con la Edición Digital PS5, los jugadores cuentan con una tecnología de juego poderoso en un diseño elegante y compacto.</em></p><p><em>1TB de almacenamiento: Ten tus juegos favoritos listos y esperando para jugar con 1TB de almacenamiento SSD integrado.</em></p><p><em>Retrocompatibilidad y mejora del juego: La consola PS5 puede reproducir más de 4.000 juegos de PS4. Con Game Boost, incluso puedes disfrutar de tasas de fotogramas más rápidas y fluidas en algunos de los mejores juegos de consola de PS4.</em></p><p>Observemos la salida de prompt generada por esta simulación.</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>Ahora se agregará un nuevo campo, <strong>dynamic_facets</strong>, al nuevo índice para almacenar las facetas generadas por la 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>Usando la <strong>API Reindex</strong>, reindexaremos el índice <strong>de juegos de video</strong> a <strong>videogames_1</strong>, aplicando la <strong>generate_filter_ai</strong> pipeline durante el proceso. Esta tubería generará automáticamente facetas dinámicas durante la indexación.</p>POST _reindex?wait_for_completion=false
{
 "source": {
   "index": "videogames"
 },
 "dest": {
   "index": "videogames_1",
   "pipeline": "generate_filter_ai"
 }
}<p>Ahora, haremos una búsqueda y obtendremos los nuevos 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 la implementación de las facetas, a continuación se muestra una interfaz sencilla:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb0d6aa40caf7a91a/6a170b86ab7f0839afdb9eb6/12b6d9d4f4d0985848d92841545fd22b7253ae6d-1600x1288.png" alt="Implementación de las facetas" /><p>El código de la interfaz que se presenta <a href="https://gist.github.com/andreluiz1987/06d9ec1b381e942e9def0e969bd811a0">está aquí</a>.</p><h2>Conclusión</h2><p>Ambos enfoques para crear filtros y facetas tienen sus beneficios y puntos de preocupación. El enfoque tradicional, basado en reglas manuales, ofrece control y costos más bajos, pero requiere actualizaciones constantes y no se adapta dinámicamente a nuevos productos o funcionalidades.</p><p>Por otro lado, el enfoque basado en IA y Aprendizaje Automático automatiza la extracción de facetas, haciendo la búsqueda más flexible y permitiendo el descubrimiento de nuevos atributos sin intervención manual. Sin embargo, este enfoque puede ser más complejo de implementar y mantener, requiriendo calibración para garantizar resultados consistentes.</p><p>La elección entre los enfoques tradicionales y basados en IA depende de las necesidades y la complejidad del negocio. Para escenarios más simples, donde los atributos de los datos son estables y previsibles, el enfoque tradicional puede ser más eficiente y fácil de mantener, evitando costos innecesarios con infraestructuras y modelos de IA. Por otro lado, el uso de ML/IA para extraer facetas puede aportar un valor significativo, mejorando la experiencia de búsqueda y haciendo que el filtrado sea más inteligente.</p><p>Lo importante es evaluar si la automatización justifica la inversión o si una solución más tradicional ya satisface eficazmente las necesidades del negocio.</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[Relevancia]]></category>
    <category><![CDATA[Investigación en ML]]></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[Cómo automatizar sinónimos y subir usando nuestra API de Sinónimos]]></title>
    <description><![CDATA[Descubre cómo los LLMs pueden usar para identificar y generar sinónimos automáticamente, permitiendo que los términos se carguen programáticamente en la API de sinónimos de Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>Mejorar la calidad de los resultados de búsqueda es esencial para ofrecer una experiencia de usuario eficiente. Una forma de optimizar las búsquedas es expandiendo automáticamente los términos consultados mediante sinónimos. Esto permite interpretar las consultas de forma más amplia, cubriendo variaciones lingüísticas y así mejorando la coincidencia de resultados.</p><p>Este blog explora cómo los grandes modelos de lenguaje (LLMs) pueden usar para identificar y generar sinónimos automáticamente, permitiendo que estos términos se carguen programáticamente en la API de sinónimos de Elasticsearch.</p><h2>¿Cuándo usar sinónimos?</h2><p>El uso de sinónimos puede ser una solución más rápida y rentable en comparación con la búsqueda vectorial. Su implementación es más sencilla ya que no requiere un conocimiento profundo de embeddings ni un proceso complejo de ingestión vectorial.</p><p>Además, el consumo de recursos es menor, ya que la búsqueda vectorial exige mayor capacidad de almacenamiento y memoria para incrustar, indexar y recuperar.</p><p>Otro aspecto importante es la regionalización de la búsqueda. Con los sinónimos, es posible adaptar términos según el idioma y las costumbres locales. Esto es útil en situaciones donde las incrustaciones pueden no coincidir con expresiones regionales o términos específicos de cada país. Por ejemplo, algunas palabras o siglas pueden tener significados diferentes según la región, pero los usuarios locales los tratan naturalmente como sinónimos. En Brasil, esto es bastante común. "Abacaxi" y "ananás" son la misma fruta (piña), pero el segundo término se usa más comúnmente en algunas regiones del noreste. De manera similar, el conocido "pão francês" en el sudeste puede ser conocido como "pão careca" en el noreste.</p><h2>¿Cómo usar los LLMs para generar sinónimos?</h2><p>Para obtener sinónimos automáticamente, podemos usar LLMs, que analizan el contexto de un término y sugieren variaciones apropiadas. Este enfoque permite expandir dinámicamente los sinónimos, cerciorando una búsqueda más amplia y precisa sin depender de un diccionario fijo.</p><p>En esta demostración, emplearemos un LLM para generar sinónimos de productos de comercio electrónico. Muchas búsquedas demuestran pocos o ningún resultado debido a las variaciones en los términos consultados. Con sinónimos, podemos resolver este problema. Por ejemplo, una búsqueda de "smartphone" puede abarcar diferentes modelos de teléfonos móviles, cerciorando que los usuarios encuentren los productos que buscan.</p><h3>Prerrequisitos</h3><p>Antes de empezar, necesitamos configurar el entorno y definir las dependencias necesarias. Emplearemos la solución proporcionada por Elastic para <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/run-elasticsearch-locally.html">ejecutar Elasticsearch y Kibana localmente en Docker</a>. El código estará escrito en Python, v3.9.6, con las siguientes dependencias:</p>pip install openai==1.59.8 elasticsearch==8.15.1<h3>Creación del índice de productos</h3><p>Inicialmente, crearemos un índice de productos sin soporte de sinónimos. Esto nos permitirá validar consultas y luego compararlas con un índice que incluya sinónimos.</p><p>Para crear el índice, cargamos en masa un conjunto de datos de producto usando el siguiente comando en 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>Generación de sinónimos con LLM</h3><p>En este paso, emplearemos un LLM para generar sinónimos dinámicamente. Para lograrlo, integraremos la API de OpenAI, definiendo un modelo y un prompt apropiados. El LLM recibirá la categoría y el nombre del producto, cerciorando que los sinónimos sean relevantes en el contexto.</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 del índice de productos creados, recuperaremos todos los artículos de la categoría "Electrónica" y enviaremos sus nombres al LLM. La salida esperada será algo así:</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>Con los sinónimos generados, podemos registrarlos en Elasticsearch usando la API de Sinónimos.</p><h3>Gestión de sinónimos con la API de Sinónimos</h3><p>La API de Sinónimos proporciona una forma eficiente de gestionar conjuntos de sinónimos directamente dentro del sistema. Cada conjunto de sinónimos consiste en reglas de sinónimos, donde un grupo de palabras se considera equivalente en las búsquedas.</p><p><strong>Ejemplo de creación de un conjunto de sinónimos</strong></p>PUT _synonyms/my-synonyms-set
{
  "synonyms_set": [
    {
      "id": "rule-1",
      "synonyms": "hello, hi"
    },
    {
      "synonyms": "bye, goodbye"
    }
  ]
}<p>
Esto crea un conjunto llamado "mis-sinónimos-conjunto", donde "hola" y "hola" se tratan como equivalentes, así como "adiós" y "adiós".</p><h2>Implementación de la creación de sinónimos para el catálogo de productos</h2><p>A continuación se muestra el método responsable de construir un conjunto de sinónimos e insertarlo en Elasticsearch. Las reglas de sinónimos se generan a partir del mapeo de sinónimos sugerido por el LLM. Cada regla tiene un ID, correspondiente al nombre del producto en formato slug, y a la lista de sinónimos calculada por el 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 continuación se muestra la carga útil de la solicitud para crear el 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>Con el conjunto de sinónimos creado en el clúster, podemos pasar al siguiente paso, que es crear un nuevo índice con soporte de sinónimos usando el conjunto definido.</p><p>El código completo en Python con los sinónimos generados por LLM y la creación de conjuntos de sinónimos definida por la API de Sinónimos es el siguiente:</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>Creación de un índice con soporte de sinónimos</h3><p>Se creará un nuevo índice donde todos los datos del índice de <code>products</code> serán reindexados. Este índice usará la <code>synonyms_filter</code>, que aplica la <code>products-synonyms-set</code> creada anteriormente.</p><p>A continuación se muestra el mapeo de índices 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 el índice de <code>products</code></h3><p>Ahora, usaremos la <strong>API Reindex</strong> para migrar los datos del índice de <code>products</code> al nuevo índice de <code>products_02</code> , que incluye soporte para sinónimos. El siguiente código se ejecutó en Kibana DevTools:
</p>POST _reindex
{
  "source": {
    "index": "products"
  },
  "dest": {
    "index": "products_02"
  }
}<p>Tras la migración, el índice de <code>products_02</code> estará llenado y listo para validar búsquedas usando el conjunto de sinónimos configurado.</p><h3>Validación de la búsqueda con sinónimos</h3><p>Comparemos los resultados de búsqueda entre los dos índices. Ejecutaremos la misma consulta en ambos índices y validaremos si los sinónimos se están empleando para obtener resultados.</p><h4>Buscar en el índice de <code>products</code> (sin sinónimos)</h4><p>Emplearemos a Kibana para realizar búsquedas y analizar los resultados. En el menú de Analítica &gt; Descubrimiento, crearemos una Vista de Datos para visualizar los datos de los índices que creamos.</p><p>Dentro de Discovery, haz clic en Vista de datos y define un nombre y un patrón de índice. Para el índice de "<strong>productos</strong>", usaremos el patrón de "<strong>productos</strong>". Luego, repetiremos el proceso para crear una nueva Vista de Datos para el índice "<strong>products_02</strong>", usando el patrón "<strong>products_02".</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte826fd932cfeb9df/6a17fdffec0f8912aa5a6841/3ad4a6891a3905e96532a312932fdf3a8216aec2-1600x599.png" alt="" /><p>Con las Vistas de Datos configuradas, podemos volver a Analytics &gt; Discovery y comenzar las validaciones.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltba3729c60068e8a0/6a17fe01e9ea87ba2aa9c82a/422c4b2b51abae6580cad25085d1b8a365fc6b9e-1294x850.png" alt="" /><p>Aquí, tras seleccionar productos DataView y buscar el término "tablet", no obtenemos resultados, aunque sabemos que existen productos como "Kindle Paperwhite" y "Apple iPad Air".</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2c6a383dd4cb0157/6a17fe02577262671d1bce0c/e4ae3a785fdd93f48d7c7d204185ded149126f2c-1600x862.png" alt="" /><h4>Buscar en el índice de <code>products_02</code> (sinónimos de soporte)</h4><p>Al realizar la misma consulta en la Vista de Datos "<strong>products_synonyms</strong>", que soporta sinónimos, los productos se recuperaron con éxito. Esto demuestra que el conjunto de sinónimos configurado funciona correctamente, cerciorando que diferentes variaciones de los términos buscados devuelvan los resultados esperados.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt986b4706e2f70014/6a17fe043e9e454edbba16d3/e609749c39e90d5c82fa846af6124679dd62bcb8-1600x526.png" alt="" /><p>Podemos lograr el mismo resultado ejecutando la misma consulta directamente en Kibana DevTools. Simplemente busca en el índice de products_02 usando la API de búsqueda de Elasticsearch:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbe829a3c4d7aac60/6a17fe05e8fbce03d73a1bd7/504d0d1f96dcfbceb309063dc0716bcee64ad2f8-1600x870.png" alt="" /><h2>Conclusión</h2><p>La implementación de sinónimos en Elasticsearch mejoró la precisión y cobertura de las búsquedas en catálogos de productos. El diferenciador clave era el uso de un <strong>LLM</strong>, que generaba sinónimos automáticamente y contextualmente, eliminando la necesidad de listas predefinidas. El modelo analizó nombres y categorías de productos, cerciorando sinónimos relevantes para el comercio electrónico.</p><p>Además, la <strong>API de Sinónimos</strong> simplificó la gestión de diccionarios, permitiendo modificar dinámicamente los conjuntos de sinónimos. Con este enfoque, la búsqueda se volvió más flexible y adaptable a diferentes patrones de consulta de usuario.</p><p>Este proceso puede mejorar continuamente con nuevos datos y ajustes de modelos, cerciorando una experiencia de investigación cada vez más eficiente.</p><h2>Referencias</h2><p><strong>Ejecuta 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>Sinónimos API</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[Relevancia]]></category>
    <category><![CDATA[Conceptos básicos]]></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[Escalar modelos de interacción tardía en Elasticsearch: parte 2]]></title>
    <description><![CDATA[Este artículo analiza técnicas para preparar los vectores de interacción tardía para las cargas de trabajo de producción a gran escala, como reducir el uso de espacio en disco y mejorar la eficiencia de cómputo.]]></description>
    <content:encoded><![CDATA[<p>En nuestro <a href="https://www.elastic.co/search-labs/blog/elastiacsearch-colpali-document-search">blog anterior sobre ColPali</a>, analizamos cómo crear aplicaciones de búsqueda visual con Elasticsearch. Nos centramos en el valor que modelos como ColPali aportan a nuestras aplicaciones, pero presentan inconvenientes de rendimiento en comparación con la búsqueda vectorial con bicodificadores como E5.</p><p>Partiendo de los ejemplos de <a href="https://www.elastic.co/search-labs/blog/elastiacsearch-colpali-document-search">la parte 1</a>, este blog analiza cómo usar diferentes técnicas y el poderoso kit de herramientas de búsqueda vectorial de Elasticsearch para preparar vectores de interacción tardía para cargas de trabajo de producción a gran escala.</p><p>Los ejemplos de código completos se pueden encontrar en <a href="https://github.com/elastic/elasticsearch-labs/tree/main/supporting-blog-content/colpali">GitHub.</a></p><h2>Desafíos de los modelos de interacción tardía</h2><p>ColPali crea más de 1000 vectores por página para los documentos de nuestro índice.</p><p>Esto plantea dos desafíos al trabajar con vectores de interacción tardía:</p><ol><li><p>Espacio en disco: almacenar todos estos vectores en los discos implicará un uso considerable de almacenamiento, lo que será costoso a escala.</p></li><li><p>Cómputo: al clasificar los documentos mediante la comparación <code>maxSimDotProduct()</code>, necesitamos comparar todos estos vectores de cada documento con los N vectores de nuestra búsqueda.</p></li></ol><p>Veamos algunas técnicas para abordar estos problemas.</p><h2>Técnicas para optimizar modelos de interacción tardía</h2><h3>Vectores de bits</h3><p>Para reducir el espacio en disco, podemos comprimir las imágenes en vectores de bits. Podemos usar una función sencilla en Python para transformar nuestros multivectores en vectores 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>El principio básico de la función es simple: los valores mayores que 0 se convierten en 1 y los valores menores que 0 se convierten en 0. Esto da como resultado un arreglo de 0 y 1, que luego se convierte en una cadena hexadecimal que representa el vector de bits.</p><p>Para nuestro mapping de índice, establecemos el parámetro <code>element_type</code> en <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>Después de haber escrito todos nuestros nuevos vectores de bits en nuestro índice, podemos clasificar nuestros vectores de bits usando el siguiente código:</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>A cambio de una pequeña pérdida de precisión, esto nos permite utilizar la distancia de Hamming (<code>maxSimInvHamming(...)</code>), la cual aprovecha optimizaciones como máscaras de bits, SIMD, etc. Obtén más información sobre <a href="https://www.elastic.co/search-labs/blog/bit-vectors-in-elasticsearch">los vectores de bits y la distancia de Hamming en nuestro blog</a>.</p><p>De forma alternativa, podemos no convertir nuestro vector de búsqueda en vectores de bits y realizar una búsqueda con el vector de interacción tardía de fidelidad completa:</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 del uso de vectores de bits para optimizar modelos de interacción tardía" /><p>Esto comparará nuestros vectores usando una función de similitud asimétrica.</p><p></p><p>Pensemos en una distancia de Hamming regular entre dos vectores de bits. Supongamos que tenemos un vector de documento <em>D:</em></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd4b6ece1ec4dedac/6a17f4694b055d248143234e/366a70a23e37d403788327b7aefc873fd4482f5e-1235x86.png" alt="" /><p>Y un vector de búsqueda  <em>Q:</em></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7721df9c8f0d84f1/6a17f46b3e03d77cf54f2dcb/978ec31e0afbc0eaebf548a015b628c0cad84625-1247x84.png" alt="" /><p></p><p>La cuantificación binaria simple transformará los vectores <em>D</em> en <code>10101101</code> y <em>Q</em> en <code>11111011</code>. Para encontrar la distancia de Hamming, necesitamos matemáticas de bits directas; es extremadamente rápido. En este caso, la distancia de Hamming es <code>01010110</code>, que tiene un recuento de bits de 4. Así que, el puntaje se convierte en el inverso de esa distancia de Hamming. Hay que recordar que cuanto más vectores similares haya, menor será la distancia de Hamming, por lo que invertirla permite que los vectores más similares tengan una puntuación más alta. Concretamente aquí, el puntaje sería 1/4 = <code>0.25</code>.</p><p>Sin embargo, observa cómo perdemos la magnitud de cada dimensión. Un <code>1</code> es un <code>1</code>. Así que, para <em>Q</em>, la diferencia entre <code>0.01</code> y <code>0.79</code> desaparece. Como simplemente estamos cuantizando según <code>&gt;0</code>, podemos hacer un pequeño truco donde el vector Q no está cuantizado. Esto no permite realizar operaciones matemáticas bit a bit extremadamente rápidas, pero mantiene bajo el costo de almacenamiento, ya que D sigue cuantificado.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blted50315518e2d599/6a17f46c414c6463709452d3/508e8498ba969534d2a0131d431c75735fc27cb9-1399x611.png" alt="" /><p>En resumen, esto conserva la información proporcionada en <em>Q</em>, lo que aumenta la calidad de estimación de distancia y mantiene el almacenamiento bajo.</p><p>El uso de vectores de bits nos permite ahorrar significativamente en espacio en disco y carga computacional en el momento de la búsqueda. Pero hay más que podemos hacer.</p><h3>Vectores promedio</h3><p>Para escalar nuestra búsqueda a cientos de miles de documentos, ni siquiera las ventajas de rendimiento que nos ofrecen los vectores de bits serán suficientes. Para escalar a este tipo de cargas de trabajo, querremos aprovechar la estructura de índice HNSW de Elasticsearch para la búsqueda vectorial.</p><p>ColPali genera alrededor de mil vectores por documento, lo que es demasiado para agregar a nuestro grafo HNSW. Por lo tanto, necesitamos reducir el número de vectores. Para esto, se puede crear una única representación del significado del documento promediando todos los vectores del documento que genera ColPali al incrustar nuestra imagen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc053425fbfcf8de8/6a17f46f148009faf1b488aa/7c3b4dffb70bd95f67deb35f8c01e73c5286c2ab-1476x1102.png" alt="Vector promedio sobre todos los vectores de interacción tardía" /><p>Por ahora, esto no es posible dentro de Elastic, por lo que tendremos que procesar previamente los vectores antes de ingestarlos en Elasticsearch. </p><p>Podemos hacer esto con Logstash o pipelines de ingesta, pero aquí usaremos una función sencilla en 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>Además, normalizamos el vector; de este modo, podremos usar la similitud por producto punto.</p><p>Luego de transformar todos nuestros vectores de ColPali en vectores promedio, podemos indexarlos en nuestro 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>Debemos tener en cuenta que esto aumentará el uso total del disco, ya que estamos almacenando más información junto con nuestros vectores de interacción tardíos. Además, usaremos RAM adicional para almacenar el grafo HNSW, lo que nos permitirá escalar la búsqueda a miles de millones de vectores. Para reducir el uso de RAM, podemos utilizar nuestra popular <a href="https://www.elastic.co/search-labs/blog/optimized-scalar-quantization-elasticsearch">característica BBQ</a>. A cambio, obtenemos resultados de búsqueda rápidos en conjuntos de datos masivos que de otra manera no serían posibles.</p><p>Ahora, simplemente hacemos una búsqueda con la consulta knn para encontrar nuestros documentos más 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>La mejor coincidencia anterior, lamentablemente, cayó al tercer rango.</p><p>Para solucionar este problema, podemos realizar una recuperación en varias etapas. En nuestra primera etapa, utilizamos la búsqueda knn para buscar los mejores candidatos para nuestra búsqueda en millones de documentos. En la segunda etapa, solo reclasificamos los principales k (aquí: 10) con la mayor fidelidad de los vectores de interacción tardía de 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 del uso de vectores promedio para optimizar modelos de interacción tardía" /><p>Aquí, usamos el <a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.18/retriever.html#rescorer-retriever">recalificador</a> introducido en 8.18 para reclasificar nuestros resultados. Después de la recalificación, vemos que nuestra mejor coincidencia está nuevamente en la primera posición. </p><p>Nota: En una aplicación de producción, podemos usar un valor de k mucho mayor que 10, ya que la función de similitud máxima sigue siendo comparativamente eficiente.</p><h3>Agrupación de tokens</h3><p>La agrupación de tokens reduce la longitud de la secuencia de incrustaciones de vectores múltiples al agrupar información redundante, como parches de fondo blanco. Esta técnica reduce el número de incrustaciones, al tiempo que conserva la mayor parte de la señal de la página.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3d643e6ac908f640/6a17f4754b055d3783432352/09eae0b768f4b450e555d7e53e57561bd52de2c0-1412x1056.png" alt="Agrupación de tokens para optimizar modelos de interacción tardía" /><p>El agrupamiento de tokens funciona mediante la agrupación de incrustaciones similares de tokens dentro de un documento en clústeres con un algoritmo de agrupamiento en clusters. A continuación, se calcula la media de los vectores de cada grupo para crear una representación única y agregada. Este vector agregado reemplaza los tokens originales en el grupo, lo que reduce el número total de vectores sin una pérdida significativa de la señal del documento.</p><p>El documento de ColPali propone un valor inicial de factor de agrupación de 3 para la mayoría de los sets de datos, lo que mantiene el 97,8 % del rendimiento original y al mismo tiempo reduce el número total de vectores en un 66,7 %. </p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2d78a15c6944a1ea/6a17f477414c64a2929452d9/343cc9eaf54af8c7a125d4115838f3c7d5659de0-1600x1007.png" alt="Factor de agrupación para optimizar modelos de interacción tardía" /><p>Pero debemos tener cuidado: el set de datos “Shift”, que contiene documentos muy densos y con mucho texto con poco espacio en blanco, disminuye rápidamente en rendimiento a medida que aumentan los factores de grupo.</p><p>Para crear los vectores agrupados, podemos usar la 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>Ahora tenemos un vector que se redujo en aproximadamente un 66,7 % en sus dimensiones. Lo indexamos como siempre y podemos hacer búsquedas en él con nuestra función <code>maxSimDotProduct()</code>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc460c14031814ede/6a17f4794202292bf629f72d/2412c5db7d79a590b96d42fe01f140c42f010612-1600x481.png" alt="Resultados de modelos de interacción tardía" /><p>Podemos obtener buenos resultados de búsqueda a costa de cierta precisión en los resultados.</p><p>Sugerencia: con un pool_factor más alto (100-200), también puedes tener un término medio entre la solución vectorial promedio y la que analizamos aquí. Con unos 5 a 10 vectores por documento, es viable indexarlos en un campo anidado para aprovechar el índice HNSW.</p><h2>Codificador cruzado vs. interacción tardía vs. bicodificador</h2><p>Con lo que hemos aprendido hasta ahora, ¿dónde se sitúan los modelos de interacción tardía, como ColPali o ColBERT, cuando los comparamos con otras técnicas de recuperación mediante AI?</p><p>Aunque la función max sim es más económica en comparación con los codificadores cruzados, todavía requiere muchas más comparaciones y cálculos que la búsqueda vectorial con codificadores binarios, en la que solo se comparan dos vectores para cada par de búsqueda-documento. </p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbfd97f3bba3e5b17/6a17f47be31791b0052d5943/75e1fc9e601aa7a6e88f137565c1919166c7a71c-1480x458.png" alt="Codificador cruzado vs. modelos de interacción tardía vs. bicodificador" /><p>Por eso, nuestra recomendación para modelos de interacción tardía es usarlos generalmente solo para reclasificar los k mejores resultados de búsqueda. También reflejamos esto en el nombre del tipo de campo: rank_vectors.</p><p>¿Pero qué pasa con el codificador cruzado? ¿Son mejores los modelos de interacción tardía porque son más baratos de ejecutar en el momento de la búsqueda? Como suele suceder, la respuesta es: depende. Los codificadores cruzados generalmente producen resultados de mayor calidad, pero requieren una gran cantidad de recursos de cómputo porque los pares de búsqueda-documento necesitan hacer un pase completo a través del modelo transformador. También se benefician del hecho de que no requieren indexar vectores y pueden operar de manera sin estado. Esto da como resultado lo siguiente:</p><ul><li><p>Menor uso de espacio en disco.</p></li><li><p>Un sistema más sencillo.</p></li><li><p>Mayor calidad de los resultados de búsqueda</p></li><li><p>Una latencia más alta y, por lo tanto, la imposibilidad de realizar una reclasificación tan profunda.</p></li></ul><p>Por otro lado, los modelos de interacción tardía pueden descargar parte de este cálculo en el índice, lo que hace que la búsqueda sea más económica. El precio que pagar es la necesidad de indexar los vectores, lo que aumenta la complejidad de nuestros pipelines de indexación y requiere más espacio en disco para almacenarlos.</p><p>En el caso concreto de ColPali, el análisis de la información de las imágenes resulta muy costoso, porque contienen una gran cantidad de datos. En este caso, el equilibrio se desplaza a favor de utilizar un modelo de interacción tardía como ColPali porque evaluar esta información en el momento de la búsqueda consumiría demasiados recursos o sería demasiado lento. </p><p>Para un modelo de interacción tardía como ColBERT, que funciona con datos de texto como la mayoría de los codificadores cruzados (por ejemplo, elastic-rerank-v1), la decisión podría inclinarse más hacia usar el codificador cruzado para beneficiarse del ahorro y la simplicidad en disco.</p><p>Te recomendamos que evalúes las ventajas y desventajas para tu caso de uso y experimentes con las diferentes herramientas que Elasticsearch te proporciona para crear las mejores aplicaciones de búsqueda.</p><h2>Conclusión</h2><p>En este blog, analizamos diversas técnicas para optimizar modelos de interacción tardía como ColPali para búsquedas vectoriales a gran escala en Elasticsearch. Si bien los modelos de interacción tardía proporcionan un sólido equilibrio entre la eficiencia de recuperación y la calidad de clasificación, también presentan desafíos relacionados con el almacenamiento de información y el cómputo.</p><p>Para abordar estos desafíos, analizamos:</p><ul><li><p><strong>Vectores de bits</strong> para reducir significativamente el espacio en disco, al tiempo que se aprovechan los cálculos de similitud eficientes como la distancia de Hamming o la similitud máxima asimétrica.</p></li><li><p><strong>Promedio de vectores</strong> para comprimir múltiples inserciones en una sola representación densa, lo que permite una recuperación eficiente con indexación HNSW.</p></li><li><p><strong>Agrupación de tokens</strong> para fusionar de forma inteligente las incorporaciones redundantes mientras se mantiene la integridad semántica, lo que reduce la sobrecarga computacional en el momento de la búsqueda.</p></li></ul><p>Elasticsearch ofrece un conjunto potente de herramientas para personalizar y optimizar las aplicaciones de búsqueda en función de tus necesidades. Ya sea que priorices la velocidad de recuperación, la calidad de clasificación o la eficiencia de almacenamiento, estas herramientas y técnicas te permiten equilibrar el rendimiento y la calidad según lo que necesites para tus aplicaciones reales.</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[Relevancia]]></category>
    <category><![CDATA[Base de datos vectorial]]></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>