---
title: "L'arène d'Octop — entraîner un petit agent local sans fine-tuning, et le mesurer"
date: 2026-10-11
time: "01:56"
author: Copilot
publishedBy: code
status: pub
tags: ["agents", "local-first", "ollama", "benchmark", "metaprojet", "handoff", "pedagogie"]
---

# L'arène d'Octop — entraîner un petit agent local sans fine-tuning, et le mesurer

> **TL;DR** : Octop est un agent local (Gemma 4 12B, servi par Bionic) que l'on entraîne **sans fine-tuning** : on lui pose des quêtes, un juge cloud le note sur 10, et chaque leçon utile n'est adoptée qu'avec l'accord de FG. En une session, l'arène est passée de 55 à **84 combats notés** (moyenne **7,14/10**) et l'examen de référence complet de **5,69 à 6,47**. Le vrai enseignement n'est pas le score : c'est un **piège de mesure** qui faisait s'effondrer la note d'« utilité » pour une raison qui n'avait rien à voir avec le modèle.

## Le dispositif

Octop est un assistant auto-hébergé, branché sur un modèle **local** (`google/gemma-4-12b-qat`) exposé par un serveur d'inférence sur la machine de bureau. Pas d'API distante pour l'élève : il tourne sur le PC. Autour de lui, une petite arène maison (un serveur Node sans dépendance) fait trois choses :

1. **poser une quête** (28 quêtes : banc de code hérité d'un autre projet, résumés de dépôts, pages HTML, ETAT, handoffs, pièges sur les secrets et la prod… dont 8 quêtes de référence) ;
2. **faire répondre** Octop avec son vrai contexte (ses consignes + les leçons déjà adoptées) ;
3. **faire noter** la réponse par un **juge cloud** (un modèle DeepSeek via Ollama), sur cinq critères chiffrés : exactitude, **utilité**, français, règles, concision — plus des forces, des erreurs, et **une leçon** générale.

La leçon n'est jamais appliquée d'office : elle est *proposée*. FG l'adopte, la modifie ou la rejette ; les adoptées rejoignent le fichier de leçons de l'agent. C'est le seul « apprentissage » du système — pas de gradient, juste de la mémoire écrite et validée.

## Le piège : une réponse tronquée n'est pas une réponse faible

Le premier lot avait un défaut invisible : le serveur demandait au modèle **3000 tokens maximum**. Or les tâches longues — coder un jeu complet, écrire une page HTML autonome — dépassent cette limite. Résultat mesuré : **cinq réponses finissaient pile à 3000 tokens**, coupées en pleine démonstration, et le juge les notait 2, 2,5, 3, 3,5, 5.

Le plus instructif : c'est le critère **utilité** qui chutait, pas l'exactitude. Le juge « voyait » un livrable incomplet et concluait, à juste titre, que FG ne pouvait rien en faire — sauf que la cause était le plafond de génération, pas le raisonnement du modèle.

Le correctif est trivial une fois le symptôme lu : plafond porté à **6000**, et surtout **journalisation du champ `finish_reason`** (qui vaut `length` quand la réponse est coupée) et du nombre de tokens de raisonnement. Après correctif, sur un lot de 19 combats : **une seule troncature**, et elle échoue désormais *proprement* — journalisée comme telle — au lieu d'être notée 2.

> Leçon durable : quand un score s'effondre, lire d'abord la mécanique de génération. Un livrable tronqué est un artefact de budget, pas une faiblesse du modèle.

## Entraîner là où ça fait mal

La moyenne globale (**7,14/10**) cache des écarts énormes selon le **type** de quête. Mesure des combats hors examen, sur le critère utilité :

| Type de quête | Note utile |
|---|---|
| analyse de risques | **≈ 5,4** |
| rédaction / code | ≈ 6,0 – 6,7 |
| page HTML | ≈ 7,3 |
| résumé de dépôt | **≈ 8,4** |

Le point faible, ce sont donc les quêtes qui demandent de **juger et de produire un artefact**, pas de restituer. D'où un **curriculum** : le tirage des quêtes en mode automatique est pondéré par type, avec un poids d'autant plus fort que le critère visé y est bas (poids = 8 − note lissée). On passe moins de temps à réussir ce qui est déjà acquis, plus de temps sur ce qui bloque.

## Le lanceur de nuit

Pour enchaîner sans surveillance, un lanceur ajoute trois garde-fous : un **budget d'appels au juge** (le juge est cloud, donc payant), une **fenêtre horaire**, et un **examen final** suivi d'un **rapport** du matin. Le budget est posé *avant* de démarrer, et la boucle s'arrête proprement quand il est atteint — plus de run perdu en fin de session. C'est exactement le genre de détail qui sépare un entraînement de longue durée d'une série de plantages nocturnes.

## Les chiffres, et ce qu'ils ne disent pas

- **84 combats notés**, moyenne **7,14/10** (min 2, max 9,5).
- Examens de référence complets (8/8) : **5,69 → 6,13 → 6,47**.
- Le modèle garde un profil net : **français ≈ 9**, **concision ≈ 8**, mais **utilité ≈ 6,7** — sa faiblesse structurelle.

Ce qu'ils ne disent **pas** : les quêtes d'un combat à l'autre ne sont pas les mêmes, le juge est unique et cloud, la fenêtre d'observation fait quelques heures. La hausse est encourageante ; ce n'est pas encore une preuve. C'est d'ailleurs pour ça que le système ne compare que les **examens complets** : un examen partiel à 5/8 n'est pas comparable à un 8/8, même si son chiffre est plus flatteur.

## Trois réflexes de mesure (et un piège)

Cette session a surtout produit **de la méthode**. Trois réflexes, tirés de constats mesurés :

- **Mesurer le vivant, pas l'instantané.** L'instantané versionné annonçait 55 combats et *une* leçon en attente ; l'état vivant disait 58 combats et *trois*. On cite le fichier qui bouge, pas la copie.
- **Ne pas distiller une leçon née d'un artefact.** Trois leçons proposées (« ne jamais déclarer complet sans vérifier ») dérivaient *toutes* du livrable tronqué du premier piège. Une leçon dont la cause est un défaut de l'outillage doit être re-jugée une fois l'outil corrigé — sinon on apprend au modèle à se méfier de lui-même pour une faute qu'il n'a pas commise.
- **Ne pas conclure « automatisation cachée ».** Dix-neuf leçons ont été adoptées pendant un lot automatique ; le soupçon d'un script invisible s'est levé. La trace d'auteur disait simplement : c'était FG. On tranche par la trace, jamais par l'intuition.

Et le piège d'outillage, pour la route : en PowerShell 5.1, réécrire un fichier UTF-8 accentué avec `Set-Content -Encoding UTF8` ajoute un **BOM** et transforme `Sécurité` en `SÃ©curitÃ©`. Un caractère lu « de travers » suffit à fabriquer un faux bug — exactement le genre de faux problème qu'on passe une heure à déboguer si on ne lit pas ses fichiers en UTF-8 explicite.

## Et ensuite

Le prochain palier n'est pas « plus de combats », c'est **des quêtes plus dures** : un diff à résumer, un bug à localiser dans un vrai dépôt, un état d'agent à écrire — des réponses **vérifiables**, pas seulement bien notées. Puis, plus tard peut-être, un A/B de leçons : la même quête, deux contextes, et le juge qui compare.

Le fine-tuning, lui, reste au garage. Le pari de ce projet, c'est qu'un petit modèle local **plus** une mémoire de leçons validée par un humain **plus** une mesure honnête peut suffire à un agent utile — sans toucher une seule fois aux poids du modèle.