Módulo 4: Re-ranking — la segunda etapa que transforma retrieval mediocre en excelente

Cápsula 05: Cohere Rerank API — la opción managed cuando no quieres mantener modelos

Descripción de la cápsula

Cross-encoder local es gratis pero requiere mantener un modelo en tu infraestructura: descarga del modelo (~80-200 MB), inferencia en CPU/GPU, ocasionalmente actualizar a nuevas versiones. LLM re-ranking es más caro y más lento, y depende de OpenAI/Anthropic. Cohere Rerank es la tercera opción: API managed especializada en re-ranking, sin infrastructure local, sin LLM general — un modelo entrenado específicamente para esta tarea.

Para muchos equipos, Cohere Rerank es el sweet spot práctico: calidad cercana a LLM rerank, latencia cercana a cross-encoder, costo razonable, y zero infrastructure overhead. Especialmente brilla en dos casos: equipos pequeños sin recursos para mantener modelos, y aplicaciones multilingües donde los cross-encoders entrenados en inglés (MS MARCO) no rinden bien.

Esta cápsula te enseña cuándo elegirlo sobre las otras opciones, cómo integrarlo correctamente, y cómo calcular el costo total de propiedad para decidir si vale el cambio.

Al finalizar esta cápsula serás capaz de:

  • ✅ Identificar los dos escenarios donde Cohere Rerank gana sobre cross-encoder local
  • ✅ Implementar Cohere Rerank con manejo correcto de API keys y errores
  • ✅ Diferenciar los modelos disponibles (rerank-v3.5, rerank-multilingual-v3) y cuándo elegir cada uno
  • ✅ Calcular el costo mensual y el TCO comparado con cross-encoder local + LLM rerank
  • ✅ Anticipar el riesgo crítico: vendor lock-in y plan de fallback
  • ✅ Diseñar un patrón de fallback automático API → cross-encoder local cuando Cohere falla

Tiempo estimado: 25-30 minutos


Las tres opciones de re-ranking lado a lado

AspectoCross-encoder localLLM-basedCohere Rerank
Calidad típica (precision@5)90%94%93%
Latencia (rerank 20 docs)150ms1500ms200-300ms
Costo$0 (gratis)$0.001-0.005/query$0.002/1K reranks
Setuppip install + descarga modeloAPI keyAPI key
MaintenanceGestionar versiones del modeloCeroCero
MultilingüeInglés bien, otros débilExcelenteExcelente
EscalabilidadCPU/GPU limit localRate limit OpenAIRate limit Cohere

Cohere Rerank es el "intermedio sensato": mejor calidad multilingüe que cross-encoder local, mucho más rápido y barato que LLM rerank, sin overhead de mantener modelos.

Cuándo Cohere gana sobre cross-encoder local

Escenario 1: dataset multilingüe. Si tu corpus tiene queries en español, portugués, francés, alemán, japonés — los cross-encoders entrenados sobre MS MARCO (inglés) degradan ~10-15% en idiomas no-ingleses. Cohere rerank-multilingual-v3 mantiene calidad similar entre 100+ idiomas porque fue entrenado específicamente con datos multilingües.

Escenario 2: equipo sin bandwidth para mantener modelos. Cross-encoder requiere:

  • Descargar el modelo en cada deploy
  • Manejar carga del modelo en cold-start
  • Decidir cuándo migrar a versiones nuevas
  • Gestionar memoria si tu app tiene otros modelos cargados

Para equipos pequeños sin un MLE dedicado, esto es overhead operacional real. Cohere lo abstrae completamente — un API call y listo.

Cuándo Cohere NO gana

  • Inglés monolingüe + equipo técnico sólido: cross-encoder local da 90%+ precision gratis. Cohere agrega ~3% calidad por $$/mes. No siempre vale.
  • Compliance que prohíbe envío de datos a APIs externas: si tus chunks son sensibles (legal, médico privado), cross-encoder local mantiene los datos en tu infra.
  • Producto a precio bajo con alto volumen: si cobras $5/mes/usuario y tienes 100K queries/mes, $200/mes en re-ranking puede no caber en márgenes.

Implementación correcta

Setup básico

# cohere_rerank.py
import cohere
import os
from dataclasses import dataclass
from typing import List

# Inicializar cliente con API key desde environment
co = cohere.Client(api_key=os.getenv("COHERE_API_KEY"))


@dataclass
class CohereRerankResult:
    document: str
    score: float
    original_index: int


def cohere_rerank(
    query: str,
    documents: List[str],
    top_k: int = 5,
    model: str = "rerank-v3.5",
) -> List[CohereRerankResult]:
    """
    Re-rank documents using Cohere's managed Rerank API.

    Models:
      - "rerank-v3.5": general purpose, English-optimized
      - "rerank-multilingual-v3": 100+ languages (use for non-English content)
    """
    response = co.rerank(
        model=model,
        query=query,
        documents=documents,
        top_n=top_k,
    )

    results = []
    for result in response.results:
        results.append(CohereRerankResult(
            document=documents[result.index],
            score=result.relevance_score,
            original_index=result.index,
        ))
    return results

Uso end-to-end

import chromadb
from chromadb.utils import embedding_functions

openai_ef = embedding_functions.OpenAIEmbeddingFunction(
    api_key=os.getenv("OPENAI_API_KEY"),
    model_name="text-embedding-3-small",
)
client_chroma = chromadb.PersistentClient(path="./chroma_db")
collection = client_chroma.get_collection("docs", embedding_function=openai_ef)

# Etapa 1: retrieval amplio
query = "¿cómo configuro autenticación OAuth2 en FastAPI?"
results = collection.query(query_texts=[query], n_results=20)
candidates = results['documents'][0]

# Etapa 2: re-ranking con Cohere (multilingüe para query en español)
top_5 = cohere_rerank(
    query=query,
    documents=candidates,
    top_k=5,
    model="rerank-multilingual-v3",  # ← multilingüe porque la query es en español
)

print(f"Top 5 después de Cohere rerank:")
for i, item in enumerate(top_5, 1):
    print(f"\n#{i} (score: {item.score:.3f}, was rank #{item.original_index+1})")
    print(f"   {item.document[:120]}...")

Output típico:

Top 5 después de Cohere rerank:

#1 (score: 0.987, was rank #4)
   FastAPI proporciona OAuth2PasswordBearer para autenticación con username/password...

#2 (score: 0.953, was rank #1)
   Para implementar OAuth2 en FastAPI, primero importar las clases de fastapi.security...

#3 (score: 0.842, was rank #6)
   La configuración de JWT con OAuth2 en FastAPI requiere un secret key y un algoritmo...

Selección de modelo correcto

ModeloCuándo usar
rerank-v3.5Inglés primario, queries y documentos consistentemente en inglés
rerank-multilingual-v3Cualquier mezcla de idiomas (español, portugués, francés, alemán, etc.)
rerank-english-v3.0Versión anterior, mantener si ya estás en producción con ella

Regla simple: si dudas, usar rerank-multilingual-v3. Pierde ~1% de calidad sobre inglés puro vs rerank-v3.5 pero gana 10-15% en cualquier otro idioma.


Calculando el costo total de propiedad

Cohere Rerank cobra por documento procesado, no por query:

Pricing (mayo 2026):
  rerank-v3.5:               $0.002 por 1,000 documentos
  rerank-multilingual-v3:    $0.002 por 1,000 documentos

Ejemplo concreto:

# Configuración típica
QUERIES_PER_DAY = 5_000
TOP_K_TO_RERANK = 25  # candidatos por query
DAYS_PER_MONTH = 30

# Cálculo
documents_processed_per_day = QUERIES_PER_DAY * TOP_K_TO_RERANK
documents_processed_per_month = documents_processed_per_day * DAYS_PER_MONTH

cost_per_thousand_docs = 0.002  # USD
monthly_cost = (documents_processed_per_month / 1000) * cost_per_thousand_docs

print(f"Documentos re-rankeados por mes: {documents_processed_per_month:,}")
print(f"Costo mensual Cohere: ${monthly_cost:.2f}")

Output:

Documentos re-rankeados por mes: 3,750,000
Costo mensual Cohere: $7.50

$7.50/mes para 5K queries/día rerankeando 25 candidatos. Realmente barato comparado con LLM rerank (~$200/mes en escenario similar).

TCO comparado: las tres opciones para un caso real

Volumen: 5K queries/día, 25 candidatos rerankeados, dataset multilingüe.

OpciónCosto mensual APICosto de mantenimientoCosto total estimado
Cross-encoder local$0~4hrs/mes ingeniería × $50/h = $200$200/mes
LLM rerank (GPT-4o-mini)$190/mes$0$190/mes
Cohere Rerank (multilingual)$7.50/mes$0$7.50/mes

Lectura: para este volumen, Cohere Rerank es 15-25x más barato que las alternativas si cuentas el costo de mantener cross-encoder. Y la calidad multilingüe es notablemente mejor que cross-encoder MS MARCO.

Cuando cross-encoder gana: volumen MUY alto (millones de queries/mes) donde el costo lineal de Cohere supera el costo fijo de mantener un modelo.


Patrón de fallback: cuando la API falla

Riesgo crítico: si tu pipeline RAG depende de Cohere Rerank y Cohere tiene un outage, tu sistema falla. Solución: fallback automático a cross-encoder local.

from sentence_transformers import CrossEncoder
import logging

logger = logging.getLogger(__name__)

# Carga el cross-encoder al startup (un solo costo, no por query)
fallback_reranker = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-12-v2")


def rerank_with_fallback(
    query: str,
    documents: List[str],
    top_k: int = 5,
) -> List[CohereRerankResult]:
    """
    Re-rank con Cohere primero. Si falla (timeout, rate limit, error), usa cross-encoder.
    Garantiza que el pipeline RAG siempre devuelve algo, aunque la API caiga.
    """
    try:
        # Intentar Cohere
        return cohere_rerank(
            query=query,
            documents=documents,
            top_k=top_k,
            model="rerank-multilingual-v3",
        )
    except (cohere.CohereAPIError, cohere.CohereConnectionError) as e:
        logger.warning(f"Cohere rerank failed ({e}), falling back to local cross-encoder")

        # Fallback: cross-encoder local
        pairs = [(query, doc) for doc in documents]
        scores = fallback_reranker.predict(pairs)

        # Convertir al mismo formato
        scored = sorted(
            enumerate(scores),
            key=lambda x: -x[1],
        )[:top_k]

        return [
            CohereRerankResult(
                document=documents[idx],
                score=float(score),
                original_index=idx,
            )
            for idx, score in scored
        ]

Por qué importa:

  • Sin fallback, un outage de Cohere = down de tu sistema RAG.
  • Cross-encoder local cargado en memoria al startup garantiza respuesta en <200ms aún en outage.
  • La calidad baja ~3-5% durante el fallback, pero el sistema sigue funcionando.

Bonus: loguear cuándo el fallback se activa permite detectar patrones (¿outage de Cohere? ¿problema de red local?). Si el fallback se activa frecuentemente, considerar suplir con redundancia o cambiar de proveedor.


Trampas y errores comunes

Trampa 1: API key en el código fuente

El error:

co = cohere.Client(api_key="co-abc123...")  # commiteado a git

Síntoma: key leakeada en GitHub, alguien la usa para sus propios queries, factura inesperada.

Cómo prevenir: siempre desde environment. .env en .gitignore. Pre-commit hook que detecte el patrón.

Trampa 2: usar rerank-v3.5 (English) con queries multilingües

El error:

co.rerank(model="rerank-v3.5", query="¿cómo configurar OAuth2?", ...)

Síntoma: la query en español falla en hacer match correcto con docs en inglés. Resultados degradados sin error explícito.

Cómo prevenir: si hay cualquier mezcla de idiomas, usar rerank-multilingual-v3 aunque pierdas ~1% en queries puramente inglesas.

Trampa 3: re-rankear documentos enormes

El error:

co.rerank(query=q, documents=[doc_de_5000_chars], ...)

Síntoma: Cohere trunca docs a sus tokens máximos (~512 tokens por defecto). El re-ranking solo "ve" la parte inicial del documento.

Cómo prevenir: chunkear correctamente antes de re-rankear (ver M02). Cada documento candidato debería ser un chunk de 300-1500 caracteres, no un documento completo.

Trampa 4: no manejar rate limits

El error: picos de tráfico exceden el rate limit del tier de Cohere. Las queries empiezan a fallar.

Síntoma: errores 429 en horas pico. Usuarios afectados.

Cómo prevenir:

  • Conocer el rate limit del tier (verificar en dashboard de Cohere).
  • Implementar exponential backoff en retry.
  • Para volumen alto, escalar a tier superior o cachear resultados de queries comunes.
import time

def rerank_with_retry(query, docs, top_k=5, max_retries=3):
    for attempt in range(max_retries):
        try:
            return cohere_rerank(query, docs, top_k)
        except cohere.CohereRateLimitError:
            wait = (2 ** attempt) * 2  # 2, 4, 8s
            logger.warning(f"Rate limit, waiting {wait}s")
            time.sleep(wait)
    raise RuntimeError("Cohere rerank failed after retries")

Trampa 5: vendor lock-in sin plan de migración

El error: todo el pipeline asume Cohere. Si los precios suben, no hay alternativa rápida.

Cómo prevenir: abstraer la interfaz de re-ranking detrás de una clase con métodos que no exponen el vendor:

class Reranker:
    def rerank(self, query: str, documents: List[str], top_k: int) -> List[RerankResult]:
        raise NotImplementedError

class CohereReranker(Reranker):
    def rerank(self, query, documents, top_k):
        # implementación Cohere
        ...

class CrossEncoderReranker(Reranker):
    def rerank(self, query, documents, top_k):
        # implementación local
        ...

# El resto del pipeline usa Reranker abstracto
reranker: Reranker = CohereReranker()  # puedes cambiar implementación con una sola línea

Trampa 6: asumir que el orden de Cohere es el final

El error: ignoras los scores. Tomas los top_k que devuelve Cohere y listo.

Síntoma: algunos resultados con score muy bajo (ej: 0.15) se incluyen aunque sean de baja relevancia. Ensucian el contexto del LLM.

Cómo prevenir: filtrar por score threshold después del rerank:

results = cohere_rerank(query, candidates, top_k=10)
# Solo incluir docs con score > 0.5
relevant = [r for r in results if r.score > 0.5]

El threshold óptimo se determina empíricamente sobre tu eval set.


Ejercicio aplicado

Escenario: eres AI Engineer en una startup de e-commerce con presencia en LATAM y España. El producto: chatbot que responde preguntas de catálogo a usuarios.

  • 200K productos chunkeados (descripción, especificaciones, reviews) en español, portugués e inglés
  • 30K queries/día (mezcla de idiomas)
  • Pipeline actual: cosine + cross-encoder ms-marco-MiniLM-L-12-v2
  • Métricas: precision@5 = 78% (bajo, debería ser ≥90%)
  • Equipo: 3 ingenieros, ningún MLE dedicado

Tu trabajo:

  1. Diagnostica por qué precision@5 está tan baja.
  2. Decide entre las tres opciones de re-ranking. Justifica con números.
  3. Diseña el plan de implementación incluyendo fallback.
Solución

1. Diagnóstico

La precision baja (78%) en un sistema con cross-encoder ya implementado tiene tres posibles causas:

  • Hipótesis 1: chunking pobre. No es probable porque el problema sería más recall que precision.
  • Hipótesis 2: cross-encoder MS MARCO no maneja bien el multilingüe. Es la hipótesis más fuerte. ms-marco-MiniLM-L-12-v2 está entrenado en inglés. Si 60-70% del tráfico es en español/portugués, la calidad cae 10-15% sobre esas queries.
  • Hipótesis 3: corpus técnico-comercial muy distinto de MS MARCO. Los cross-encoders MS MARCO se entrenaron sobre queries y respuestas tipo "search engine". Catálogos de e-commerce tienen estructura distinta.

Las dos hipótesis combinadas explican fácilmente el ~12% de pérdida de precision.

Validación rápida: medir precision@5 segmentado por idioma. Si español/portugués son ~70% pero inglés es ~88%, la hipótesis 2 está confirmada.

2. Decisión: Cohere Rerank multilingual

Comparación de opciones para este escenario:

OpciónCalidad esperadaCosto mensual estimadoSetup time
Mantener cross-encoder MS MARCO78% (actual)$0 + maintenance0 hrs
Cambiar a cross-encoder multilingüe local85%$0 + maintenance1-2 días
LLM rerank (GPT-4o-mini)90%~$135/mes1 día
Cohere Rerank multilingual-v388%$45/mes2-3 hrs

Cálculo del costo Cohere:

queries_per_day = 30_000
top_k_rerank = 25
docs_per_month = queries_per_day * top_k_rerank * 30  # 22.5M
cost = (docs_per_month / 1000) * 0.002  # $45/mes

Justificación:

  • La startup necesita salir del problema rápido (3 ingenieros, no hay MLE para optimizar cross-encoder local).
  • $45/mes es trivial para una startup de e-commerce con 30K queries/día.
  • Multilingual-v3 está hecho exactamente para este caso (LATAM + España).
  • Setup en horas vs días.

LLM rerank también funcionaría pero a 3x el costo y 5x la latencia, sin ganar tanto sobre Cohere para este caso.

3. Plan de implementación con fallback

# reranker.py
import cohere
import os
from sentence_transformers import CrossEncoder
from dataclasses import dataclass
from typing import List, Protocol


class Reranker(Protocol):
    def rerank(self, query: str, documents: List[str], top_k: int) -> List[dict]: ...


# Cliente Cohere
_cohere_client = cohere.Client(api_key=os.getenv("COHERE_API_KEY"))

# Fallback cross-encoder cargado al startup
_fallback_model = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-12-v2")


def rerank_with_fallback(query: str, documents: List[str], top_k: int = 5):
    try:
        response = _cohere_client.rerank(
            model="rerank-multilingual-v3",
            query=query,
            documents=documents,
            top_n=top_k,
        )
        return [
            {"document": documents[r.index], "score": r.relevance_score}
            for r in response.results
        ]
    except Exception as e:
        # Fallback: cross-encoder local (sabemos que da 78% pero el sistema funciona)
        log_event("cohere_rerank_fallback", error=str(e))
        pairs = [(query, doc) for doc in documents]
        scores = _fallback_model.predict(pairs)
        scored = sorted(enumerate(scores), key=lambda x: -x[1])[:top_k]
        return [
            {"document": documents[i], "score": float(s)}
            for i, s in scored
        ]

Plan de rollout:

  1. Día 1 (3-4 horas):

    • Setup de cuenta Cohere, API key en environment
    • Implementar rerank_with_fallback en código
    • Tests unitarios (Cohere OK, Cohere falla → fallback funciona)
  2. Día 2 (2-3 horas):

    • Deploy a staging
    • Correr eval set de 100 queries multilingües (50 español, 25 portugués, 25 inglés)
    • Medir precision@5 antes y después por idioma
  3. Día 3 (medio día):

    • Si precision en multilingüe ≥85%, deploy a producción con feature flag
    • Monitoreo activo: latencia, error rate de Cohere, fallback rate
    • Rollback inmediato si hay regresión
  4. Semanas 2-4:

    • A/B test: 50% Cohere, 50% cross-encoder original
    • Métricas: precision, NPS, latencia, costo
    • Decisión final basada en datos

Monitoreo continuo:

  • cohere_rerank_fallback rate: debería ser <1%. Si sube, investigar.
  • Costo mensual real vs estimado: alerta si supera $80/mes (75% sobre presupuesto).
  • Precision por idioma: alerta si cualquier idioma cae bajo 80%.

Plan B si Cohere no alcanza el target:

  • Si precision queda en 84-86% pero el target es 90%: cambiar a LLM rerank en cascada (cross-encoder Cohere → GPT-4o-mini sobre top-10).
  • Si Cohere tiene problemas de disponibilidad recurrentes: evaluar Voyage AI rerank o build cross-encoder multilingüe in-house.

Resumen y siguiente paso

Lo que aprendiste:

  • Cohere Rerank es opción managed que ofrece calidad cercana a LLM rerank a costo cercano a cross-encoder local.
  • Brilla en dos casos: corpus multilingüe y equipos sin recursos para mantener modelos.
  • Modelos: rerank-v3.5 para inglés puro, rerank-multilingual-v3 para cualquier mezcla de idiomas.
  • Pricing por documento procesado: $0.002 por 1K docs. Volumen típico = $5-50/mes.
  • Implementación robusta requiere: API key en environment, fallback a cross-encoder local, manejo de rate limits, threshold de score para descartar resultados de baja relevancia.
  • Fallback automático a cross-encoder local protege contra outages — el pipeline siempre funciona, aunque con calidad ligeramente menor.
  • Vendor lock-in es riesgo real; abstraer la interfaz facilita migrar entre proveedores.

Checkpoint: antes de avanzar, deberías poder:

  • Decidir entre cross-encoder local, LLM rerank y Cohere para un escenario dado.
  • Calcular el costo mensual de Cohere para un volumen específico de queries.
  • Implementar fallback automático a cross-encoder local si Cohere falla.

Siguiente cápsula: 06 — Trade-offs y optimizaciones de re-ranking.

Cubrimos las tres técnicas de re-ranking. Pero hay decisiones operativas más finas que las tres comparten: ¿cuántos candidatos pasar al re-ranker? ¿cómo cachear resultados? ¿cuándo re-rankear vs cuándo confiar en el retrieval directo? La cápsula 06 cubre estas optimizaciones que pueden mejorar 10-20% la performance sin cambiar la técnica subyacente.


Recursos

  1. Cohere Rerank Documentation — Documentación oficial completa
  2. Cohere Rerank Models Guide — Comparación de modelos disponibles
  3. Cohere Pricing — Precios actualizados
  4. Multilingual Reranking — Cohere Blog — Casos de uso multilingüe
  5. Voyage AI Rerank — Alternativa managed a Cohere
  6. Anthropic — Contextual Retrieval with Reranking — Patrones combinados con rerank

Tiempo estimado: 25-30 minutos Siguiente: 06-tradeoffs-optimizations.md