Plus d’agents, ce n’est pas plus d’intelligence
Un système multi-agents est un programme où un appel au modèle confie du travail à d’autres appels, chacun avec son propre contexte. Cela compte, car chaque agent ajouté se paie en jetons, en temps et en nouvelles pannes possibles.
On présente souvent les équipes d’agents comme l’étape suivante. Parfois c’est vrai. Souvent, un seul agent bien outillé fait le travail pour moins cher.
À la fin de cette leçon
Remarque
Je peux dire quand plusieurs agents valent leur coût, et le montrer avec des estimations de jetons.
Mots-clés
| Mot | Ce que ça veut dire |
|---|---|
| Fenêtre de contexte | le maximum de texte qu’un agent tient en une fois |
| Orchestrateur | l’agent qui découpe le travail et rassemble les réponses |
| Exécutant | un agent qui fait une partie et en rend compte |
| Texte commun | les consignes que chaque agent doit relire |
| Travail couplé | des étapes où chacune a besoin du résultat de la précédente |
| Parallèle | des parties qui peuvent se faire en même temps |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Chaque agent relit le texte commun
Un agent seul lit ses consignes une fois. Une équipe, non. L’orchestrateur les lit, et chaque exécutant aussi, car il a son propre contexte et ne voit pas celui des autres.
Une équipe coûte donc le texte commun une fois par agent, plus une consigne et un résultat par partie. La partie elle-même n’est lue qu’une fois, par l’exécutant qui la traite.
Exemple travaillé : trois rapports
| Qui | Lit | Jetons |
|---|---|---|
| Un seul agent | Commun 1500 + trois rapports 5500 + réponse 400 | 7400 |
| Orchestrateur | Commun 1500 + trois consignes 600 + final 300 | 2400 |
| Trois exécutants | Commun 1500 chacun + un rapport + un résultat | 10600 |
| L’équipe en tout | Orchestrateur et exécutants ensemble | 13000 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Quand un découpage est rentable
Découpez quand un agent seul ne peut pas tenir le travail. Découpez quand les parties sont indépendantes et que la vitesse compte. Découpez quand une partie exige un contexte propre, pour qu’un texte précédent ne l’induise pas en erreur.
Ne découpez pas un travail couplé. Si l’étape deux a besoin du résultat exact de l’étape un, un second agent n’ajoute qu’un résumé qui perd de l’information.
Une erreur fréquente
Attention
Beaucoup découpent une tâche parce qu’elle contient plusieurs noms. Comptez les dépendances, pas les noms. Un travail qui partage un seul enregistrement et le modifie dans l’ordre est l’affaire d’un seul agent.
Écrire l’assistant du modèle, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// Les jetons d’une réponse, ou null si elle n’en donne pas.' 'function compter(donnees, nom) {' ' return donnees.usage && typeof donnees.usage[nom] === \"number\" ? donnees.usage[nom] : null;' '}' > model.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire l’assistant du modèle, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function demander(messages, echantillon, max) {' ' try {' ' const res = await fetch(base + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"statut \" + res.status);' ' const d = await res.json();' ' return { texte: d.choices[0].message.content, entree: compter(d, \"prompt_tokens\"), sortie: compter(d, \"completion_tokens\"), enregistre: false };' ' } catch (erreur) {' ' console.log(\"Échantillon enregistré : aucun modèle n’a répondu (\" + erreur.message + \").\");' ' return { texte: echantillon, entree: null, sortie: null, enregistre: true };' ' }' '}' 'module.exports = { demander };' >> model.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le script de coût, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander } = require(\"./model\");' 'const FENETRE = 8000; // jetons qu’un agent peut contenir' 'const NOTE = 200; // une consigne ou un résultat' 'const CAS = [' ' { nom: \"trois rapports\", commun: 1500, parties: [1800, 2000, 1700], couple: false },' ' { nom: \"un long rapport\", commun: 1500, parties: [900], couple: false },' ' { nom: \"modifier un fichier\", commun: 1500, parties: [1200, 1000], couple: true },' ' { nom: \"dix documents\", commun: 1500, parties: Array(10).fill(900), couple: false },' '];' > scinder.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le script de coût, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function somme(liste) { return liste.reduce(function (a, b) { return a + b; }, 0); }' '// Un seul agent lit le texte commun une fois, puis toutes les parties, puis répond.' 'function seul(c) { return c.commun + somme(c.parties) + 400; }' '// Une équipe : le chef relit le texte commun, et chaque exécutant aussi.' 'function equipe(c) {' ' const chef = c.commun + NOTE * c.parties.length + 300;' ' const execs = c.parties.map(function (p) { return c.commun + p + NOTE; });' ' return chef + somme(execs);' '}' >> scinder.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le script de coût, partie 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function choisir(c) {' ' if (c.couple || c.parties.length < 2) return \"un seul\";' ' if (seul(c) > FENETRE) return \"plusieurs\";' ' return equipe(c) <= 2 * seul(c) ? \"plusieurs\" : \"un seul\";' '}' 'async function main() {' ' for (const c of CAS) {' ' const x = Math.round((equipe(c) * 10) / seul(c)) / 10;' ' console.log(c.nom + \" : un seul \" + seul(c) + \", équipe \" + equipe(c) + \" (x\" + x + \"), choix \" + choisir(c));' ' }' ' const q = [{ role: \"user\", content: \"En une phrase : citez un travail qu’il ne faut pas partager entre plusieurs agents.\" }];' ' const r = await demander(q, \"Modifier un fichier par étapes, car chaque étape a besoin de la précédente.\", 40);' ' console.log(\"Modèle : \" + r.texte.trim());' '}' 'main();' >> scinder.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Lancer le script de coût
docker exec -w /home/node/project agent node scinder.jsAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Ce sont des estimations
Le Run n’appelle pas d’équipe. Il fait les calculs sur quatre cas enregistrés, car une vraie équipe épuiserait d’un coup le quota du labo. Les tailles en jetons sont inventées, et un vrai système mesure les siennes.
Le seul appel en direct demande simplement une phrase.
Une sortie possible
| Ligne | Ce qu’elle montre |
|---|---|
| trois rapports : un seul 7400, équipe 13000 (x1.8), choix plusieurs | Cela tient dans une fenêtre, mais l’équipe reste sous le double |
| un long rapport : … choix un seul | Une seule partie ne se partage pas |
| modifier un fichier : … choix un seul | Un travail couplé reste à un agent |
| dix documents : un seul 10900, équipe 29800 (x2.7), choix plusieurs | Un agent ne peut pas tout tenir, donc on paie |
| Modèle : … | Une phrase qui change à chaque exécution |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.