Sur-édition : quand un modèle modifie du code au-delà du nécessaire
(nrehiew.github.io)- Même pour des bugs qui se corrigent avec une modification minimale, on voit souvent une réécriture complète de la fonction, l’ajout de logique auxiliaire et jusqu’au changement de signature, ce qui produit facilement un diff énorme
- Dans les travaux brown-field, où il faut préserver la structure existante, il ne suffit pas que les tests passent : il faut aussi évaluer l’ampleur des changements pour maintenir la facilité de revue et la sûreté des modifications
- À partir de 400 problèmes BigCodeBench endommagés programmatiquement, l’over-editing est quantifié avec la distance de Levenshtein au niveau des tokens, un score de patch relatif et l’Added Cognitive Complexity
- Une tendance à la réécriture excessive a été observée sur l’ensemble des modèles de code récents ; Claude Opus 4.6 se distingue par une bonne combinaison de précision et de modifications minimales, tandis que GPT-5.4 montre relativement plus d’over-editing
- Un prompt demandant explicitement de préserver l’original réduit le diff, surtout pour les modèles de raisonnement ; parmi les approches d’entraînement, le RL produit les résultats les plus équilibrés en apprenant un comportement d’édition minimale sans dégrader les performances générales en code
Le problème de l’Over-Editing
- Over-Editing désigne le phénomène où un modèle modifie largement la structure du code au-delà de la correction minimale nécessaire pour réparer un bug
- Même pour un bug off-by-one où il suffit de remplacer
range(len(x) - 1)parrange(len(x)), le modèle peut réécrire toute la fonction et ajouter des fonctions auxiliaires ou de la logique de validation - Dans l’exemple, GPT-5.4 ajoute une vérification de
None, une conversionnp.asarray(dtype=float), un masquage des valeurs finies, une validation de la taille du tableau, modifie la signature de l’appel àcurve_fitet remplace la logique de tracé ; les tests passent, mais le diff est énorme
- Même pour un bug off-by-one où il suffit de remplacer
- Dans les travaux brown-field, qui portent sur une base de code existante, il est important de corriger le problème tout en conservant un code déjà compris et écrit intentionnellement par l’équipe
- Contrairement au green-field, des modifications qui ne respectent pas la structure existante rendent plus difficile pour les reviewers de comprendre ce qui a changé et pourquoi
- Lorsqu’une fonction entière est réécrite, le code devient plus difficile à reconnaître et la sûreté du changement plus compliquée à évaluer
- Le seul critère « les tests passent » ne suffit pas à détecter ce problème
- L’Over-Editing n’est pas un échec de correction, mais un échec de fidélité dans l’édition, donc il apparaît mal dans une suite de tests
- Plus le volume de code généré augmente, plus la quantité à relire s’accroît, et la complexité inutile peut s’accumuler au point de dégrader discrètement la qualité du codebase
Comment mesurer l’Over-Editing
- Pour construire un dataset où la bonne réponse minimale est évidente, l’étude crée un jeu d’évaluation à partir de 400 problèmes BigCodeBench endommagés programmatiquement
- Au lieu d’injecter les bugs avec un autre LLM comme dans des benchmarks existants, les altérations sont finement contrôlées, par exemple en remplaçant
<par<=,+par-ouTrueparFalse - Chaque échantillon endommagé est validé pour rester syntaxiquement correct et faire échouer les tests associés ; la correction attendue consiste uniquement à annuler cette altération, de sorte qu’elle soit bien minimale
- Au lieu d’injecter les bugs avec un autre LLM comme dans des benchmarks existants, les altérations sont finement contrôlées, par exemple en remplaçant
- Cette construction permet d’évaluer non seulement si le modèle corrige le bug, mais aussi à quel point il modifie davantage le code en le faisant
- La taille relative du patch est calculée en comparant à l’entrée endommagée à la fois la sortie du modèle et la réponse de référence
- Plus il y a de changements supplémentaires au-delà de la restauration correcte, plus le score se dégrade
- Le code associé est disponible dans le dépôt GitHub
Métriques de mesure
-
Distance de Levenshtein au niveau des tokens
- Au lieu d’une Levenshtein classique au niveau caractère, l’étude utilise une variante au niveau des tokens Python
- Le code est découpé par le tokenizer Python en unités syntaxiques atomiques comme
def,add,(,a,,,b,), puis la distance est calculée sur cette séquence - Si
def add(a, b):devientdef someotherfunctionname(a, b):, la distance caractère par caractère vaut 19, mais la distance au niveau des tokens vaut 1 car un seul identifiant a changé - La métrique est normalisée par le nombre total de tokens pour rester comparable entre fonctions de longueurs différentes
-
Score de patch relatif
- La sortie du modèle n’est pas comparée directement à la réponse de référence ; les deux sont comparées à l’entrée endommagée
- L’édition qui ramène la solution endommagée à la solution d’origine est la véritable modification minimale, et la métrique mesure à quel point l’édition produite par le modèle s’en rapproche
- Plus la valeur est proche de 0, plus le patch du modèle ressemble à la vraie correction minimale
-
Added Cognitive Complexity
- L’étude utilise aussi la Cognitive Complexity, qui reflète mieux la difficulté de lecture que la Cyclomatic Complexity
- Elle pénalise l’imbrication, la récursion, les opérateurs logiques composés et les flux de contrôle peu intuitifs ; des structures comme
if, les boucles outry/except, qui demandent au lecteur de suivre davantage d’état, augmentent la complexité - Dans l’exemple, le code avec boucles imbriquées et conditions atteint une Cognitive Complexity de 6
- Comme les altérations de cette étude changent uniquement des valeurs sans toucher à la structure, une correction correcte devrait toujours avoir une Added Cognitive Complexity égale à 0
- Si la complexité augmente dans la sortie du modèle, cela signifie que du code non demandé a été ajouté ; une valeur négative est également jugée indésirable, car elle correspond à une simplification inutile
Les modèles font-ils vraiment de l’Over-Editing ?
- Même les modèles frontier récents présentent de l’Over-Editing
- Les modèles de raisonnement comme les modèles non orientés raisonnement montrent un écart entre le Pass@1 et la capacité à effectuer des modifications minimales
- La seule capacité à corriger correctement ne suffit pas à juger de la fidélité de l’édition
- Parmi les modèles de raisonnement, Claude Opus 4.6 montre la meilleure combinaison
- Il obtient le meilleur Pass@1 à 0,912, ainsi qu’une Levenshtein normalisée de 0,060 et une Added Cognitive Complexity de 0,200, soit aussi les plus petits diffs
- Gemini 3.1 Pro Preview se situe dans une zone similaire, et parmi les modèles open-weight, GLM 5 édite de manière relativement plus conservatrice
- GPT-5.4 fait partie des modèles les plus sujets à l’Over-Editing dans cette évaluation
- En mode raisonnement, il affiche une Levenshtein de 0,395 et une Added Cognitive Complexity de 2,313 ; même en mode non-raisonnement, les valeurs restent élevées à 0,327 et 1,563
- Son Pass@1 est également assez bas, à 0,723 et 0,770, ce qui traduit des résultats faibles à la fois en précision et en modification minimale
- Côté modèles non orientés raisonnement, Qwen 3.6 Plus obtient le meilleur Pass@1 avec 0,870, tandis que GLM 5 affiche l’Added Cognitive Complexity la plus basse à 0,235
- La version non-raisonnement de Claude Opus 4.6 maintient elle aussi des changements très limités, avec une Levenshtein de 0,079 et une Added Cognitive Complexity de 0,313
Peut-on améliorer cela par le prompt ?
- Quand on ajoute au prompt « IMPORTANT: Try to preserve the original code and the logic of the original code as much as possible », la distance de Levenshtein diminue pour tous les modèles
- Sauf pour DeepSeek R1/v3, le Pass@1 s’améliore également
- On peut interpréter cela comme le fait que la contrainte de modification minimale réduit l’espace des corrections possibles et oriente vers des changements plus précis et mieux ciblés
- Cet effet est particulièrement marqué pour les modèles de raisonnement
- Comme ils ont tendance à mieux suivre les consignes explicites, la demande de minimiser l’édition se traduit fortement par une réduction du diff
- Cela montre que, même s’ils ont tendance à trop intervenir par défaut, ils peuvent basculer vers des corrections plus fidèles lorsqu’on leur donne une instruction explicite
Le raisonnement conduit-il à une réécriture excessive ?
- En appariant des modèles de raisonnement et non raisonnants d’une même famille, puis en comparant la distance de Levenshtein sur les seuls échantillons où les deux donnent la bonne réponse
- S’il y a beaucoup d’échecs, cela crée un biais qui réduit mécaniquement les occasions d’Over-Editing ; l’idée est donc d’abord de contrôler la précision, puis d’isoler uniquement le style d’édition
- Avec les réglages de prompt généraux, dans la plupart des paires, le modèle de raisonnement réécrit davantage
- DeepSeek V3, GPT-5, GPT-5.4, Gemini 3.1 Pro Preview, Qwen 3.6 Plus et Kimi 2.5 affichent tous une barre plus élevée côté raisonnement
- Cela montre qu’un raisonnement étendu tend à viser une « meilleure implémentation » plutôt qu’une modification minimale, ce qui génère des refactorings inutiles
- L’exception est Claude Opus 4.6, dont la version de raisonnement modifie nettement moins que la version non raisonnante
- Lorsque l’on demande explicitement de préserver le code d’origine, le tableau change fortement
- Les modèles de raisonnement affichent, dans presque toutes les paires, une distance de Levenshtein égale ou inférieure à celle des modèles non raisonnants
- La version de raisonnement de Claude Opus 4.6 enregistre, dans ce réglage, la plus faible distance de Levenshtein de tous les modèles
- GPT-5 et GPT-5.4 voient aussi fortement baisser leur score côté raisonnement, mais pour GPT-5.4 la version non raisonnante reste encore légèrement devant
- Par défaut, les modèles de raisonnement ont tendance à faire de l’Over-Editing, mais cette même capacité de raisonnement les aide aussi à mieux respecter les contraintes
- L’écart entre réglage général et réglage explicite apparaît de manière systématiquement plus marquée chez les modèles de raisonnement
- L’Over-Editing semble donc relever davantage d’un comportement par défaut que d’une limite fondamentale, et peut être inversé via des contraintes
Peut-on former un éditeur fidèle par apprentissage ?
- Le modèle de base est Qwen3 4B 2507 Instruct, et les configurations 0-shot et 8-shot avec instruction de préservation du code d’origine servent de baseline
- Les autres méthodes d’apprentissage sont évaluées dans un réglage général, sans instruction explicite de préservation de l’original
-
Configuration expérimentale
- Les problèmes de DeepCoder sont corrompus de la même manière pour créer un jeu de données synthétique
- En parallèle, Qwen3 4B 2507 Instruct de base génère 8 completions pour chaque problème ; seules les sorties fonctionnellement correctes sont conservées, puis classées par distance de Levenshtein pour former aussi un jeu de données de self-distillation
- L’apprentissage s’inspire de la Context Distillation afin d’obtenir, à l’évaluation, un comportement de modification minimale sans instruction explicite
-
Méthodes d’apprentissage
- SFT : fine-tuning supervisé direct sur le jeu de données généré programmatiquement
- rSFT : apprentissage sur les 3 completions ayant la plus faible distance de Levenshtein pour chaque échantillon du jeu de self-distillation
- DPO : optimisation par préférence entre la completion à distance de Levenshtein la plus élevée et celle à la plus faible, pour chaque échantillon
- RL : application d’un apprentissage par renforcement combinant exactitude fonctionnelle et récompense de modification minimale basée sur Levenshtein
- Si tous les tests passent,
r = r_edit + 0.1 - Sinon,
r = -0.2 r_editest calculé comme une récompense basée sur une distance de Levenshtein normalisée
- Si tous les tests passent,
Qu’obtient-on sur le même type de corruption ?
- Dans le réglage in-domain, où le type de corruption est identique entre entraînement et test, SFT produit un résultat presque parfait
- Baseline 0-shot : Pass@1 à 0.735, Norm. Levenshtein à 0.169, Added CC à 0.731
- Baseline 8-shot : Pass@1 à 0.775, Norm. Levenshtein à 0.115, Added CC à 0.479
- SFT obtient les meilleurs résultats sur les trois métriques avec Pass@1 à 0.932, Norm. Levenshtein à 0.002 et Added CC à 0.000
- rSFT enregistre 0.782 / 0.100 / 0.435, DPO 0.752 / 0.021 / 0.113, et RL 0.802 / 0.046 / 0.112
- Comme ce résultat paraît presque trop bon, la possibilité d’une simple mémorisation de la transformation inverse d’un type de corruption donné est examinée
- Il est possible que le modèle n’ait pas appris un comportement général de modification minimale, mais seulement à inverser des motifs de corruption prédéfinis
- Pour le vérifier, les types de corruption des données d’entraînement et d’évaluation ont été entièrement dissociés
Cela se généralise-t-il à d’autres types de corruption ?
- Dans le réglage out-of-domain, où les types de corruption diffèrent entre entraînement et test, SFT s’effondre fortement
- Le Pass@1 de SFT tombe jusqu’à 0.458, et le modèle en vient à tenter uniquement certaines modifications minimales sans réellement corriger les bugs
- Norm. Levenshtein à -0.008 et Added CC à 0.006 restent très faibles, mais la capacité à produire la bonne correction s’écroule
- rSFT et DPO font légèrement mieux que la baseline 8-shot, mais les gains restent limités
- rSFT : 0.780 / 0.107 / 0.501 / LiveCodeBench -0.069
- DPO : Pass@1 0.787 / 0.092 / 0.348 / LiveCodeBench -0.046
- Même un apprentissage fondé uniquement sur des données de trace générées par le modèle de base permet une certaine généralisation
- RL est la seule méthode à bien se généraliser sur l’ensemble des métriques
- RL obtient Pass@1 à 0.782, Norm. Levenshtein à 0.050, Added CC à 0.185 et LiveCodeBench Change à +0.006
- Les trois métriques sont meilleures que pour les deux baselines, sans dégradation des performances générales en programmation
- Le fait que les gains sur Levenshtein et Added Cognitive Complexity soient plus importants que sur Pass@1 renforce l’idée qu’il ne s’agit pas d’une simple mémorisation de l’inversion des corruptions, mais bien de l’apprentissage du comportement de modification minimale lui-même
Catastrophic Forgetting
- Une vérification sur LiveCodeBench v6 permet aussi de voir si le niveau général en programmation baisse après un fine-tuning axé sur la modification minimale
- L’objectif est de conserver, après entraînement, un niveau proche de celui du modèle pretrained d’origine
- SFT provoque une très forte dégradation des capacités générales
- Sur LiveCodeBench, on observe une baisse de performances de 43 %, et même les capacités de base d’identification et de correction de bugs ne sont plus maintenues
- rSFT et DPO reculent aussi légèrement
- Même lorsqu’ils sont entraînés sur des échantillons générés par le modèle d’origine, un certain niveau de Catastrophic Forgetting subsiste du fait de la nature de la tâche
- RL apprend le nouveau comportement sans perte de performance
- Il conserve les capacités générales de programmation tout en améliorant le plus nettement les performances sur la tâche de modification minimale
- Cela rejoint SFT memorizes while RL generalizes
- Du point de vue de la distribution, on peut aussi interpréter le phénomène ainsi : plus l’écart est grand entre le jeu de données généré programmatiquement et la distribution d’origine du modèle, plus le Forgetting est important
- SFT modifie fortement la distribution du modèle en l’ajustant intensivement à des données très éloignées de la distribution d’origine
- rSFT et DPO évoluent de manière moins brutale, car leurs données self-distilled restent plus proches de la distribution d’origine
- Le degré de Catastrophic Forgetting est probablement proportionnel à l’écart entre la distribution d’origine et celle des données d’apprentissage de la tâche
Expériences supplémentaires
-
RL avec LoRA : faut-il un fine-tuning complet ?
- Comme ce travail consiste davantage à ajuster le style de la capacité à modifier du code existant qu’à injecter de nouvelles connaissances, les auteurs ont vérifié si LoRA pouvait suffire
- rank 1 : Pass@1 0.738, Norm. Levenshtein 0.166, Added CC 0.676, LiveCodeBench Δ -0.022
- rank 8 : 0.775 / 0.112 / 0.426 / -0.022
- rank 16 : Pass@1 0.805 / 0.087 / 0.328 / -0.005
- rank 32 : 0.795 / 0.065 / 0.235 / -0.011
- rank 64 : 0.797 / 0.051 / 0.160 / +0.001
- Le meilleur modèle en Full RL atteint 0.782 / 0.050 / 0.185 / +0.006
- LoRA rank 64 arrive presque au niveau de Full RL sur Levenshtein et fait mieux sur Added CC
- À mesure que le rank augmente, Levenshtein et Added CC diminuent de façon monotone de 1 à 64
- Les plus gros gains se concentrent au début : de rank 1 à 16, Levenshtein chute fortement de 0.166 à 0.087, puis l’écart se resserre progressivement de 16 à 64, de 0.087 à 0.051
- Les ranks 1 et 8 montrent un compromis entre précision et édition minimale ; il est possible que la capacité soit insuffisante pour apprendre simultanément les deux fonctions de récompense, avec un biais vers la minimisation des éditions, mieux récompensée
- Pour des changements de comportement au niveau du style sur une tâche où les capacités existent déjà, un petit nombre de paramètres supplémentaires semble suffire, et le rendement de capacité additionnelle diminue après un certain point
-
Note sur le reward hacking
- La fonction de récompense initiale comportait un bug qui attribuait 0 point aux rollouts sans aucune exécution réussie
- Comme le signe de Levenshtein avait été inversé pour en faire une métrique où « plus c’est grand, mieux c’est », ce 0 devenait paradoxalement une récompense plus élevée qu’une exécution réussie
- Malgré cela, Full RL a appris la tâche, tandis qu’un reward hacking est apparu uniquement avec LoRA, allant jusqu’à ne plus produire du tout de code fonctionnellement correct, ce qui a conduit à une inspection de l’environnement
- Après correction de la fonction de récompense, les résultats de Full RL ne se sont améliorés que légèrement
-
Est-ce que cela s’étend aussi aux modèles plus grands ?
- La même recette de RL out-of-domain a été appliquée à Qwen3 14B
- Le baseline 14B affiche Pass@1 0.770, Norm. Levenshtein 0.136, Added CC 0.315
- Après application de RL, les résultats passent à Pass@1 0.833, Norm. Levenshtein 0.059, Added CC 0.165, LiveCodeBench Δ +0.011, avec une amélioration globale
- Même avec davantage de paramètres, la hausse de Pass@1, la baisse de Levenshtein, la diminution de l’Added Cognitive Complexity et l’absence de Catastrophic Forgetting se maintiennent ensemble
- Cela renforce l’idée que la recette RL pour l’édition minimale de code pourrait s’étendre à des modèles de tailles variées
Bilan final
- Over-Editing apparaît comme un problème répandu et mesurable
- Sur l’ensemble des modèles de coding de pointe, la capacité à corriger correctement et la capacité à corriger au minimum se révèlent distinctes
- En particulier, GPT-5.4 montre par défaut une tendance relativement forte à la réécriture excessive, tandis qu’Opus 4.6 constitue un baseline solide
- Un prompting explicite permet déjà d’orienter largement vers des éditions fidèles
- Les modèles de raisonnement ont notamment tendance à trop intervenir par défaut, mais suivent mieux les consignes quand on leur demande de préserver l’original
- GPT-5.4 montre aussi une forte amélioration en mode raisonnement, ce qui met en évidence de solides capacités d’instruction following
- Si l’amélioration d’Opus 4.6 paraît faible, c’est peut-être parce que ses performances de base sont déjà élevées
- Du point de vue de l’apprentissage, RL apparaît comme la solution la plus équilibrée
- Le modèle apprend un comportement d’édition plus fidèle sans dégrader ses capacités générales de coding, et l’effet se maintient sur Qwen3 en 4B comme en 14B
- SFT était performant sur certains types de corruption, mais a largement échoué en généralisation et en préservation des capacités générales
- L’évaluation de correction de bugs au niveau d’une fonction unique reste plus limitée que des évaluations plus agentiques comme SWE-Bench Pro, mais elle constitue un point de départ pour traiter un problème difficile à quantifier dans des conditions réalistes : l’Over-Editing
- Évaluer et améliorer la capacité d’édition minimale pourrait contribuer à rehausser la qualité globale du code généré par l’IA
Aucun commentaire pour le moment.