Point d’étape sur l’entraînement de l’agent de codage récursif en Golang.
Depuis quelques semaines, je fais du training développemental sur un modèle de code Qwen tournant sur un DGX Spark. Le modèle participe à son propre développement : il exprime des intérêts, un modèle plus puissant les transforme en tâches de programmation bornées, un vérificateur décide si le code fonctionne, un autre modèle critique, et l’enfant a une chance de réviser ou de garder sa réponse. Dire « je comprends » ne rapporte rien. Écrire un meilleur code, si.
Le premier grand enfant, v125, montrait des signes d’un meilleur goût technique lors de comparaisons à l’aveugle entre plusieurs implémentations correctes. Pas juste « est-ce que ça passe ? », mais « quelle implémentation voudrais-je vraiment dans la base de code ? ». Ensuite, on a entraîné v125 récursivement sur un second corpus. La première tentative s’est mal passée : avec le taux d’apprentissage initial de 2e-5, l’enfant est tombé à 66/120 résolutions et a perdu son avantage en termes de goût.
L’ablation du taux d’apprentissage
On a donc lancé une ablation propre : même parent, mêmes données, mêmes mises à jour, même seed, même géométrie LoRA et même évaluation. Un seul changement : 2e-5 → 5e-6.
La régression a disparu : l’enfant à taux faible 74/120, la base exacte 72/120, le parent v125 70/120, le SFT précédent 68/120. Le rétablissement était global. Sur les gestionnaires HTTP, l’enfant à taux plein s’était effondré à 17/30 ; l’enfant à taux faible est remonté à 22/30. La dose d’entraînement compte.
Justesse et goût ont divergé
Mais c’est là que c’est devenu bizarre. L’enfant est devenu meilleur pour être juste, tout en devenant apparemment moins bon pour choisir comment l’être. Sur l’ensemble large du goût, le parent et l’enfant étaient proches : 18 contre 16. Mais sur le sous-ensemble strict pré-enregistré, où les quatre modèles étaient justes et distincts :
Base : 16
parent v125 : 10
SFT précédent : 6
enfant à taux faible : 3
Ça a fait échouer notre porte de promotion. Alors on a arrêté. Pas de nouveau benchmark de promotion. Pas de déplacement des poteaux de corner sous prétexte que 74/120, c’était joli.
C’est peut-être là le résultat clé : la compétence et le jugement technique semblent être partiellement indépendants. Est-ce que vous savez résoudre le problème et survivre au vérificateur ? Et, séparément, quand plusieurs approches fonctionnent, laquelle choisissez-vous ? Quelle structure préservez-vous ? Quelle complexité refusez-vous d’introduire ? Quand vous arrêtez-vous ?
Ce que le signal d’entraînement a privilégié
Le corpus 2 contenait 559 trajectoires de solutions ordinaires, 89 paires de révisions et 115 enregistrements de préférences comparatives. Mais ces enregistrements de préférences étaient des preuves, pas des cibles SFT directes. Donc, la majeure partie du gradient disait encore : « Voici une autre solution. » Beaucoup moins disait : « Voici deux solutions qui fonctionnent. Celle-ci est préférable, et voici pourquoi. »
Avant d’entraîner ce signal, on doit valider la règle. La suite, c’est une étude de stabilité du critique utilisant des solutions correctes fixes, des permutations d’étiquettes à l’aveugle, une seed de critique indépendante et aucun rééchantillonnage du solveur.
Il y a quelques semaines, la question était de savoir si le jeu développemental pouvait améliorer un modèle de code. Maintenant, c’est : la compétence et le jugement technique peuvent-ils être entraînés comme des axes développementaux distincts, puis améliorés ensemble sans que l’un n’efface l’autre ?
C’est ça, l’expérience.