Le reranking des résultats
Sur cette page
La recherche hybride ramène de bons candidats, mais pas toujours dans le bon ordre. Pour « Qu’a fait l’équipe d’ingénierie au sujet de l’incident INC-2023-Q4-011 ? », on attend la section ingénierie logicielle en tête, puisqu’elle parle de l’équipe et de l’incident ; le système peut pourtant placer la section cybersécurité devant. Le reclassement (reranking) ajoute une dernière étape : un modèle relit la question et chaque candidat, puis réordonne la liste.
Le principe
- La recherche hybride renvoie N candidats.
- Un modèle de reclassement juge la pertinence de chaque candidat pour la question.
- On garde les K meilleurs, que Claude lira pour répondre.
Dans l’étude d’Anthropic sur la récupération contextuelle, la recherche initiale renvoyait 150 morceaux, et le reclassement en gardait 20. Cette étape réduisait encore nettement les échecs de récupération (leçon 42).
Option 1 : Claude comme reclasseur
C’est l’approche de l’ancienne version du cours officiel : on donne à Claude la question et les candidats, et il renvoie les plus pertinents dans l’ordre. Deux précautions la rendent efficace.
Des identifiants plutôt que des textes. Faire recopier les passages retenus serait lent et coûteux en jetons de sortie. On attribue à chaque candidat un identifiant court, et Claude ne renvoie que la liste des identifiants.
Une sortie structurée. Le cours d’origine obtenait la liste par pré-remplissage et séquence d’arrêt, que les modèles actuels refusent (erreur 400). Les sorties structurées de la leçon 9 garantissent un objet {"document_ids": [...]}.
import json
SCHEMA_RERANK = {
"type": "object",
"properties": {"document_ids": {"type": "array", "items": {"type": "string"}}},
"required": ["document_ids"],
"additionalProperties": False,
}
def rerank_with_claude(docs, query, k):
by_id = {f"doc{i}": doc for i, doc in enumerate(docs)}
joined = "\n".join(
f"<document>\n<document_id>{doc_id}</document_id>\n"
f"<document_content>\n{doc['content']}\n</document_content>\n</document>"
for doc_id, doc in by_id.items()
)
prompt = (
"Trouve les documents les plus pertinents pour répondre à la question de l'utilisateur.\n\n"
f"<user_question>\n{query}\n</user_question>\n\n"
f"<documents>\n{joined}\n</documents>\n\n"
f"Renvoie les identifiants des {k} documents les plus pertinents, du plus au moins pertinent."
)
response = client.messages.create(
model=model,
max_tokens=4096,
messages=[{"role": "user", "content": prompt}],
output_config={"format": {"type": "json_schema", "schema": SCHEMA_RERANK}},
)
text = next(block.text for block in response.content if block.type == "text")
ids = json.loads(text)["document_ids"]
return [by_id[doc_id] for doc_id in ids if doc_id in by_id][:k]
Les identifiants sont créés au moment du reclassement : les documents indexés ne changent pas. Un identifiant inventé est ignoré, et la liste est tronquée à k. Le texte se lit en cherchant le bloc text, jamais avec content[0] : sur Sonnet 5.5, un bloc de réflexion peut précéder la réponse. Enfin, max_tokens est assez grand pour la réflexion, qui compte dans ce plafond.
query = "Qu'a fait l'équipe d'ingénierie au sujet de l'incident INC-2023-Q4-011 ?"
candidates = [doc for doc, _ in retriever.search(query, k=10)]
best = rerank_with_claude(candidates, query, k=3)
Option 2 : un service de reclassement dédié
Certains modèles sont entraînés pour cette seule tâche. Sur Google Cloud, c’est le rôle de l’API de classement d’Agent Search, le nouveau nom de Vertex AI Search. On lui envoie la question et les candidats, jusqu’à 1 000 par requête ; elle renvoie pour chacun un score de pertinence entre 0 et 1, sans générer de texte. Son modèle par défaut, semantic-ranker-default@latest, désigne aujourd’hui semantic-ranker-default-005, qui lit 25 langues et jusqu’à 1 024 tokens par candidat ; une variante rapide existe aussi. L’API est sans état : rien à indexer au préalable.
Un reclasseur dédié note tous les candidats d’un coup, ce qui le rend adapté à des listes longues. L’étude d’Anthropic a utilisé celui de Cohere. Le cours officiel, lui, reclasse avec Claude.
Le compromis
- Précision : le reclassement améliore l’ordre des résultats, et donc ce que Claude lit.
- Latence et coût : c’est une étape de plus à chaque question. Reclasser davantage de candidats améliore le résultat, mais allonge et renchérit l’étape. Anthropic recommande d’ajuster ce nombre sur votre propre cas d’usage.
À vous de jouer
Mesurer l’effet. Sur cinq questions, comparez les trois premiers résultats de la recherche hybride seule, puis reclassés par Claude, puis par l’API de classement de Google si elle est ouverte dans votre projet. Notez la latence de chaque variante et le nombre de fois où le bon passage arrive en tête.
Sources officielles : Contextual Retrieval (Anthropic : reclassement, 150 puis 20 morceaux) · Improve search and RAG quality with ranking API (Google Cloud : API de classement, modèles) · Structured outputs (documentation Claude)
Points clés à retenir
- Le reclassement relit la question et chaque candidat, puis réordonne la liste.
- Avec Claude : des identifiants courts, une sortie structurée, et le texte lu par type de bloc.
- Avec un service dédié comme l’API de classement de Google : tous les candidats notés d’un coup, sans génération.
- Dans l’étude d’Anthropic : 150 candidats, 20 gardés après reclassement.
- Le gain de précision se paie en latence et en coût : ajustez le nombre de candidats.