Apogée Consult
Retour au blog
Jules Ginhac
Jules GinhacCo-Founder & ingénieur IA

Je suis Jules Ginhac, Co-Founder & ingénieur IA chez Apogée Consult à Lyon. Je conçois et déploie des architectures IA génératives (RAG, agents, LLMOps) pour des PME, startups et organisations publiques.

Reranking RAG : cross-encoder dédié ou LLM-as-judge, ce que coûte vraiment chaque approche

  • rag

Cross-encoder ou LLM-as-judge pour reranker les résultats de votre RAG ? Comparaison honnête des coûts, latences et seuils de pertinence à partir de cas réels.

Reranking RAG : cross-encoder dédié ou LLM-as-judge, ce que coûte vraiment chaque approche

Le retrieval initial remonte les chunks les plus proches dans l'espace vectoriel, pas nécessairement les plus utiles pour répondre à la question posée. Le reranking est l'étape qui réordonne ce premier lot avant de l'envoyer au LLM.

Deux approches dominent : le cross-encoder dédié et le LLM-as-judge. Elles ne ciblent pas le même problème et ne coûtent pas pareil. Voici ce qu'on a mesuré.

Pourquoi le retrieval initial ne suffit pas

La similarité cosinus mesure la proximité sémantique entre la requête et le chunk. Elle ne mesure pas la capacité du chunk à répondre à la question. Ces deux choses divergent régulièrement.

Exemple concret : une requête "quel est le délai de garantie légale" remonte un chunk qui cite le délai dans un exemple négatif ("contrairement à la garantie légale de 2 ans, notre contrat prévoit..."). Similarité cosinus élevée, pertinence réelle nulle.

Un reranker examine la paire (question, chunk) ensemble et attribue un score de pertinence directe. C'est une tâche différente, et plus coûteuse.

Cross-encoder : le modèle dédié

Un cross-encoder prend la concaténation (question, chunk) et produit un score de pertinence. Il ne génère pas d'embedding séparé, il évalue directement la paire.

Modèles couramment utilisés :

  • BAAI/bge-reranker-v2-m3 (Hugging Face) : multilingue, très bon rapport qualité/coût, tourne sur GPU A10G ou en CPU pour de petits volumes
  • cross-encoder/ms-marco-MiniLM-L-6-v2 : rapide, léger, anglais seulement
  • Cohere Rerank API (docs) : service managé, facturé par appel
from sentence_transformers import CrossEncoder

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

def rerank_chunks(
    query: str,
    chunks: list[str],
    top_n: int = 3,
) -> list[tuple[str, float]]:
    """
    Reranke une liste de chunks par pertinence à la query.
    
    On récupère top-10 au retrieval et on garde top-3 après reranking.
    Le ratio 10→3 est empirique : en dessous de 5 candidats,
    le reranker n'a pas assez de matière pour discriminer.
    """
    pairs = [(query, chunk) for chunk in chunks]
    scores = reranker.predict(pairs)
    ranked = sorted(zip(chunks, scores), key=lambda x: x[1], reverse=True)
    return ranked[:top_n]

Latence : sur un GPU A10G, bge-reranker-v2-m3 traite 10 paires en 80-120 ms. En CPU, comptez 400-800 ms selon la longueur des chunks. Pour une application interactive avec une contrainte < 2 secondes end-to-end, le CPU est limite.

Coût Cohere : 0,002 USD pour 1 000 documents rerankés (grille tarifaire). Sur un volume de 50 000 requêtes/mois avec top-10, ça représente 1 USD/mois, négligeable.

LLM-as-judge : le modèle généraliste comme évaluateur

LLM-as-judge consiste à demander au LLM d'évaluer la pertinence de chaque chunk avant de le synthétiser. On passe les chunks un par un (ou en batch) avec un prompt d'évaluation.

JUDGE_PROMPT = """Tu es un évaluateur de pertinence documentaire.

Question : {query}

Extrait de document :
{chunk}

Cet extrait contient-il une information directement utile pour répondre à la question ?
Réponds uniquement par un JSON : {{"score": 0|1, "reason": "..."}}"""

async def llm_judge_chunk(
    query: str,
    chunk: str,
    llm_client,
) -> dict:
    response = await llm_client.chat.completions.create(
        model="gpt-4o-mini",  # modèle rapide et bon marché pour le jugement
        messages=[{"role": "user", "content": JUDGE_PROMPT.format(
            query=query,
            chunk=chunk,
        )}],
        response_format={"type": "json_object"},
        temperature=0,
    )
    return json.loads(response.choices[0].message.content)

Latence : avec gpt-4o-mini, un jugement sur un chunk de 500 tokens prend 600-1200 ms. Sur 10 chunks en parallèle : 1,5-2 s selon la charge OpenAI. C'est significatif dans une boucle synchrone.

Coût : gpt-4o-mini coûte 0,15 USD / million de tokens input et 0,60 USD / million de tokens output (tarifs OpenAI). Un prompt de jugement avec un chunk de 500 tokens représente environ 700 tokens input. Sur 50 000 requêtes/mois avec top-10 chunks jugés : 50 000 × 10 × 700 = 350 millions de tokens → ~52 USD/mois. Non négligeable.

Comparatif synthétique

CritèreCross-encoder dédiéLLM-as-judge
Qualité de discriminationHaute sur le domaine d'entraînementHaute, flexible sur requêtes complexes
Latence (10 chunks)80-120 ms (GPU) / 400-800 ms (CPU)600-2000 ms (parallèle)
Coût opérationnelInfra GPU ou API managée (~1 USD/mois à 50k req)~50 USD/mois à 50k req (gpt-4o-mini)
MultilingueSelon le modèle (bge-v2-m3 : oui)Oui, natif
Domaine spécialiséNécessite fine-tuning ou bon modèle génériquePrompt engineering suffisant
ExplicabilitéAucune (score brut)Partielle (reason dans le JSON)

Ce qu'on choisit et pourquoi

On utilise le cross-encoder dédié par défaut. Sur des corpus de documentation technique ou juridique francophone, bge-reranker-v2-m3 donne de bons résultats sans fine-tuning, et la latence GPU reste acceptable.

Le LLM-as-judge est pertinent dans deux cas précis : quand la requête nécessite un raisonnement multi-critères (pas seulement "est-ce pertinent" mais "est-ce pertinent ET récent ET applicable à ce contexte"), ou quand on a besoin d'une raison machine-readable pour logger la décision et la déboguer.

On n'utilise pas LLM-as-judge comme unique reranker en production sur un volume > 20 000 requêtes/mois, le coût devient inconfortable et la latence parallèle reste un risque.

Une limite réelle : les cross-encoders sont sensibles à la langue et au domaine. Un bge-reranker-v2-m3 sur un corpus de brevets techniques ou de textes médicaux peut sur-noter des chunks superficiellement proches mais incorrects sur le fond. Le LLM-as-judge avec un prompt métier spécifique dépasse le cross-encoder dans ces cas, mais à quel prix acceptable ?

Disponible pour de nouveaux projets

Un projet à concrétiser ?
Parlons-en, sans engagement.

Un échange de 30 minutes pour cadrer votre besoin, qualifier la faisabilité et vous proposer une trajectoire claire.

1// kick-off : réponse sous 24h
2const project = await apogee.scope({
3 type: 'web | mobile | IA',
4 timeline: '6 à 16 semaines',
5 approach: 'sur-mesure'
6})
7// → cadrage offert
Reranker RAG : cross-encoder vs LLM-as-judge | Apogée Consult