Le reranking des résultats
Mis à jour le 30 juillet 2026
Notre pipeline hybride classe déjà bien ; le reranking le fait classer mieux. C’est une technique de post-traitement qui améliore significativement la précision de la récupération en ajoutant une étape après la recherche hybride : demander à un modèle de langage de relire les candidats et de les reclasser. L’idée sous-jacente : BM25 compte des termes, les embeddings comparent des sens comprimés en vecteurs — mais aucun des deux ne lit vraiment. Un LLM, si.
Le processus
Le flux complet s’allonge d’un maillon :
- Exécuter la recherche hybride (vectorielle + BM25)
- Fusionner les résultats comme avant
- Envoyer les résultats fusionnés à Claude avec un prompt de reranking
- Récupérer une liste réordonnée des documents les plus pertinents
La division du travail est astucieuse : la recherche hybride, rapide et bon marché, réduit des milliers de segments à une poignée de candidats ; le LLM, lent mais fin, n’intervient que sur cette poignée. On ne demande jamais à Claude de fouiller le corpus entier — seulement d’arbitrer entre dix finalistes.
Le prompt de reranking
Tu vas recevoir un ensemble de documents avec un identifiant chacun.
Ta tache est de selectionner les {k} documents les plus pertinents
pour repondre a la question de l'utilisateur.
<question>
{query_text}
</question>
<documents>
{joined_docs}
</documents>
Reponds dans ce format :
{
"document_ids": str[] // Liste des IDs, {k} elements, tries par pertinence decroissante
}
Le prompt applique plusieurs techniques du cours : balises XML pour séparer la question des documents, format de sortie explicite pour obtenir du JSON parsable. Claude lit chaque candidat en entier, à la lumière de la question réelle — il perçoit l’intention, les nuances, le contexte que les scores numériques écrasent.
Optimisation avec les IDs
Un détail du format de sortie vaut la peine d’être souligné : on demande des identifiants de documents plutôt que le texte complet. Cela évite à Claude de recopier de gros blocs de texte et accélère considérablement le reranking — la réponse tient en une ligne de JSON, quelques dizaines de tokens au lieu de plusieurs milliers. Votre code retrouve ensuite les contenus à partir des IDs, opération instantanée. Règle générale à retenir : quand la sortie d’un LLM référence des données que vous possédez déjà, faites-lui produire des références, jamais des copies.
Implémentation
def reranker_fn(docs, query_text, k):
joined_docs = "\n".join([
f"""
<document>
<document_id>{doc["id"]}</document_id>
<document_content>{doc["content"]}</document_content>
</document>
"""
for doc in docs
])
# Construire le prompt, envoyer à Claude, parser les IDs
retriever = Retriever(bm25_index, vector_index, reranker_fn=reranker_fn)
Chaque candidat est enveloppé dans ses balises avec son identifiant, puis le tout rejoint le prompt. Et regardez la dernière ligne : le reranker s’intègre au Retriever comme simple paramètre optionnel — l’architecture façade des leçons précédentes absorbe l’étape supplémentaire sans changer l’interface. L’application appelle toujours search(), et reçoit simplement de meilleurs classements.
Compromis
Le reranking n’est pas gratuit, et le choix mérite d’être posé explicitement. Il ajoute de la latence — un appel LLM supplémentaire sur le chemin de chaque recherche — et un coût : chaque requête utilisateur déclenche désormais un appel API de plus. En échange, la précision monte réellement : le LLM comprend le contexte et l’intention là où les scores approximaient. L’arbitrage dépend de votre application — un assistant de recherche documentaire où chaque réponse compte absorbera volontiers 500 ms de plus ; un champ d’autocomplétion, jamais. Bonne nouvelle : le reranker étant un paramètre optionnel, activer ou désactiver l’étape est une décision locale, réversible en une ligne.
Points clés à retenir
- Le reranking fait relire les candidats par Claude après la fusion — le LLM lit, les scores approximent
- Division du travail : la recherche hybride présélectionne à bas coût, le LLM arbitre entre les finalistes
- Sortie en identifiants, jamais en texte recopié : réponse courte, reranking rapide
- Intégré au
Retrieveren paramètre optionnel — l’interfacesearch()ne change pas - Compromis latence/coût contre précision : à activer là où la qualité de réponse prime