Traiter un prompt comme du code livré
Un prompt change ce que fait une fonction : il demande donc le soin qu’on donne au code. Cela veut dire un fichier, une version, une relecture, un déploiement progressif et un retour en arrière. C’est important, car un mot changé peut améliorer un cas et en casser un autre, sans qu’un test le montre.
Une équipe modifie un prompt dans un tableau de bord le vendredi après-midi. Le lundi, les plaintes arrivent. Personne ne sait ce qui a changé, ni comment revenir.
À la fin de cette leçon
Remarque
Je peux versionner, relire et déployer un prompt comme du code.
Mots-clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Version de prompt | un état nommé et enregistré d’un prompt | v2 |
| Cas d’évaluation | une entrée avec une règle de réussite | |
| Régression | un cas qui réussissait avant et échoue maintenant | |
| Déploiement progressif | servir un changement à une part des utilisateurs | |
| Seau | un nombre de 0 à 99 propre à un utilisateur |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Un prompt vit dans un fichier versionné
Rangez chaque prompt dans un fichier du dépôt, avec un nom et une version. Un changement devient alors un commit, une relecture et une différence. Le code désigne un prompt par son nom et sa version, jamais par une chaîne collée.
La version est écrite dans chaque trace du journal. Quand une réponse est mauvaise, on peut dire quel prompt l’a produite.
Jugez un changement sur des résultats enregistrés
Lancez les mêmes cas d’évaluation sur l’ancien et le nouveau prompt. Comparez le taux de réussite et listez les régressions : les cas qui réussissaient et échouent maintenant. Deux prompts au même taux peuvent réussir sur des cas différents.
Marquez certains cas comme obligatoires, par exemple un refus qui protège un utilisateur. Un changement qui en rate un ne part pas, quel que soit le taux.
Exemple travaillé : v1 contre v2
| Cas | v1 | v2 | Remarque |
|---|---|---|---|
| c1 (obligatoire) | réussi | réussi | Conservé |
| c2 (obligatoire) | réussi | réussi | Conservé |
| c3 | échec | réussi | Corrigé |
| c4 | réussi | réussi | Conservé |
| c5 | réussi | échec | Régression : une personne doit regarder |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Déployez par un seau déterministe
Ne basculez pas tous les utilisateurs d’un coup. Transformez un identifiant d’utilisateur en seau de 0 à 99 avec une fonction fixe. Un utilisateur reçoit le nouveau prompt quand son seau est sous le pourcentage du déploiement.
Le même utilisateur reçoit toujours la même version, et monter le pourcentage ne fait qu’ajouter des utilisateurs. N’utilisez jamais un nombre aléatoire par requête : une personne verrait les deux versions.
Gardez un chemin de retour
Gardez l’ancienne version dans le dépôt et le pourcentage dans un seul réglage. Pour revenir en arrière, mettez le pourcentage à zéro. Pas de déploiement, pas de modification, pas de dispute.
Montez le pourcentage par paliers et surveillez les mêmes mesures à chaque palier : réussite sur des échantillons réels, coût et plaintes.
Une erreur fréquente
Attention
Beaucoup pensent qu’un meilleur taux de réussite garantit un changement sûr. Il peut cacher un échange : un cas corrigé, un autre cassé. Lisez la liste des régressions et vérifiez les cas obligatoires, pas seulement le taux.
É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 la livraison du prompt, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const fs = require(\"fs\");' 'const { demander } = require(\"./model\");' '// Un prompt vit dans un fichier avec une version : un changement est une différence.' 'const fichier = { nom: \"resume\", version: \"v2\", texte: \"Résumez le ticket en une phrase. Nommez le produit.\" };' 'fs.writeFileSync(\"prompt-resume.json\", JSON.stringify(fichier, null, 1));' '// Résultats d’évaluation enregistrés : chaque cas a-t-il réussi ? Inventés pour la leçon.' 'const ancien = { c1: true, c2: true, c3: false, c4: true, c5: true };' 'const nouveau = { c1: true, c2: true, c3: true, c4: true, c5: false };' 'const OBLIGATOIRES = [\"c1\", \"c2\"]; // des cas qui ne doivent jamais échouer' > prompts.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 la livraison du prompt, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function taux(passage) {' ' const noms = Object.keys(passage);' ' const reussis = noms.filter(function (n) { return passage[n]; });' ' return Math.floor(reussis.length * 100 / noms.length);' '}' 'function raisons(a, b) {' ' const sortie = [];' ' if (taux(b) < taux(a)) sortie.push(\"taux plus bas\");' ' OBLIGATOIRES.forEach(function (n) { if (b[n] === false) sortie.push(\"obligatoire en échec : \" + n); });' ' return sortie;' '}' 'const glisses = Object.keys(ancien).filter(function (n) { return ancien[n] && nouveau[n] === false; });' 'console.log(\"ancien\", taux(ancien), \"nouveau\", taux(nouveau));' 'console.log(\"peut partir :\", raisons(ancien, nouveau).length === 0, \"régressions :\", glisses.join(\",\"));' >> prompts.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 la livraison du prompt, partie 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function seau(utilisateur) {' ' let h = 0;' ' for (const c of utilisateur) h = (h * 31 + c.charCodeAt(0)) % 1000003;' ' return h % 100;' '}' 'const deploiement = { prompt: \"v2\", secours: \"v1\", pourcentage: 20 };' 'function version(u) { return seau(u) < deploiement.pourcentage ? deploiement.prompt : deploiement.secours; }' '[\"lea\", \"ines\", \"camille\", \"theo\", \"manon\", \"hugo\"].forEach(function (u) { console.log(u, seau(u), version(u)); });' 'deploiement.pourcentage = 0; // le retour en arrière tient en un nombre' 'console.log(\"après retour :\", version(\"lea\"), version(\"ines\"));' >> prompts.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 la livraison du prompt, partie 4
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' const texte = fichier.texte + \" Ticket : le téléphone Orbit ne charge plus depuis lundi.\";' ' const echantillon = \"Le téléphone Orbit ne charge plus depuis lundi.\";' ' console.log(\"Appel réel avec v2 :\", await demander([{ role: \"user\", content: texte }], echantillon, 40));' '}' 'main();' >> prompts.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.
Juger et déployer un prompt
docker exec -w /home/node/project agent node prompts.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 qui est enregistré, ce qui est réel
Les résultats d’évaluation sont enregistrés et inventés. Une vraie équipe lance ses propres cas et range les résultats à côté de la version du prompt. La fonction du seau et le réglage du déploiement sont la vraie technique.
Le Run écrit prompt-resume.json. Ouvrez-le et lisez la version.
Une sortie possible
| Ligne | Ce qu’elle montre |
|---|---|
| ancien 80 nouveau 80 | Le taux de réussite est le même |
| peut partir : true régressions : c5 | La règle l’autorise, et une personne lit quand même c5 |
| lea 16 v2 et les autres utilisateurs | Chaque utilisateur a un seau et une version fixes |
| après retour : v1 v1 | Un pourcentage de zéro renvoie tout le monde à v1 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.