Reranking con cross-encoders: cuándo compensa el coste
Bi-encoder frente a cross-encoder, tamaño del candidato inicial y el impacto real en latencia y factura.
Tercera entrega del bloque de técnicas de recuperación. El reranking es probablemente la mejora con mejor relación entre esfuerzo de integración y ganancia de calidad de todo el catálogo. También es la que más fácilmente se aplica donde no hace falta, y entonces sólo añade latencia y factura.
Por qué el buscador no puede ser preciso
Para entender el reranking hay que entender primero una limitación que la búsqueda vectorial acepta a cambio de poder existir.
Un modelo de embeddings convencional es un bi-encoder: codifica dos textos por separado, cada uno en su propio vector, sin que ninguno de los dos vea al otro. El fragmento se vectorizó durante la indexación, hace semanas, sin saber qué preguntas le iban a hacer. La pregunta se vectoriza ahora, sin saber qué hay en el índice. La relevancia se estima después, comparando dos números que se calcularon en soledad.
Esa arquitectura tiene una propiedad decisiva: los vectores de los fragmentos se pueden precalcular una vez y reutilizar siempre. Por eso es posible buscar entre diez millones de fragmentos en decenas de milisegundos, con los índices aproximados que vimos en la entrega 05. Toda la búsqueda vectorial descansa sobre esto.
Y tiene un precio: la interacción entre pregunta y fragmento nunca se modela. El vector del fragmento es un resumen de propósito general de su contenido. Comprime todo lo que dice el párrafo —que puede tratar tres temas— en un único punto. Si tu pregunta va sobre el tercer tema, el que se menciona de pasada al final, ese matiz está diluido en la media.
El cross-encoder hace justo lo contrario
Un cross-encoder recibe pregunta y fragmento juntos, concatenados, en una sola pasada por el modelo. Los mecanismos de atención pueden relacionar cada palabra de la pregunta con cada palabra del fragmento. La salida no es un vector: es un único número, la puntuación de relevancia de ese fragmento para esa pregunta.
La diferencia de calidad es sustancial y tiene una explicación mecánica sencilla: el modelo puede comprobar si la condición concreta que pide la pregunta se cumple en el texto, en lugar de estimar si el texto trata del mismo tema. Un fragmento que habla de plazos de devolución para pedidos nacionales y otro que habla de plazos de devolución para pedidos internacionales tienen vectores casi idénticos. Un cross-encoder los distingue sin dificultad si la pregunta especifica cuál.
Y tiene el precio simétrico: nada se puede precalcular. Cada par pregunta-fragmento exige una pasada completa por el modelo en el momento de la consulta. Puntuar diez millones de fragmentos con un cross-encoder no es lento, es inviable. Ese es el motivo, y el único, por el que la búsqueda no se hace así.
Recuperar muchos, reordenar pocos
De la incompatibilidad entre ambos sale el patrón estándar, que consiste en usar cada modelo para lo que sirve:
- Recuperación amplia. El buscador —denso, léxico o híbrido con RRF— devuelve una lista generosa de candidatos: 50, 100, 200. Barato y rápido. Aquí el objetivo no es acertar, es no dejarse fuera el fragmento bueno.
- Reordenación precisa. El cross-encoder puntúa esos candidatos, uno a uno, contra la pregunta real.
- Corte. Se toman los 3 a 8 mejores y sólo esos entran en el prompt.
La división del trabajo es limpia: el buscador optimiza recall (que la respuesta esté en algún sitio de la lista) y el reranker optimiza precisión (que esté arriba del todo). Son dos objetivos distintos y por eso se necesitan dos modelos distintos.
Hay un efecto secundario que se subestima: el reranking permite reducir el número de fragmentos que llegan al modelo generador. Sin reranker, mucha gente pasa diez o quince fragmentos «por si acaso», lo cual encarece la generación, alarga la latencia y activa el efecto de «perdido en el medio». Con un reranker fiable bastan cuatro. Parte del coste del reranking se recupera en la factura de generación.
Elegir k inicial y k final
Son los dos parámetros del patrón y conviene razonarlos por separado, porque responden a preguntas distintas.
El k inicial lo fija el recall. La regla es dura: el reranker no puede rescatar lo que el buscador no trajo. Si el fragmento correcto estaba en la posición 87 y recuperaste 50, ningún reranker del mundo lo pondrá primero. El k inicial es, por tanto, una decisión empírica que se toma midiendo: con tu conjunto de preguntas verificadas, calcula qué porcentaje de respuestas correctas aparece dentro del top-20, del top-50, del top-100 y del top-200. Esa curva se aplana en algún punto. Ese punto es tu k inicial, y por debajo estás recortando el techo de todo el sistema.
Como orden de magnitud, los sistemas en producción suelen moverse entre 30 y 100. Por debajo de 20 el reranker tiene poco margen para aportar; por encima de 200 la latencia crece de forma lineal sin que el recall mejore apenas, porque a esas alturas los candidatos nuevos son ruido.
El k final lo fija el presupuesto de contexto y la naturaleza de las preguntas. Si son atómicas, tres o cuatro fragmentos bastan y sobran. Si son comparativas o de síntesis, harán falta seis u ocho para cubrir las distintas facetas. Un criterio adicional útil: mirar la distribución de puntuaciones del reranker y cortar por umbral en lugar de por número fijo. Si sólo dos fragmentos superan la puntuación mínima, pasar ocho es meter seis distractores en el prompt.
La cuenta de latencia y de coste
El reranking es la única etapa del pipeline cuyo coste crece de forma directamente proporcional al k inicial, y eso lo hace fácil de razonar.
| Etapa | Orden de magnitud de latencia | Escala con |
|---|---|---|
| Embedding de la consulta | Decenas de milisegundos | Nada |
| Búsqueda vectorial (ANN) | Decenas de milisegundos | Logarítmicamente con el corpus |
| Reranking | Centenares de milisegundos | Linealmente con k inicial |
| Generación | Segundos | Con los tokens generados |
Leída la tabla, la conclusión es que en un sistema conversacional el reranking suele quedar enterrado bajo la latencia de la generación: añade una fracción de lo que ya se está esperando. En un buscador que sólo devuelve documentos, sin generar texto, el reranking es de golpe la etapa dominante y se nota mucho más.
En cuanto a la factura, hay dos modelos de coste. Con un reranker gestionado por API se paga por búsqueda, y el precio suele escalonarse según el número de documentos puntuados, lo que penaliza los k iniciales grandes. Con un reranker autoalojado se paga infraestructura: un modelo de reranking de tamaño moderado funciona en CPU con latencias aceptables para pocos candidatos, pero para k iniciales de 100 en adelante y varias consultas por segundo, quieres GPU. La entrega 27 compara los modelos concretos.
Cuándo el reranking no aporta nada
Cinco situaciones en las que introducirlo es puro coste.
Cuando el recall ya es el problema. Si tus preguntas fallan porque el fragmento correcto no aparece ni en el top-100, el reranker no arregla nada: reordena basura. El diagnóstico va antes que el remedio, y ese fallo apunta al troceado, a los metadatos o a la ausencia de componente léxica.
Cuando el corpus es pequeño. Con unos pocos cientos de fragmentos, el buscador ya devuelve casi todo lo relevante en las primeras posiciones. Hay poco que reordenar.
Cuando las preguntas son navegacionales. Si el usuario busca un identificador exacto y BM25 lo devuelve primero con una puntuación despegada del resto, el reranker sólo puede confirmar lo que ya se sabía, o empeorarlo.
Cuando el presupuesto de latencia es estricto. Un autocompletado o una sugerencia en línea con presupuesto de 200 milisegundos no admite un cross-encoder sobre 50 candidatos.
Cuando el reranker no habla tu idioma o tu dominio. Un modelo de reranking entrenado mayoritariamente en inglés puede rendir peor que el orden original sobre un corpus técnico en español. Esto no es hipotético y hay que medirlo, no suponerlo.
Dos advertencias de implementación
La primera: el reranker debe ver el mismo texto que verá el modelo generador. Si tu pipeline expande el fragmento recuperado con su contexto —el patrón padre-hijo de la entrega 10— decide de forma consciente si el reranker puntúa el fragmento hijo o el padre expandido, y sé coherente. Puntuar una cosa y enviar otra produce una selección que no corresponde a lo que se evaluó.
La segunda: la puntuación del reranker es una señal aprovechable más allá del orden. Si el mejor candidato puntúa bajo, es una indicación razonablemente fiable de que el corpus no contiene la respuesta, y ahí el sistema puede responder que no lo sabe en lugar de improvisar. Es la forma más barata de introducir verificación en un pipeline, y anticipa lo que veremos en la entrega 19. El umbral concreto hay que calibrarlo con datos propios, porque las escalas varían entre modelos.
Qué viene ahora
Hasta aquí hemos mejorado lo que ocurre después de tener la consulta. La siguiente entrega mira antes: qué hacer cuando la pregunta que llega es la que está mal. Reescritura, resolución de referencias conversacionales del tipo «¿y en ese caso?», descomposición de preguntas compuestas en subconsultas independientes, generación de varias variantes y fusión de sus resultados, y step-back prompting. Con la cuenta de llamadas y latencia que todo eso añade.
Si prefieres leerlo todo de golpe y en orden, los tres libros gratuitos de los que nace esta serie están disponibles en PDF y EPUB: RAG para tu negocio (nivel básico), RAG por dentro (intermedio) y RAG en producción (avanzado).
Aviso de contenido generado con inteligencia artificial.
Este artículo ha sido redactado con la asistencia de sistemas de inteligencia artificial y revisado antes de su publicación. Se informa de ello de forma expresa en cumplimiento de la normativa vigente sobre transparencia en el uso de IA.