Noter sans un second modèle
Noter une réponse par des règles, c’est la contrôler avec du code ordinaire : est-elle valide, l’étiquette est-elle juste, le nombre est-il dans la plage. C’est utile, car une règle est rapide, gratuite et donne toujours la même réponse.
Le trieur de la boutique répond désormais en JSON, avec une étiquette, une urgence et une phrase pour le client. Chaque partie se contrôle par une règle.
À la fin de cette leçon
Remarque
Je peux noter une réponse avec des règles qui n’ont pas besoin d’un modèle.
Mots-clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Règle | un contrôle écrit en code qu’une réponse réussit ou rate | |
| Égalité exacte | la valeur doit être égale à l’attendue | facturation |
| JSON valide | la réponse se décode dans le format demandé | |
| Dans la plage | un nombre se situe entre deux bornes | |
| Note | le nombre de règles qu’une réponse réussit | |
| Phrase interdite | des mots qu’une réponse ne doit jamais contenir |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Quatre sortes de règles suffisent presque toujours
La plupart des contrôles tiennent en quatre sortes. Valide : la réponse est le JSON demandé. Égalité exacte : un champ vaut la valeur attendue. Dans la plage : un nombre reste entre deux bornes. Contient : une phrase est là, ou ne doit pas y être.
Chaque règle tient en quelques lignes. Aucune n’a besoin d’un modèle : un lancement ne coûte rien.
Exemple travaillé : une règle par partie
| Partie de la réponse | Règle | Un exemple qui échoue |
|---|---|---|
| Toute la réponse | C’est un objet JSON valide | Bien sûr, c’est un message de livraison |
| etiquette | Égalité exacte avec le cas | facturation alors que livraison était voulue |
| urgence | Un entier de 1 à 3 | 7 |
| reponse | Au plus 120 caractères, aucune phrase interdite | Votre remboursement a été accepté |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une note par cas montre où ça casse
Donnez un point à la réponse pour chaque règle qu’elle réussit. Ne vous arrêtez pas au premier échec : les points montrent quelle règle a cassé. Un cas réussit seulement quand toutes les règles tiennent.
Si la réponse n’est pas valide, aucune règle suivante ne peut tourner : sa note est 0.
Écrire l’aide 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\";' '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 du 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 règles, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const interdits = [\"remboursement a été\", \"garanti\"];' 'function noter(texte, voulue) {' ' const sortie = { valide: false, etiquette: false, plage: false, reponse: false };' ' let donnees = null;' ' try { donnees = JSON.parse(texte); } catch (erreur) { return sortie; }' ' if (donnees === null || Array.isArray(donnees) || typeof donnees === \"string\" || typeof donnees === \"number\" || typeof donnees === \"boolean\") return sortie;' ' sortie.valide = true;' ' sortie.etiquette = donnees.etiquette === voulue;' > score.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 règles, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' ' sortie.plage = Number.isInteger(donnees.urgence) && donnees.urgence >= 1 && donnees.urgence <= 3;' ' const dit = typeof donnees.reponse === \"string\" ? donnees.reponse : \"\";' ' const bas = dit.toLowerCase();' ' const exclu = interdits.some(function (phrase) { return bas.includes(phrase); });' ' sortie.reponse = dit.length > 0 && dit.length <= 120 && exclu === false;' ' return sortie;' '}' 'function points(sortie) {' ' return (sortie.valide ? 1 : 0) + (sortie.etiquette ? 1 : 0) + (sortie.plage ? 1 : 0) + (sortie.reponse ? 1 : 0);' '}' 'module.exports = { noter, points };' >> score.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 contrôle, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander } = require(\"./model\");' 'const { noter, points } = require(\"./score\");' 'function reponse(etiquette, urgence, texte) {' ' return JSON.stringify({ etiquette: etiquette, urgence: urgence, reponse: texte });' '}' 'const enregistres = [' ' { id: 1, voulue: \"facturation\", texte: reponse(\"facturation\", 2, \"Désolé pour le double débit, nous vérifions.\") },' ' { id: 2, voulue: \"livraison\", texte: reponse(\"facturation\", 2, \"Nous regardons cela.\") },' ' { id: 3, voulue: \"autre\", texte: \"Bien sûr, c’est un message de livraison.\" },' > controle2.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 contrôle, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' ' { id: 8, voulue: \"livraison\", texte: reponse(\"livraison\", 7, \"Désolé d’apprendre cela.\") },' ' { id: 10, voulue: \"inconnu\", texte: reponse(\"inconnu\", 1, \"Votre remboursement a été accepté.\") },' '];' 'function oui(valeur) { return valeur ? \"oui\" : \"non\"; }' 'function afficher(nom, sortie) {' ' console.log(nom + \" : \" + points(sortie) + \" sur 4 (JSON valide \" + oui(sortie.valide) + \", étiquette \" + oui(sortie.etiquette) + \", plage \" + oui(sortie.plage) + \", réponse \" + oui(sortie.reponse) + \")\");' '}' 'for (const un of enregistres) afficher(\"Cas enregistré \" + un.id, noter(un.texte, un.voulue));' >> controle2.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 contrôle, partie 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' const echantillon = reponse(\"facturation\", 2, \"Désolé, nous vérifions votre commande.\");' ' const consigne = \"Triez ce message de boutique. Répondez uniquement par du JSON à trois clés : etiquette (facturation, livraison, autre ou inconnu), urgence (un nombre entier de 1 à 3) et reponse (une phrase polie de moins de 100 caractères).\n\nMessage : Débité deux fois pour une seule commande\";' ' const texte = await demander([{ role: \"user\", content: consigne }], echantillon, 120);' ' console.log(\"Réponse réelle : \" + texte);' ' afficher(\"Cas réel 1\", noter(texte, \"facturation\"));' '}' 'main();' >> controle2.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 cinq réponses et une réelle
docker exec -w /home/node/project agent node controle2.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.
Une sortie possible
| Ligne | Ce qu’elle montre |
|---|---|
| Cas enregistré 1 | 4 sur 4, toutes les règles tiennent |
| Cas enregistré 2 | 3 sur 4, l’étiquette est fausse |
| Cas enregistré 3 | 0 sur 4, des mots et pas du JSON |
| Cas enregistré 8 | 3 sur 4, l’urgence 7 sort de la plage |
| Cas enregistré 10 | 3 sur 4, la phrase interdite |
| Cas réel 1 | Souvent 3 ou 4 sur 4, et cela peut changer à chaque lancement |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
À vous
Astuce
Dans score.js, ajoutez une troisième phrase interdite, désolé pour le double débit, puis relancez. Le cas enregistré 1 doit perdre son dernier point.
Une erreur fréquente
Attention
Beaucoup croient qu’une note pleine par les règles signale une bonne réponse. Les règles ne contrôlent que la forme et les faits. Une réponse peut être valide, porter la bonne étiquette et rester impolie ou inutile. Gardez les règles pour ce que le code peut trancher.