Learning to Rank
Le pipeline LTR dans Relevance Studio — feedback de clics, correction du biais de position, entraînement, versioning des modèles, tests A/B et activation. Comment interpréter la significativité du z-test et choisir un gagnant.
Learning to Rank (LTR) est la boucle de feedback fermée qui transforme de vrais clics utilisateurs en un modèle de classement appris. Studio livre les quatre panneaux correspondant aux quatre étapes : Feedback de clics, Exécutions d'entraînement, Modèles et Tests A/B.
Pipeline en un coup d'œil
clics (SearchUsageEvent)
│
▼ correction du biais de position (debias)
│
▼ entraînement (shim LightGBM aujourd'hui ; LightGBM/XGBoost natifs différés)
│
▼ artefact de modèle + métriques (NDCG, MRR, AUC)
│
▼ test A/B : split de trafic, significativité par z-test
│
▼ activer le gagnant → classement au chemin de lectureChaque étape est réversible. Un mauvais modèle est à un clic de la désactivation — l'ancien modèle actif est toujours conservé.
1 · Feedback de clics
Le panneau Feedback de clics résume le signal brut qui nourrit l'entraîneur. Trois chiffres par index :
- clics-avec-contexte — combien d'événements
clickarrivent avec unqueryIdetpositionvalides. SansqueryId, on ne peut pas relier un clic à une recherche. - correction du biais de position — la courbe de debias en vigueur.
Le biais de position est le phénomène bien connu selon lequel la
position 1 est cliquée indépendamment de la pertinence. Le score
corrigé est en gros
observed_ctr / propensity[position], oùpropensityest ajusté par index. - lignes d'entraînement utilisables — après debias et filtre des zéro-résultats, combien de lignes sont éligibles pour l'entraîneur.
Si les lignes utilisables sont sous ~5k, Training refuse de lancer le run et affiche une bannière "signal insuffisant". Sous ce seuil, le modèle surapprend et fait moins bien que le ranker statique.
2 · Exécutions d'entraînement
Un run produit un artefact de modèle à partir d'une fenêtre choisie de feedback de clics. Dans Studio vous choisissez :
- Fenêtre — 7, 30 ou 90 derniers jours.
- Algorithme — actuellement
shim(seule option en releases livrées). LightGBM et XGBoost natifs sont différés — voir note ci-dessous. - Features — set prédéfini (pertinence textuelle, récence, prix, popularité, cohorte de catégorie). Les features custom sont sur la feuille de route.
Le run montre la progression, puis trois métriques à l'arrivée :
| Métrique | Sens |
|---|---|
| NDCG@10 | Normalized discounted cumulative gain au top 10 — métrique primaire |
| MRR | Mean reciprocal rank du premier résultat cliqué |
| AUC | Aire sous la courbe clic vs non-clic |
Statut du shim (mai 2026)
L'entraîneur LTR livré est un algorithme shim : un combinateur
linéaire simplifié qui ajuste quelques poids sur les features
pré-calculées. Il est volontairement conservateur et tourne derrière le
feature flag ltr.shim.
Les entraîneurs LightGBM et XGBoost natifs complets sont différés.
Ils sont implémentés derrière le flag ltr.native mais ne sont pas en GA
— ils requièrent plus de tests de charge et un déploiement du model
registry. Pour l'heure, considérez le shim comme le seul algorithme
supporté et attendez-vous à un lift NDCG@10 de 5–15% par rapport à la
baseline non rankée, pas les 25–40% de certains papers. Les clients qui
ont besoin de LightGBM natif aujourd'hui peuvent contacter le support pour
une preview privée.
3 · Modèles
Chaque run réussi produit un modèle dans le panneau Modèles. Les modèles sont des artefacts immuables et portent :
- un ID versionné (
mdl_<random>), horodatage de création, run source, - le tuple de métriques
(NDCG@10, MRR, AUC), - le feature set et la fenêtre sur lesquels il a été entraîné,
- le statut de déploiement :
draft,in_ab_test,activeouarchived.
Un modèle en active est ce que le chemin de lecture consulte à chaque
requête de recherche pour cet index. Il y a exactement un modèle actif
par index à tout instant.
4 · Tests A/B
On ne promeut pas un modèle de draft directement vers active. On lance
plutôt un test A/B qui partage le trafic live entre le modèle candidat
(bras B) et le modèle actif courant (bras A, contrôle).
Lancer un test A/B
Depuis Studio → LTR → Tests A/B → Nouveau test :
// Ce que Studio fait en interne — appelable directement aussi
import { client } from "@repo/api/client";
const test = await client.ltr.abTests.create.call({
indexSlug: "products",
controlModelId: "mdl_active_now",
variantModelId: "mdl_candidate",
trafficSplit: 0.10, // 10% du trafic live voit le bras B
primaryMetric: "ctr", // ctr | cvr | ndcg10
minSampleSize: 50_000, // recherches par bras avant calcul de significativité
});Le split de trafic est par requête, pas par utilisateur — un même utilisateur peut donc tomber sur des bras différents au fil des sessions. Le modèle variant s'applique au bras B ; le bras A continue avec le modèle actif existant.
Lire les résultats
Pendant le test, le panneau montre des compteurs live par bras :
n— recherches assignées au bras.clicks,ctr,cvr— métriques primaires, rafraîchies toutes les 5 min.- z-score — différence standardisée entre bras B et A sur la métrique primaire.
- p-value — bilatérale.
- décision —
running,significant_win,significant_loss,±borderlineouno_effect.
Comment lire la significativité
L'entraîneur utilise un z-test de deux proportions standard, en traitant chaque recherche comme un essai Bernoulli indépendant sur la métrique primaire. Seuils :
| Décision | Plage de z | Sens |
|---|---|---|
significant_win | z ≥ +1.96 (p ≤ 0.05) | Candidat bat le contrôle avec 95% de confiance. |
significant_loss | z ≤ −1.96 | Candidat perd avec 95% de confiance — arrêter le test. |
±borderline | 1.65 ≤ |z| < 1.96 | 90–95% de confiance — attendre plus d'échantillons ou décider d'avance. |
no_effect | |z| < 1.65 et n ≥ minSampleSize | Pas de différence détectable à cette taille. |
running | n < minSampleSize | Pas encore assez de données. |
La bande ±borderline est exposée comme décision propre parce que la
plupart des équipes produit ont une règle pré-test du type "ship à 90% si
delta positif, hold à 95% si négatif". Studio ne promeut pas
automatiquement en borderline — un humain doit cliquer Activer le gagnant.
Guide de taille d'échantillon
Le minSampleSize par défaut est 50 000 recherches par bras. Avec un
split de 10%, un index à 50k recherches/jour atteint la significativité en
~11 jours pour un effet de 2 points de pourcentage sur le CTR. Pour des
index plus petits, comptez 3–4 semaines. Le panneau Studio affiche un ETA
live.
Activer un gagnant
Quand la décision est significant_win (ou que vous décidez de shipper
sur ±borderline), cliquez Activer le gagnant dans le panneau A/B.
Cela :
- Passe le modèle variant en
active. - Rétrograde l'ancien modèle actif en
archived(réactivable en un clic si le nouveau régresse en production). - Clôt le test A/B avec un rapport final.
- Route 100% du trafic live via le nouveau modèle en ~60 secondes
(TTL du LRU
policy-cache).
await client.ltr.abTests.activateWinner.call({
testId: test.id,
// safety check optionnel — refuse si la décision live a divergé de
// `significant_win` entre le fetch et l'appel
expectedDecision: "significant_win",
});En cas de besoin de rollback après activation, le panneau Modèles
conserve l'ancien modèle actif en archived et expose Réactiver en un clic.
Bonnes pratiques
- Toujours lancer un test A/B. Même un modèle qui gagne en NDCG offline peut régresser sur le CTR live — biais de position et effets de présentation n'apparaissent pas dans les métriques offline.
- Choisissez la métrique qui mappe au métier. CTR est le défaut ; les
catalogues conversion-driven posent
primaryMetric: "cvr". - Pas de "peek-and-stop". Le z-test suppose une taille d'échantillon
fixe — regarder avant
minSampleSizeet arrêter gonfle le taux de faux positifs. Fixez la taille, partez, décidez ensuite. - Archivez agressivement. Gardez au plus 5–10 modèles archivés par index. Le registry est peu coûteux mais le journal d'audit se lit mieux avec moins de lignes.
Lié
- Référence API LTR — liste complète des procedures :
ltr.training.runs.*,ltr.models.*,ltr.abTests.*. - Personnalisation — couche orthogonale qui se compose avec LTR au chemin de lecture.
- Architecture → Boucle de feedback analytique — origine des événements clic qui alimentent l'entraîneur.
- Plans et limites — LTR demande le plan Scale ou supérieur.
Personnalisation
Profils utilisateur, segments, reranking de session et recommandations dans Relevance Studio. Comment personalize=true + sessionId câblent le boost de profil au classement, et bonnes pratiques sur les PII.
Démarrage
Commencez ici — créez un compte, configurez votre premier index de recherche et connectez votre première boutique.