Aller au contenu
Blog
Technique17 octobre 2026

31 personas, un orchestrateur

Faire produire un plan d'exécution JSON valide à un modèle local de 8 milliards de paramètres, puis l'exécuter sur une flotte de 31 personas spécialisés : ce qui casse, ce qu'on blinde, et pourquoi le plus dur est d'empêcher le planificateur d'être créatif.

Le décor : un studio virtuel qui tourne en local

Depuis quelques mois, je fais tourner un studio virtuel : une interface Godot, un daemon local, et un registre de 32 personas, soit 31 exécutants plus cap, l'orchestrateur. Chaque exécutant a un rôle étroit : correction de texte, traduction, fact-check, rédaction, code review, QA logicielle. Quatorze d'entre eux tournent sur des fine-tunes maison spécialisés ; les autres se rabattent sur un qwen3:8b générique coiffé d'un préfixe de role-play.

Détail qui compte : ce fallback reçoit une directive /no_think forcée en tête de prompt. Un qwen3 en mode réflexion consomme tout son budget de génération à réfléchir et rend des réponses vides. Je l'ai appris en benchmark, pas dans une doc.

Le principe d'usage : je dépose un brief en langage naturel, cap produit un plan d'exécution, et le plan tourne en parallèle sur la flotte. Sur le papier, c'est élégant. En pratique, tout se joue dans les garde-fous autour du planificateur.

Le contrat : un DAG JSON strict, ou rien

cap doit sortir un objet JSON conforme à un schéma maison, brief-plan-v1 : un identifiant de plan daté, un titre, et une liste de steps formant un graphe orienté sans cycle. Chaque step porte un id, un persona_slot pris obligatoirement dans le registre, ses inputs et ses dépendances. additionalProperties à false partout : un champ inventé en trop et le plan est rejeté.

Côté client, je fais le strict minimum avant dispatch : retrait des fences markdown (un 8B adore emballer son JSON dans des ```), parsing, détection de cycle dans les dépendances, normalisation des champs. La validation stricte du schéma, elle, est déportée au daemon via un endpoint dédié. Et une règle explicite dans le prompt : cap n'a pas le droit de se désigner lui-même comme exécutant d'un step. Il planifie, il ne produit pas.

La boucle de survie : retry avec l'erreur en main

Un petit modèle rate son JSON. Souvent. La réponse n'est pas d'espérer mieux, c'est de boucler : plan invalide égale nouvelle tentative avec l'erreur exacte réinjectée dans le prompt, trois essais maximum, puis abandon franc plutôt qu'exécution d'un plan douteux.

  • Une step en échec a droit à 2 retries, puis elle est marquée failed ; la synthèse finale reçoit l'ordre de signaler l'output manquant, pas de l'inventer.
  • Les steps dont les dépendances sont satisfaites partent en un seul appel batch parallèle au daemon, pas en série.
  • Le timeout silencieux d'Ollama est traité comme un échec : zéro token généré après plus de 500 secondes, on coupe au lieu d'attendre indéfiniment.
brigit@7sailgdscript
const PLAN_RETRY_MAX := 3
const STEP_RETRY_MAX := 2

# Dans la construction du prompt de cap :
if not error_feedback.is_empty():
	prompt += "[RETRY] Ton JSON précédent avait cette erreur: %s\nCorrige et renvoie un JSON valide.\n\n" % error_feedback

La leçon inattendue : la matrice persona vers tâche

Ma première version du prompt de cap listait les personas avec leurs rôles et lui laissait le choix. Erreur. Un 8B fait des substitutions créatives : la testeuse QA qui rédige un post marketing parce que le sujet est un jeu, le game designer réquisitionné pour du SEO. Techniquement plausible, systématiquement faux.

Le prompt a donc muté en une matrice explicite tâche vers persona, avec des restrictions écrites noir sur blanc. En voici un extrait réel, légèrement raccourci :

brigit@7sailtranscription
MATRICE PERSONA → TÂCHE (respecte strictement, ne dévie pas) :
• Communication / posts social / LinkedIn → noa
• Fact-check / vérification factuelle → serge
• Traduction FR↔EN → tara
• Correction orthographe / grammaire FR → cora (elle ne produit pas de contenu nouveau)

RESTRICTIONS CRITIQUES :
• tina est une testeuse QA LOGICIEL — pas de community management ni de rédaction marketing
• Si tu hésites entre plusieurs personas, choisis celui spécifiquement listé ci-dessus
  pour la tâche ; ne fais pas de substitution créative
Le plus dur n'est pas d'apprendre à un petit modèle à planifier. C'est de lui retirer le droit d'improviser.

L'autre leçon : le minimalisme s'écrit noir sur blanc

Un 8B qui planifie veut faire un beau plan. Sur un brief du type « corrige cette phrase », il ajoute spontanément un step de synthèse, un step de validation, parfois un résumé final : trois appels de modèle là où un seul suffit. Chaque step parasite coûte du temps, ajoute un point de défaillance, et dilue l'output utile.

La parade tient en une règle du prompt, formulée sans nuance :

  • Le code va dans le même sens : quand un plan n'a qu'un step et qu'il a réussi, l'orchestrateur rend son output directement, sans repasser par un appel de synthèse LLM.
brigit@7sailtranscription
MINIMALISME (critique) : pour une tâche unitaire simple (corriger une phrase,
traduire un texte court, répondre à une question factuelle, résumer un document),
produis UN SEUL step. N'ajoute JAMAIS de step 'synthèse' ou 'résumé final' ou
'validation' après — l'orchestrateur s'occupe de la synthèse automatiquement.
Plan à 1 step = réponse correcte pour 80% des briefs.

Ce que je retiens

Orchestrer des petits modèles locaux, c'est 20% d'architecture et 80% de garde-fous en code autour d'un planificateur qu'on ne peut pas croire sur parole. Le contrat JSON strict, le retry qui rend l'erreur au modèle, la matrice qui interdit la substitution, la règle du step unique : rien de tout ça n'est de l'intelligence, tout est du cadrage.

Et c'est peut-être la vraie inversion mentale de l'exercice : la créativité du modèle, précieuse chez les 31 exécutants, est exactement ce qu'il faut éteindre chez celui qui distribue le travail. Un bon orchestrateur est ennuyeux. Le mien a mis quelques semaines de prompts rallongés à l'accepter.