La variance d’un benchmark LLM entre deux runs n’est pas un détail : sur le banc d’essai de l’assistant du Journal des Nuisances, le même adaptateur LoRA a obtenu 51,4 % puis 39,8 % de réussite, à trois heures d’écart, sur les mêmes 22 cas et avec le même juge. Soit ±12 points de bruit, plus que l’écart entre la plupart des candidats. La règle depuis : on ne compare que des moyennes sur 3 passages, détail affiché. Rejouée trois fois, la référence de production est d’ailleurs passée de 57 % à 54,5 % : son unique passage était un bon jour.
Le banc : 22 cas, des contrôles et un LLM-juge
L’assistant du Journal des Nuisances, une application de suivi de nuisances que j’ai co-fondée, tourne sur un modèle local. Je cherche un modèle plus léger que la référence de production, assistant-gemma4 (dérivé de gemma4:26b, servi par Ollama 0.34.2 sur pc-llm).
Le banc d’essai rejoue 22 cas pilotes contre chaque candidat. Chaque réponse passe des contrôles déterministes (D-…), puis un LLM-juge, qwen3.6:35b-a3b, d’une autre famille que les modèles jugés. Les pièges de ce juge sont détaillés dans l’article sur le time-out fetch failed du LLM-juge.
Deux mesures sortent d’un passage :
- la réussite : la part des critères de réussite remplis sur l’ensemble des cas ;
- les bloquants : les cas où un contrôle
D-…échoue, où le juge retient un échec critique (fait inventé, affirmation juridique, danger mal traité), ou que le juge n’a pas pu juger.
Un passage = les 22 cas une fois, soit près de 40 minutes (rapports de la référence horodatés 15h11, 15h50, 16h27).
Variance d’un benchmark LLM entre deux runs : les chiffres
Le bruit est apparu le 13 octobre, en rejouant un adaptateur de Gemma 4 E4B, et s’est confirmé ensuite :
| Modèle (même banc, même juge) | Réussite par passage | Moyenne | Bloquants par passage |
|---|---|---|---|
| Gemma 4 E4B affiné, lr 3e-5 (13/10) | 51,4 / 39,8 % | 45,6 % | 1,5 en moyenne |
| Ministral 3 8B, non entraîné | 61,6 / 69,6 / 56,1 % | 62,4 % | 8 / 10 / 7 |
| Ministral 3 8B + DPO, point 116 | 56,4 / 62,2 / 72,6 % | 63,7 % | 11 / 10 / 4 |
| Gemma 4 12B QAT, non entraîné (16/10) | 65,2 / 62,1 / 57,8 % | 61,7 % | 0 / 0 / 3 |
Référence assistant-gemma4 (17/10) | 53,9 / 55,4 / 54,3 % | 54,5 % | 1 / 1 / 1 |
Ministral 8B couvre 13,5 points entre son pire et son meilleur passage ; après DPO, 16,2 points. Les bloquants bougent autant : Gemma 4 12B QAT fait 0, 0, puis 3. Un passage unique à 0 aurait suffi à le déclarer « sans bloquant ».
La référence, elle, tient en 1,5 point : le bruit dépend du modèle, et on ne le connaît qu’après plusieurs passages.
Sur un banc jugé par un LLM, un écart entre deux modèles plus petit que l’écart entre deux passages du même modèle n’est pas un résultat.
C’est ce qui a tranché entre Gemma 4 12B QAT et non QAT : 62,2 % contre 61,9 %, écart dans le bruit, donc le plus léger des deux.
Pourquoi un juge à temperature: 0 n’empêche pas le bruit ?
Le juge est appelé à température nulle :
options: { temperature: 0 },
messages: [{ role: "user", content: prompt }],
Mais il ne juge pas un texte fixe. Les candidats sont servis par mlx_lm.server sur mac-train, avec un échantillonnage :
.venv/bin/python servir_socle.py --model "$1" --host 10.66.0.21 --port 8080 \
--temp 0.8 --top-p 0.95 --top-k 40 --min-p 0.05 --max-tokens 1024
Et la référence, côté Ollama, est échantillonnée elle aussi : le générateur du jeu d’entraînement le note en commentaire, « le modèle de référence étant échantillonné (température 1), un essai raté n’est pas rejoué à l’identique ».
Le bruit vient donc de la génération, pas du jugement. Chaque passage produit 22 nouvelles conversations : il suffit qu’une réponse oublie le syndic ou invente un fait pour que des critères basculent, parfois un cas entier.
Mettre les candidats à température 0 ? Le script de service répond : « mêmes réglages que le banc : ce qui est servi est ce qui a été mesuré ». Un banc à température nulle mesurerait un modèle que personne n’utilise.
La référence rejouée : 57 % sur un passage, 54,5 % sur trois
La référence n’avait qu’un passage, le 10 octobre : 57 %, 0 bloquant. Rejouée trois fois le 17 octobre, sur la même machine et avec le même juge : 54,5 % (53,9 / 55,4 / 54,3), 1 bloquant à chaque passage, premier mot en 8,8 s, réponse complète en 14,2 s. Le passage unique du 10/10 était au-dessus de sa moyenne.
Or les seuils d’acceptation des candidats avaient été posés à partir de ce passage :
| Critère | Seuil |
|---|---|
| Cas bloquants | 0 (moyenne de 3 passages) |
| Réussite | ≥ 57 % (« la référence ») |
| Mémoire en service | ≤ ~8 Go |
| Premier mot | quelques secondes |
| Licence | Apache 2.0 ou équivalente |
Ironie du sort, la référence ne passe plus ses propres seuils : 54,5 % de réussite, 1 bloquant. J’ai laissé le seuil de 57 % tel quel, puisque tous les candidats retenus le dépassent : Gemma 4 12B fait 61,9 %, 7 points de mieux que la référence. En revanche, aucun ne tient les deux seuils à la fois : Gemma 4 12B affiné par LoRA fait 0 bloquant sur trois passages, mais 55,8 % de réussite, et Gemma 4 12B non affiné, le meilleur compromis, en est à 0,7 bloquant.
Lessons learned
- Un banc LLM se mesure en moyenne de plusieurs passages. Le même adaptateur a fait 51,4 % puis 39,8 % : un passage seul ne départage rien.
- Un LLM-juge à température nulle ne rend pas le banc déterministe. Le candidat est échantillonné, donc le juge lit une réponse différente à chaque passage.
- On mesure le modèle avec ses réglages de production. Un candidat à température 0 serait plus stable au banc, mais ce ne serait pas le modèle servi.
- La référence doit être rejouée autant que les candidats. Un seuil tiré d’un passage unique (57 %) peut dépasser la moyenne réelle de la référence (54,5 %).
- Le détail des passages compte autant que la moyenne. Des bloquants à 0, 0 puis 3 ne racontent pas la même histoire qu’un 1 constant.