Artefact d’entraînement : quand le RNG trompe le LLM
En générant plusieurs échantillons, j’ai remarqué que le même mot apparaissait au même rang dans cinq textes sans lien apparent. J’avais réinitialisé la même graine avant chaque échantillon, ce qui ne les rendait pas comparables mais corrélés : mêmes tirages pseudo-aléatoires aux mêmes positions.
Rien ne plantait, l’entraînement n’était pas affecté. Seule la lecture des sorties était faussée.
L’architecture retenue
La correction consiste en une graine dérivée par échantillon, via derive_seed, qui garantit la reproductibilité sans corrélation. Chaque invite reçoit sa propre graine, calculée à partir de la graine du run et de son index.
La boucle d’évaluation utilise derive_seed pour générer une graine unique par prompt, puis seed_everything avant chaque appel à model.generate.
Ce que ça change en pratique
Chaque échantillon reste déterministe, mais les tirages ne se recoupent plus entre prompts. J’ai corrigé le problème en dérivant une graine par échantillon, ce qui conserve la reproductibilité tout en supprimant la corrélation entre les échantillons.
Les trade-offs, assumés
Outil écarté : MLX. Le banc le donnait à égalité stricte avec PyTorch/MPS en bf16 (29,5 vs 29,5 TFLOPS). Sans avantage de performance, maintenir deux implémentations Mac/H100 revenait à risquer une divergence numérique silencieuse et à brûler des crédits H100 sur un run subtilement cassé.
Piste abandonnée : le SFT sur jeu d’instructions. Il apprend bien au modèle à s’arrêter (0/10 → 8/10 sur le jeton de fin) mais fait tomber le français de 7/10 à 3/10. 650 pas érodent ce que 38 000 pas avaient installé, d’où le renoncement à tout apprentissage « depuis les interactions ».
Compromis refusé : trancher sur Muon. Il perdait de 2 % au balayage, mais le banc (chaîne de Markov d’ordre 1) est dominé par les couches embedding/sortie qui vont à AdamW dans les deux cas. Structurellement incapable de départager, annoncer un verdict aurait été une faute de mesure.
Quand ça vaut le coup, et quand non
Ça vaut le coup pour celui qui veut comprendre chaque brique et maîtriser son corpus. Tokenizer sur mesure, muP, reprise nocturne : c’est une école complète et un vrai actif de portfolio.
Ça ne vaut pas le coup pour celui qui veut un assistant utilisable. À 188 M, on obtient du français correct et de la cohérence locale mais aucun raisonnement. Un RAG ou un fine-tuning sur un modèle existant y arrive en une fraction du temps.
Ce que je changerais si je recommençais
Je mesurerais la nouveauté et pas le volume dès le premier jour. Cinq nuits de collecte ont rapporté 10 Md de tokens et zéro document neuf sans qu’aucune alerte ne bronche, exactement comme la validation qui lisait 1,6 % du split toujours au même endroit.
La leçon : chaque automatisation doit rapporter ce qu’elle apporte, pas ce qu’elle produit. Un split de validation se décide à la génération du corpus, jamais après coup.
La stack
PyTorch, avec backend MPS sur Mac et CUDA sur H100.
Lightning AI pour l’accès au H100.