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

Journaliser sobrement une application d’IA

Après cette leçon: Je peux journaliser assez pour déboguer une requête, et pas plus qu’il ne faut.

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

Un journal qui aide et ne fuit pas

Un journal est une trace que l’application écrit sur ce qu’elle a fait. Quand une réponse est lente ou fausse, c’est là qu’on regarde.

Un journal négligent copie chaque message et chaque courriel dans un fichier que beaucoup de gens peuvent lire. Le but est d’en garder assez pour réparer, et pas plus.

À la fin de cette leçon

Remarque

Je peux journaliser assez pour déboguer une requête, et pas plus qu’il ne faut.

Mots clés

MotCe que ça veut direExemple
Fiche de journalune ligne qu’un programme écrit sur un événement
Identifiant de requêteune étiquette qui relie toutes les fiches d’une requêter-001
Empreinteun court code calculé à partir d’une valeur, qu’on ne peut pas défaire
Selun mot secret mêlé à la valeur avant l’empreinte
Tronquercouper une valeur à quelques caractères

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

Gardez ce qu’il faut pour déboguer

Demandez-vous à quoi servira le journal. Pour réparer une réponse lente, il faut l’identifiant de requête, l’heure, le modèle et la longueur. Il ne faut pas les mots.

Une fiche sans les mots peut toujours se relier à sa requête : l’identifiant de requête est la clé.

Si un texte doit rester, on le tronque : on le coupe à quelques caractères.

Exemple détaillé : une fiche, avant et après

ChampFiche bruteFiche sûrePourquoi
id_requeter-001r-001Il relie le journal à la requête
courriel[email protected]7e9c70d3Une empreinte salée compte encore les utilisateurs
messageRemboursez ma commande svp26 (sa longueur)Les mots restent hors du journal
ms420420Utile pour trouver les réponses lentes

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

Une empreinte cache la valeur, pas la personne

Une empreinte transforme un courriel en court code. Le même courriel donne toujours le même code, donc on peut encore compter les utilisateurs. Personne ne peut défaire le code en le lisant.

Un sel rend le code plus difficile à deviner. Décidez aussi qui peut lire le journal. Un journal que personne n’a besoin de lire ne devrait pas exister.

Une erreur courante

Attention

Beaucoup pensent qu’une empreinte est anonyme. Ce n’est pas vrai. Qui possède une liste de courriels peut tous les hacher et comparer les codes. Une empreinte est un pseudonyme, et le journal reste fait de données personnelles. Utilisez un sel, et gardez-le loin du journal.

É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 journal sûr, partie 1

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander } = require(\"./model\");' 'const crypto = require(\"crypto\");' 'const brutes = [' '  { id_requete: \"r-001\", courriel: \"[email protected]\", message: \"Remboursez ma commande svp\", modele: \"lab\", ms: 420 },' '  { id_requete: \"r-002\", courriel: \"[email protected]\", message: \"Rappelez-moi au 0600000123\", modele: \"lab\", ms: 380 },' '  { id_requete: \"r-003\", courriel: \"[email protected]\", message: \"Où est mon colis\", modele: \"lab\", ms: 910 },' '];' > journalsur.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 journal sûr, partie 2

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function empreinte8(v) {' '  return crypto.createHash(\"sha256\").update(\"sel-labo:\" + v).digest(\"hex\").slice(0, 8);' '}' 'function fiche(r) {' '  return { id_requete: r.id_requete, utilisateur: empreinte8(r.courriel), longueur: r.message.length, modele: r.modele, ms: r.ms };' '}' 'function contientCourriel(r) {' '  return Object.values(r).some(function (v) { return typeof v === \"string\" && v.includes(\"@\"); });' '}' >> journalsur.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 journal sûr, partie 3

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  const sures = brutes.map(fiche);' '  brutes.forEach(function (r, i) {' '    console.log(r.id_requete + \" brute avec courriel : \" + contientCourriel(r) + \" | sûre avec courriel : \" + contientCourriel(sures[i]));' '    console.log(\"  \" + JSON.stringify(sures[i]));' '  });' '  console.log(\"r-001 et r-003 même utilisateur : \" + (sures[0].utilisateur === sures[2].utilisateur));' '  console.log(\"r-001 et r-002 même utilisateur : \" + (sures[0].utilisateur === sures[1].utilisateur));' '  const q = \"En une courte phrase, pourquoi journaliser la longueur d’un message et non le message ?\";' '  const echantillon = \"Une longueur aide à déboguer les réponses lentes et ne dit rien sur la personne.\";' '  const r = await demander([{ role: \"user\", content: q }], echantillon, 60);' '  console.log(\"le modèle dit : \" + r.texte);' '}' 'main();' >> journalsur.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 journal sûr

Commande
docker exec -w /home/node/project agent node journalsur.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 le Run affiche

LigneCe qu’elle montre
r-001 brute avec courriel : true | sûre avec courriel : falseLa fiche sûre n’a pas de courriel
{"id_requete":"r-001","utilisateur":"7e9c70d3",...}L’empreinte et la longueur, rien d’autre
r-001 et r-003 même utilisateur : trueLa même personne se retrouve
r-001 et r-002 même utilisateur : falseDeux personnes restent distinctes
le modèle dit : ...Une phrase. 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.