Autres blogs
Pendant des mois, ça me dérange : comment savoir vraiment si les modifications apportées à mon agent de modélisation 3D l'améliorent ? Les evals (évaluations) sont la solution, mais construire le bon système d'évaluation pour un agent IA complexe n'est pas simple.
Pour moi, les evals sont des expériences reproductibles sur l'ensemble de l'agent. Chacune utilise un jeu de prompts et une configuration spécifique, exécute le workflow de bout en bout et produit des scores que je peux comparer entre les exécutions. Les exécutions génèrent des artefacts (code, aperçu, 3MF) et les métriques qui comptent, donc une modification gagne ou perd sans devoir deviner à l'aveugle.
Parce qu'elles sont standardisées et faciles à exécuter, j'ai commencé à beaucoup m'y fier. Au moment où j'écris, la suite a produit 2712 générations sur 85 exécutions pour 562,43 $ au total (environ 6,62 $ par exécution). Temps total : 5869m 27s, soit environ 69m 3s par exécution. L'échelle n'est pas énorme, mais ça suffit comme signal pour guider l'itération au jour le jour.
J'ai d'abord essayé un simple "battleground" où je pouvais comparer deux modèles différents côte à côte. C'était un début, mais ça s'est vite effondré. Mon agent n'est pas juste un appel LLM unique. C'est un workflow multi-étapes. Et si je veux utiliser un modèle plus rapide et moins cher juste pour réparer le code généré ? Et si je modifie le prompt système ? Le battleground était trop rigide.

Les frameworks d'évaluation existants ne correspondaient pas non plus. La plupart sont conçus pour un flux simple appel -> réponse. Ils se concentrent aussi sur des métriques génériques comme les "hallucinations". Franchement, je me fiche des hallucinations. Ce qui m'intéresse, c'est de savoir si l'agent produit un excellent modèle 3D imprimable. Ça voulait dire qu'il me fallait une solution personnalisée.
Donc, le problème central était de construire un système d'évaluation flexible qui puisse :
Après beaucoup de réflexion, j'ai trouvé une solution : le commit git est la source unique de vérité.
Toute modification que je veux tester (un nouveau modèle, un prompt différent, un workflow refactorisé) est commitée. Je peux ensuite exécuter une eval contre ce commit spécifique. Ça encapsule l'état complet de l'agent et sa configuration. Simple et puissant.
Mais qu'est-ce qu'on mesure vraiment ? Pour générer des modèles 3D, j'ai défini quelques métriques clés :
Les deux premiers sont subjectifs. Pour gérer ça, j'utilise une approche à deux volets :
Pour garder mes propres notes cohérentes, j'ai créé une échelle claire. Je pense que c'est super important, parce que dans six mois, j'aurai oublié ce qu'un "0.3" en esthétique signifiait.
Ok, donc maintenant j'ai toutes ces métriques. Comment les combiner en un seul score pour savoir si une modification est bonne ou mauvaise ? Avec une équation pondérée.
Ça me permet d'ajuster ce qui m'importe le plus. Par exemple, je pourrais faire de l'adhérence notée par un humain le facteur le plus important et la vitesse secondaire, en ignorant tout le reste.

Ou je pourrais faire du coût deux fois plus important que la vitesse.

Voici ma configuration actuelle pour prendre des décisions :

Mes priorités sont :
Je pondère aussi beaucoup plus mes propres scores que ceux de l'IA.
Une leçon durement apprise après avoir noté plus de 1000 modèles : ma propre notation dérive. Même avec la grille à l'écran, je finissais souvent par faire un rapide passe/échoue au seuil de 0.4 (serais-je d'accord pour montrer ça à un utilisateur ou pas). Ça m'a poussé vers un signal humain plus simple. J'expérimente un oui/non binaire pour l'adhérence, puis je laisse le score pondéré l'utiliser comme une caractéristique forte. Ça réduit le bruit, accélère les révisions et correspond à comment je prends vraiment les décisions sous pression temporelle. L'IA peut garder un score continu ; ma note peut être nette et vérifiable.
Voyons ça en action. J'ai récemment changé l'"effort de raisonnement" de l'agent à "high", mais je n'étais pas sûr que ça aidait vraiment. C'était définitivement plus lent et plus cher. Pourrais-je m'en sortir avec un effort "medium" ou "low" et réduire le temps de génération de moitié ?
J'ai deux jeux de prompts que j'utilise pour les evals : un jeu "base" avec 7 prompts et un jeu "extra" avec 27. Chaque prompt est exécuté 3 fois pour tenir compte de la variabilité, donc une exécution extra génère 81 modèles. Je commence généralement avec le jeu de base pour avoir une idée générale. Si les résultats sont trop serrés pour trancher, j'exécute le jeu extra complet. C'est pas un échantillon énorme, mais c'est bien mieux que de piloter à vue. Ça coûte déjà environ 5 $ par exécution base et environ 15 $ par exécution extra, et c'est un projet perso...
Les résultats étaient clairs :
Le gagnant était évident : l'effort de raisonnement Medium. Il offrait la même qualité que High pour moitié du coût et du temps. Vous pouvez voir tous les résultats sur la page evals.
Depuis, GPT-5.1 est sorti (18.11.2025). Les premières exécutions sur le même réglage de raisonnement "medium" montrent des complétions 2-3x plus rapides que GPT-5 avec une qualité légèrement inférieure sur l'adhérence et l'esthétique. Sur la capacité globale, il se situe entre Gemini 2.5 Pro et GPT-5 pour ma charge de travail. Vu la vitesse, je préfère maintenant GPT-5.1 pour la génération de modèles quand j'ai besoin d'itération rapide, et je reviens à GPT-5 quand ce dernier petit plus de qualité compte. Les deux restent dans le harnais donc c'est le tableau de scores qui décide, pas le ressenti. (C'était l'état des lieux fin 2025. Le roster a beaucoup bougé depuis, j'en reparle plus bas.)

Je modifie constamment des variables comme celles-ci et je relance les evals :
const INITIAL_MODEL = "openai/gpt-5";
const INITIAL_REASONING_EFFORT = "medium";
const CODE_ERRORS_MAX = 4;
const FIX_MODEL = "openai/gpt-5-mini";
const FIX_REASONING_EFFORT = "low";
const VISUAL_ADHERENCE_MIN = 0.4;
const VISUAL_ERRORS_MAX = 1;
const VISUAL_EVALUATION_MODEL = "2.5-flash";
const VISUAL_FIX_MODEL = "openai/gpt-5";
const VISUAL_FIX_REASONING_EFFORT = "low";
Vous vous demandez peut-être à propos de ces variables VISUAL_. C'est là que ça devient intéressant. J'ai implémenté une fonctionnalité de "vérification visuelle" où un modèle IA regarde une image rendue du modèle 3D et note son adhérence au prompt. Si le score est trop bas, l'agent réessaye.
Mon intuition était que ça n'aidait pas assez pour justifier le temps et le coût supplémentaires. Ça faisait prendre trois fois plus de temps aux générations. Exécuter le jeu de prompts extra a confirmé cette suspicion. Les vérifications visuelles n'étaient pas assez cohérentes. Pourquoi ? La note de l'IA était-elle juste aléatoire ? Mon seuil était-il trop bas, causant des tentatives inutiles ?
J'avais entendu parler de régression linéaire mais je n'avais jamais eu de vraie utilité pour ça. Jusqu'à maintenant. J'ai des paires de scores pour le même modèle : (score IA, score humain). C'est un ajustement parfait.
En termes simples, la régression linéaire trouve la ligne droite qui correspond le mieux à un ensemble de points de données. Dans mon cas, les points de données sont les paires (score IA, score humain). Si l'IA est un bon juge, ses scores devraient avoir une relation linéaire avec mes scores. Par exemple, quand l'IA donne un 0.2, je pourrais constamment donner un 0.3. Quand elle donne un 0.8, je pourrais donner un 0.7. La régression linéaire trouve la formule pour cette ligne.
C'est utile pour deux raisons. D'abord, ça me permet d'entraîner un tout petit modèle pour prédire mon score basé sur le score de l'IA. Plus important, ça me donne une valeur appelée R-carré (R²). Ça me dit à quel point les scores de l'IA prédisent les scores humains. Un R² de 1 signifie une prédiction parfaite ; 0 signifie aucune corrélation. Je serais content avec n'importe quoi au-dessus de 0.4.
Ce que j'ai trouvé :
2.5-flash.Après avoir ajusté les vérifications visuelles avec ces données, j'ai relancé les benchmarks.

Les résultats initiaux ont montré une certaine amélioration du "taux de réussite" - le nombre de modèles avec un score d'adhérence au-dessus de 0.4. Mais quand j'ai creusé plus profond avec le jeu de prompts extra, le R² était en fait plus proche de 0.1 (soit 10%). C'est... pas génial. Ça signifie que la note de l'IA est un mauvais prédicteur de la mienne.
Donc pour l'instant, j'ai désactivé les vérifications visuelles. C'est pas juste une question d'attendre que les modèles de vision sous-jacents s'améliorent. Il y a d'autres choses que je dois explorer, comme améliorer le prompt système pour le LLM de vérification visuelle ou rendre le modèle sous plusieurs angles pour donner à l'IA une meilleure vue. La bonne nouvelle, c'est que j'ai tout le système prêt, donc je peux facilement tester ces idées et activer le switch quand les vérifications deviendront assez fiables.
J'ai écrit la première version de ce billet avec deux modèles dans le harnais et un workflow en un coup. Depuis, le tableau de scores a dépassé les 85 exécutions, et l'image s'est bien étoffée. Quelques constats sont restés.
Le harnais teste maintenant plus d'un moteur CAO. Une partie de la raison pour laquelle le nombre d'exécutions a explosé, c'est que je benchmarke tout l'agent séparément par moteur : OpenSCAD, et les bibliothèques CAO Python CadQuery et Build123d. Une bonne partie de ces exécutions n'existent que pour casser le moteur du moment. Je les appelle les exécutions de minage d'erreurs : balancer un gros jeu de prompts difficiles à l'agent (116 dans le plus grand jeu), compter les erreurs de code, puis réinjecter ces échecs précis dans le prompt système et les docs de la skill. Un nombre d'erreurs élevé sur ces exécutions, c'est le but, pas une régression, alors j'ai arrêté de lire une exécution à 56 erreurs de code comme un mauvais résultat pour la lire comme 56 corrections en attente. Quel moteur a vraiment gagné, c'est son propre billet : OpenSCAD vs CadQuery vs Build123d (version courte : OpenSCAD, parce que les modèles actuels l'écrivent avec bien moins d'erreurs de code).
Les modèles ont des personnalités, et elles tiennent d'une exécution à l'autre. Pour ma charge de travail, le motif est constant. Gemini achète de la vitesse au chrono, mais tu la repayes dans une boucle de réparation plus chargée. Opus est le fiable : Opus 4.7 est devenu ma référence du "ça marche, point", rapide, peu cher par génération, seulement deux à quatre erreurs de code sur un jeu complet. Et GPT-5.x en raisonnement élevé est un piège à coûts pour la CAO, environ le double du coût et du temps pour une qualité que je n'arrive honnêtement pas à distinguer du medium. Le raisonnement medium comme point d'équilibre n'était pas un coup de chance de ce premier sweep, ça s'est répété sur GPT-5, 5.1 et 5.2.
Les modèles bon marché ne le sont généralement pas. J'ai passé un moment à chercher un modèle vraiment pas cher capable de porter la génération, parce que les prix affichés sont séduisants (certains coûtent quelques centimes par génération). Puis tu regardes un truc comme minimax-m3 accumuler plus de 90 erreurs de code et tourner pendant des heures, et le modèle "pas cher" finit par coûter plus une fois qu'on compte les boucles de réparation et la latence. En dessous d'environ 0,15 $ la génération, les économies s'évaporent surtout dans une boucle de correction plus chargée. Le coût réel n'est pas le coût affiché, et le taux de réussite final le cache pendant que le chrono et la facture de tokens, eux, ne le cachent pas. Pour l'instant, gemini-3.1-pro en raisonnement medium est ma base OpenSCAD : un juste milieu raisonnable.
Le tableau de bord a gagné des outils pour suivre. Une liste plate de 85 exécutions ne sert à rien, alors j'ai ajouté quelques choses. Les exécutions sont taguées par modèle, effort de raisonnement et moteur, pour filtrer le tableau jusqu'à une seule comparaison. Je peux épingler deux exécutions ou plus et les comparer côte à côte, ou en envoyer exactement deux dans un duel en tête-à-tête, génération par génération. Il y a un tableau de tiers en glisser-déposer pour quand je veux juste classer au ressenti. Et un panneau "Ce qu'on a appris" épingle les enseignements en une ligne en haut pour que je ne les perde pas entre les exécutions. Les anciennes exécutions ne sont pas supprimées, elles sont archivées et sortent de la vue par défaut, donc le tableau que je regarde chaque jour reste honnête.
Ce système n'est pas parfait, évidemment. Le jeu de données de test est petit, donc les résultats ne sont pas statistiquement blindés, mais c'est un excellent début. L'évaluation humaine c'est aussi juste moi et parfois ma copine, donc il y a un biais personnel. Enfin, l'évaluation IA est encore en cours de développement ; un R² de 0.1 montre qu'il y a un long chemin à parcourir.
Une autre mise en garde : toutes les evals historiques n'ont pas été configurées de manière identique. Au début, j'ai découvert quelques erreurs d'implémentation et certaines exécutions utilisaient une comptabilité légèrement différente, donc certains coûts ou timings sont décalés. La page /evals est toujours utile, mais traitez les entrées plus anciennes comme indicatives plutôt que précises. Je les garde pour la postérité, et j'ai depuis ajouté des tags et l'archivage, donc les exécutions périmées sortent de la vue par défaut et les comparaisons de tous les jours restent honnêtes.
Ce système d'évaluation a été essentiel pour prendre des décisions éclairées. Il remplace les conjectures par une approche basée sur les données, ce qui est indispensable quand on gère autant de variables.
Je peux maintenant tester systématiquement des hypothèses et quantifier l'impact des changements :
Le framework permet une amélioration méthodique et itérative. Pour un développeur solo qui construit un système complexe, avoir un harnais de test robuste comme celui-ci n'est pas juste un bonus, c'est indispensable.