Avanzado 12 minOptimización

Añadir un reranker a tu pipeline

Respuesta directa

Un reranker es un cross-encoder que relee cada par pregunta-pasaje y reordena los candidatos devueltos por la búsqueda vectorial: se recupera un conjunto amplio (de 20 a 100 pasajes) y se conservan los 3 a 5 mejores para el modelo. Para el francés, BAAI/bge-reranker-v2-m3 (licencia Apache 2.0, aproximadamente 568 millones de parámetros) es el punto de partida más sencillo, en local, con GPU o incluso con CPU si el volumen sigue siendo modesto.

Los embeddings encuentran pasajes cercanos a una pregunta, no necesariamente pasajes que la respondan. El reranker corrige este defecto evaluando cada par pregunta-pasaje en un solo cálculo. Esta guía explica cuándo compensa su coste, qué modelo elegir en francés, cómo integrarlo en treinta líneas y cómo comprobar en tus propios documentos que realmente mejora los resultados.

Por Mohamed Meguedmi·Actualización 2026-09-30·Probado en Windows, macOS y Linux

#Reranker: para qué sirve en un pipeline RAG

Un reranker recibe la pregunta y un pasaje, los lee juntos y devuelve una puntuación de relevancia; luego se ordenan los candidatos por puntuación decreciente y se envían solo los mejores al modelo de lenguaje. En un pipeline RAG local, se inserta entre la base vectorial (ChromaDB, Qdrant, Weaviate) y el LLM: la búsqueda vectorial, por ejemplo, devuelve 30 pasajes, y el reranker selecciona 5. La ficha oficial de BAAI lo describe así: a diferencia de un modelo de embedding, el reranker recibe la pregunta y el documento como entrada y produce directamente una similitud, en lugar de un vector. El beneficio es más notable cuando la respuesta correcta está entre los candidatos pero no en las primeras posiciones: pasajes que hablan del tema general correcto pero que no responden a la pregunta específica ocupan los primeros lugares, y el modelo genera entonces una respuesta que no responde a la pregunta o es inventada. Si la respuesta correcta no está entre los candidatos, un reranker no puede hacer nada: no busca, solo ordena.

Un embedding genera un vector para cada documento, independientemente de la pregunta planteada, y la distancia mide una proximidad temática global. Dos pasajes sobre el mismo tema pueden obtener puntuaciones similares aunque solo uno contenga la respuesta. El cross-encoder examina el par completo: comprueba si la fecha, el nombre o la condición solicitados figuran en el pasaje. Es más preciso en esta evaluación local y más costoso, porque requiere una pasada por el transformer por cada par, en lugar de un solo cálculo por documento.

i
La metáfora
El embedding es el bibliotecario que te lleva a la sección adecuada y te entrega veinte libros. El reranker es el experto que hojea esos veinte libros con tu pregunta en mente y coloca encima los tres que la responden.

#Bi-encoder y cross-encoder: por qué se combinan ambos

El kit RAG Local

Tus documentos, tu IA: un RAG local fiable sobre tus PDF, notas y correos — sin enviar nada a la nube.

  • Espacio en línea de por vida
  • PDF + archivos
  • Reembolsado 30 j
Bi-encoder (embedding)
Codifica la pregunta y cada documento por separado; los vectores de los documentos se calculan una sola vez durante la indexación, la búsqueda se reduce a una comparación de vectores. Rápido, adecuado para millones de pasajes.
Cross-encoder (reranker)
Codifica la pregunta y el pasaje juntos y devuelve una puntuación. Ningún cálculo se puede reutilizar: hay que hacerlo de nuevo para cada pregunta y cada candidato. Preciso, pero imposible de aplicar a todo el corpus.

La documentación de Sentence Transformers explica el razonamiento: evaluar miles o millones de pares sería bastante lento, por lo que se utiliza el retriever para generar un conjunto de candidatos, por ejemplo un centenar, que luego el cross-encoder reordena. El esquema en dos etapas es el mismo que el de los motores de búsqueda clásicos. También explica el ajuste principal: el número de candidatos recuperados controla tanto la exhaustividad (recall) —cuantos más candidatos se recuperan, más probabilidades hay de que el conjunto contenga la respuesta correcta— como la latencia (cada candidato adicional requiere una pasada por el cross-encoder).

#¿Qué modelo de reranking elegir en francés?

La decisión se basa en tres criterios: el idioma, la licencia y la memoria. Los tamaños indicados a continuación provienen de las fichas de Hugging Face; ten en cuenta que el tamaño del archivo depende de la precisión de los pesos, F32 para bge-reranker-v2-m3 (aproximadamente 4 bytes por parámetro), F16 para mxbai.

Rerankers utilizables en local (fichas de Hugging Face, septiembre de 2026)
ModeloIdiomasTamaño anunciadoLicenciaVeredicto para el francés
BAAI/bge-reranker-v2-m3Multilingüe0,6 mil millones de parámetros, peso en F32 (aproximadamente 2,3 GB)Apache 2.0Opción predeterminada: multilingüe, ligera y con buen soporte de herramientas
BAAI/bge-reranker-v2-gemmaMultilingüe3 mil millones de parámetros, pesos en F32 (aproximadamente 10 GB)Apache 2.0Reservado para casos exigentes con GPU dedicado; reranker basado en Gemma-2B
mixedbread-ai/mxbai-rerank-large-v1Inglés0,4 mil millones de parámetros, pesos en F16Apache 2.0Evitar para un corpus francés: la ficha indica inglés
Cohere RerankMultilingüeServicio alojadoComercialNo es adecuado para un pipeline 100 % local: los pasajes salen de tu máquina

La ficha de bge-reranker-v2-m3 lo presenta como un reranker ligero, con sólidas capacidades multilingües, fácil de desplegar y rápido en inferencia; la ficha de bge-reranker-v2-gemma lo orienta a contextos multilingües, con buenos resultados tanto en inglés como en tareas multilingües. Dos correcciones útiles respecto a lo que se lee a menudo: el archivo de bge-reranker-v2-m3 pesa más de 2 GB, no 560 MB (568 millones de parámetros en F32), y mxbai-rerank-large-v1 es un modelo para inglés que no debe elegirse para documentos en francés. Una vez cargado en media precisión, el modelo m3 ocupa aproximadamente 1,1 GB para los pesos (568 millones de parámetros × 2 bytes, cálculo de esta guía), a los que se suman las activaciones del lote procesado.

→
El modelo de embedding y el reranker son independientes
Puedes cambiar uno sin reindexar el otro: el reranker solo lee el texto de los fragmentos, nunca sus vectores. Para elegir el modelo de embeddings, consulta la guía dedicada a los modelos de embeddings para el francés.

#El pipeline antes y después de añadir un reranker

Antes / después
AVANT :
  Question → Embedding → Base vectorielle (top-5) → LLM

APRÈS :
  Question → Embedding → Base vectorielle (top-20 à top-50)
                       → Reranker (top-5) → LLM

On récupère large, puis on ordonne finement.

Dos parámetros regulan el proceso: k_retrieve, el número de candidatos que devuelve la base vectorial, y k_final, el número de pasajes enviados al LLM. Un k_final de 3 a 5 es adecuado para la mayoría de los modelos locales de 7 a 14 mil millones de parámetros; por encima de eso, se llena la ventana de contexto sin ganancia neta y el tiempo de procesamiento del prompt aumenta. El k_retrieve depende de la dificultad del corpus: 20 es un buen primer intento, 50 a 100 si las preguntas son vagas o si el corpus contiene muchos pasajes cercanos. La guía sobre la ventana de contexto explica el costo de pasajes adicionales en el prompt.

#Implementación: sentence-transformers, FlagEmbedding, llama.cpp

#Con sentence-transformers

La clase CrossEncoder carga el modelo y evalúa pares. Su método rank acepta directamente la pregunta y la lista de documentos y devuelve los mejores; el parámetro top_k limita el número de resultados (sin él, se devuelven todos los documentos).

CrossEncoder.rank
from sentence_transformers import CrossEncoder

reranker = CrossEncoder("BAAI/bge-reranker-v2-m3", max_length=512)

def retrieve_and_rerank(question, k_retrieve=20, k_final=5):
    # 1. Récupération par embedding (ChromaDB, Qdrant, etc.)
    candidats = embedding_search(question, top_k=k_retrieve)  # liste de textes

    # 2. Scoring par le cross-encoder, tri et coupe en une seule étape
    resultats = reranker.rank(question, candidats, top_k=k_final, batch_size=16)
    # resultats = [{'corpus_id': 3, 'score': 0.91}, ...]
    return [candidats[r['corpus_id']] for r in resultats]

#Con FlagEmbedding, la biblioteca de los autores del modelo

La ficha del modelo utiliza la biblioteca FlagEmbedding. Especifica que la puntuación bruta puede transformarse en un valor entre 0 y 1 mediante una función sigmoide con normalize=True, y que use_fp16=True acelera el cálculo a costa de una ligera disminución de calidad. Ten en cuenta que la puntuación bruta es un valor sin escala absoluta, a menudo negativo para los pasajes que no son pertinentes; solo importa el orden, salvo que establezcas un umbral.

FlagReranker
from FlagEmbedding import FlagReranker

reranker = FlagReranker('BAAI/bge-reranker-v2-m3', use_fp16=True)
score = reranker.compute_score(['ma question', 'un passage'], normalize=True)  # entre 0 et 1

#Con llama.cpp, sin Python

El servidor llama.cpp ofrece un punto de acceso de reranking, desactivado por defecto. La documentación indica que requiere un modelo de reranking, cita bge-reranker-v2-m3 como ejemplo y que el servidor se inicia con las opciones --embedding y --pooling rank. Se necesita una versión GGUF del modelo. Esta es la opción que conviene elegir si tu pila ya está construida alrededor de llama.cpp y quieres evitar instalar PyTorch. Comprueba la opción exacta en la versión instalada: la documentación advierte que este punto de acceso podría evolucionar.

llama-server (adaptar a tu versión)
llama-server -m bge-reranker-v2-m3-Q8_0.gguf --embedding --pooling rank --reranking --port 8081

#Con LlamaIndex

SentenceTransformerRerank
from llama_index.core.postprocessor import SentenceTransformerRerank

reranker = SentenceTransformerRerank(model="BAAI/bge-reranker-v2-m3", top_n=5)

query_engine = index.as_query_engine(
    similarity_top_k=20,
    node_postprocessors=[reranker],
)

#Costo: latencia, memoria, longitud de pasajes

No se garantiza ninguna cifra de latencia: depende de la tarjeta, de la precisión (FP16 o FP32), del número de candidatos y de la longitud de los pasajes. Ten en cuenta las proporciones. El tiempo de reranking crece linealmente con el número de pares: pasar de 20 a 100 candidatos multiplica el trabajo por cinco. También crece con la longitud del pasaje, ya que cada par se codifica por completo. Mide en tu máquina con tus pasajes en lugar de fiarte de una cifra de un blog: cronometra cien consultas reales y observa la mediana del tiempo y el peor caso.

Número de candidatos
Primera palanca de ajuste. Empieza con 20, mide el recall y sube a 50 solo si siguen quedando buenas respuestas fuera del conjunto.
Precisión
use_fp16=True (FlagEmbedding) o cargar en media precisión reduce el uso de memoria y acelera el cálculo, con una ligera disminución del rendimiento según la ficha del modelo.
Tamaño del lote
El método rank de sentence-transformers procesa 32 pares por lote por defecto. Reduce el tamaño del lote a 8 o 16 si falta memoria y auméntalo si la GPU está infrautilizada.
Longitud máxima
512 tokens por par de entrada (valor max_length de los ejemplos oficiales). Un fragmento más largo se recorta: si tus chunks superan este tamaño, la parte final del fragmento no se lee. Acorta los chunks antes de aumentar el límite.
CPU o GPU
En CPU, el reranker funciona, pero cada consulta con entre 20 y 50 candidatos requiere segundos de procesamiento; es aceptable para un asistente documental interno, menos para un chat interactivo.
→
Ignorar el reranker cuando no es útil
En un corpus pequeño y bien estructurado (unas decenas de páginas bien divididas), el top-5 vectorial suele contener ya la respuesta. Medir primero, y solo mantener el reranker si el recuerdo mejora.

#Reranker y segmentación: los dos ajustes interactúan

Un cross-encoder evalúa un pasaje completo. Si el pasaje mezcla tres temas, su puntuación será intermedia para las tres preguntas correspondientes; si es demasiado corto, pierde el contexto que permitiría reconocerlo como respuesta. La división en pasajes de tamaño medio, con un ligero solapamiento, proporciona al reranker contenido con el que trabajar sin superar su longitud máxima. Si cambias el tamaño de los chunks, repite la prueba de recuperación: tanto el valor óptimo de k_retrieve como la mejora que aporta el reranker cambian con ese tamaño. La guía sobre estrategias de chunking detalla estas opciones.

Otra interacción: la búsqueda híbrida. Cuando la búsqueda por palabras clave (BM25) y la búsqueda vectorial se combinan, el conjunto de candidatos es más diverso, lo que da al reranker más posibilidades de encontrar una buena respuesta que cada método por separado habría pasado por alto. El reranker es la última etapa y la búsqueda híbrida, la segunda: se complementan en lugar de sustituirse.

#Medir la mejora con tus documentos

La mejora anunciada en los blogs oscila entre una y cinco veces según el corpus, y ninguna cifra general es aplicable al tuyo. En un corpus muy estructurado (documentación técnica limpia), la búsqueda vectorial por sí sola ya funciona bien; en un corpus con ruido (correos, notas, PDF mal extraídos), la diferencia es más marcada. La única manera de saberlo es evaluar.

  1. 01
    Reunir entre 30 y 50 preguntas
    Toma preguntas reales de usuarios y, para cada una, indica el pasaje que contiene la respuesta (basta con un identificador).
  2. 02
    Medir el recall@5 sin reranker
    Para cada pregunta, revisa si el fragmento adecuado aparece en los 5 primeros resultados de la base vectorial.
  3. 03
    Medir el recall@5 con reranker
    Recupera 20 candidatos, reordénalos y cuenta de nuevo los pasajes relevantes entre los 5 primeros.
  4. 04
    Comparar también la latencia
    Anota la mediana del tiempo de extremo a extremo. Una mejora de unos pocos puntos en la exhaustividad (recall) no justifica necesariamente un segundo de espera adicional.
  5. 05
    Ver los errores
    Para cada pregunta mal respondida, comprueba si la respuesta correcta estaba entre los 20 candidatos. Si no, el problema está en una etapa anterior: segmentación, embeddings o extracción del texto.
Evaluar el recall
def rappel_a_k(pipeline, questions, cibles, k=5):
    ok = 0
    for q, cible in zip(questions, cibles):
        ok += cible in [p.id for p in pipeline(q)[:k]]
    return ok / len(questions)

sans = rappel_a_k(pipeline_sans_reranker, questions, cibles)
avec = rappel_a_k(pipeline_avec_reranker, questions, cibles)
print(f"Sans : {sans:.0%}   Avec : {avec:.0%}")
!
Límites del reranker
No corrige ni un texto mal extraído de un PDF, ni una segmentación que divida la respuesta en dos, ni una pregunta ambigua. También puede desfavorecer pasajes cortos cuya puntuación sea baja aunque contengan la cifra correcta: revisa los fallos en lugar de confiar en la media.

#¿Se necesita un reranker? Criterios para decidir

Cuándo añadir un reranker
SituaciónDecisión
Corpus de unos pocos decenas de documentos limpios, top-5 vectorial ya buenoNo, mide primero
La respuesta correcta aparece con frecuencia entre el 6.º y el 30.º puestoSí: es el caso de uso típico
Preguntas vagas, corpus ruidoso o muy heterogéneoSí, con entre 30 y 50 candidatos
Chat interactivo en máquina sin GPUPrecaución: mide la latencia en la CPU y reduce el número de candidatos a entre 10 y 20.
Buena respuesta ausente incluso entre los 50 primeros candidatosNo: corrige primero la división en fragmentos, los embeddings o la extracción

#Preguntas frecuentes sobre el reranking

FAQ
¿Reemplaza un reranker la búsqueda vectorial?+
No. No recorre el corpus: reordena las pocas decenas de candidatos que le proporciona la búsqueda vectorial. Sin una primera etapa rápida, habría que ejecutarlo sobre cada fragmento de la base, lo que sería demasiado lento. Las dos etapas se complementan: la búsqueda vectorial garantiza la exhaustividad (recall), y el reranker aporta precisión en los primeros puestos de la clasificación.
¿Qué reranker elegir para documentos en francés?+
BAAI/bge-reranker-v2-m3 es un punto de partida razonable: multilingüe, bajo licencia Apache 2.0, con alrededor de 600 millones de parámetros, por lo que se puede utilizar en una tarjeta gráfica modesta. Evita mxbai-rerank-large-v1, cuya ficha indica el inglés. El modelo bge-reranker-v2-gemma, más pesado, solo se justifica si el primero no es suficiente en tu conjunto de preguntas.
¿Cuántos candidatos se deben reclasificar?+
Empieza con 20 candidatos y conserva 5 fragmentos. Si, en la evaluación, algunas respuestas correctas siguen quedando fuera de los 20, aumenta a 50. Cada candidato adicional añade un cálculo, por lo que la latencia crece aproximadamente de forma lineal. Por encima de 100, rara vez se obtienen mejoras: suele ser señal de un problema de segmentación o de embeddings.
¿Se necesita un GPU para un reranker?+
No, pero ayuda. En CPU, el modelo m3 funciona, con una latencia del orden de un segundo o más por lote de candidatos, según el equipo: medirla en tu propio equipo. Esto sigue siendo aceptable para un uso documental interno. Para un chat fluido, una GPU, incluso modesta, o un modelo más ligero cambia la experiencia de uso.
¿Se puede usar un reranker con Ollama?+
Ollama sirve el modelo de generación y los embeddings, pero el reranking se realiza por separado: con sentence-transformers o FlagEmbedding en Python, o con el servidor llama.cpp que expone un punto de acceso de reranking. El reranker es un modelo distinto, cargado en su propio proceso, que coexiste con el modelo de generación si la memoria lo permite.
¿Cómo saber si el reranker mejora realmente mis resultados?+
Prepara entre 30 y 50 preguntas reales con el pasaje esperado y compara la exhaustividad (recall) de los 5 primeros resultados con y sin reranker, así como la latencia mediana. En un corpus limpio, la diferencia puede ser pequeña; en un corpus con ruido, es más clara. Después, analiza los fallos para determinar si se originan en etapas anteriores del proceso.
¿Esta guía te ha ayudado?

¿Un comentario, un error, una precisión? Avísanos, eso mejora la guía para todos.