Plus facile à lire avec un fond crème, une teinte, plus de contraste ou un texte plus grand ? Choisissez vos couleurs et votre texte, une fois pour toutes les pages.

Leçon gratuite

Concevoir des outils pour agents LLM

Après cette leçon: Je peux écrire un outil qu’un modèle utilise correctement, avec un nom clair, une limite dite et une erreur utile.

Leçon de 60 min7 commandesLab agent de code IA : utiliser opencode pour expliquer et corriger du code, et vérifier son travail

Un outil est le mode d’emploi du modèle

Concevoir un outil pour un agent, c’est écrire son nom, sa description, ses paramètres et ses erreurs pour qu’un modèle l’utilise correctement. Ces mots sont le seul mode d’emploi du modèle.

Un outil nommé faire avec cinq options floues se devine. Un outil nommé lire_fichier avec un seul chemin s’utilise bien.

À la fin de cette leçon

Remarque

Je peux écrire un outil qu’un modèle utilise correctement, avec un nom clair, une limite dite et une erreur utile.

Mots clés

MotCe que ça veut dire
Outilune fonction que l’agent peut demander au harnais d’exécuter
Descriptionles mots qui disent au modèle quand utiliser un outil
Outil étroitun outil qui fait une seule chose
Paramètreune entrée nommée d’un outil
Ambiguïtédeux outils qui semblent convenir à une même tâche
Erreur d’outille texte qu’un outil renvoie quand il échoue

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Les outils étroits valent mieux que les larges

Un outil étroit fait une seule chose et prend peu de paramètres. Un outil large, comme tout_executer(options), force le modèle à inventer un mini-langage, et il se trompe souvent.

Donnez à chaque tâche son outil : lire_fichier, ecrire_fichier, lister_fichiers. Gardez quatre paramètres ou moins. Un outil qui en demande davantage est souvent deux outils.

Noms et descriptions disent quand ne pas l’utiliser

Un nom est un verbe et un nom commun : chercher_texte, pas aide. Une description dit ce que fait l’outil, et aussi quand ne pas l’utiliser.

Cette seconde phrase départage deux outils qui se ressemblent. Sans elle, le modèle choisit au hasard entre lire_fichier et chercher_texte, et vous le découvrez dans une trace.

Défauts à vérifier

DéfautÀ quoi il ressembleCorrection
Nom vague`faire`, `aide`Un verbe et un nom
Description courte`Fait des choses`Dire ce qu’il lit ou modifie
Pas de limiteAucun « ne pas utiliser »Ajouter ce pour quoi il n’est pas fait
Trop de paramètresCinq ou plusLe couper en plusieurs outils

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Écrire les erreurs pour le modèle

Une erreur d’outil est la prochaine entrée que le modèle lit. Écrivez-la donc pour lui : ce qui s’est passé, puis quoi faire ensuite.

Erreur : aucun fichier à src/app.pyy. Appelez lister_fichiers, puis réessayez. dit au modèle comment s’en sortir. Un ENOENT seul ne le dit pas. Pour un refus, dites de ne pas réessayer, sinon le modèle recommence sans fin.

Une erreur courante

Attention

Beaucoup écrivent les mots d’un outil pour eux-mêmes, et les gardent courts. Le modèle n’a rien d’autre. Écrivez la description comme pour un collègue qui n’a jamais vu le code.

Écrire l’assistant du modèle, partie 1

Commande
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

Commande
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 vérificateur d’outils, partie 1

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander } = require(\"./model\");' 'const VAGUES = [\"faire\", \"executer\", \"gerer\", \"outil\", \"aide\", \"traiter\", \"util\"];' 'const outils = [' '  { nom: \"lire_fichier\", description: \"Lit le texte du fichier indiqué par son chemin. Ne pas utiliser pour un dossier.\", params: [\"chemin\"] },' '  { nom: \"chercher_texte\", description: \"Trouve les lignes qui contiennent un mot dans tous les fichiers du projet\", params: [\"mot\"] },' '  { nom: \"faire\", description: \"Fait des choses\", params: [\"a\", \"b\", \"c\", \"d\", \"e\"] },' '];' > outils2.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 vérificateur d’outils, partie 2

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function defauts(outil) {' '  const trouves = [];' '  if (VAGUES.includes(outil.nom)) trouves.push(\"nom-vague\");' '  if (outil.description.split(\" \").length < 8) trouves.push(\"description-courte\");' '  if (outil.description.toLowerCase().includes(\"ne pas utiliser\") === false) trouves.push(\"sans-limite\");' '  if (outil.params.length > 4) trouves.push(\"trop-de-params\");' '  return trouves;' '}' >> outils2.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 vérificateur d’outils, partie 3

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function texteErreur(e) {' '  if (e.code === \"introuvable\") return \"Erreur : aucun fichier à \" + e.chemin + \". Appelez lister_fichiers, puis réessayez.\";' '  if (e.code === \"trop_gros\") return \"Erreur : \" + e.chemin + \" compte \" + e.taille + \" lignes et la limite est \" + e.limite + \". Demandez une plage de lignes.\";' '  return \"Erreur : \" + e.code + \". Ne réessayez pas.\";' '}' >> outils2.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 vérificateur d’outils, partie 4

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  for (const o of outils) console.log(o.nom + \" : \" + (defauts(o).join(\", \") || \"aucun défaut\"));' '  console.log(texteErreur({ code: \"introuvable\", chemin: \"src/app.pyy\" }));' '  console.log(texteErreur({ code: \"trop_gros\", chemin: \"data.csv\", taille: 9000, limite: 500 }));' '  const liste = outils.slice(0, 2).map(function (o) { return o.nom + \" : \" + o.description; }).join(\" | \");' '  const tache = \"Montrez-moi les premières lignes de src/app.py. Répondez par un seul nom d’outil.\";' '  const reponse = await demander([{ role: \"user\", content: \"Outils : \" + liste + \" | \" + tache }], \"lire_fichier\", 10);' '  console.log(\"le modèle a choisi : \" + reponse.texte);' '}' 'main();' >> outils2.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 vérificateur d’outils

Commande
docker exec -w /home/node/project agent node outils2.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.

Ce que montre l’appel au modèle

Le modèle du labo s’utilise en texte simple, sans fonction d’appel d’outils. Le Run colle donc les descriptions des outils dans le prompt et demande un nom d’outil. Cela suffit à montrer que les mots sont le mode d’emploi.

Les vérifications et les deux erreurs n’ont besoin d’aucun modèle.

Une sortie possible

LigneCe qu’elle montre
lire_fichier : aucun défautUn outil étroit, avec une limite
chercher_texte : sans-limiteIl ne dit jamais quand ne pas l’utiliser
faire : nom-vague, description-courte, sans-limite, trop-de-paramsQuatre défauts dans un seul outil
Erreur : aucun fichier à src/app.pyy. Appelez lister_fichiers, puis réessayez.Une erreur avec une suite
Erreur : data.csv compte 9000 lignes et la limite est 500. Demandez une plage de lignes.Une erreur qui dit comment demander moins
le modèle a choisi : ...Sans doute lire_fichier. Les mots changent à chaque exécution

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

À propos de ce labo et de sa source: Lab agent de code IA : utiliser opencode pour expliquer et corriger du code, et vérifier son travail

Vous enseignez à une classe ? Proposez ce module à vos étudiants avec un guide de l'enseignant, des devoirs corrigés et un laboratoire pour chaque étudiant.