Inteligencia Artificial

Re-ranking en RAG: la pieza que sube la calidad de verdad

Re-ranking en RAG: la pieza que sube la calidad de verdad

Actualizado: 2026-05-03

Un pipeline RAG básico hace recuperación top-k con embeddings y pasa los documentos directamente al LLM. Funciona, pero esconde una carencia estructural. Los embeddings son bi-encoders: codifican la consulta y el documento por separado y comparan con un producto escalar. Eso los hace rapidísimos sobre millones de vectores, pero mediocres a la hora de discriminar entre los diez o veinte candidatos más parecidos. Ahí es donde entra un reranker, y ahí es donde la mayoría de proyectos RAG pasan de “decente” a “realmente útil”.

Puntos clave

  • El flujo canónico es: embedding retrieval top-100, reranker selecciona top-10, LLM genera con ese contexto.
  • Un reranker bien elegido sube Precisión@10 entre un 15 y un 30 % en corpus de más de 100k documentos.
  • Cohere Rerank es la opción hosted más sólida; BGE-reranker-large es el estándar open-source.
  • El reranker no arregla un retrieval inicial malo: si el bi-encoder ya descartó el documento correcto, el reranker no lo puede recuperar.
  • Por debajo de 200 ms de presupuesto de latencia, el reranker probablemente no cabe; en chat asíncrono, sí.

Bi-encoder frente a cross-encoder

Un bi-encoder genera dos vectores independientes —uno para la query, otro para el documento— y los compara con coseno o producto escalar. Todo el contexto tiene que comprimirse en esos vectores sin saber qué se va a preguntar. Es una aproximación eficiente, no una medida fina de relevancia.

Un cross-encoder hace lo contrario. Concatena query y documento y los pasa juntos por el transformer, dejando que las cabezas de atención miren token a token qué palabras de la consulta activan qué fragmentos del documento. El coste es alto —una llamada al modelo por cada par— pero la señal es mucho más rica. Un bi-encoder dice “este documento se parece al tipo de cosas que suele preguntar alguien”; un cross-encoder dice “este documento responde a esta pregunta concreta”.

La consecuencia práctica: no se puede usar un cross-encoder sobre millones de documentos, pero sí sobre cien. Por eso el patrón estándar combina ambos. El bi-encoder hace recall barato sobre el corpus entero y el cross-encoder hace precisión cara sobre la lista corta.

El flujo canónico en producción

Tres etapas bien delimitadas:

  1. Recuperación vectorial: top-100 del índice en menos de 100 ms.
  2. Reranker: reordena los 100, selecciona el top-10, en 300-500 ms dependiendo del modelo.
  3. LLM: genera la respuesta con esos 10 documentos en contexto.

Se añaden unos cientos de milisegundos, pero la calidad del top-10 mejora tanto que el LLM alucina menos y responde con más concreción. El usuario percibe un sistema que entiende, no uno que devuelve “algo parecido”. El reranking tiene especial valor en pipelines que también se benefician de pgvector para el almacenamiento vectorial o Cohere Embed v3 para embeddings de calidad.

Rerankers que importan hoy

Cohere Rerank es la opción hospedada de referencia. Los modelos rerank-english-v3.0 y rerank-multilingual-v3.0 marcan el techo en la mayoría de benchmarks públicos. La API es una sola llamada, cobran por cada mil documentos procesados, y el coste ronda los dos dólares por mil queries con cien candidatos. La desventaja es la clásica: dependencia externa, latencia de red y datos que salen de tu infraestructura.

BGE-reranker, de BAAI, es el estándar de facto en open-source. La versión bge-reranker-large con 568 millones de parámetros se acerca mucho a Cohere en calidad, y la generación v2 (bge-reranker-v2-m3) ofrece opciones multilingüe competitivas. Requiere GPU para latencias razonables, pero una T4 o L4 modesta basta para cargas medias.

Como baseline ligero están los cross-encoders clásicos de sentence-transformers, como cross-encoder/ms-marco-MiniLM-L-12-v2. No baten a BGE large, pero corren en CPU y son suficientes para prototipos.

from sentence_transformers import CrossEncoder

model = CrossEncoder("BAAI/bge-reranker-large", max_length=512)
pairs = [(query, doc) for doc in candidates]
scores = model.predict(pairs, batch_size=32)
ranked = sorted(zip(candidates, scores), key=lambda x: -x[1])[:10]

Cuándo compensa de verdad

El reranker ayuda claramente en:

  • Corpus grandes (más de 100k documentos) donde el recall del embedding es bueno pero la ordenación del top-20 es ruidosa.
  • Consultas ambiguas donde varios documentos son plausibles y la diferencia no cabe en la geometría vectorial.
  • Long tail temático donde los embeddings generales pierden matiz de dominio.

No compensa en:

  • Corpus pequeños bien curados (<10k documentos) donde el embedding suele clavar el top-1.
  • Consultas exactas como búsqueda de código o identificadores.
  • Presupuesto de latencia <200 ms end-to-end: no hay sitio para medio segundo extra.

En benchmarks internos típicos sobre QA con 200k documentos, pasar de solo embeddings a embeddings + Cohere Rerank sube Precisión@10 del 45 al 68 %, con Recall@10 subiendo del 68 al 72. Con cross-encoder open-source, del 45 al 62. Los saltos se traducen directamente en menos alucinación del LLM.

Presupuesto de latencia realista

Pensar en tramos:

  • Recuperación vectorial (índice HNSW bien dimensionado): 20-80 ms.
  • Reranker BGE large en GPU: 300-500 ms. Cohere hospedado: 200-400 ms.
  • Generación LLM: el tramo dominante, casi siempre >1 segundo.

Suma total: 1,5-3 segundos, aceptable para chat asíncrono o búsqueda enriquecida. Para sub-segundo, hay margen: reducir el top-k inicial a 50, usar el reranker base en lugar del large, y cachear queries frecuentes. El cache sobre queries normalizadas tiene tasas de acierto superiores al 30 % en dominios estrechos.

Errores habituales

  • Recuperar solo el top-10 antes de rerankear: si el bi-encoder ya descartó el documento correcto, el reranker no lo resucita. Hay que llegar al top-50 o top-100.
  • No medir antes y después: sin Precisión@5, Recall@10 y MRR sobre queries reales, la intuición de “mejora” no se sostiene.
  • Rerankear un retrieval inicial malo: chunks demasiado grandes, embeddings sin ajuste al dominio. El reranker puede elegir lo mejor de lo que recibe, no inventar lo que falta.

Conclusión

El reranking es una de las intervenciones con mejor ratio coste-beneficio en todo el stack RAG. Integrar Cohere Rerank son unas horas y un endpoint; desplegar BGE-reranker en GPU propia son un par de días y un servicio más. La decisión hosted vs. self-hosted depende casi siempre del volumen: por debajo de 10k queries diarias Cohere sale a cuenta, por encima de 100k la GPU amortiza. La decisión de si rerankear o no ha dejado de ser realmente una decisión: cualquier pipeline RAG que aspire a calidad medible lo hace. El trabajo interesante se ha desplazado a cómo trocear, cómo evaluar y cómo cachear.

¿Te ha resultado útil?
[Total: 11 · Media: 4.6]

Escrito por

CEO - Jacar Systems

Apasionado de la tecnología, la infraestructura cloud y la inteligencia artificial. Escribe sobre DevOps, IA, plataformas y software desde Madrid.