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
| Mot | Ce que ça veut dire |
|---|---|
| Outil | une fonction que l’agent peut demander au harnais d’exécuter |
| Description | les mots qui disent au modèle quand utiliser un outil |
| Outil étroit | un outil qui fait une seule chose |
| Paramètre | une entrée nommée d’un outil |
| Ambiguïté | deux outils qui semblent convenir à une même tâche |
| Erreur d’outil | le 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 ressemble | Correction |
|---|---|---|
| Nom vague | `faire`, `aide` | Un verbe et un nom |
| Description courte | `Fait des choses` | Dire ce qu’il lit ou modifie |
| Pas de limite | Aucun « ne pas utiliser » | Ajouter ce pour quoi il n’est pas fait |
| Trop de paramètres | Cinq ou plus | Le 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
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 vérificateur d’outils, partie 1
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
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
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
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
docker exec -w /home/node/project agent node outils2.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 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
| Ligne | Ce qu’elle montre |
|---|---|
| lire_fichier : aucun défaut | Un outil étroit, avec une limite |
| chercher_texte : sans-limite | Il ne dit jamais quand ne pas l’utiliser |
| faire : nom-vague, description-courte, sans-limite, trop-de-params | Quatre 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.