La bonne réponse par un mauvais chemin
Une trajectoire est la liste des étapes qu’un agent a suivies pour arriver à sa réponse. La noter est utile, car un agent peut donner la bonne réponse après des appels gaspillés, ou par chance, et chaque étape se paie.
La boutique a un agent de support qui rembourse les commandes. Ses réponses semblent bonnes. Ses chemins, beaucoup moins.
À la fin de cette leçon
Remarque
Je peux noter les étapes qu’un agent a suivies par rapport à un parcours de référence.
Mots-clés
| Mot | Ce que ça veut dire |
|---|---|
| Trajectoire | les étapes suivies par un agent, dans l’ordre |
| Parcours de référence | les étapes qu’un bon essai doit suivre |
| Appel inutile | une étape qui répète une étape précédente |
| Budget d’étapes | le nombre maximal d’étapes d’un essai |
| Note de parcours | des points pour la façon d’y arriver |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Noter le chemin, pas seulement la réponse
Un contrôle de la réponse finale pose une seule question : la réponse est-elle juste ? Un contrôle du chemin demande comment l’agent y est arrivé. Il regarde la trajectoire et la compare à un parcours de référence.
Un chemin montre quatre défauts. Une étape manque. Un appel inutile en répète un autre. Une étape est dans le désordre. Ou il y a trop d’étapes pour le budget d’étapes.
Exemple travaillé : quatre essais enregistrés
| Essai | Étapes suivies | Réponse | Défauts du chemin |
|---|---|---|---|
| A | chercher, rembourser, écrire | juste | aucun |
| B | chercher, chercher, aide, rembourser, écrire | juste | une répétition, hors budget |
| C | rembourser, chercher, écrire | juste | remboursement avant la recherche |
| D | chercher, écrire | fausse | remboursement manquant |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Transformer les défauts en une note
Donnez un coût fixe à chaque défaut et retirez-le de 100. Ici, une étape manquante coûte 25, un appel inutile 10, dépasser le budget 20 et un mauvais ordre 15.
Choisissez les coûts avant de regarder les essais. La référence n’est pas le seul bon chemin : ne notez l’ordre que là où il compte.
Écrire l’aide au 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\";' '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 || 200 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"statut \" + res.status);' ' return (await res.json()).choices[0].message.content;' > 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’aide au modèle, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' ' } catch (erreur) {' ' console.log(\"Échantillon enregistré : aucun modèle n’a répondu (\" + erreur.message + \").\");' ' const liste = [].concat(echantillon);' ' const tour = messages.filter(function (m) { return m.role === \"assistant\"; }).length;' ' return liste[Math.min(tour, liste.length - 1)];' ' }' '}' '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 les essais enregistrés
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const reference = [\"chercher_commande:A17\", \"rembourser:A17\", \"envoyer_message:A17\"];' '// Essais enregistrés d’un agent de support. Chaque étape est un outil et son argument.' 'const essais = [' ' { nom: \"Essai A\", reponse: \"ok\", etapes: [\"chercher_commande:A17\", \"rembourser:A17\", \"envoyer_message:A17\"] },' ' { nom: \"Essai B\", reponse: \"ok\", etapes: [\"chercher_commande:A17\", \"chercher_commande:A17\", \"chercher_aide:remboursement\", \"rembourser:A17\", \"envoyer_message:A17\"] },' ' { nom: \"Essai C\", reponse: \"ok\", etapes: [\"rembourser:A17\", \"chercher_commande:A17\", \"envoyer_message:A17\"] },' ' { nom: \"Essai D\", reponse: \"fausse\", etapes: [\"chercher_commande:A17\", \"envoyer_message:A17\"] },' '];' 'module.exports = { reference, essais };' > parcours.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 notateur de parcours, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { reference, essais } = require(\"./parcours\");' 'const { demander } = require(\"./model\");' 'const budget = 4;' 'function inutiles(etapes) {' ' const vues = [];' ' let compte = 0;' ' etapes.forEach(function (etape) {' ' if (vues.includes(etape)) compte = compte + 1;' ' else vues.push(etape);' ' });' ' return compte;' '}' 'function manquantes(etapes) {' ' return reference.filter(function (etape) { return etapes.includes(etape) === false; });' '}' > note.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 notateur de parcours, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function dansLOrdre(etapes) {' ' let rang = 0;' ' etapes.forEach(function (etape) {' ' if (rang < reference.length && etape === reference[rang]) rang = rang + 1;' ' });' ' return rang === reference.length;' '}' 'function note(etapes) {' ' let points = 100 - 25 * manquantes(etapes).length - 10 * inutiles(etapes);' ' if (etapes.length > budget) points = points - 20;' ' if (dansLOrdre(etapes) === false) points = points - 15;' ' return Math.max(points, 0);' '}' >> note.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 notateur de parcours, partie 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const faibles = [];' 'essais.forEach(function (essai) {' ' const points = note(essai.etapes);' ' console.log(essai.nom + \" : \" + points + \" points, étapes \" + essai.etapes.length + \" sur \" + budget + \", manquantes \" + manquantes(essai.etapes).length + \", inutiles \" + inutiles(essai.etapes) + \", dans l’ordre \" + dansLOrdre(essai.etapes) + \", réponse \" + essai.reponse);' ' if (essai.reponse === \"ok\" && points < 100) faibles.push(essai.nom);' '});' 'console.log(\"Bonne réponse, parcours faible : \" + faibles.join(\", \"));' >> note.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 notateur de parcours, partie 4
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' const consigne = \"Un client demande le remboursement de la commande A17. Outils : chercher_commande, rembourser, envoyer_message, chercher_aide. Répondez uniquement par le nom de l’outil que vous appelleriez en premier.\";' ' const texte = await demander([{ role: \"user\", content: consigne }], \"chercher_commande\", 20);' ' console.log(\"Première étape en direct : \" + texte.trim());' ' console.log(\"Conforme à la référence : \" + texte.includes(\"chercher_commande\"));' '}' 'main();' >> note.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.
Noter les quatre essais
docker exec -w /home/node/project agent node note.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 le notateur affiche
| Ligne | Ce qu’elle montre |
|---|---|
| Essai A | 100 points, aucun défaut |
| Essai B | 70 points : un appel inutile et 5 étapes sur 4 |
| Essai C | 85 points : pas dans l’ordre |
| Essai D | 60 points : remboursement manquant, réponse fausse |
| Bonne réponse, parcours faible | l’essai B et l’essai C |
| Première étape en direct | Une sortie possible : chercher_commande |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
À vous
Astuce
Dans note.js, changez le budget de 4 à 5, puis notez de nouveau. L’essai B doit gagner 20 points. Dites si cela en fait un bon chemin.
Une erreur fréquente
Attention
Beaucoup croient que le parcours de référence est le seul correct et comptent toute autre séquence comme un défaut. Un agent a souvent deux bons chemins. Ne notez l’ordre que si une étape a besoin du résultat d’une autre, et admettez une seconde référence quand deux ordres marchent.