6. RerankingAvancé

Reranking : Améliorer la Précision de Récupération

10 février 2025
11 min de lecture
Équipe de Recherche Ailog

Cross-encoders, reranking basé sur LLM et stratégies de reranking pour optimiser le contexte récupéré et améliorer les réponses RAG.

TL;DR

  • Reranking = Deuxième passage de notation des docs récupérés pour une meilleure précision
  • Cross-encoders apportent 10-25% d'amélioration de précision par rapport à la récupération pure
  • API Cohere Rerank : Option la plus simple (1 $/1000 requêtes)
  • Auto-hébergé : cross-encoders ms-marco (gratuit, bonne qualité)
  • Comparez les rerankers sur vos données avec Ailog

Le Problème du Reranking

La récupération initiale (recherche vectorielle, BM25) jette un large filet pour rappeler les documents potentiellement pertinents. Cependant :

  • Faux positifs : Certains chunks récupérés ne sont pas réellement pertinents
  • Qualité de classement : Les chunks les plus pertinents peuvent ne pas être classés en premier
  • Pertinence spécifique à la requête : Le classement initial ne tient pas compte des nuances de la requête

Solution : Reclasser les candidats récupérés avec un modèle plus sophistiqué.

Récupération en Deux Étapes

Requête → [Étape 1: Récupération] → 100 candidats
        → [Étape 2: Reranking] → 10 meilleurs résultats
        → [Étape 3: Génération] → Réponse

Pourquoi deux étapes ?

  • Récupération : Rapide, s'adapte à des millions/milliards de documents
  • Reranking : Coûteux mais précis, seulement sur un petit ensemble de candidats
  • Le meilleur des deux : Vitesse + Qualité

Approches de Reranking

Modèles Cross-Encoder

Contrairement aux bi-encoders (embedder requête et document séparément), les cross-encoders traitent la requête et le document ensemble.

Bi-encoder (Récupération)

DEVELOPERpython
query_emb = embed(query) # [768] doc_emb = embed(document) # [768] score = cosine(query_emb, doc_emb) # Similarity

Cross-encoder (Reranking)

DEVELOPERpython
# Traiter ensemble input = f"[CLS] {query} [SEP] {document} [SEP]" score = model(input) # Score de pertinence direct

Pourquoi les cross-encoders sont meilleurs :

  • Attention entre les tokens de requête et de document
  • Capture les interactions au niveau des mots
  • Notation de pertinence plus précise

Pourquoi ne pas les utiliser pour la récupération :

  • Doit noter chaque paire requête-document (O(n))
  • Trop lent pour de grandes collections
  • Pas d'embeddings pré-calculés

Modèles Cross-Encoder Populaires

ms-marco-MiniLM-L6-v2

DEVELOPERpython
from sentence_transformers import CrossEncoder model = CrossEncoder('cross-encoder/ms-marco-MiniLM-L6-v2') # Score query-document pairs scores = model.predict([ (query, doc1), (query, doc2), (query, doc3) ]) # Rerank by score ranked_indices = np.argsort(scores)[::-1]

Caractéristiques :

  • Taille : 80MB
  • Vitesse : ~50ms par batch
  • Qualité : Bonne pour l'anglais
  • Entraînement : Entraîné sur MS MARCO

ms-marco-TinyBERT-L2-v2

  • Encore plus petit/rapide
  • Légère baisse de qualité
  • Bon pour les applications critiques en latence

mmarco-mMiniLMv2-L12-H384-v1

  • Support multilingue
  • Performance similaire aux modèles anglais
  • Supporte plus de 100 langues

Implémentation

DEVELOPERpython
class RerankedRetriever: def __init__(self, base_retriever, reranker_model): self.retriever = base_retriever self.reranker = CrossEncoder(reranker_model) def retrieve(self, query, k=5, rerank_top_n=20): # Stage 1: Retrieve more candidates candidates = self.retriever.retrieve(query, k=rerank_top_n) # Stage 2: Rerank pairs = [(query, doc['content']) for doc in candidates] scores = self.reranker.predict(pairs) # Sort by reranker scores ranked_indices = np.argsort(scores)[::-1] reranked_docs = [candidates[i] for i in ranked_indices] # Return top-k return reranked_docs[:k]

Reranking Basé sur LLM

Utiliser un LLM pour juger la pertinence.

Pertinence Binaire

Demander au LLM si le document est pertinent.

DEVELOPERpython
def llm_rerank_binary(query, documents, llm): relevant_docs = [] for doc in documents: prompt = f"""Ce document est-il pertinent pour la requête ? Requête: {query} Document: {doc} Réponds seulement 'yes' ou 'no'.""" response = llm.generate(prompt, max_tokens=5) if 'yes' in response.lower(): relevant_docs.append(doc) return relevant_docs

Notation de la Pertinence

Obtenir des scores numériques de pertinence.

DEVELOPERpython
def llm_rerank_score(query, documents, llm): scored_docs = [] for doc in documents: prompt = f"""Note la pertinence de ce document pour la requête sur une échelle de 1-10. Requête: {query} Document: {doc} Score de pertinence (1-10):""" score = int(llm.generate(prompt, max_tokens=5)) scored_docs.append((doc, score)) # Sort by score scored_docs.sort(key=lambda x: x[1], reverse=True) return [doc for doc, score in scored_docs]

Classement Comparatif

Comparer les documents par paires ou par lots.

DEVELOPERpython
def llm_rerank_comparative(query, documents, llm): prompt = f"""Classe ces documents par pertinence pour la requête. Requête: {query} Documents: {format_documents(documents)} Fournis le classement (du plus au moins pertinent):""" ranking = llm.generate(prompt) ranked_docs = parse_ranking(ranking, documents) return ranked_docs

Avantages :

  • Très précis
  • Peut gérer une pertinence nuancée
  • Explique le raisonnement

Inconvénients :

  • Coûteux (appel LLM par document ou lot)
  • Lent (centaines de ms à secondes)
  • Peut dépasser la fenêtre de contexte avec de nombreux docs

Utiliser quand :

  • Qualité maximale requise
  • Coût/latence acceptable
  • Petit ensemble de candidats (< 10 docs)

API Cohere Rerank

Service de reranking géré.

DEVELOPERpython
import cohere co = cohere.Client(api_key="your-key") def cohere_rerank(query, documents, top_n=5): response = co.rerank( query=query, documents=documents, top_n=top_n, model="rerank-english-v2.0" ) return [doc.document for doc in response.results]

Modèles :

  • rerank-english-v2.0 : Anglais
  • rerank-multilingual-v2.0 : Plus de 100 langues

Tarification :

  • 1,00 $ pour 1000 recherches (en 2025)

Avantages :

  • Service géré
  • Haute qualité
  • Multilingue

Inconvénients :

  • Latence API
  • Coût continu
  • Dépendance au fournisseur

FlashRank

Reranking local efficace.

DEVELOPERpython
from flashrank import Ranker, RerankRequest ranker = Ranker(model_name="ms-marco-MultiBERT-L-12") def flashrank_rerank(query, documents, top_n=5): rerank_request = RerankRequest( query=query, passages=[{"text": doc} for doc in documents] ) results = ranker.rerank(rerank_request) return [r.text for r in results[:top_n]]

Avantages :

  • Très rapide (inférence optimisée)
  • Auto-hébergé
  • Pas de coûts API

Reranking Hybride

Combiner plusieurs signaux.

DEVELOPERpython
def hybrid_rerank(query, documents, weights=None): if weights is None: weights = { 'vector_score': 0.3, 'bm25_score': 0.2, 'cross_encoder': 0.5 } # Obtenir les scores de différents modèles vector_scores = get_vector_scores(query, documents) bm25_scores = get_bm25_scores(query, documents) ce_scores = get_cross_encoder_scores(query, documents) # Normaliser les scores à [0, 1] vector_scores = normalize(vector_scores) bm25_scores = normalize(bm25_scores) ce_scores = normalize(ce_scores) # Combinaison pondérée final_scores = ( weights['vector_score'] * vector_scores + weights['bm25_score'] * bm25_scores + weights['cross_encoder'] * ce_scores ) # Classer les documents ranked_indices = np.argsort(final_scores)[::-1] return [documents[i] for i in ranked_indices]

Stratégies de Reranking

Reranking Top-K

Reclasser uniquement les meilleurs candidats de la récupération initiale.

DEVELOPERpython
# Récupérer top 20, reclasser pour obtenir top 5 candidates = retriever.retrieve(query, k=20) reranked = reranker.rerank(query, candidates, top_n=5)

Paramètres :

  • Récupérer : 3-5x le k final
  • Reranker : K final nécessaire

Exemple :

  • Besoin de 5 résultats finaux
  • Récupérer 20 candidats
  • Reclasser en top 5

Reranking en Cascade

Plusieurs étapes de reranking avec précision croissante.

DEVELOPERpython
# Stage 1: Fast retrieval candidates = fast_retriever.retrieve(query, k=100) # Stage 2: Fast reranker reranked_1 = tiny_reranker.rerank(query, candidates, top_n=20) # Stage 3: Accurate reranker reranked_2 = large_reranker.rerank(query, reranked_1, top_n=5) return reranked_2

Utiliser quand :

  • Ensembles de candidats très larges
  • Plusieurs niveaux de qualité nécessaires
  • Optimisation coût/latence

Reranking Adaptatif à la Requête

Différent reranking selon le type de requête.

DEVELOPERpython
def adaptive_rerank(query, documents): query_type = classify_query(query) if query_type == "factual": # Utiliser des signaux de mots-clés return bm25_rerank(query, documents) elif query_type == "semantic": # Utiliser cross-encoder return cross_encoder_rerank(query, documents) elif query_type == "complex": # Utiliser LLM return llm_rerank(query, documents)

Optimisation des Performances

Traitement par Lots

Reclasser plusieurs requêtes efficacement.

DEVELOPERpython
# Mauvais : Un à la fois for query in queries: rerank(query, docs) # Bon : Par lots pairs = [(q, doc) for q in queries for doc in docs] scores = reranker.predict(pairs, batch_size=32)

Mise en Cache

Mettre en cache les résultats de reranking.

DEVELOPERpython
from functools import lru_cache import hashlib def cache_key(query, doc): return hashlib.md5(f"{query}:{doc}".encode()).hexdigest() @lru_cache(maxsize=10000) def cached_rerank_score(query, doc): return reranker.predict([(query, doc)])[0]

Reranking Asynchrone

Paralléliser les appels de reranking.

DEVELOPERpython
import asyncio async def async_rerank_batch(query, documents): tasks = [ rerank_async(query, doc) for doc in documents ] scores = await asyncio.gather(*tasks) return rank_by_scores(documents, scores)

Évaluation

Métriques

Precision@k : Docs pertinents dans le top-k après reranking

DEVELOPERpython
def precision_at_k(reranked_docs, relevant_docs, k): top_k = set(reranked_docs[:k]) relevant = set(relevant_docs) return len(top_k & relevant) / k

NDCG@k : Normalized Discounted Cumulative Gain

DEVELOPERpython
from sklearn.metrics import ndcg_score def evaluate_reranking(predictions, relevance_labels, k=5): return ndcg_score([relevance_labels], [predictions], k=k)

MRR : Mean Reciprocal Rank

DEVELOPERpython
def mrr(reranked_docs, relevant_docs): for i, doc in enumerate(reranked_docs, 1): if doc in relevant_docs: return 1 / i return 0

Tests A/B

Comparer les stratégies de reranking.

DEVELOPERpython
# Contrôle : Pas de reranking control_results = retriever.retrieve(query, k=5) # Traitement : Avec reranking treatment_candidates = retriever.retrieve(query, k=20) treatment_results = reranker.rerank(query, treatment_candidates, k=5) # Mesurer : Satisfaction utilisateur, qualité de réponse

Analyse Coût-Bénéfice

RerankerLatenceCoût/1KQualitéMeilleur Pour
Pas de reranking0ms0 $BaselineBudget/vitesse critique
TinyBERT+30ms0 $ (auto-hébergé)+10%Équilibré
MiniLM+50ms0 $ (auto-hébergé)+20%Axé qualité
Cohere+100ms1 $+25%Simplicité gérée
LLM+500ms5-20 $+30%Qualité maximale

Bonnes Pratiques

  1. Toujours sur-récupérer pour le reranking : Récupérer 3-5x le k final
  2. Commencer avec cross-encoder : MiniLM est un bon défaut
  3. Mesurer l'impact : Test A/B reranking vs pas de reranking
  4. Ajuster le nombre de récupération : Équilibrer coût et rappel
  5. Considérer le budget de latence de requête : Le reranking ajoute 50-500ms
  6. Surveiller les coûts : Le reranking LLM peut être coûteux à grande échelle

Choisir un Reranker

Prototypage :

  • cross-encoder/ms-marco-MiniLM-L6-v2
  • Facile à utiliser, bonne qualité

Production (Sensible aux Coûts) :

  • cross-encoder/ms-marco-TinyBERT-L2-v2
  • Auto-hébergé, rapide

Production (Axé Qualité) :

  • API Cohere Rerank
  • Qualité maximale, géré

Multilingue :

  • mmarco-mMiniLMv2-L12-H384-v1
  • cross-encoder/mmarco-mMiniLMv2-L12

Qualité Maximale (Budget Disponible) :

  • Reranking basé LLM
  • GPT-4, Claude pour les meilleurs résultats

Conseil d'Expert d'Ailog : Le reranking a un impact élevé mais n'est pas la première priorité. Commencez par bien faire votre découpage, vos embeddings et votre récupération - ce sont les fondations. Une fois que vous avez un système RAG fonctionnel, le reranking est le moyen le plus simple de gagner 10-25% de précision supplémentaire. Commencez avec l'API Cohere Rerank pour des gains sans configuration. Nous avons ajouté le reranking en production en un après-midi et avons immédiatement vu moins d'hallucinations et une meilleure qualité de réponse.

Tester le Reranking sur Ailog

Comparez les modèles de reranking sans configuration :

La plateforme Ailog inclut :

  • Cohere Rerank, cross-encoders, reranking LLM
  • Comparaison de qualité côte à côte
  • Analyse de latence et de coût
  • Tests A/B avec de vraies requêtes

Testez le reranking gratuitement →

Prochaines Étapes

Avec la récupération et le reranking optimisés, il est crucial de mesurer les performances. Le prochain guide couvre les métriques et méthodologies d'évaluation pour évaluer la qualité du système RAG.

Tags

rerankingcross-encoderrécupérationprécision

Articles connexes

Ailog Assistant

Ici pour vous aider

Salut ! Pose-moi des questions sur Ailog et comment intégrer votre RAG dans vos projets !