Les LLM n’écrivent pas du code correct : ils écrivent seulement du code plausible
(blog.katanaquant.com)- La version de SQLite réécrite en Rust par un LLM affiche des performances environ 20000 fois plus lentes que l’original sur les recherches par clé primaire
- Le code compile et passe les tests, mais comporte en interne des erreurs algorithmiques critiques et une conception inefficace
- Les causes principales sont notamment l’absence de détection de la PRIMARY KEY et un appel à
fsyncà chaque requête ; la structure semble plausible, mais le comportement réel est anormal - Ce phénomène vient de l’optimisation de la “plausibilité” par les modèles d’IA (
sycophancy) ; sans critères de validation (acceptance criteria) clairement définis par l’utilisateur, il est facile de se laisser tromper - Les LLM ne peuvent améliorer la productivité que lorsque des développeurs expérimentés définissent clairement les critères de correction ; sinon, ils ne sont guère plus que de simples générateurs de tokens
Expérience de performance sur du code généré par un LLM
- Sur une recherche de clé primaire SQLite (base de 100 lignes), l’implémentation d’origine met 0.09ms, contre 1,815.43ms pour la version Rust générée par un LLM, soit environ 20,171 fois plus lent
- Les deux implémentations utilisent la même requête, le même schéma et les mêmes options de compilation
- Cela n’a rien à voir avec Turso/libsql ; Turso affiche des performances normales, autour de 1,2x celles de SQLite
- En apparence, la version Rust fonctionne normalement : compilation réussie, tests validés, compatibilité du format de fichier préservée
- En réalité, elle subit une dégradation sévère des performances sur des opérations de base de base de données
Analyse des principaux bugs
- Bug n°1 : absence de détection de
INTEGER PRIMARY KEY- SQLite mappe
id INTEGER PRIMARY KEYvers lerowidinterne pour effectuer une recherche en O(log n) - La version Rust ne reconnaît dans
is_rowid_ref()que"rowid","_rowid_"et"oid" - Résultat : la requête
WHERE id = Nest traitée par un scan complet de table (O(n²)), ce qui explique le ralentissement d’un facteur 20000
- SQLite mappe
- Bug n°2 : appel à
fsyncà chaque requête- Chaque
INSERThors transaction déclenche une synchronisation complète (fsync) - SQLite utilise
fdatasync, ce qui évite la synchronisation des métadonnées et s’avère bien plus efficace - Sur 100
INSERT, la version Rust prend 2,562.99ms contre 32.81ms pour SQLite, soit un écart de 78x
- Chaque
Facteurs d’inefficacité cumulés
- Copie et recompilation de l’AST, allocations heap de 4 KB, rechargement du schéma, formatage de chaînes, recréation d’objets et d’autres choix de conception s’accumulent pour produire une baisse de performances d’environ 2900x
- Chaque décision peut être justifiée au nom de la “sécurité”, mais sur le hot path, elle devient au contraire un goulet d’étranglement critique
- Les performances de SQLite ne viennent pas seulement du langage C, mais de 26 ans de profilage et de micro-optimisations
Deuxième cas : un outil de gestion disque inutilement complexe
- Un autre projet Rust généré par un LLM implémente un daemon de nettoyage des artefacts de build en 8200 lignes
- 192 dépendances, un dashboard de 7 écrans, un moteur de scoring bayésien et d’autres fonctionnalités excessives
- Alors que le problème réel peut être résolu par une simple ligne cron (
find ... -exec rm -rf)
- C’est un exemple où la “fonction demandée” est bien implémentée, mais au prix d’une complexité inutile pour résoudre le problème réel
L’écart entre intention et exactitude : le phénomène de sycophancy
- Les LLM ont tendance à adopter une “conformité flatteuse” (
sycophancy) pour répondre aux attentes de l’utilisateur- Une étude d’Anthropic (2024) et le benchmark BrokenMath (2025) confirment un problème structurel : les modèles apprennent l’accord plus que l’exactitude
- Même GPT-5 génère dans 29 % des cas une preuve d’un faux théorème lorsque l’utilisateur envoie des signaux positifs
- Le RLHF (apprentissage par renforcement à partir de retours humains) renforce ce biais d’approbation
- OpenAI a même procédé à un rollback de modèle après une mise à jour de GPT-4o en 2025 à cause de ce problème
- Ce biais agit non seulement pendant la génération de code, mais aussi lors de l’auto-review du code, empêchant le modèle de détecter lui-même ses erreurs
Recherche externe et données du secteur
- Expérience METR (2025–2026) : 16 développeurs open source expérimentés ont été 19 % plus lents avec l’IA, tout en ayant l’impression d’aller plus vite
- Analyse GitClear (2020–2024) : sur 211 millions de lignes, augmentation du copier-coller et baisse du refactoring
- Incident Replit (2025) : un agent IA a supprimé une base de données de production puis créé 400 faux utilisateurs
- Rapport Google DORA 2024 : quand l’usage de l’IA augmente de 25 % à l’échelle des équipes, la stabilité de livraison baisse de 7,2 %
Ce que SQLite montre comme standard de “correction”
- SQLite compte environ 15600 lignes de code C, avec une couverture MC/DC de 100 % et un niveau de validation comparable au logiciel aéronautique
- Principaux facteurs de performance :
- Cache de pages en zero-copy
- Réutilisation des prepared statements
- Vérification du schema cookie pour éviter les rechargements inutiles
- Usage de
fdatasyncpour minimiser la latence des commits - Vérification de
iPKeypour garantir une recherche en O(log n)
- À l’inverse, la réécriture Rust compte 57600 lignes mais omet une ligne critique : la vérification de
is_ipk
Conclusion : il faut définir l’“exactitude”, pas la “plausibilité”
- Les LLM imitent des motifs, mais ne savent pas apprendre d’eux-mêmes les invariants de performance
- Le fait que “le code compile” ne suffit pas ; il faut aussi être capable d’identifier directement les bugs et de les expliquer
- Les LLM deviennent des outils puissants lorsque des développeurs expérimentés définissent clairement les critères de correction
- Sinon, ils ne sont que des générateurs de tokens plausibles, cantonnés au niveau du “vibe coding”
- Message essentiel : définissez d’abord les critères de correction, puis mesurez-les.
16 commentaires
Cela semble être un bon exemple de ce qui se passe lorsqu’on ne fournit même pas de success criteria simples liés aux performances. Les agents de codage que j’ai utilisés jusqu’à présent cherchent surtout à résoudre le problème lui-même, mais sans prompt explicite en amont ni boucle de validation, ils n’optimisent presque jamais les performances par eux-mêmes. Il faut donner des consignes à l’IA comme si l’on proposait un problème de test de code. Surtout, même lorsqu’il existe une baseline comme dans ce cas, ne pas préciser les contraintes de performance tout en espérant un résultat optimal peut aussi être considéré comme une forme de négligence de la part de la personne qui utilise l’IA.
+1 👍
En réalité, ce n’est pas propre aux LLM, les humains aussi font ça parfois.
La différence, c’est qu’un humain peut intégrer le feedback, alors qu’avec un LLM, il est presque impossible de corriger ses mauvaises habitudes étranges. Même quand on le lui fait remarquer, il finit par refaire la même chose tôt ou tard.
N’est-ce pas là que naissent l’inefficacité et la fatigue ?
Au moment où les gens commencent à cerner les caractéristiques du modèle et à trouver puis appliquer les prompts et workflows de compétences appropriés, un nouveau modèle est déjà sorti....
Je me demande même s’il est possible d’utiliser correctement les agents à l’heure actuelle.
George Hotz lui aussi utilise l’IA en la considérant simplement comme une sorte de compilateur. Pour la conception, l’architecture ou les choix, le jugement humain reste encore nécessaire... Globalement, si on laisse l’IA prendre les commandes, il n’y a plus vraiment de raison qu’un développeur le fasse lui-même.
Évidemment que ce sera plus lent si on compare ça à une requête déjà implémentée à la perfection et ultra optimisée, puis qu’on lui demande de la réécrire dans un autre langage.
Puisqu’on lui a juste dit « écris-la », haha
Les vibe coders de niveau big tech devraient bientôt faire leur apparition dans les commentaires.
Si vous n’allez pas écrire un commentaire constructif, alors n’en écrivez pas du tout.
Ça m’a bien fait rire.
mdr mdr mdr, même un post pourri reste un post
Ne dites rien
Avant qu’on finisse dans la théorie de l’Internet mort
Caca, hihi
C’est repris de Hacker News, mais vous croyez vraiment que là-bas aussi il n’y a toujours que des commentaires constructifs… Ce n’est pas très agréable à voir.
Tu as au moins lu les règles de Hacker News..? Il vaut mieux éviter ce genre de billet ; cette mentalité du style « lui aussi fait de la merde, alors pourquoi on ne s’en prend qu’à moi ? » est franchement puérile.
Non. Il faudrait plutôt dire : lui aussi, il chie, alors pourquoi ne s'en prendre qu'à lui ?
Il suffit d’essayer un peu pour le sentir immédiatement. Je ne comprenais pas pourquoi d’autres développeurs disaient ressentir de la fatigue lors de la revue, mais peu importe la qualité des prompts et des techniques utilisées, le code généré par l’IA présentait toujours quelque part un défaut.
J’ai lu l’article original, et l’analyse comme la critique me semblent pertinentes. En revanche, les modèles expérimentaux utilisés dans les études citées donnent, à l’heure actuelle, une impression un peu datée (?).
Réactions sur Hacker News
Fondamentalement, les LLM ont tendance, lorsqu’un problème survient, à essayer de le résoudre en creusant davantage dans le code
Si l’implémentation repose sur une approche inefficace, ils continuent ensuite à ajouter du code de contournement ou du code dupliqué à chaque nouvelle contrainte
Si les performances sont trop lentes, ils empilent des optimisations de chemin rapide, des routines spécialisées et des structures de données personnalisées, si bien que le volume de code augmente de façon exponentielle
S’il y a beaucoup de bugs, ils créent dix tests par bug et, si le framework de mocking existant ne convient pas, ils en fabriquent un nouveau
Si on leur demande de fusionner les doublons, ils répondent : « Très bien, je vais créer un metamock abstract adapter framework qui couvre toutes les fonctionnalités ! », puis ajoutent encore une autre couche de complexité
Cette revue est indispensable pour éviter les hypothèses erronées et la dette technique
Il faut d’abord leur faire concevoir une architecture raisonnable, puis, si les modules s’emmêlent, les faire repartir de zéro dans un contexte propre
Les LLM sont mauvais pour retoucher encore et encore le même code, mais bons pour tout réimplémenter depuis le début à la manière de Groundhog Day
Les LLM ne signalent pas ce type de choix et ne le rappellent pas
C’est pour ça que je préfère Claude Code à Codex
Dans la rédaction de documents juridiques aussi, le caractère « plausible » des résultats des LLM pose problème
À première vue, cela semble valable, mais ce sont souvent en réalité des affirmations logiquement inadaptées ou dangereuses
Les juges n’ont parfois ni le temps ni la volonté d’examiner ces documents en détail, si bien qu’ils peuvent être acceptés tels quels
Cela crée une asymétrie à la Brandolini : produire est facile, réfuter est difficile
Au fond, c’est semblable à la situation où les développeurs du futur devront démêler la dette cognitive et technique produite par les LLM
Quand un LLM rédige des documents fondés sur des règles, il y glisse des insinuations plausibles mais sans fondement
Je lui redemande donc ensuite de relire son propre texte pour signaler ce genre de passages, mais au final une relecture humaine reste nécessaire
Des collègues génèrent avec des LLM des PR de plusieurs milliers de lignes en quelques minutes
Il y a des tests, mais en pratique c’est souvent du grand n’importe quoi
Au final, le reviewer doit passer sa journée à tout examiner, à comprendre la mauvaise structure et à expliquer comment la corriger
Du coup, j’ai envie de proposer que les PR produites par l’IA rapportent des story points au reviewer
Il faut une structure où le jugement rationnel est calculé par logique formelle, puis traduit en langage naturel
Le LLM doit rester au niveau de l’interprétation et de l’expression, pas de la pensée
Le code produit par les LLM passe souvent les tests tout en ne satisfaisant pas les exigences
Par exemple, ils appellent
fsyncà chaque requête ou identifient mal la clé primaireSur ce type de gros projets, il y a tellement de code qu’un humain ne peut pas tout lire
C’est pourquoi les LLM sont surtout efficaces au niveau d’un autocompléteur amélioré
On peut relire immédiatement de petits fragments de code, et Claude est en général exact
Mais si on lui confie l’ensemble du code, cela demande plus de temps en planification et en gestion, et la maintenance devient plus difficile
Au final, l’avantage de vitesse n’existe vraiment que lorsqu’il s’agit de reproduire du code déjà présent dans les données d’entraînement
Les LLM génèrent statistiquement les motifs de code les plus fréquents
Donc, sans consignes particulières, ils produisent un code « très enterprise, fondé sur l’OOP, avec une montagne de dépendances à la mode »
Il faut définir et mesurer la « justesse »
Pour automatiser, il faut de l’intention (intent) et de la mesure (measurement)
Il faut comprendre le périmètre de risque pour savoir jusqu’où couvrir en amont
Si des outils comme AI evals ou eval-ception
deviennent un langage commun entre les rôles, la collaboration sera beaucoup plus simple
Générer le code le plus plausible est dans la nature même des LLM
C’est la conséquence de la cross entropy loss, et même si un post-traitement comme le RLVR cherche à améliorer l’exactitude,
il reste encore beaucoup de traces de ce comportement
À l’avenir, les progrès du reward engineering pourraient produire de meilleurs résultats
À la question « en quoi est-ce différent d’un humain ? »
Pendant le sommeil, cette fonction s’éteint, d’où une pensée illogique semblable au rêve ; la pensée des LLM est d’un niveau comparable, une sorte de logique de rêve
Avant, on ressentait l’angoisse de ne pas comprendre complètement la technologie ; aujourd’hui, les outils recouvrent cette angoisse
On est entré dans une époque où l’on produit des résultats sans compréhension profonde
Pourtant, les gens attendent une IA objective qui donne la bonne réponse
Cet écart crée une différence de perception entre les utilisateurs ordinaires et les experts
Il y a des gens qui soumettent chaque jour des PR de plusieurs milliers de lignes
La plupart sont ingérables, donc impossibles à relire correctement
Avant, produire ce type de PR prenait une semaine ; maintenant, ça pleut en une journée
Il y a aussi beaucoup de questions sur le terme même de « LLM »
Le modèle appelé directement via une API brute est le LLM ; Claude.ai ou ChatGPT sont, au-dessus, enveloppés dans un harness
Ce harness inclut diverses fonctions comme les templates de prompts et la gestion de l’état de la conversation
Au final, nous utilisons presque toujours plus qu’un simple LLM
Ce type d’agent peut exécuter le code, le tester lui-même et le corriger
ChatGPT comme Claude disposent de cette capacité, donc ce sont de fait des coding agents
Donc, dire qu’un « LLM n’a pas de mémoire » ne s’applique qu’au modèle lui-même
Claude Code ou Cursor sont des systèmes agentiques qui maintiennent un état
Le titre de l’article est intéressant, mais dire que les LLM écrivent du « code plausible » est inexact
En réalité, ils ne font que générer un code similaire aux clusters de code vus dans les données d’entraînement
Ils ne génèrent librement que dans les zones non contraintes par le RLHF ou le RLVR
C’est pourquoi l’ensemble du secteur parle le même langage, mais cela devient aussi une source de malentendus
Cela donne à tout le monde l’illusion qu’ils résolvent le même problème
Par exemple, si on lui demande des requêtes tree-sitter, il invente des directives qui n’existent pas
Pas besoin d’expliquer sa mécanique interne complexe
Récemment, j’ai demandé à Codex de créer un composant d’interface basé sur Datastar, et ce fut un échec total
La tâche était simple, mais à chaque nouvelle tentative, le JavaScript inline et le code backend continuaient à s’accumuler
Il ne nettoyait même pas le code précédent
Il est bon sur des tâches complexes, mais montre paradoxalement des échecs contre-intuitifs sur des tâches élémentaires