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

Une chaîne du texte aux fiches

Après cette leçon: Je peux construire une petite chaîne qui mène du texte brouillon à des fiches contrôlées.

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

Une pile de messages

Une chaîne du texte aux fiches transforme des messages brouillons en fiches contrôlées qu’un programme peut ranger. C’est utile, car chaque étape vue jusqu’ici est petite et qu’un vrai travail les demande toutes ensemble.

Le service des moyens d’un lycée reçoit une pile de demandes de fournitures en texte libre. Quelqu’un les veut sous forme de lignes : l’article, la quantité et l’urgence. Personne ne veut en taper trois cents.

À la fin de cette leçon

Remarque

Je peux construire une petite chaîne qui mène du texte brouillon à des fiches contrôlées.

Mots-clés

MotCe que ça veut dire
Chaînedes étapes qui se passent chacune leur résultat
Lotun groupe de textes traités ensemble
Rejeterécarter un texte, avec une raison
Taux de rejetla part des textes qui ont été rejetés
Enregistrerécrire les fiches contrôlées quelque part
Données personnellesdes faits qui identifient une personne

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

Quatre étapes, l’une après l’autre

Chaque message passe par les mêmes étapes. Extraire : demander les champs au modèle. Valider : contrôler la fiche avec le schéma. Réparer : en cas d’échec, redemander une fois avec la faute. Enregistrer : écrire la bonne fiche.

Un message qui échoue encore est rejeté. Il n’est ni enregistré ni perdu : vous gardez le texte et la raison.

Compter les rejets et dire pourquoi

Un rejet est une information. Gardez le texte et la raison, et calculez le taux de rejet. S’il est élevé, la consigne ou le schéma demandent du travail.

Soyez prudent avec les données personnelles. N’envoyez au modèle que le texte dont il a besoin. Écrivez dans le journal la raison, pas le texte d’un message qui parle d’une personne.

Écrire l’aide 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\";' '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

Commande
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 chaîne, partie 1

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const fs = require(\"fs\");' 'const { demander } = require(\"./model\");' '' 'const textes = [' '  \"Merci d’envoyer 12 crayons à la salle d’arts, ce n’est pas urgent.\",' '  \"Il nous faut 3 boîtes de craie aujourd’hui, le plus vite possible.\",' '  \"Quelqu’un peut-il me dire où est la salle des professeurs ?\",' '];' '// Échantillons enregistrés, utilisés seulement si aucun modèle ne répond : une réponse propre, une' '// réponse qui demande une réparation, et un message sans commande, qui est rejeté.' 'const echantillons = [' '  JSON.stringify({ article: \"crayons\", quantite: 12, urgent: false }),' '  [\"Voici : \" + JSON.stringify({ article: \"craie\", quantite: \"trois\", urgent: true }), JSON.stringify({ article: \"craie\", quantite: 3, urgent: true })],' '  [JSON.stringify({ article: null, quantite: null, urgent: false }), \"Je ne trouve aucune commande dans ce message.\"],' '];' > chaine6.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 chaîne, partie 2

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function extraireJson(texte) {' '  const debut = texte.indexOf(\"{\");' '  const fin = texte.lastIndexOf(\"}\");' '  if (debut === -1 || fin < debut) return null;' '  try { return JSON.parse(texte.slice(debut, fin + 1)); } catch (erreur) { return null; }' '}' '' '// Le premier problème, ou un texte vide quand la fiche est bonne.' 'function problemeDe(fiche) {' '  if (fiche === null) return \"pas du JSON\";' '  if ((typeof fiche.article === \"string\") === false || fiche.article === \"\") return \"article invalide\";' '  if (Number.isInteger(fiche.quantite) === false || fiche.quantite < 1 || fiche.quantite > 20) return \"quantite invalide\";' '  if ((typeof fiche.urgent === \"boolean\") === false) return \"urgent invalide\";' '  return \"\";' '}' >> chaine6.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 chaîne, partie 3

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const DEMANDE = \"Extrais l’article, la quantité (de 1 à 20) et l’urgence (true ou false) de ce message. Réponds uniquement par le JSON.\n\nMessage : \";' '' 'async function traiter(texte, echantillon) {' '  const messages = [{ role: \"user\", content: DEMANDE + texte }];' '  let reponse = await demander(messages, echantillon, 80);' '  let probleme = problemeDe(extraireJson(reponse));' '  if (probleme.length > 0) {' '    // Une réparation : renvoyer la mauvaise réponse et le problème, puis redemander une fois.' '    messages.push({ role: \"assistant\", content: reponse });' '    messages.push({ role: \"user\", content: \"Corrigez ce problème et répondez uniquement par le JSON : \" + probleme });' '    reponse = await demander(messages, echantillon, 80);' '    probleme = problemeDe(extraireJson(reponse));' '  }' '  return { fiche: extraireJson(reponse), probleme: probleme };' '}' >> chaine6.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 chaîne, partie 4

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  const gardees = [];' '  const rejetees = [];' '  for (let rang = 0; rang < textes.length; rang = rang + 1) {' '    const resultat = await traiter(textes[rang], echantillons[rang]);' '    if (resultat.probleme.length > 0) rejetees.push({ texte: textes[rang], pourquoi: resultat.probleme });' '    else gardees.push({ article: resultat.fiche.article, quantite: resultat.fiche.quantite, urgent: resultat.fiche.urgent });' '  }' '  fs.writeFileSync(\"fiches.json\", JSON.stringify(gardees, null, 2));' '  console.log(\"Enregistré : \" + gardees.length + \" fiches dans fiches.json\");' '  for (const une of rejetees) console.log(\"Rejeté : \" + une.texte + \" (\" + une.pourquoi + \")\");' '  console.log(\"Taux de rejet : \" + Math.floor(rejetees.length * 100 / textes.length) + \" pour cent\");' '}' 'main();' >> chaine6.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.

La lancer sur trois messages

Commande
docker exec -w /home/node/project agent node chaine6.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.

Une sortie possible

LigneCe qu’elle peut montrer
EnregistréEnregistré : 2 fiches dans fiches.json, par exemple
RejetéLe message sur la salle des professeurs, avec une raison comme article invalide
Taux de rejetTaux de rejet : 33 pour cent si un message sur trois est rejeté

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

Une erreur fréquente

Attention

Beaucoup pensent qu’un message rejeté montre que la chaîne a échoué. Rejeter est juste quand un message ne contient aucune commande. Ce qui échoue, c’est de rejeter sans compter ni dire pourquoi.

À 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.