Thinking Progress Vectors : une barre de chargement pour les modèles de raisonnement, lue dans l’article et le code
Les modèles de raisonnement réfléchissent longtemps et ne montrent rien pendant ce temps. Thinking Progress Vectors, ou TPV, est un dépôt de recherche qui tente de lire une barre de progression directement dans les états cachés du modèle, puis d’utiliser le même signal pour le faire réfléchir moins longtemps. J’ai lu l’article et chaque script. Je n’ai rien exécuté.

Les modèles de raisonnement réfléchissent longtemps et ne montrent rien pendant ce temps. Thinking Progress Vectors, ou TPV, est un dépôt de recherche qui tente de lire une barre de progression directement dans les états cachés du modèle, puis d’utiliser le même signal pour le faire réfléchir moins longtemps. J’ai lu l’article et chaque script. Je n’ai rien exécuté.
En bref
Le dépôt accompagne l’article « Overclocking LLM Reasoning » (arXiv 2506.07240, juin 2025). Un régresseur linéaire sur les états cachés de la dernière couche estime l’avancement du modèle dans ses jetons de réflexion. Ajouter ce vecteur, multiplié par un nombre appelé alpha, pendant la génération raccourcit la réflexion. L’article rapporte de gros gains avec de petits budgets de jetons sur des benchmarks de maths, mais ces gains diminuent ou s’inversent avec des budgets plus grands et sur le plus petit modèle. Il faut des poids ouverts et un GPU, aucun vecteur entraîné ni aucune interface n’est fourni, et la licence interdit l’usage commercial. Personne n’a exécuté le code pour ce compte rendu.
Ce que l’article affirme
L’article est signé Roy Eisenstadt, Itamar Zimerman et Lior Wolf, rattachés à l’université de Tel-Aviv (Zimerman aussi à IBM Research). La version que j’ai lue est la v1 du 8 juin 2025, indiquée comme préprint en cours de relecture. Son point de départ est un problème connu : un modèle qui réfléchit trop peu manque la complexité de la tâche, et un modèle qui réfléchit trop longtemps peut tourner en rond, douter de lui et épuiser son budget.
Il avance deux affirmations. D’abord, le modèle garde en interne une estimation de son avancement dans la phase de réflexion, et une simple projection linéaire de la dernière couche cachée retrouve cette estimation. Les auteurs appellent le vecteur de projection un vecteur de progression de la réflexion. Ensuite, ce signal est causal : si l’on pousse l’état caché le long du vecteur pendant la génération, le modèle termine sa réflexion plus tôt. Ils appellent cela l’overclocking.
Tout est testé sur deux modèles DeepSeek-R1 distillés, un 32B construit sur Qwen et un 8B construit sur Llama, et sur deux benchmarks de maths, Math-500 et GSM-8K. Ce périmètre compte pour tout ce qui suit.
La chaîne, étape par étape
Le README découpe le travail en quatre scripts. Voici ce que fait chacun, tel que je lis le code.
- generate_tpv_data.py. Charge un modèle en demi-précision, construit le prompt « {problem}, please reason step by step, and put your final answer within \boxed{} », le termine par une balise ouvrante de réflexion et échantillonne des réponses. Les valeurs par défaut suivent l’article : 30 problèmes Math-500, 5 échantillons chacun, température 0,6, top-p 0,95, graine 42. Le script demande à generate de Hugging Face tous les états cachés et enregistre le vecteur de la dernière couche pour chaque jeton généré.
- prepare_tpv_dataset.py. Écarte les échantillons en erreur ou sans fichiers, puis cherche la balise fermante de réflexion dans les jetons générés. Un échantillon dont la réflexion ne se ferme jamais est ignoré. Pour les autres, le jeton numéro j sur N reçoit l’étiquette j/N, qui monte donc de presque 0 à exactement 1. Le découpage entraînement/test (80/20, graine 42) se fait par problème : un même problème n’apparaît jamais des deux côtés.
- train_tpv.py. Ajuste un modèle linéaire par la solution en forme close : H transposée fois H plus un epsilon minuscule (1e-10 par défaut) fois l’identité, contre les étiquettes. Il n’y a pas de terme constant. Le script affiche l’erreur quadratique moyenne en entraînement et en test et trace un nuage de points. Le vecteur de poids enregistré est le TPV.
- tpv_intervention.py. Charge le modèle et le vecteur, enregistre un hook et génère en décodage glouton. Par défaut : le modèle Llama 8B, alpha 100 et 2048 nouveaux jetons.
Le hook : ce que fait vraiment l’intervention
Toute l’intervention tient en un seul hook de passe avant sur model.model.norm, la couche de normalisation finale d’un modèle décodeur Hugging Face. Une fois cette couche exécutée, le hook copie sa sortie et ajoute alpha fois le TPV à la dernière position de jeton. L’article l’écrit h_alpha = h + alpha fois theta, si bien que la progression prédite theta fois h augmente de alpha fois la longueur au carré de theta.
L’emplacement est voulu. L’article explique que la dernière couche cachée se trouve en aval des couches d’attention : les clés et valeurs mises en cache pour les jetons précédents ne sont donc pas touchées. Le coup de pouce n’agit que sur le choix du jeton suivant. Mais ce jeton devient l’entrée de l’étape suivante, et l’effet s’accumule donc sur toute la phase de réflexion. Le hook est retiré dans un bloc finally à la fin de la génération.
Deux remarques pratiques tirées du code. Alpha n’est pas transposable : la taille du vecteur dépend de l’entraînement du régresseur, si bien que 100 ne veut pas dire la même chose pour chaque modèle et chaque jeu d’entraînement. Et le vecteur est un simple float32 ajouté à des états en demi-précision, ce que je voudrais vérifier lors d’une vraie exécution.
Ce qu’est la « barre de chargement » dans ce dépôt
L’article présente une barre de progression interactive et renvoie à une page de projet pour des exemples. Le dépôt lui-même n’a pas d’interface de ce genre. Le suivi s’arrête à un graphique de régression : un nuage de points de la position prédite contre la position réelle pour jusqu’à 1000 jetons de test, avec une ligne de lissage exponentiel (facteur 0,1) tracée sur des échantillons triés par position réelle. Ce graphique vérifie le régresseur. Ce n’est pas une barre en direct sur une vraie génération.
Pour avoir une barre dans une interface, il faut la construire : exécuter le modèle en local, prendre le dernier état caché à chaque étape, le multiplier par le vecteur, lisser la série et la dessiner. L’article ajoute qu’un petit réseau récurrent (un GRU à une couche) peut remplacer le lissage exponentiel et obtient une perte plus faible en entraînement comme en zero-shot. Cette variante est décrite dans l’article ; je ne l’ai pas cherchée dans le dépôt.
Les chiffres de l’article
L’article compare TPV à trois références avec des budgets de jetons fixes : le modèle de base, la plus courte de cinq réponses à température 0,6, et un prompt qui demande au modèle d’être concis et de s’arrêter. Il compte les réponses correctes. Le tableau ci-dessous reprend le nombre de réponses correctes sur Math-500 pour cinq lignes, tel qu’imprimé dans l’article. Je n’en ai recalculé aucune.
| Méthode | 32B : 512 | 32B : 1024 | 32B : 2048 | 8B : 512 | 8B : 1024 | 8B : 2048 |
|---|---|---|---|---|---|---|
| Modèle de base | 36 | 154 | 278 | 6 | 47 | 112 |
| Température (la plus courte de 5) | 54 | 146 | 294 | 29 | 95 | 137 |
| Prompt concis | 53 | 211 | 316 | 50 | 107 | 153 |
| TPV alpha 100 | 100 | 201 | 284 | 26 | 70 | 102 |
| TPV alpha 100 + prompt concis | 148 | 256 | 300 | 91 | 124 | 142 |
Comment lire ces chiffres
Sur le modèle 32B avec un budget de 512 jetons, TPV avec alpha 100 fait passer les réponses correctes de 36 pour le modèle de base à 100, et dépasse les deux références (54 et 53). C’est le résultat phare, et il est net. Les auteurs rapportent aussi que TPV ajouté au prompt concis donne le meilleur résultat, jusqu’à 148 à 512 jetons. Pour eux, les deux méthodes sont complémentaires.
Le tableau est moins homogène ailleurs. À 2048 jetons sur le même modèle, le prompt concis seul obtient 316 et TPV seul 284, et les auteurs le disent eux-mêmes. Sur le modèle 8B, TPV seul avec alpha 100 bat le modèle de base à 512 et 1024 jetons, mais reste derrière les deux références pour chaque budget Math-500, et à 2048 jetons il obtient 102 contre 112 pour le modèle de base. Alpha 5 ne change presque rien sur ce modèle.
L’affirmation sur l’efficacité est plus modeste et plus claire. Avec alpha 100 sur le modèle 8B plus le prompt concis sur GSM-8K, l’article indique que la longueur moyenne de réflexion passe d’environ 500 jetons à moins de 350, soit 30 % d’économie. Un exemple détaillé montre un problème de placement à table où la réflexion d’origine dépasse 2048 jetons, alors que l’exécution avec coup de pouce répond 720 en 806 jetons.
Là où les preuves sont minces
Ce sont mes propres jugements à la lecture de l’article, pas des constats issus d’une exécution. Le jeu d’entraînement est petit, 30 problèmes pour l’étude de suivi et 80 problèmes Math-500 pour le régresseur de l’évaluation, et chaque échantillon d’entraînement est une réflexion qui s’est terminée. Les longues exécutions qui ne se sont jamais fermées ne sont pas dans les données, alors que ce sont précisément celles qu’une barre de progression aurait le plus besoin de gérer.
La cible est aussi une position relative, pas du travail restant. Deux problèmes dont la solution fait 400 et 4000 jetons finissent tous deux à 1,0. Une barre à 50 % dit que le modèle est à mi-chemin de ce qu’il finira par écrire, pas combien de temps cela prendra. Et la section limites de l’article énumère le reste : maths uniquement, aucune étude des effets de bord sur la cohérence ou l’exactitude factuelle, besoin d’un accès aux états cachés, rien sur l’ampleur de l’exploration ni sur l’incertitude.
Une dernière réserve. Plus vite n’est pas mieux pour les problèmes difficiles. Un modèle poussé à cesser de douter de lui cessera aussi de se vérifier. L’article annonce un taux d’erreur inchangé, mais ses propres tableaux montrent davantage de réponses fausses (réponses moins réponses correctes) dans certaines lignes, par exemple 2 pour le modèle 32B de base sur Math500 à 512 jetons contre 6 avec TPV à alpha 100, et bien plus de problèmes traités. Je n’ai rien exécuté : c’est la lecture des auteurs, pas une vérification de ma part.
Comparé aux indicateurs de progression habituels
Les repères de progression actuels pour les modèles de raisonnement sont surtout extérieurs au modèle : une roue qui tourne, un compteur de temps écoulé, un nombre de jetons ou un court résumé des pensées jusque-là. Le tableau les compare à TPV sur ce que chacun peut dire honnêtement à l’utilisateur. C’est ma propre analyse, et elle décrit des types d’indicateurs, pas des produits précis.
| Indicateur | Ce qu’il dit à l’utilisateur | Exige les états cachés | Principale faiblesse |
|---|---|---|---|
| Roue qui tourne | Quelque chose s’exécute | Non | Ne dit rien sur la durée |
| Compteur de temps | Depuis combien de temps ça tourne | Non | Ne prédit pas la fin |
| Compteur de jetons | Combien de réflexion est écrite | Non | La longueur n’est pas la progression |
| Résumé des pensées jusque-là | Ce que le modèle envisage | Non | C’est aussi une sortie du modèle, donc elle peut être fausse |
| Barre TPV | Part estimée de la réflexion déjà faite | Oui, avec des poids ouverts | Position relative seulement, testée sur les maths uniquement |
La licence et le coût d’exécution
Le README et le fichier LICENSE indiquent CC BY-NC-SA 4.0, et les en-têtes du code ajoutent que l’usage commercial exige une licence distincte du titulaire des droits nommé dans le README. Les métadonnées de GitHub elles-mêmes parlent de licence « Other ». En clair : étudiez, reproduisez et partagez vos modifications aux mêmes conditions, mais ne bâtissez pas un produit dessus sans accord.
L’article dit que chaque expérience a tourné sur un seul GPU A100 et duré au plus deux jours. requirements.txt est une liste de commandes conda et pip pour Python 3.10, PyTorch 2.3.1 avec CUDA 12.1, accelerate, bitsandbytes, datasets et quelques autres. Il ne liste pas transformers, que chaque script importe : une installation propre demandera de l’ajouter. Le dernier commit date du 7 juillet 2025, et le dépôt comptait un contributeur, 56 étoiles et un ticket ouvert à ma consultation.
À qui il s’adresse
Il convient aux chercheurs et aux bricoleurs qui font tourner des modèles de raisonnement à poids ouverts en local et veulent étudier des signaux de progression ou tester l’« overclocking » sur leurs propres tâches. Il convient aussi à ceux qui construisent une interface d’inférence locale et cherchent un point de départ pour une barre de progression, si une licence non commerciale leur va.
Il ne convient pas à ceux qui utilisent un modèle de raisonnement hébergé via une API, puisque la méthode exige les états cachés. Il ne convient pas à une équipe qui veut une fonction commerciale sans licence. Et il ne convient pas à ceux qui attendent un produit fini : pas de vecteur entraîné, pas d’interface, pas de tests.
En pratique : non fait
Je n’ai rien installé ni exécuté un seul script, il n’y a donc dans ce compte rendu ni mesure de temps, ni graphique, ni sortie. Si je devais tester, j’entraînerais un vecteur sur le modèle 8B, je tracerais la barre sur des prompts qui ne sont pas des maths, et je comparerais alpha 0, 5 et 100 sur des tâches dont la réponse se vérifie. C’est un plan, pas un résultat, et je le dirai clairement si une édition ultérieure en rapporte un.
Sources et limites
Chaque affirmation ci-dessus vient de l’article (texte complet, v1) ou du dépôt au commit indiqué dans la liste des sources, que j’ai lu le 4 octobre 2026. Aucun code n’a été exécuté.
- https://github.com/royeisen/reasoning_loading_bar
- https://github.com/royeisen/reasoning_loading_bar/blob/master/LICENSE
- https://github.com/royeisen/reasoning_loading_bar/blob/master/tpv_intervention.py
- https://github.com/royeisen/reasoning_loading_bar/blob/master/requirements.txt
- https://github.com/royeisen/reasoning_loading_bar/blob/master/README.md
- https://github.com/royeisen/reasoning_loading_bar/blob/master/train_tpv.py
- https://github.com/royeisen/reasoning_loading_bar/blob/master/prepare_tpv_dataset.py
- https://github.com/royeisen/reasoning_loading_bar/blob/master/generate_tpv_data.py
- https://arxiv.org/abs/2506.07240
- https://arxiv.org/pdf/2506.07240