À la fin du deuxième article de cette campagne, une phrase désignait le chantier suivant sans le savoir : les collisions de noms, linear_search_issues contre github_search_issues, survivent au changement d'échelle, « ce qui suggère un problème de format ou de retriever plus que de capacité ». Le troisième article a réglé son compte à l'hypothèse du format, et les collisions ont survécu à la correction aussi. Il se refermait sur un constat en quatre mesures, sans mécanisme : un entraînement bon marché installe des dispositions et ne corrige pas les correspondances fines. Restait à comprendre pourquoi.
Voici pourquoi. Ce n'était ni le format, ni le retriever, ni la capacité. Le modèle sait quel outil est le bon : l'information est dans son état interne, lisible à 96-100 % avec le classifieur le plus bête qui existe. Il échoue à la lire au moment de générer. Le mur des 60 n'était pas un plafond de capacité, c'était un plafond de lecture.
Ce constat se mesure, il se répare, et la réparation se confirme. Une sonde posée sur les états internes rend un verdict sans ambiguïté, 36 mesures sur 36, significatives après correction. Un correcteur de lecture, zéro paramètre entraîné, des centroïdes et des produits scalaires, fait passer le champion 2,9B de 61 à 67/82. Et parce que ce genre de chiffre est exactement celui qu'on obtient en se racontant des histoires, nous l'avons soumis à une confirmation en aveugle, politique et seuil gelés par un commit antérieur au run, sur un juge neuf jamais vu : +8 points, p = 0,039. Le tout pour environ deux dollars de calcul, Kaggle gratuit compris. Comme d'habitude, générations brutes, corpus, protocoles figés et empreintes sont dans le banc public.
Le point de départ est une énigme laissée ouverte par la campagne : 135 exemples d'entraînement visant sept confusions précises n'en avaient corrigé aucune. Les erreurs se déplaçaient au lieu de disparaître. Pendant ce temps, des dispositions générales, savoir se taire par exemple, s'apprenaient en un epoch. Deux observations de la communauté RWKV donnaient une piste. Smerky appelle « context referral » cette faiblesse où l'information est dans l'état mais où le modèle ne sait pas la ré-adresser. Et le dépôt rwkv7-state-embedding de cgisky mesure la même chose de l'intérieur : une sonde supervisée récupère 93 % de l'information des états, mais l'espace est si anisotrope que l'accès non supervisé s'effondre.
Si c'est la bonne explication, elle est testable. Il suffit d'extraire les états au moment exact où le modèle doit choisir, et de vérifier si un classifieur y sépare les paires confondues. Nous avons figé le protocole avant toute mesure : huit paires réellement confondues par le banc (313 paires de confusion distinctes recensées sur 56 bras de résultats), 240 requêtes neuves écrites pour l'occasion et filtrées contre toute fuite (Jaccard ≤ 0,20 contre le juge public), un contrôle positif qui doit séparer, un contrôle négatif qui doit rester à la chance, et une grille de verdict écrite d'avance. Deux régimes de contexte : la paire seule, et le contexte réaliste du banc, quarante outils dans le prompt.
Le verdict tient en un tableau. En contexte à quarante outils, celui où le modèle se trompe vraiment, le comportement s'effondre pendant que l'état, lui, sait :
| Paire (contexte top-40, modèle brut) | Comportement | Séparabilité de l'état |
|---|---|---|
| Ensemble des 8 paires | 147/270 (54 %) | 0,96-1,00 |
runtime_info vs model_get_info | 2/30 (7 %) | 0,99 |
Une précaution que le troisième article nous a apprise à la dure : un banc mesure aussi le harnais. Ici la critique s'annule par construction, les mêmes prompts nourrissent le comportement et les états, le contraste est intra-régime. Et sa signature est absente des données : le mauvais format se manifeste en sorties non parsables, nos 540 mesures comportementales n'en contiennent aucune. Toutes les erreurs sont de mauvais outils bien formés. Du jugement, pas de la syntaxe.
Trente-six combinaisons paire × bras × régime de contexte, trente-six significatives après correction de Bonferroni (1 000 permutations par cellule, contrôles propres des deux côtés). Et « séparable » ne veut pas dire au prix d'un gros classifieur entraîné : le centroïde le plus proche, en cosinus, suffit presque partout. La distinction vit dans les couches moyennes-tardives. Les paires difficiles sont à la chance dans les couches 0 à 9, puis à 1,00 dès la couche 12.
Les 135 exemples ne pouvaient donc pas marcher : ils soignaient un organe sain. La représentation n'a jamais été le problème. La lecture, si.
Deux trouvailles annexes valent d'être notées. La « confusion » valkyrie_remove_subtask → valkyrie_delete_subtask n'en est pas une : le second outil n'existe pas dans le catalogue. C'est une hallucination de nom, un phénomène distinct. Et l'état entraîné, placé devant un contexte de deux outils au lieu de quarante, ne répond pas : il continue le catalogue, en générant une entrée plausible du bon namespace. La preuve involontaire que l'état porte des associations namespace → noms.
Si l'information est dans l'état et lisible au centroïde, alors un correcteur de lecture coûte trois fois rien : un centroïde par outil, calculé une fois pour toutes depuis les données d'entraînement existantes (231 outils × 8 requêtes, aucune donnée nouvelle), et au moment de choisir, un produit scalaire entre l'état du préfill et les candidats de la shortlist.
Un détail technique conditionne tout le reste, et il illustre l'anisotropie mesurée par cgisky : des centroïdes appris dans un régime de contexte ne transfèrent vers un autre qu'à 76 %. Il suffit de centrer chaque distribution par sa propre moyenne pour remonter à 95 %, et retrancher la moyenne du corpus seule ne suffit pas (73 %). La direction commune du contexte écrase la géométrie fine ; on l'enlève, le signal réapparaît. C'est ce qui permet d'apprendre les centroïdes en contexte court, dix fois moins cher.
Restait la politique. La version naïve, celle où la sonde choisit toujours, échoue d'une façon instructive : elle détruit l'abstention (16/17 → 1/17). Un centroïde « aucun de ces outils » ne modélise pas l'abstention, et le modèle, lui, sait déjà très bien se taire, c'est la première chose que le state-tuning lui avait apprise. D'où une politique asymétrique qui découle du mode d'échec : ne jamais contredire une abstention, ne corriger que outil → outil, et seulement quand la sonde est nettement plus sûre que la génération, avec une marge sur le cosinus.
| Politique (2,9B champion, juge public) | Score |
|---|---|
| Génération libre (baseline, réplication exacte du 61/82 publié) | 61/82 |
| Sonde seule (sélecteur) | 50/82 |
| Correcteur outil → outil | 65-67/82 selon la marge, 67 au meilleur réglage |
Le plateau est la partie importante : 65 à 67 sur toute la courbe de marge, y compris marge nulle. Le gain ne dépend pas d'un réglage fin. Six points de plus que le champion, sans un paramètre entraîné, en préservant l'abstention (16/17) et les arguments (18/22).
Un +6 obtenu en choisissant la politique et le seuil sur le juge qui le mesure ne vaut pas grand-chose, c'est précisément le genre de résultat qui s'évapore à la réplication. Et notre juge de 82 cas est public depuis fin juillet : tout verdict de vague future exigeait un instrument neuf. Nous avons donc fait ce que la littérature recommande et que presque personne ne fait, une confirmation pré-enregistrée.
Quatre-vingt-deux cas nouveaux, même distribution que le juge public, chaque cas validé mécaniquement contre les schémas réels du catalogue, anti-fuite vérifié contre tout ce qui existe (juge public, données d'entraînement, corpus de sonde), recall du retriever contrôlé à 65/65. Puis un document de pré-enregistrement, commité avant le run : politique outil → outil, marge 0,02, couche de décision, centroïdes réutilisés tels quels avec leurs empreintes, critère de confirmation (Δ ≥ +3 et McNemar p < 0,05), un seul scoring autorisé. Le kernel de mesure vérifie lui-même les empreintes du pré-enregistrement avant de toucher au GPU.
Résultat, en un seul passage :
| Juge de confirmation (privé, jamais vu) | libre | corrigé |
|---|---|---|
| Total | 48/82 | 56/82 |
| Sélection simple | 13/18 | 17/18 |
| Arguments | 15/22 | 18/22 |
| Abstention (intouchée par construction) | 7/17 | 7/17 |
Δ = +8, dix cas gagnés contre deux dégradés, McNemar exact p = 0,039. Critère rempli. L'effet réplique sur des requêtes d'un autre style, écrites par une autre main, et il grossit. Détail inattendu : les arguments gagnent trois points, alors que le correcteur ne touche qu'au nom de l'outil. Sélectionner le bon outil fait suivre les bons arguments.
Ce juge de confirmation reste privé, et c'est le prix de sa validité : un juge publié est un juge contaminé pour toute mesure future. Le nôtre a servi une fois, il est grillé comme instrument de confirmation, un v3 prendra son rôle. Les sceptiques ont mieux qu'un fichier à relire : le protocole complet est rejouable, et le pré-enregistrement du prochain round peut se faire sous leurs yeux.
Le deuxième article s'était arrêté sur le 7,2B à 69/82. La question de composition s'impose : le correcteur de lecture aide-t-il encore un modèle plus gros ? La réponse est en trois temps, et chacun nuance l'autre.
D'abord, la sonde : le signal interne s'améliore avec la taille. À corpus identique, procédure identique, l'erreur du classifieur de centroïdes est divisée par deux entre 2,9B et 7,2B :
| CV multiclasse, 231 outils | 2,9B | 7,2B |
|---|---|---|
| Couche 15 | 89,5 % | 91,6 % |
| Couche 21 | 89,9 % | 93,3 % |
| Couche 27 | — | 94,9 % |
Et l'information migre en profondeur : à 2,9B le profil culmine vers la couche 21 puis décline ; à 7,2B il monte encore à la couche 27. L'échelle ne se contente pas d'améliorer la géométrie, elle la réorganise.
Ensuite, le correcteur : le gain décroît. Baseline répliqué exactement (69/82, profil par catégorie identique au chiffre publié), puis la surprise utile : la politique calibrée sur le 2,9B, appliquée telle quelle, dégrade le 7,2B (67/82). Un modèle qui se trompe moins rend les corrections à faible marge net-négatives ; il faut une marge plus exigeante pour repasser en positif. 71/82 au meilleur réglage, un chiffre que nous étiquetons exploratoire tant qu'un juge v3 pré-enregistré ne l'a pas confirmé. Rien d'exponentiel là-dedans, au contraire : +6 au 2,9B, +2 au 7,2B, l'arithmétique d'un plafond qui se rapproche, il reste moins d'erreurs à récolter.
Enfin, la composition des trois faits, le signal croît, la lecture ne suit pas toute seule, le gain du correcteur décroît, donne la conclusion pratique de cet article : le correcteur de lecture est un égalisateur de petits modèles. Le 2,9B corrigé (67) arrive à deux points du 7,2B state-tuné nu (69), pour 2,5 fois moins de paramètres et un artefact de 150 Mo. Là où le compute manque, la lecture assistée rapporte le plus. C'est exactement la répartition qu'il faut à qui fait tourner ses modèles en local.
Un p à 0,039 sur 82 cas est significatif, pas écrasant : dix contre deux sur les cas discordants. Ce qui nous fait tenir le résultat pour réel, c'est la convergence, quatre mesures directionnellement cohérentes sur deux juges et deux échelles, dont une en aveugle pré-enregistré. Pas un chiffre isolé. Le 71/82 du 7,2B est post-hoc et le restera jusqu'à confirmation. Les centroïdes viennent de la distribution des données d'entraînement ; le juge de confirmation, écrit dans un autre style, teste déjà une généralisation, mais pas celle de vraies requêtes utilisateur en conditions sales. L'abstention reste le point faible du modèle hors curriculum (7/17 sur le juge de confirmation) et le correcteur n'y touche pas, par construction. C'est le chantier suivant désigné. Le multi-étapes reste à zéro, harnais d'un tour, comme depuis le début. Et tout ceci vit dans le runtime natif : le format GGUF ne transporte ni l'état entraîné ni l'accès aux états internes, la production llama.cpp n'y a pas droit aujourd'hui.
Le coût marginal du correcteur est presque nul : l'état existe déjà à la fin du préfill, le correcteur ajoute un produit scalaire contre au plus quarante candidats. L'artefact, 231 centroïdes d'une couche, pèse 150 Mo en fp32, compressible. Pour le 2,9B interactif, c'est le deuxième gain gratuit identifié après le cache d'état du deuxième article, et les deux se cumulent : l'état mis en cache après le préfixe fixe est l'objet même que la sonde lit.
La brique a une portée au-delà du tool-calling. Les mêmes centroïdes d'états, avec le même centrage par distribution, sont un candidat naturel pour router entre états entraînés, ou pour mesurer une dérive de comportement sans le bruit qui rendait nos comparaisons de sorties si trompeuses : deux générations d'un même modèle peuvent être quasi orthogonales, mais les états de préfill, eux, sont déterministes. Nous en reparlerons.
Tout est dans le banc (miroir Forgejo) : probes/state-separability/ pour le protocole figé, les corpus, les résultats bruts et le 36/36, probes/state-reranker/ pour le corpus de centroïdes, les kernels, les générations libres et forcées des deux échelles, et les courbes complètes, y compris celles qui ne nous arrangent pas. La sonde et le correcteur 2,9B ont tourné sur Kaggle gratuit ; le run 7,2B a coûté un dollar de pod A40. Le pré-enregistrement de la confirmation, son juge et son unique scoring sont horodatés par commits ; le juge reste privé pour rester un instrument, son protocole de construction est publié.
Un trou dans le protocole ? Une explication concurrente ? Écrivez-nous : contact@scarletwolf.ai. C'est à ça que sert la publication.