Mon agent d'IA a construit un outil de benchmark pour mes agents d'IA

Publié
11 août 2026
Mis à jour
19 août 2026
Par
Jacob Lloyd — rédigé avec l'aide de l'IA, une fois le projet terminé
Temps de lecture
13 min de lecture

En clair : J'ai demandé à mon agent d'IA de codage Hermes de construire un outil de benchmark pour mes LLM locaux. Le résultat est bench-llm : un CLI Python de 1 660 lignes qui teste vitesse, raisonnement et aptitude d'agent sur n'importe quel modèle chargé dans LM Studio. Une seule commande, sortie JSON + tableau récapitulatif dans le terminal, et c'est gratuit à télécharger.

Mon agent de codage Hermes a écrit un outil de benchmark. Il teste la vitesse, l'intelligence et l'aptitude d'agent de mes modèles locaux — les mêmes modèles sur lesquels tournent d'autres agents d'IA — et il sort du JSON plus un tableau dans le terminal. L'outil compte 1 660 lignes de Python et s'appelle bench-llm — un agent d'IA a construit un outil de benchmark pour des agents d'IA.

Mise à jour du 2026-08-19. bench-llm était la première passe. Il est devenu un benchmark multi-suites (vitesse, codage, utilisation d'outils, suivi d'instructions, raisonnement, écriture évaluée) puis Gauntlet, une réécriture complète avec un palier difficile et une interface graphique — article à venir. Le script mono-fichier ci-dessous fonctionne toujours avec LM Studio et reste le moyen le plus rapide d'obtenir un premier chiffre. Deux corrections à l'article d'origine : le tableau de résultats montre désormais de vraies exécutions des suites successeurs sur mon rig GPU (le tableau d'origine n'était pas reproductible et a disparu), et le script nécessite deux dépendances, pas une (voir Configuration).

En bref

  • Ce que c'est : un CLI Python de 1 660 lignes qui benchmark n'importe quel modèle local chargé dans LM Studio sur trois dimensions : Vitesse (TTFT, tokens/s), Capacité (codage, logique, JSON, résumé) et Aptitude d'agent (reconnaissance de tâche, respect du format, concision).
  • Ça coûte combien : rien. Téléchargement gratuit.
  • Ce qu'il vous faut : Python 3.8+, pip install openai requests, et LM Studio lancé avec des modèles chargés.
  • Ce que vous obtenez : un fichier JSON dans ~/benchmarks/, un tableau récapitulatif dans le terminal, et une image claire de quels modèles peuvent réellement faire le boulot — pas seulement lequel génère le texte le plus vite.
  • Qui l'a construit : Hermes, mon agent de codage. J'ai demandé, il a codé, on a itéré ; le tout a pris un après-midi.

Ce que vous obtenez

Une commande contre un modèle vous donne cette forme de sortie dans votre terminal (exécution d'exemple) :

$ bench-llm gemma-4-31b-it

============================================================
  bench-llm — Benchmarking: gemma-4-31b-it
  GGUF Status:   READY
  GGUF Path:     ~/.lmstudio/models/google/gemma-4-31b-it-Q4_K_M.gguf
  GGUF Size:     16.5 GB
  Arch:          gemma4
  Quant:         Q4_K_M
============================================================

  🔥 Warming up model... OK (0.23s TTFT)

  ⚡ SPEED BENCHMARKS
  ----------------------------------------
    short_50 (131 chars, 3 runs)...
      TPS:  mean=84.2 median=83.8
      TTFT: mean=0.231s median=0.228s
    medium_200 (323 chars, 3 runs)...
      TPS:  mean=85.7 median=85.2
      TTFT: mean=0.312s median=0.308s
    long_800 (769 chars, 3 runs)...
      TPS:  mean=82.1 median=81.5
      TTFT: mean=0.541s median=0.537s

  🔍 Validating speed plausibility...
    Confidence: HIGH

  🧠 ABILITY TESTS
  ----------------------------------------
    Running: Code Generation (median_of_list)... PASS
    Running: Logic Puzzle (Pet Ownership)... PASS
    Running: JSON Compliance... PASS
    Running: Instruction Following... PASS
    Running: Summarization (Key Facts)... FAIL

    Ability Score: 4/5

  🤖 AGENT FITNESS TESTS
  ----------------------------------------
    Running: Task Acknowledgment... PASS
    Running: Format Adherence... PASS
    Running: Conciseness (Output/Input Ratio)... PASS

    Agent Fitness Score: 3/3

  📄 Results saved: ~/benchmarks/gemma-4-31b-it-2026-08-11.json

================================================================================
  BENCHMARK RESULTS: gemma-4-31b-it
================================================================================

  📊 SUMMARY TABLE
  ──────────────────────────────────────────────────────────────────────
  Model ID                         gemma-4-31b-it
  GGUF Size                        16.5 GB
  Architecture                     gemma4
  Quantization                     Q4_K_M
  T/s (short, mean)                84.2
  TTFT (short, mean)               0.231s
  Ability Score                    4/5 (80.0%)
  Agent Fitness Score              3/3 (100.0%)
  Confidence                       🟢 HIGH
  ──────────────────────────────────────────────────────────────────────

Il écrit aussi un payload JSON complet dans ~/benchmarks/ avec chaque mesure brute, chaque réponse de test et un résumé structuré — pour que vous puissiez réinjecter les résultats dans votre agent et lui demander « quels modèles devraient gérer le gros du travail JSON ? ».

Ce qu'il teste

Trois dimensions, chacune choisie parce qu'elle compte pour une pile d'agents toujours allumée.

⚡ Vitesse

Trois longueurs de prompt — court (~50 caractères, « explique ce qu'est une variable »), moyen (~200 caractères, « explique la récursion ») et long (~800 caractères, « compare trois paradigmes de programmation ») — avec trois exécutions d'échauffement suivies des mesures réelles.

Ce qui est mesuré :

  • TTFT (Time To First Token) — le délai avant que le modèle ne commence à écrire. Critique pour l'UX du chat ; au-delà de 500 ms, ça paraît mou.
  • Débit (tokens/s) — la vitesse de génération une fois démarrée. Important pour les longs blocs de code et les rapports.
  • T/s de préremplissage — la vitesse de traitement du prompt d'entrée avant génération. Un coût caché mais bien réel.

Il lance aussi une vérification de plausibilité par rapport aux plafonds matériels connus. Si votre modèle de 30 Go prétend faire 200 T/s sur une 7900 XTX, bench-llm le signale — ce chiffre est probablement contaminé par du décodage spéculatif ou un cache préchauffé.

🧠 Capacité

Cinq tests triviaux pour un modèle compétent et révélateurs pour un modèle en difficulté :

  • Génération de code — Écrire median_of_list(numbers) avec les cas limites (liste vide, longueur paire, longueur impaire, ne pas muter l'entrée). La fonction est exécutée dans bench-llm contre six cas de test — ce n'est pas une correspondance de motifs sur le texte de réponse, c'est le code qui tourne vraiment.
  • Énigme logique — Une énigme de possession de quatre animaux (Alice/poisson, Bob/oiseau, Carol/chat, Dan/chien). Une regex extrait les attributions de la réponse et vérifie les quatre.
  • Conformité JSON — « Renvoie un objet JSON avec exactement ces clés. » Teste si le modèle peut produire du JSON valide et conforme au schéma à la demande — le minimum absolu pour l'appel d'outils.
  • Suivi d'instructions — Écrire les nombres de 1 à 10, marquer les pairs d'un *, les additionner. Teste l'adhérence précise au format : la réponse est triviale, le format est tout l'enjeu.
  • Résumé — Un paragraphe dense sur l'informatique quantique à base d'hélium. Vérifie si six faits techniques clés ont survécu à la compression. La plupart des modèles en perdent au moins un.

🤖 Aptitude d'agent

C'est là que bench-llm fait quelque chose que je n'ai vu dans aucun autre outil de benchmark. Il envoie au modèle une vraie tâche d'agent — chercher les lignes ERROR dans syslog, regrouper par service, produire un rapport JSON — et évalue la réponse comme le ferait un superviseur d'agents :

  • Reconnaissance de tâche — Le modèle comprend-il ce qu'on lui demande ? Peut-il esquisser une approche et identifier les blocages ? (Un modèle qui se lance directement dans l'hallucination d'entrées syslog échoue ici.)
  • Respect du format — La sortie correspond-elle au schéma JSON demandé ? Vérifie le tableau services, l'entier total_errors et la chaîne scan_period.
  • Concision — Quel est le ratio sortie/entrée ? Les modèles qui répondent à un prompt de 1 300 caractères par 20 000 caractères de bavardage sont signalés VERBOSE. Un agent qui ne sait pas être concis brûle votre fenêtre de contexte à chaque tour.

Les trois tests d'aptitude d'agent partagent le même prompt — ils évaluent différents aspects de la même réponse. Cela garde le benchmark rapide tout en mesurant les qualités qui comptent quand un modèle tourne sans supervision.

Comment il a été construit

Hermes — l'agent de codage de ma machine — a tout écrit. Je lui ai donné une spec approximative : « Il me faut un outil qui benchmark les modèles locaux dans LM Studio, teste vitesse et intelligence, et sort du JSON et un tableau. » Il est parti, revenu avec un script fonctionnel, et on a itéré.

Le processus :

  1. Première passe : uniquement les tests de vitesse — connexion à l'API compatible OpenAI de LM Studio, streaming des tokens, mesure du TTFT et des T/s.
  2. Deuxième passe : tests de capacité — codage (avec exécution réelle), énigmes logiques, conformité au schéma JSON, suivi d'instructions, résumé.
  3. Troisième passe : aptitude d'agent — la tâche syslog, évaluation de la réponse comme si le modèle était un agent de ma pile.
  4. Passes de finition : résolution des fichiers GGUF (trouver le vrai fichier modèle sur le disque, rapporter sa taille et sa quantification), validation de plausibilité de la vitesse, le tableau récapitulatif, le mode --quick, le --list pour découvrir les modèles, la commande de pré-vol --check.

Les quatre itérations se sont déroulées en un après-midi. Le script final fait 1 660 lignes. Chaque ligne a été écrite par Hermes — j'ai relu, testé sur de vrais modèles, signalé des problèmes (« ce débit ne peut pas être juste pour un modèle de 123B »), et il les a corrigés. Le validateur de plausibilité est né exactement de ce genre de boucle de rétroaction.

Les décisions de conception qui ont tenu

  • Streaming, pas de polling. bench-llm utilise le streaming compatible OpenAI pour obtenir le timing token par token. Une approche par polling brouillerait la mesure du TTFT et perdrait la granularité au niveau du token.
  • Exécution réelle du code pour le test de codage. Il ne demande pas « est-ce que ça ressemble à une fonction médiane ? » — il fait exec() du code dans un namespace neuf et lance six cas de test ; une sortie qui a l'air confiante mais ne tourne pas, échoue.
  • Extraction de réponse par regex pour les tests logique/JSON. Les benchmarks qui exigent un format précis échouent durement sur les modèles qui ajoutent « Bien sûr ! Voici votre réponse : » avant la sortie réelle. Les vérificateurs de bench-llm extraient le payload quel que soit l'emballage que le modèle met autour — testant le contenu du modèle, pas sa verbosité.
  • Nettoyage VRAM entre les benchmarks. Il exécute pkill -f llama-server et attend que LM Studio affiche zéro modèle chargé avant chaque exécution. Sans ça, le cache KV d'un modèle précédent peut contaminer la mesure TTFT du benchmark suivant.
  • Résolution des fichiers GGUF. Il remappe les ID de modèles de LM Studio vers les vrais fichiers GGUF sur disque via une correspondance floue sur le nom de l'éditeur et l'architecture. Ça donne la taille du modèle, sa quantification et si le fichier existe même — répondant à « ce modèle est-il vraiment prêt à être benchmarké ? » avant de gaspiller une exécution.

Configuration

Trois étapes :

# 1. Install the two dependencies (requests talks to LM Studio's model-metadata
#    endpoint — without it every model shows as "not found")
pip install openai requests

# 2. Make sure LM Studio is running with at least one model loaded
# (it should be listening on localhost:1234 — that's the default)

# 3. Run it
./bench-llm --list                         # see what's available
./bench-llm gemma-4-31b-it --quick         # smoke test
./bench-llm gemma-4-31b-it                 # full benchmark

Pas de fichiers de config, pas de clés API (LM Studio accepte n'importe quelle chaîne), pas de base de données. Les résultats atterrissent dans ~/benchmarks/.

Optionnel mais utile : copiez bench-llm dans votre PATH pour l'exécuter de n'importe où.

cp bench-llm ~/bin/
chmod +x ~/bin/bench-llm

Résultats réels : modèles de base sur mon rig et mon portable

Les chiffres ci-dessous proviennent des suites successeurs (même méthode de vitesse, jeu de tests plus large) et couvrent uniquement les modèles de base — pas de fine-tunes communautaires. Le « rig » est un boîtier GPU headless, 2× RTX 5090 + 2× RTX 3090 ; « APU » est le GPU intégré de ce portable. La vitesse n'est comparable qu'au sein d'un même appareil. La réserve des suites s'applique : les transcriptions couvrent plusieurs révisions, donc lisez les petits écarts comme du bruit.

Vitesse + aptitude d'agent (suite bench, rapport du 2026-08-18 — Code / Tools / Instruct / Reason sont des taux de réussite) :

ModèleAppareilGen tok/sTTFTCodeToolsInstructReason
Gemma 4 26B-A4B (QAT, Q4)rig229.0110 ms88%100%50%95%
Nemotron 3 Nano 4B (Q8)APU18.5175 ms92%70%94%95%
Gemma 4 12BAPU10.1633 ms

Palier difficile (Gauntlet, 2026-08-19 — taux de réussite sur les cas difficiles uniquement ; « — » = catégorie non exécutée pour ce modèle) :

ModèleDifficile %CodeMathToolsInstructReasonLong-ctx
DeepSeek V4-Flash (référence cloud)API95% (110/116)95%82%100%100%100%90%
Qwen3.8 27B (Q5)rig74% (23/31)74%
Qwen2.5 1.5Brig36% (80/225)32%9%59%18%16%74%
SmolVLM 256Mrig4% (8/194)0%0%6%0%9%14%

Ce que j'en retire : le MoE Gemma 4 26B (4B actifs) est le cheval de trait quotidien du rig — 229 T/s, TTFT de 110 ms, appel d'outils parfait — et sa colonne faible est le suivi d'instructions, précisément ce sur quoi s'appuie une boucle d'agent non supervisée. Le Nemotron 4B est la surprise : sur une APU de portable, il suit les instructions mieux que le 26B sur le rig, juste cinq fois plus lentement (18,5 T/s sur APU contre 229 sur le rig). Sur le palier difficile, le Qwen3.8 27B de base atteint 74 % en codage, les lignes 1.5B et 256M montrent à quoi ressemble « trop petit pour du travail d'agent », et la ligne V4-Flash cloud est le plafond que les modèles locaux poursuivent — à 0,088 $ pour toute l'exécution difficile.

Ce qui le rend différent

Il existe des tas de benchmarks LLM. La plupart sont des ensembles d'énigmes académiques (MMLU) ou des quiz optimisés pour les leaderboards. bench-llm fait trois choses qui comptent pour quelqu'un qui fait tourner réellement des modèles locaux :

  1. Il teste des qualités d'agent, pas des qualités de chatbot. Le respect du format, la reconnaissance de tâche et la concision sont ce qui fait ou défait un modèle dans une boucle d'agent non supervisée. Un modèle génial en conversation mais incapable de suivre un schéma JSON est inutile dans un workflow d'appel d'outils.
  2. Il valide ses propres mesures. Le vérificateur de plausibilité attrape les chiffres qui ne peuvent pas être justes — contamination par décodage spéculatif, caches préchauffés, bugs de mesure. Si un outil de benchmark ne peut pas vous dire quand sa propre sortie est de la camelote, vous ne pouvez rien lui confier.
  3. C'est un seul script. Pas de Docker, pas de base de données, pas de dépendances de pilotes GPU, pas de téléchargement de dataset de 50 Go. Un fichier Python, un pip install, et ça marche avec tout ce que vous avez chargé dans LM Studio à l'instant.

Pièges à éviter

  • LM Studio doit d'abord tourner. bench-llm ne lance pas LM Studio pour vous — il se connecte à localhost:1234. Si rien n'écoute, il échoue avec une erreur claire.
  • Le nettoyage VRAM est agressif. Il exécute pkill llama-server entre les benchmarks pour vider le cache KV. Si vous avez d'autres processus llama-server à garder en vie, ne lancez pas bench-llm — ou modifiez l'étape de nettoyage.
  • Le résumé est le test le plus dur. Presque tous les modèles que j'ai testés perdent au moins un fait clé. Si un modèle score 4/5 avec le résumé comme seule défaillance, c'est un résultat fort — ne le lisez pas comme une carence.
  • Les modèles de raisonnement ont un TTFT plus lent. Les modèles pensants passent du temps dans une phase de raisonnement avant de produire une sortie. bench-llm mesure le TTFT à partir du premier token de n'importe quel type — tokens de raisonnement inclus. Cela fait paraître les modèles de raisonnement plus lents qu'ils ne le semblent en pratique, car les tokens de pensée circulent pendant ce qui serait sinon du temps mort. La sortie JSON sépare le TTFT en ttft_reasoning_s et ttft_content_s pour que vous voyiez la répartition.
  • Le test de codage fait exec() de la sortie du modèle. Il tourne dans un namespace neuf avec des fonctions de test pures — pas un vrai sandbox, donc exécutez-le en tant qu'utilisateur qui n'a rien à perdre — mais si l'idée d'exécuter du code généré par LLM vous gêne, sautez les tests de capacité avec --speed-only.
  • Beaucoup de modèles, c'est long. Un benchmark complet sur un modèle prend 2 à 5 minutes selon la vitesse ; quelques dizaines, c'est une soirée. Utilisez --quick pour les comparaisons et gardez la suite complète pour vos principaux candidats.

Téléchargement

bench-llm est un script Python unique plus un README. Pas d'étape de build, pas d'assistant d'installation — décompressez et lancez.

Le zip contient :

  • bench-llm — le script de benchmark de 1 660 lignes
  • README.md — instructions condensées de configuration et d'utilisation

Les deux fichiers ont été écrits par Hermes, mon agent de codage. Sous licence MIT — utilisez-le, modifiez-le, embarquez-le dans votre propre toolchain. Dépendances : openai et requests.

À lire aussi : Ce que mes agents IA coûtent vraiment (pourquoi la vitesse locale compte), Reasonix et DeepSeek Harness (les agents de codage que ces modèles soutiennent), et la stack d'agents locaux dans laquelle ils tournent.

Téléchargements

Gratuit pour un usage personnel. Si ça vous fait gagner un après-midi, le bouton café n'est pas loin.


← Plus de IA et LLM locaux