Documentation

Ajuster finement Laya sur tes propres décisions

Sur le benchmark typed-decisions, les checkpoints de base obtiennent près du hasard sans exemples — 0.36 et 0.35 contre une référence aléatoire de 0.318 — tandis que le checkpoint ajusté atteint 0.766 sur les mêmes 2,000 décisions, au-dessus du 0.727 publié de TypeSafe Jev et au-dessus du plafond d’auto-accord de 0.735 de l’enseignant. L’ajustement fin est là où se trouve l’essentiel de la valeur, et le public notebook d’ajustement fin exécute toute la boucle sur les GPU 2xT4 gratuits de Kaggle : construire le jeu de données, entraîner avec RLCD, ajuster les températures de calibration, évaluer et pousser le résultat vers le Hub. Cette page parcourt ce notebook et pointe les parties qui restent porteuses quand tu remplaces les données par les tiennes.

L’autre exemple travaillé — une tête de décision d’agent de navigation sur un seul GPU de 16 GB sans API payante — est à Ajuster finement Laya comme tête de décision d’un agent de navigation.

Ce que fait le notebook, dans l’ordre

# étape ce qui se passe
1 Environnement vérifie que les deux GPU T4 sont visibles et alloués
2 Installation laya, transformers, datasets et les dépendances d’entraînement
3 Prétraitement les 1,200 cas d’entraînement (6,000 décisions typées) deviennent des éléments tokenisés avec cibles souples, écrits sur disque pour les deux rangs DDP
4 Entraînement train_ddp.py sous torchrun --nproc_per_node=2, quatre époques
5 Calibration une température par type, ajustée sur une tranche mise de côté avant l’entraînement (dans le script d’entraînement, après la dernière époque)
6 Évaluation la partition test officielle répondue par le checkpoint ajusté — 400 cas, 2,000 décisions — avec latence par cas
7 Métriques exactitude, exactitude souple, Brier, ECE, MAE de score, à-un-niveau, KL/TV et percentiles de latence ; un tableau comparatif contre Jev et le plafond de l’enseignant
8 Publication (optionnel) une fiche de modèle construite à partir des nombres de l’exécution elle-même, dossier téléversé vers le Hub
9 Rapport benchmark_report.json avec le tableau de métriques et l’exactitude par workflow

Réglages Kaggle : Accelerator GPU T4 x2, Internet On. Les sorties atterrissent dans /kaggle/working/laya_finetuned_typed_decisions.

La recette d’entraînement

RLCD s’entraîne sur les distributions gold du benchmark, pas sur des étiquettes dures : chaque élément porte la probabilité que l’enseignant a attribuée à chaque option, et les deux moitiés de la perte lisent cette cible —

  • un terme de gradient de politique sur des projections de logits bruitées échantillonnées (style GRPO : quatre échantillons par élément, bruit d’exploration amorti 0.4 → 0.1), récompensé par des règles de score propres (sphérique 0.75, probabilité classée 1.0) ;
  • un terme d’entropie croisée souple à plein poids contre la même distribution.

Les réglages que le notebook fixe pour une carte de 16 GB :

époques 4
lot effectif 64 séquences (8 par micro-lot, 2 GPU, 4 étapes d’accumulation)
taux d’apprentissage encodeur 2.5e-5, tête 1e-4 — AdamW, plan cosinus
mémoire autocast fp16, gradient checkpointing sur l’encodeur et la tête, clip de norme de gradient 1.0
budget de séquence max_len 1024, head_max_len 256, max_tokens_per_batch 4096

Le temps d’exécution sur 2xT4 est de quelques minutes pour la démo et d’heures pour de vraies données : environ 4–6 minutes pour les 6,000 décisions de la démo, et environ 4–5 heures pour quatre époques sur ~30k questions.

Pour le pointer sur tes données, remplace les deux appels load_dataset et garde le schéma de lignes : chaque cas porte state, questions et gold (les probabilités de l’enseignant par question), et le préprocesseur les transforme en éléments. Les types de question sont choice, score et noul ; tout ce que tu peux exprimer avec eux sur un état est permis.

La calibration fait partie de l’exécution

C’est l’étape la plus susceptible d’être abandonnée quand on copie la boucle, et elle est porteuse dès que quelqu’un conditionne sur la confiance.

Le notebook prélève une tranche de calibration hors des données d’entraînement avant de les répartir entre les rangs (jusqu’à 400 éléments, ou 10 %, à graine fixe, identique sur chaque rang). Ajuster les températures sur des éléments que l’exécution a déjà entraînés mesure l’ajustement plutôt que la calibration — le modèle est quasi certain et quasi correct sur eux, donc l’optimiseur n’a rien à assouplir et renvoie une échelle dégénérée.

Après la dernière époque, le rang 0 ajuste une température par type de question (choice, score, noul) par LBFGS sur le logarithme de la température, écrêtée à [0.1, 10] (1.0 pour une tranche de moins de dix éléments, 1.2 si l’ajustement lève une erreur). Les valeurs vont dans rl_agent_config.json comme temperature, et le notebook supprime toute temperature_by_options héritée dans la même écriture : ces vieilles valeurs par compartiment prennent le pas à l’inférence et masqueraient silencieusement le nouvel ajustement.

L’échelonnage de température laisse l’argmax — et l’exactitude — inchangés ; ce qui bouge, c’est la confiance. Les checkpoints tels quels sont trop confiants, alors ajuste avant de te fier à un seuil, et évalue le résultat sur des données mises de côté avant de revendiquer une amélioration. Le test de régression de persistance de configuration tourne sans téléchargements ni entraînement :

python tests/test_calibration_persistence.py

Évaluer avant de s’y fier

L’évaluation est une passe complète sur la partition de test officielle : 400 cas, 2,000 décisions couvrant Agent Trace Observability, Customer Service, Invoice Processing et Security Incidents. Elle calcule l’exactitude, l’exactitude souple, Brier, ECE (via laya.common.ece_score), la MAE de score, à-un-niveau et les percentiles de latence, puis construit un tableau comparatif dont les lignes de référence sont fixes :

modèle type exactitude ECE
TypeSafe Jev 1.13.0 général 0.727 0.144
ModernBERT-base (149M) spécialiste 0.646 0.179
Teacher Self-Agreement plafond 0.735 —
Laya (checkpoint publié) ajusté 0.766 —

La ligne Laya de ta propre exécution est calculée de la même façon — le notebook reconstruit le tableau à partir des nombres de l’exécution elle-même. Deux habitudes à copier : garde les tranches qui t’intéressent (une langue, un workflow) dans des données mises de côté, et rapporte la calibration à côté de l’exactitude, parce que le signal d’entraînement est une distribution, pas seulement une étiquette. Quand tu as des nombres, un post dans les Discussions du dépôt est l’endroit pour les partager ; les benchmarks et les limites connues vivent dans BENCHMARKS.md à la racine du dépôt.

Pousser vers le Hub

La cellule de publication est le dernier kilomètre de la boucle, et elle est délibérément ennuyeuse :

  1. Mets un HF_TOKEN en écriture dans Kaggle (Add-ons → Secrets). La cellule lève une erreur avec les instructions exactes s’il manque.
  2. Définis le dépôt de destination — la cellule livrée pointe par défaut vers un nom dans l’espace de noms du projet, alors change-le avant d’exécuter.
  3. Exécute-la. Elle écrit une fiche de modèle dont les nombres viennent du tableau de comparaison de cette exécution, puis téléverse model.safetensors, encoder/, tokenizer/, rl_agent_config.json, la fiche et le rapport de benchmark.

Le résultat se charge comme n’importe quel autre checkpoint — il n’y a pas d’API spécifique à l’ajustement fin :

import laya

agent = laya.load("your-org/your-checkpoint")   # the repo you just pushed
result = agent.predict(state, questions)

Un checkpoint_latest/ roulant est écrasé après chaque époque, donc un timeout Kaggle ou un OOM coûte une époque plutôt que l’exécution.

Ce qu’il faut surveiller

  • La boucle ne vaut que par ses cibles. RLCD imite la distribution d’un enseignant sur tes questions ; collecte les confiances de l’enseignant avant (ou pendant) l’entraînement, et traite leur qualité comme le plafond.
  • La tranche de calibration est petite exprès. Jusqu’à 400 éléments ou 10 % — assez pour trois scalaires par type, pas assez pour valider contre. Mets de côté tes propres données d’évaluation.
  • Tes étiquettes doivent rentrer dans les trois primitives. Si ta décision n’est pas un choice, une échelle ou une probabilité oui/non, façonne-la d’abord en l’une d’elles. Deux arêtes vives sont déjà documentées : les nombres d’options élevés dégradent la sélection par confiance (#394), et la négation en choix forcé peut suivre la question plutôt que l’état (#377).
  • Livre la config, pas seulement les poids. La temperature_by_options supprimée est la partie qui dé-ajuste silencieusement une calibration si elle survit dans une config copiée.