[!NOTE] Traducción automática Este artículo se tradujo automáticamente a partir de la versión original en inglés.

La arquitectura de clasificación de búsquedas en 2026: BM25, Embeddings, codificadores cruzados y LLM Reranking

La búsqueda debe satisfacer tanto la intención exacta como la semántica. Una consulta como “auriculares inalámbricos” debe coincidir con esas palabras, pero el orden final también puede depender de la calidad del producto, las preferencias del usuario y la disponibilidad. Ningún método de clasificación por sí solo logra manejar adecuadamente todos estos factores.

Este artículo construye la pila paso a paso: recuperación mediante BM25, embeddings denso, Fusión de rangos recíprocos, reranking de codificador cruzado, y finalmente el ranking por lista de LLM. A demo en funcionamiento benchmarks en cada una de las etapas del proceso de búsqueda de productos de Amazon ESCI dataset.

TL;DR: Construya el sistema de búsqueda en fases medibles. Comience con BM25, añada la recuperación densa cuando mejore el recuerdo en sus consultas, fusione los resultados solo si los dos mecanismos de recuperación presentan errores complementarios, y realice una nueva clasificación solo del conjunto de candidatos que se ajuste al presupuesto de latencia. En esta demostración ESCI del tamaño de una laptop, el pipeline completo mejoró el NDCG@10 de 0,585 a 0,717. Ese resultado es un ejemplo práctico, no una prueba de que toda arquitectura de producción necesite las cinco fases ni un LLM en línea.


Seleccionar fases según el modo de fallo

La pila de producción funciona como un embudo, pero el tipo de embudo adecuado depende de la consulta y de las necesidades del negocio.

Caso de usoPila inicial del candidatoValidar
Búsqueda de productosBM25 + recuperación densa + RRF + codificador cruzadoRecuperación de atributos, sustituciones, latencia, restricciones empresariales
Búsqueda de documentaciónRecuperación híbrida + codificador cruzado
Soporte para la deflexiónRecuperación híbrida + verificación de citacionesRecuperación de precisión, anclaje en contexto y abstención
Mercado o listadosFiltros léxicos + recuperación densa + negocio rerankerDisponibilidad, actualidad, política y diversidad de vendedores
Pequeño corpus internoLínea de referencia BM25, seguida de un rerankerSi la discrepancia en el vocabulario justifica la utilización de un índice denso
Búsqueda legal o médica de alto riesgoRecuperación orientada al recuerdo más revisión por expertosCobertura, procedencia y abstención calibrada

Comience utilizando BM25 como línea de base. Incorpore una recuperación densa cuando la discrepancia en el vocabulario perjudique la tasa de recuperación. Añada un codificador cruzado cuando la primera página contenga los candidatos adecuados pero en el orden incorrecto. Introduzca un LLM únicamente una vez que pueda permitirse el retraso adicional y sea capaz de evaluar las decisiones de clasificación.

Cómo llegamos hasta aquí

Dicho stack resulta más fácil de comprender si se divide en tres capas. La recuperación léxica permite encontrar términos exactos, la recuperación densa subsana las carencias del vocabulario, y rerankers se utilizan para comparar en detalle a los candidatos más sólidos.

BM25 y recuperación léxica

Durante décadas, BM25 Era el valor predeterminado. Se trata de un modelo probabilístico que califica los documentos en función de la frecuencia de los términos de consulta dentro de ellos, normalizada mediante la longitud del documento y la frecuencia inversa de documentos (IDF).

BM25 muestra un rendimiento excelente cuando los términos literales reflejan con precisión la intención del usuario: códigos de error, códigos SKU de productos, nombres y identificadores como API. Su principal limitación radica en la incompatibilidad léxica. Por ejemplo, una consulta como “portátil barato” podría pasar por alto un documento sobre un “ordenador portátil económico” si el texto indexado no cuenta con ningún elemento que establezca una relación entre ambas expresiones.

Dicho esto, BM25 constituye una línea de base sólida. Obtiene una puntuación media de 0.429 en nDCG@10 en todos los casos. BEIR benchmark’s 18 datasets y Sigue siendo mejor que algunos modelos neuronales. en tareas de recuperación argumentativa como Touche-2020.

Recuperación densa y embeddings

Los codificadores de estilo BERT han hecho que la recuperación densa sea viable en la práctica. Estos modelos mapean las consultas y los documentos a un espacio vectorial compartido, para posteriormente ordenar los resultados candidatos mediante una función de similitud como la similitud coseno o el producto escalar.

La arquitectura de bi-encoder (o “dos torres”) procesa la consulta y el documento de forma independiente mediante torres codificadoras separadas, generando vectores de longitud fija embeddings. Los vectores de documento pueden calcularse y indexarse previamente de forma offline, para luego ser recuperados rápidamente mediante algoritmos de Vecino Más Cercano Aproximado (ANN). Actualmente, términos como “portátil económico” y “notebook de bajo presupuesto” aparecen muy cerca uno del otro en el espacio vectorial.

Algunos bi-encoders emplean una arquitectura siamesa, tal como ocurre en Sentence-BERT, En este enfoque, ambos lados comparten los mismos pesos. Otros sistemas emplean torres de consulta y de documentos independientes. La agrupación de vectores, el tamaño del vector, la función de similitud y el objetivo de entrenamiento son decisiones propias del modelo, y no características inherentes a todos los recuperadores densos.

Estos modelos se entrenan mediante aprendizaje contrastivo, generalmente con el InfoNCE pérdida. Dado un lote de pares (consulta, documento_positivo), el objetivo consiste en maximizarla. sim(query, positive_doc) mientras se minimiza sim(query, negative_docs). Los negativos provienen de los positivos de otras consultas dentro del mismo lote (negativos intra-lote). Un parámetro de temperatura τ\tau controla qué tan pronunciada es la distribución: valores más bajos obligan al modelo a realizar distinciones más precisas entre positivos y negativos.

Los datos de entrenamiento suelen ser más importantes que la dimensión embedding. Los modelos de recuperación aprenden a partir de pares consulta-positivo y de negativos difíciles seleccionados cuidadosamente: documentos plausibles pero no relevantes. La sección posterior dedicada al entrenamiento muestra cómo SimANS evita tanto los negativos triviales como los falsos negativos probables.

El costo radica en el cuello de botella de representación. Los bi-encoders comprimen toda la nuancia semántica en un vector de tamaño fijo, por lo que con frecuencia pasan por alto las interacciones detalladas entre términos de consulta específicos y contenidos de documentos concretos.

Codificadores cruzados y LLMs

Codificadores cruzados (Nogueira y Cho, 2019) Inyectar la consulta y el documento en un Transformer como una secuencia concatenada.[CLS] Query [SEP] Document), por lo que cada token de consulta puede prestar atención a cada token de documento mediante autointeracción total. Dicha interacción profunda permite capturar matices que la codificación independiente no logra detectar.

LLM reranking emplea un modelo estimulado para comparar varios candidatos de forma simultánea. RankGPT Presentó resultados muy sólidos de tipo zero-shot y a nivel de lista con GPT-4 en los benchmarks evaluados, pero la estabilidad de las salidas, el costo computacional y la adecuación al dominio siguen requiriendo pruebas independientes.

Dado que estas puntuaciones no pueden calcularse de antemano para consultas arbitrarias, reranking se aplica tras la recuperación de los resultados. Dicha asimetría en los costes es la razón que impulsa la estructura en forma de embudo de múltiples etapas.


El embudo multinivel

Ejecutar un codificador cruzado costoso o LLM sobre millones de documentos no es viable, por lo que las arquitecturas de búsqueda modernas emplean un sistema en forma de embudo. Cada etapa reduce progresivamente el conjunto de documentos candidatos, al tiempo que aumenta la complejidad del modelo.

Un modelo complejo es demasiado lento para evaluar todo el corpus, mientras que un recuperador económico carece de precisión en la fase final. El embudo utiliza cada modelo únicamente allí donde su costo resulta razonable.

Embudo de clasificación multietapa

EtapaEscala de entradaObjetivo principalMétodos típicosMedición de salida
RecuperaciónCorpus o índiceRecuperación de candidatosBM25, bi-encodersRecuperación en el punto de corte de candidatos
PreclasificaciónGran conjunto de candidatosFiltrado económicoModelos ligeros, reglasRecuperación retención por milisegundo
Ranking completoLista de candidatos seleccionadosCalidad de alto rangoCodificadores cruzados, LLMsNDCG/MRR, latencia, costo
MezclaListas finales ordenadas o posiciones asignadasRestricciones y mezclaReglas, clasificación multiobjetivoPolítica, diversidad y límites operativos empresariales

El proceso de recuperación establece el límite máximo, y reranking se encarga de optimizar el trabajo dentro de ese marco. Si un documento relevante no logra superar la fase de recuperación, ningún modelo posterior podrá recuperarlo.


La demostración: un proceso de cinco etapas pipeline

Para concretar esto, he desarrollado un stack de clasificación y búsqueda demostración que ejecuta un pipeline de cinco etapas sobre el Amazon ESCI Búsqueda de productos benchmark. Cada etapa se mide de forma independiente para que pueda determinar con precisión de dónde provienen los mejoras reales.

Demostración de la arquitectura Pipeline

El pipeline:

  1. Recuperación dispersa BM25 — línea de base léxica (rank_bm25)
  2. Recuperación con bi-encoder denso — generación de candidatos semánticos (all-MiniLM-L6-v2)
  3. Fusión híbrida de RRF — fusión basada en rangos de resultados dispersos y densos
  4. Codificador cruzado reranking — puntuaciones de relevancia entre pares (ms-marco-MiniLM-L-12-v2)
  5. LLM por lista reranking — comparación solicitada de la lista final reducida (Ollama, API o modelo local)

Los pasos del 1 al 3 corresponden a la fase de retrieval del embudo (con el objetivo de maximizar el recuerdo); los pasos del 4 al 5 corresponden a la fase de full ranking (con el fin de maximizar la precisión). La demostración omite las fases de pre-ranking y blending. Con aproximadamente 8.500 documentos, es posible enviar todos los resultados híbridos directamente a reranking.

Inicio rápido

git clone https://github.com/slavadubrov/search-ranking-stack.git
cd search-ranking-stack
uv sync

# Download and sample ESCI dataset (~2.5GB download, ~5MB sample)
uv run download-data

# Run the full pipeline (without LLM reranking)
uv run run-all

# Run with LLM reranking via Ollama
uv run run-all --llm-mode ollama

Dataset y muestreo: Amazon ESCI

La demostración utiliza las consultas de compras de Amazon Dataset (ESCI) provenientes de KDD Cup 2022 — una búsqueda de productos real benchmark con etiquetas de relevancia graduadas en cuatro niveles:

EtiquetaObtener
Exacto (E)3Cumple con todos los requisitos de la consulta.Auriculares inalámbricos Sony WH-1000XM5
Sustituir (S)2Alternativa funcionalAuriculares con cable e adaptador Bluetooth
Complemento (C)1Elemento útil relacionadoEstuche para auriculares
Irrelevante (I)0No existe una relación significativa.Cable de carga USB

La relevancia graduada es importante porque permite utilizar el NDCG (Normalized Discounted Cumulative Gain), el cual distingue entre un ranking “perfecto” y uno “solo adecuado”. Las métricas binarias tratan ambos casos como igualmente relevantes y no pueden diferenciar los distintos niveles de relevancia en la misma posición.

Utilicé la demostración. small_version Ejemplo: alrededor de 500 consultas, 8.500 productos y 12.000 juicios. Es lo suficientemente pequeño como para ejecutarse en una laptop, pero demasiado reducido y específico del dominio como para establecer un sistema de clasificación en entorno de producción. Úselo para reproducir las distintas fases del proceso e inspeccionar los modos de fallo; emplee consultas representativas que no hayan sido utilizadas anteriormente para tomar decisiones sobre su despliegue.


Recuperación de información: búsqueda híbrida

La función de la capa de recuperación es maximizar el recuerdo: es necesario extender la red de búsqueda lo más posible para que nada relevante se escape.

BM25: la línea de referencia léxica

BM25 calcula las puntuaciones de los documentos en función de la superposición de términos con la consulta, aplicando una saturación por frecuencia de términos y una normalización por longitud del documento:

\text{BM25}(q, d) = \sum_{t \in q} \text{IDF}(t) \cdot \frac{tf(t,d) \cdot (k_1 + 1)}{tf(t,d) + k_1 \cdot (1 - b + b \cdot |d|\(\text{avgdl}\)

¿Dónde? \text{IDF}(t) es la frecuencia de documento inversa del término tt; tf(t,d)tf(t,d) es la frecuencia del término en el documento dd.|d|eslalongituddeldocumento,mientrasquees la longitud del documento, mientras que\text{avgdl}representalalongitudmediadelosdocumentosentodoelcorpus.Haydosparaˊmetrosclave:representa la longitud media de los documentos en todo el corpus. Hay dos parámetros clave:k_1(tıˊpicamenteentre1,2y2,0)regulalasaturacioˊndelTF,esdecir,larapidezconlaquelosteˊrminosrepetidosdejandeaportarvalor,y(típicamente entre 1,2 y 2,0) regula la saturación del TF, es decir, la rapidez con la que los términos repetidos dejan de aportar valor, yb$ (generalmente 0,75) controla la normalización de la longitud de los documentos.

La implementación es breve. Se trata de una simple tokenización basada en espacios en blanco. rank_bm25:

# src/search_ranking_stack/stages/s01_bm25.py

from rank_bm25 import BM25Okapi

def run_bm25(data: ESCIData, top_k: int = 100):
    doc_ids = list(data.corpus.keys())
    tokenized_corpus = [text.lower().split() for text in data.corpus.values()]

    bm25 = BM25Okapi(tokenized_corpus)

    results = {}
    for query_id, query_text in data.queries.items():
        scores = bm25.get_scores(query_text.lower().split())
        top_indices = np.argsort(scores)[::-1][:top_k]
        results[query_id] = {doc_ids[idx]: float(scores[idx]) for idx in top_indices}

    return results

BM25 alcanza un Recall@100 de 0.741: el 74 % de los productos relevantes aparecen en alguna posición dentro de los 100 primeros resultados. No está mal para un método puramente léxico, pero el 26 % de los elementos relevantes queda invisible en todas las etapas posteriores del proceso.

Recuperación con codificador bi-dense

El bi-encoder mapea de forma independiente las consultas y los documentos hacia un espacio compartido embedding:

# src/search_ranking_stack/stages/s02_dense.py

from sentence_transformers import SentenceTransformer

model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")

# Encode corpus once, cache to disk
corpus_embeddings = model.encode(
    doc_texts,
    batch_size=128,
    normalize_embeddings=True,  # Cosine sim = dot product
    convert_to_numpy=True,
)

# At query time: encode query, compute dot product
query_embeddings = model.encode(query_texts, normalize_embeddings=True)
similarity_matrix = np.dot(query_embeddings, corpus_embeddings.T)

Con embeddings normalizado, la similitud coseno se reduce a un producto escalar. La demostración calcula la matriz completa de consulta por corpus, ya que 8.500 documentos caben cómodamente en memoria; normalmente, un corpus de producción utilizaría un índice de vecino más cercano aproximado. En esta muestra, all-MiniLM-L6-v2 Aumenta el Recall@100 de 0.741 a 0.825.

Cómo aprenden los bi-encoders representaciones adecuadas

El entrenamiento del bi-encoder suele realizarse en dos fases. Primero, el modelo se entrena previamente en Inferencia de Lenguaje Natural (NLI) y Similitud Textual Semántica (STS) datasets, técnicas que permiten adquirir una comprensión semántica de uso general; de este modo, el modelo aprende que frases como “un gato está sentado sobre una alfometa” y “un felino descansa sobre una colcha” deben presentar una embeddings similar. Segundo, se realiza un ajuste fino con datos específicos para la recuperación de información, como MS MARCO, donde el modelo comprende que una consulta de búsqueda y su pasaje relevante deben encontrarse más cerca que la consulta y los pasajes irrelevantes.

El componente esencial en la segunda fase es la extracción de negativos duros. Los negativos aleatorios (por ejemplo, un documento sobre cocina emparejado con una consulta sobre auriculares) son extremadamente fáciles de distinguir; el modelo no aprende nada de ellos. En su lugar, se utiliza al propio modelo actual para identificar documentos que este clasifica como altamente relevantes, pero que en realidad no lo son.

El SimANS El enfoque de (Simple Ambiguous Negatives Sampling) formaliza este proceso: se clasifica a todos los documentos mediante el bi-encoder actual y, a continuación, se descartan los negativos fáciles (con una clasificación demasiado baja, ya que el modelo puede manejarlos por sí mismo) y los posibles falsos negativos (con una clasificación demasiado alta, ya que podrían ser relevantes pero no estar etiquetados). El “terreno intermedio difícil” genera la señal de aprendizaje máxima.

# What a training triplet looks like after hard negative mining
training_triplet = {
    "query": "wireless noise canceling headphones",
    "positive": "Sony WH-1000XM5 Wireless Noise Cancelling Headphones",
    "negative": "Sony headphone replacement ear pads",  # Hard negative: same brand, related product, but wrong intent
}
# The bi-encoder must learn that "ear pads" is NOT what the user wants,
# even though it shares many tokens with the positive document.

La función de pérdida contrastiva (InfoNCE) une todo esto. Para cada consulta qq con un documento positivo d+d^+ y un conjunto de documentos negativos {d1,,dn}\{d^-_1, \ldots, d^-_n\}:

L=logesim(q,d+)/τesim(q,d+)/τ+i=1nesim(q,di)/τ\mathcal{L} = -\log \frac{e^{\text{sim}(q, d^+) / \tau}}{e^{\text{sim}(q, d^+) / \tau} + \sum_{i=1}^{n} e^{\text{sim}(q, d^-_i) / \tau}}

Donde sim(q,d)\text{sim}(q, d) representa la similitud coseno entre la consulta y el documento embeddings, y τ\tau es el parámetro de temperatura (típicamente entre 0,05 y 0,1) que controla qué tan nítida es la distribución; valores más bajos hacen que la función de pérdida sea más sensible a los negativos contundentes. Básicamente se trata de un entropía cruzada softmax: Se debe elevar la similitud de la pareja positiva con respecto a todos los negativos. Cuando τ\tau es pequeño, incluso diferencias leves en la similitud generan gradientes elevados, lo que obliga al modelo a realizar distinciones de mayor precisión.

Entrenamiento de bi-encoder Pipeline

Serving bi-encoder embeddings a gran escala

La ventaja arquitectónica de un bi-encoder radica en la división offline/online. Los documentos embeddings se calculan en el momento del índiceo y se almacenan en un índice vectorial. En el momento de la consulta, el sistema codifica la misma y busca entre esos vectores almacenados. La latencia depende del encoder, del hardware, del índice, de los filtros y del objetivo de recuperación, por lo que es necesario realizar un análisis detallado de cada uno de estos dos pasos por separado.

En la demostración, los cálculos son modestos: 8.500 documentos × 384 dimensiones × 4 bytes por número flotante = ~13 MB de embeddings. A escala de producción, las cifras dejan de ser modestas: 1 mil millones de documentos con embeddings de 768 dimensiones requieren aproximadamente 3 TiB de almacenamiento. Es aquí donde entra en juego la cuantización (compresión de números flotantes de 32 bits en enteros de 8 bits). cuantización de productos (descomposición de vectores en subespacios), y índices respaldados por SSD como DiskANN Entra. El Sección de indexación por vectores densos Aborda los algoritmos de índice.

Bi-Encoder Serving Pipeline

¿Por qué probar la recuperación híbrida?

Los dos métodos suelen fallar de manera distinta. BM25 es especialmente adecuado para nombres propios, códigos SKU de productos y códigos de error. La recuperación densa puede solucionar desajustes en el vocabulario, como en el caso de “laptop barato” frente a “computadora portátil económica”. Que la fusión sea útil depende de la frecuencia con la que se presenten estos casos complementarios en el conjunto de consultas objetivo.

Un experimento habitual a continuación es la búsqueda híbrida: se ejecutan ambos métodos de recuperación y, posteriormente, se fusionan sus listas ordenadas.

Fusión de rangos recíprocos (RRF)

BM25 y la recuperación densa generan puntuaciones con significados y escalas distintas. Por lo tanto, una combinación lineal requiere calibración y validación cada vez que cambian los recuperadores o el corpus.

Búsqueda híbrida con RRF

Fusión de rangos recíprocos (Cormack et al., 2009) descarta por completo las puntuaciones brutas y utiliza únicamente la posición de clasificación:

RRF(d)=rRankings1k+rank(d,r)\text{RRF}(d) = \sum_{r \in \text{Rankings}} \frac{1}{k + \text{rank}(d, r)}

Aquí, kk es una constante de suavizado; 60 es un valor de partida habitual. RRF recompensa los elementos que ocupan posiciones cercanas a la cima en las listas de entrada, sin comparar sus puntuaciones brutas. Evita la calibración de la escala de puntuación, pero los umbrales de recuperación, los pesos y kk siguen requiriendo evaluación.

La implementación:

# src/search_ranking_stack/stages/s03_hybrid_rrf.py

def reciprocal_rank_fusion(ranked_lists, k=60, top_k=100):
    fused_results = {}

    for query_id in all_query_ids:
        rrf_scores = defaultdict(float)

        for results in ranked_lists:
            sorted_docs = sorted(results[query_id].items(),
                                 key=lambda x: x[1], reverse=True)

            for rank, (doc_id, _score) in enumerate(sorted_docs, start=1):
                rrf_scores[doc_id] += 1.0 / (k + rank)

        sorted_rrf = sorted(rrf_scores.items(),
                            key=lambda x: x[1], reverse=True)[:top_k]
        fused_results[query_id] = dict(sorted_rrf)

    return fused_results

El RRF híbrido alcanza un Recall@100 de 0.842 y un NDCG@10 de 0.628, superando por sí solo tanto a BM25 (0.585) como a Dense (0.611). Para que los documentos sobrevivan en la fusión, basta con que obtengan buenos resultados en solo un método.


Codificador cruzado reranking

Al contar con 100 candidatos híbridos por consulta, es posible optar por un modelo de mayor costo. El cross-encoder procesa la consulta y el documento juntos mediante un único Transformer, permitiendo una atención cruzada completa entre todos los tokens.

Bi-Encoder frente a Cross-Encoder

Interacción a nivel de token

La verdadera diferencia radica en la matriz de atención. En un bi-encoder, la atención es bloco-diagonal: los tokens de consulta solo prestan atención a otros tokens de consulta, y los tokens de documento solo lo hacen con otros tokens de documento. Las dos representaciones nunca se encuentran a nivel de token; solo se intersecan al final mediante un producto escalar. Un cross-encoder calcula la matriz de atención completa, donde cada token de consulta presta atención a cada token de documento y viceversa. Es esta atención cruzada la que permite una interacción profunda a nivel de token.

Arquitectura de atención de codificador cruzado

En un bi-encoder, la consulta “apple” se codifica antes de que se examine ningún documento. Un cross-encoder, por su parte, procesa tanto la consulta como los documentos candidatos simultáneamente, lo que le permite aprovechar su relación a nivel de tokens. Esto puede ser útil en casos como:

La entrada del codificador cruzado se formatea como [CLS] query tokens [SEP] document tokens [SEP]. [CLS] es un token de clasificación cuyo estado oculto final se pasa por una cabeza lineal para generar una única puntuación de relevancia. El segmento embeddings sirve para distinguir los tokens de consulta de los tokens de documento, y [SEP] Marca el límite entre los segmentos.

Cómo se entrena a los cross-encoders

Los cross-encoders pueden aprender a partir de (query, document, relevance_label) Ejemplos con objetivos por punto, por par o por lista. El ejemplo por punto que se muestra a continuación utiliza una única etiqueta de relevancia; no se trata del único diseño de entrenamiento posible.

# Cross-encoder training data format
training_example = {
    "query": "wireless headphones",
    "document": "Sony WH-1000XM5 Wireless Headphones",
    "label": 1.0,  # Relevant
}
# Forward pass: [CLS] hidden state → Linear layer → sigmoid → score
# Loss: binary cross-entropy between predicted score and label

Un clasificador común mapea los resultados finales [CLS] La conversión de dicha representación en una puntuación. Para las etiquetas binarias se puede emplear la entropía cruzada binaria; en el caso de la relevancia graduada, son aplicables pérdidas de tipo regresión, ordinal, entre pares o por lista. Es recomendable elegir el método basándose en métricas de clasificación independientes, en lugar de asumir que un objetivo sea universalmente superior.

La extracción de negativos duros es aún más importante para los codificadores cruzados. en comparación con los bi-encoders. Los cross-encoders son costosos de entrenar, ya que cada ejemplo de entrenamiento requiere una pasada completa hacia adelante a través de la secuencia concatenada; por lo tanto, no se puede permitir desperdiciar recursos de cómputo en ejemplos negativos que son trivialmente fáciles de obtener. La solución práctica consiste en utilizar un bi-encoder para recuperar los K mejores candidatos para cada consulta de entrenamiento y, a continuación, seleccionar negativos difíciles de rangos de posición específicos (por ejemplo, las posiciones del 10 al 100). De este modo, los cross-encoders reciben ejemplos en los que distinguir entre lo relevante y lo irrelevante realmente exige una interacción profunda entre los tokens.

# src/search_ranking_stack/stages/s04_cross_encoder.py

from sentence_transformers import CrossEncoder

model = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-12-v2")

def run_cross_encoder(data, hybrid_results, top_k_rerank=50):
    for query_id, query_text in data.queries.items():
        candidates = list(hybrid_results[query_id].items())[:top_k_rerank]

        # Form (query, document) pairs for joint encoding
        pairs = []
        doc_ids = []
        for doc_id, _ in candidates:
            doc_text = data.corpus.get(doc_id, "")[:2048]
            pairs.append([query_text, doc_text])
            doc_ids.append(doc_id)

        # Score all pairs with full cross-attention
        scores = model.predict(pairs, batch_size=64)

        # Rerank by cross-encoder score
        scored_docs = sorted(zip(doc_ids, scores),
                             key=lambda x: x[1], reverse=True)
        reranked_results[query_id] = {
            doc_id: float(score) for doc_id, score in scored_docs
        }

En la ejecución de la demostración grabada, ms-marco-MiniLM-L-12-v2 Vuelve a ordenar los 50 candidatos por consulta y eleva el valor de NDCG@10 de 0.628 a 0.645. Es necesario medir su latencia en el hardware de despliegue, ya que tanto el modelo, la longitud de las secuencias, el tamaño del lote como runtime influyen directamente en el resultado.

El equilibrio entre velocidad y calidad

¿Por qué no utilizar cross-encoders para todo? Porque la precomputación es imposible. Los bi-encoders de documentos embeddings son independientes de la consulta, por lo que se calculan una sola vez y se almacenan. La salida de un cross-encoder depende tanto de la consulta como del documento simultáneamente. La puntuación de relevancia para “auriculares inalámbricos” junto con un producto de Sony proviene de la atención cruzada completa entre esos tokens específicos. No es posible cachearla ni reutilizarla para una consulta diferente.

Un bi-encoder requiere una codificación de la consulta además de una búsqueda vectorial sobre documentos precomputados embeddings. Un cross-encoder calcula la puntuación de cada par consulta-documento de la lista preliminar, siendo el costo proporcional tanto al número de candidatos como a la longitud de la secuencia. Aunque el agrupamiento por lotes ayuda, evaluar 100.000 candidatos sigue siendo un punto de operación inadecuado; primero se deben recuperar los resultados y luego benchmark seleccionar la lista preliminar más extensa que cumpla con los objetivos de calidad y latencia.

La regla que confirma la demostración es la siguiente: Recall@100 se mantiene constante en 0,842 durante ambas fases de reranking. Reranking permite reordenar los resultados, pero nunca añadir nuevos documentos; el proceso de recuperación establece el límite máximo.


LLM de forma lista reranking

La fase de demostración final utiliza un LLM para realizar una reranking por lista. En lugar de evaluar cada documento de forma independiente, el modelo analiza los 10 mejores resultados y devuelve un orden específico. Inspirado en RankGPT, El prompt hace explícita la comparación relativa, pero también genera limitaciones de contexto, sesgo de posición, fallos en el análisis sintáctico y variabilidad entre ejecuciones.

LLM Reranking Enfoques

La lista por elementos prompt

El plantilla prompt solicita al LLM que tenga en cuenta la jerarquía de relevancia ESCI:

# src/search_ranking_stack/stages/s05_llm_rerank.py

def _create_listwise_prompt(query, documents, max_words=200):
    n = len(documents)

    doc_texts = []
    for i, (doc_id, doc_text) in enumerate(documents, start=1):
        words = doc_text.split()[:max_words]
        doc_texts.append(f"[{i}] {' '.join(words)}")

    return (
        f"I will provide you with {n} product listings, each indicated by "
        f"a numerical identifier [1] to [{n}]. Rank the products based on "
        f'their relevance to the search query: "{query}"\n\n'
        "Consider:\n"
        "- Exact matches should rank highest\n"
        "- Substitutes should rank above complements\n"
        "- Irrelevant products should rank lowest\n\n"
        f"{chr(10).join(doc_texts)}\n\n"
        "Output ONLY a comma-separated list of identifiers: [3], [1], [2], ...\n"
        "Do not explain your reasoning."
    )

Tres modos de ejecución

La demostración admite tres servidores backend para LLM reranking:

ModoModeloCómo funciona
ollamallama3.2:3b (configurable)Lanzamiento local mediante Ollama API
apiclaude-haiku-4-5-20251001Anthropic API
localQwen/Qwen2.5-1.5B-InstructHuggingFace Transformers

Análisis y solución de fallback

Los resultados generados por LLM no siempre cumplen con el esquema solicitado, por lo que el proceso de análisis y la existencia de una ruta de fallback resultan cruciales:

def _parse_ranking(output: str, n: int) -> list[int] | None:
    """Parse LLM output to extract ranking order."""
    matches = re.findall(r"\[(\d+)\]", output)

    if not matches:
        return None

    positions = [int(m) - 1 for m in matches]

    # Pad with remaining positions if LLM returned partial output
    if len(positions) < n:
        seen = set(positions)
        for i in range(n):
            if i not in seen:
                positions.append(i)

    return positions[:n]

Si el análisis falla por completo, la demostración recurre al ordenamiento del codificador cruzado. Un analizador de producción también debe rechazar identificadores fuera del rango o duplicados, añadir los candidatos omitidos en el orden anterior, registrar el fallo y comparar la tasa de recurrencia de este método alternativo con un umbral establecido para el lanzamiento.


Resultados de esta muestra ESCI

A continuación se presentan los resultados obtenidos al ejecutar el pipeline completo sobre aproximadamente 500 consultas ESCI:

Resultados Pipeline

EtapaNDCG@10MRR a los 10 añosRecuperación@100NDCG Delta
BM250.5850.8120.741
Dense codificador bilateral0.6110.8080.825+0.026
Híbrido (RRF)0.6280.8340.842+0.017
+ Codificador cruzado0.6450.8600.842+0.017
+ LLM Reranker0.7170.9010.842+0.072

Observaciones clave

La búsqueda híbrida supera a cualquiera de los métodos por sí solo. El RRF NDCG (0.628) obtiene el mejor resultado, superando tanto al BM25 (0.585) como al Dense (0.611). La recuperación esparsa y la densa presentan modos de fallo complementarios; al combinarlas se logra recuperar documentos que, de otro modo, pasarían desapercibidos con cada uno de ellos por separado.

El recuerdo se fija en el nivel de recuperación. El valor de Recall@100 se mantiene constante en 0,842 durante ambas etapas de reranking. Tras realizar el reordenamiento con Rerankers, no se añaden nuevos documentos al conjunto. Si se desea un mayor recuerdo, es necesario corregir el layer de recuperación.

El LLM estimulado genera el mayor incremento medido en esta ejecución. El valor de NDCG@10 aumenta en 0,072 tras la fase de LLM. Dado que el prompt incorpora la jerarquía de relevancia ESCI, el resultado sirve para evaluar esta combinación de modelo-prompt-dataset. Antes de atribuir dicho mejoramiento a un reranker globalmente superior, es necesario realizar ejecuciones repetidas, calcular intervalos de confianza, analizar la latencia y el costo, además de examinar un conjunto de dominios no utilizados en los entrenamientos.

La recuperación densa supera a BM25 en este ejemplo. Es necesario examinar las porciones de la consulta antes de determinar la causa. Una discrepancia en el vocabulario es un factor plausible, pero la estructura del ejemplo, el tokenizador, el dominio de entrenamiento del modelo y los campos del corpus también influyen en la comparación.


Evaluación: medir lo que realmente importa

La demostración utiliza tres métricas complementarias. Cada una analiza el ranking desde un ángulo distinto:

NDCG@10 (métrica principal)

El Ganancia Acumulada Descuentada Normalizada mide la calidad de la clasificación de los 10 mejores resultados mediante una relevancia graduada. Premia el hecho de colocar documentos altamente relevantes cerca de la parte superior aplicando un descuento logarítmico:

DCG@k=i=1k2reli1log2(i+1)NDCG@k=DCG@kIDCG@k\text{DCG@k} = \sum_{i=1}^{k} \frac{2^{rel_i} - 1}{\log_2(i + 1)} \qquad \text{NDCG@k} = \frac{\text{DCG@k}}{\text{IDCG@k}}

NDCG es la única métrica que utiliza en su totalidad la escala de relevancia de cuatro niveles de ESCI: un sistema según el cual una coincidencia exacta en la posición 1 obtiene una puntuación más alta que aquella en la que se encuentra un sustituto en ese mismo lugar. Por eso, constituye la métrica principal para evaluar la calidad general de las búsquedas.

MRR@10 (primer resultado relevante)

Rank Recíproco Promedio utiliza la posición del primer resultado considerado relevante. Si se encuentra en la posición 1, su rank recíproco es de 1.0; si está en la posición 3, este valor es de 0.333. En el caso de etiquetas graduadas como ESCI, se debe indicar el umbral de relevancia empleado para convertir dichas calificaciones en esa decisión binaria.

Recall@100 (cobertura de recuperación)

El recall mide qué fracción de los documentos considerados relevantes aparecen entre los 100 primeros resultados. Se trata de una métrica de techo para los juicios evaluados: un reranker no puede incluir un documento que la recuperación haya omitido, mientras que los juicios incompletos pueden hacer que dicho techo aparente sea incierto.


Indexación de vectores densos más allá de la demostración

Los métodos embeddings densos solo resultan útiles a gran escala una vez que se dispone de un índice de Vecino Más Cercano Aproximado (ANN). La demostración emplea la similitud coseno por fuerza bruta (lo cual es aceptable con alrededor de 8,500 documentos), pero los sistemas en producción requieren índices especializados.

HNSW (mundo pequeño jerárquico navegable)

HNSW M controla la conectividad del grafo, mientras que efSearch Prefiere el trabajo de consulta sobre la precisión. Los valores útiles dependen de la dimensión, la distribución de distancias, los filtros, la implementación y el nivel de precisión deseado.

Las actualizaciones y eliminaciones constituyen un factor operativo importante, ya que los índices de grafo pueden seguir conservando registros inactivos o requerir reparaciones en segundo plano. El comportamiento varía según la base de datos. A Problema en Qdrant,

IVF (archivo invertido)

Los índices IVF dividen el espacio vectorial en clústeres y, a continuación, realizan un escaneo del nprobe

Para escalas extremas, IVF_RaBitQ (Gao & Long, SIGMOD 2024) comprime vectores de punto flotante en representaciones de un solo bit. En espacios de alta dimensión, el signo (+/-) de una coordenada contiene suficiente información angular para realizar cálculos de similitud.

DimensiónHNSW grafoClústeres IVF
Control de consultasefSearchnprobe
Control de construcciónConectividad y viga de construcciónNúmero de clústeres y muestras de entrenamiento
Perfil de memoriaAristas de grafo más vectoresCentroside, listas y vectores almacenados
Comportamiento de actualizaciónReparación/limpieza específica de la base de datosMantenimiento de listas específicas para la base de datos
Evaluar conCurva de retención-latencia-memoria y rotación de usuariosCurva de retención-latencia-memoria-y rotación

En uno Estudio de caso de búsqueda de entregas en Uber, Al reducir un parámetro de búsqueda a nivel de shard de 1.200 a 200, se logró disminuir la latencia reportada en un 34 % y CPU en un 17 %, con una pérdida apenas perceptible en el nivel de recuperación de resultados. La lección clave que se puede extraer es la necesidad de ajustar la curva costo-recuperación utilizando tráfico similar al de producción, en lugar de simplemente copiar el valor 200.


Extensiones opcionales después de la parte principal pipeline

Una vez que la recuperación de información y reranking cuentan con mediciones independientes, resulta más sencillo evaluar diversas extensiones sin que ello afecte negativamente al núcleo principal de pipeline.

Comprensión de consultas

La expansión y reescritura de consultas permite solucionar las discrepancias de vocabulario antes de realizar la recuperación. Query2doc Generó pseudo-documentos y reportó mejoras en los resultados obtenidos con el algoritmo BM25 en sus experimentos con MS MARCO. Además, la expansión de términos puede introducir intenciones erróneas; por lo tanto, es necesario comparar la tasa de recuperación y la precisión en los conjuntos de consultas ambiguas, de tipo navegacional y那些 que requieren identificadores exactos.

Patrones prácticos: expansión de abreviaturas, enriquecimiento de entidades, descomposición de subconsultas para razonamiento multi-paso, y RAG-Fusión — generación de múltiples variantes de consulta y combinación de resultados mediante RRF.

LLM-etiquetado de relevancia asistido

LLMs puede generar etiquetas de relevancia cuando escasean los juicios humanos. TALEC y El trabajo de etiquetado de relevancia de Pinterest Presente dos diseños ya evaluados. La etiqueta LLM sigue representando la salida del modelo: calíbrela mediante juicios realizados por personas sin conocer los resultados, analice las zonas de desacuerdo y mantenga un conjunto de referencia humano como base para pruebas de regresión.

Entre los controles útiles se incluyen:

Destilación de conocimiento

Cuando un profesor LLM aporta valor pero no puede cumplir con las restricciones serving, la destilación es una de las opciones posibles:

  1. Utilizar un LLM potente (el profesor) para volver a ordenar miles de consultas de entrenamiento.
  2. Entrenar un codificador cruzado pequeño y rápido (el estudiante, con entre 100 millones y 200 millones de parámetros) para imitar la distribución de clasificación del LLM.
  3. Comparar al estudiante tanto con el profesor como con el modelo de referencia en términos de calidad, calibración y costo de serving.

InRanker Extrae información esencial de MonoT5-3B para crear modelos con 60 millones y 220 millones de parámetros, logrando una reducción de tamaño de 50 veces con un rendimiento competitivo. El Rank-Without-GPT Este enfoque genera una lista de 7 mil millones de modelos de código abierto aplicados de forma independiente rerankers, los cuales alcanzan el 97 % de la eficacia del GPT-4 mediante el uso de QLoRA fine-tuning.

Los resultados de compresión publicados constituyen puntos de partida, y no los ratios de rendimiento esperados en producción. El proceso de destilación puede heredar los sesgos del modelo maestro y perder calidad en aquellos casos de consultas poco frecuentes; por lo tanto, es necesario mantener las evaluaciones originales de relevancia dentro del bucle de evaluación.


Personalización y sesgo de posición

La relevancia genérica solo te lleva hasta cierto punto. Una búsqueda de “apple” debería devolver iPhones para un entusiasta de la tecnología y recetas con manzana para quien esté consultando contenido de cocina.

Una arquitectura de recuperación habitual para la personalización emplea un modelo de dos torres embedding: la torre de consultas codifica la consulta y el contexto del usuario, mientras que la torre de elementos codifica los propios elementos junto con sus metadatos. La separación entre modo offline y online permite realizar búsquedas por vecino más cercano aproximado; no obstante, su latencia sigue dependiendo del codificador, del índice, de los filtros y del sistema serving.

La ficha de Airbnb embeddings, de Pinterest OmniSearchSage, y Los sistemas de dos torres de Uber Muestren diferentes diseños de producción. Su escala y los incrementos reportados corresponden a dichos sistemas; el patrón transferible consiste en una torre de elementos fuera de línea junto con una torre de consultas o usuarios en línea.

Los datos de clics presentan sesgo de posición y sesgo de exposición. PAL Un enfoque de desbiasado consiste en utilizar la posición durante el entrenamiento y, a continuación, mantenerla constante durante serving. No se trata de una solución universal; las intervenciones aleatorizadas, los métodos de propensidad inversa y la evaluación contrafáctica pueden ser más adecuados para otro producto.


Adaptación de dominio mediante consultas sintéticas

Un error frecuente en las estrategias de búsqueda es suponer que un modelo entrenado con datos generales de la web (como MS MARCO) funcionará bien en un dominio especializado. Este es el problema de fuera de dominio (OOD).

LLMs puede reducir, pero no eliminar, el cuello de botella derivado de los datos etiquetados mediante Generative Pseudo-Labeling (GPL, InPars):

  1. Tome su corpus de documentos específico del dominio.
  2. Prompt un LLM para “Generar una consulta de búsqueda a la que respondería este documento”.
  3. Utilice las parejas sintéticas (consulta, documento) para ajustar con precisión su recuperador y reranker.

Las parejas sintéticas pueden ser útiles cuando escasean las consultas reales, pero reflejan al generador y a prompt. Es necesario eliminar las duplicadas, filtrar las consultas poco plausibles y validarlas con el tráfico real no utilizado en el entrenamiento.

Secuencia de experimentos

Solo se debe añadir complejidad cuando la etapa anterior presente un fallo medible:

Ruta práctica de maduración

Paso 1 (referencia): implementar BM25 o el sistema léxico actual y crear un conjunto de consultas evaluadas. Registrar la tasa de recuperación, el NDCG, la latencia y los intervalos de fallo.

Paso 2 (recuperación de candidatos): probar la recuperación densa y la fusión únicamente si el método de referencia omite documentos relevantes. Ajustar el umbral de los candidatos en función del porcentaje de recuperación y del costo asociado.

Paso 3 (precisión de clasificación): se debe añadir un codificador cruzado cuando existen los candidatos adecuados pero aparecen en el orden incorrecto. La elección del tamaño de la lista corta correspondiente se realiza a partir de una curva de calidad-latencia.

Paso 4 (adecuación al dominio): realizar el ajuste fino o la destilación únicamente después de que los modelos genéricos muestren fallos estables específicos del dominio. Mantener las evaluaciones reales no utilizadas separadas de los datos de entrenamiento sintéticos.

Paso 5 (capa opcional y costosa): probar los métodos basados en listas o en razonamiento reranking únicamente cuando la mejora de calidad que aportan resista ejecuciones repetidas y justifique el retraso, el costo, las consideraciones de privacidad y la complejidad asociada a las soluciones alternativas.


Direcciones de investigación que se deben evaluar por separado

El razonamiento rerankers y los agentes basados en búsquedas son prometedores, pero abordan tipos de preguntas distintos a los que se plantean en la demostración de búsqueda de productos de cinco etapas.

Razonamiento basado en rerankers

Rank1 entrena rerankers utilizando rastros de razonamiento y obtiene resultados muy sólidos en el BRIGHT benchmark. Esa evidencia es relevante para la recuperación basada en razonamiento complejo, y no constituye una predicción directa para búsquedas de productos ESCI.

Para búsquedas legales o científicas, se debe comparar el razonamiento rerankers con bases de referencia basadas en codificadores cruzados de alta capacidad y en enfoques por lista, evaluando criterios como los juicios de expertos, las citaciones, la latencia y la consistencia ante fallos.

Agentic búsqueda

Search-o1 Analiza un modelo que realiza búsquedas adicionales durante la respuesta a preguntas de múltiples saltos. Se trata de un problema de orquestación —generación de consultas, detección de fin, uso de evidencias y evaluación de respuestas— y no de otra etapa reranking. Su evaluación debe realizarse mediante la corrección en la tarea final y el soporte mediante citas, y no únicamente con métricas de recuperación de información.


Conclusiones principales

  1. Trate la pila como una secuencia de experimentos. Establezca una línea base léxica y un conjunto de consultas evaluadas antes de incorporar mecanismos de recuperación densa, fusión o reranking.

  2. Mida el recuerdo de los candidatos por separado de la precisión del ranking. En esta muestra de ESCI, el Recuerdo@100 alcanza el valor de 0.842 tras la fusión y se mantiene constante en ambas etapas de reranking.

  3. Utilice la recuperación híbrida cuando los errores sean complementarios. RRF mejoró tanto Recall@100 como NDCG@10 en la demostración, pero otro corpus podría no justificar el uso de dos índices.

  4. Añadir un codificador cruzado cuando la lista de candidatos es adecuada pero el orden está incorrecto. Seleccionar el número de candidatos a partir de una curva medida de calidad y latencia.

  5. Trate LLM reranking como un experimento final opcional. El aumento de 0.072 en NDCG@10 que obtiene en este caso corresponde a esta prompt, es decir, al modelo, a las muestras y a la escala de relevancia aplicada. Las ejecuciones repetidas, el análisis estricto, las soluciones alternativas y los costes forman parte integral de la evaluación.

  6. Mantenga los tipos de evidencia separados. Un resultado obtenido en un artículo científico, un estudio de caso de un proveedor, esta demostración en portátil y una prueba A/B en entorno de producción responden a preguntas diferentes.

El código completo de pipeline se encuentra en github.com/slavadubrov/search-ranking-stack. Clónalo, ejecútalo, sustituye los modelos y parámetros por otros diferentes, y observa los resultados por ti mismo.

Referencias

Artículos científicos

Datasets y benchmarks

Modelos utilizados en la demostración

Herramientas y plataformas

Referencias del sector

Proyecto de demostración