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

Valider du JSON avec un schéma

Après cette leçon: Je peux contrôler une réponse avec un schéma.

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

Du JSON valide, des données fausses

Valider du JSON avec un schéma, c’est comparer chaque champ d’une fiche à une liste de règles. Ces règles donnent le type, disent si le champ est requis et listent les valeurs permises. C’est utile, car un JSON qui s’analyse bien peut contenir un nombre de pages égal à « beaucoup ».

Une appli de bibliothèque demande une fiche de livre à un modèle. La réponse s’analyse sans erreur. Puis un nombre de pages arrive sous la forme du texte « 180 » et la page des totaux affiche n’importe quoi.

À la fin de cette leçon

Remarque

Je peux contrôler une réponse avec un schéma.

Mots-clés

MotCe que ça veut direExemple
Schémaune liste de contrôle des champs d’une fiche
Typele genre de valeur qu’un champ contiententier
Requisun champ qui doit être présent
Valeurs permisesles seules valeurs qu’un champ peut prendreroman, histoire, science
Fauteune façon d’enfreindre une règle
Ficheun objet qui regroupe des champs

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

Un schéma est une liste de contrôle

L’analyse dit que le texte est du JSON. Elle ne dit pas que les données sont justes. Pour cela, il faut un schéma : une règle par champ.

Une règle donne le type du champ, dit s’il est requis et indique parfois ses valeurs permises. Une norme appelée JSON Schema écrit ces règles dans un format fixe. Ici, vous écrivez votre propre liste de contrôle, en code.

Exemple travaillé : un schéma pour un livre

ChampTypeRequisValeurs permises
titretexteouin’importe quel texte
pagesentierouin’importe quel nombre entier
genretexteouiroman, histoire, science
notenombrenonn’importe quel nombre

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

Relever toutes les fautes, pas seulement la première

Un contrôle qui s’arrête à la première faute en dit peu. Relevez toutes les fautes dans une liste, un court texte chacune, par exemple pages: mauvais type.

La liste sert à deux choses. Elle décide d’accepter ou non la fiche, et la leçon suivante la renvoie au modèle comme retour d’information.

É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 le contrôle du schéma, partie 1

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander } = require(\"./model\");' '' '// Un schéma est une liste de contrôle : une règle par champ.' 'const schema = [' '  { nom: \"titre\", type: \"texte\", requis: true },' '  { nom: \"pages\", type: \"entier\", requis: true },' '  { nom: \"genre\", type: \"texte\", requis: true, permis: [\"roman\", \"histoire\", \"science\"] },' '  { nom: \"note\", type: \"nombre\", requis: false },' '];' > 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 contrôle du schéma, partie 2

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function estUneFiche(x) {' '  if (x === null) return false;' '  if (Array.isArray(x)) return false;' '  return typeof x === \"object\";' '}' '' 'function typeCorrect(valeur, type) {' '  if (type === \"texte\") return typeof valeur === \"string\";' '  if (type === \"entier\") return Number.isInteger(valeur);' '  if (type === \"nombre\") return typeof valeur === \"number\";' '  if (type === \"booleen\") return typeof valeur === \"boolean\";' '  return false;' '}' >> 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 contrôle du schéma, partie 3

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' '// Relever toutes les fautes, pas seulement la première.' 'function fautes(fiche, schema) {' '  if (estUneFiche(fiche) === false) return [\"pas un objet\"];' '  const trouvees = [];' '  for (const regle of schema) {' '    if (Object.prototype.hasOwnProperty.call(fiche, regle.nom) === false) {' '      if (regle.requis) trouvees.push(regle.nom + \": absent\");' '      continue;' '    }' '    const valeur = fiche[regle.nom];' '    if (typeCorrect(valeur, regle.type) === false) trouvees.push(regle.nom + \": mauvais type\");' '    else if (regle.permis && regle.permis.includes(valeur) === false) trouvees.push(regle.nom + \": valeur interdite\");' '  }' '  return trouvees;' '}' >> 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 contrôle du schéma, partie 4

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; }' '}' >> 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 contrôle du schéma, partie 5

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const fiches = [' '  { titre: \"Atlas des rivières\", pages: 240, genre: \"science\" },' '  { titre: \"Tables des marées\", pages: \"180\", genre: \"histoire\" },' '  { titre: \"Lettres de lune\", pages: 96, genre: \"poésie\", note: 4.5 },' '  { pages: 310, genre: \"roman\", note: \"bien\" },' '];' 'fiches.forEach(function (fiche, rang) {' '  const trouvees = fautes(fiche, schema);' '  console.log(\"Fiche \" + (rang + 1) + \" :\", trouvees.length === 0 ? \"ok\" : trouvees.join(\", \"));' '});' >> 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 contrôle du schéma, partie 6

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  const messages = [{ role: \"user\", content: \"Invente un livre pour une bibliothèque universitaire. Réponds par un objet JSON avec les clés titre (texte), pages (un nombre entier) et genre (roman, histoire ou science). Réponds uniquement par le JSON.\" }];' '  // Échantillon enregistré, utilisé seulement si aucun modèle ne répond. Il casse deux règles exprès.' '  const echantillon = JSON.stringify({ titre: \"Le Port tranquille\", pages: \"210\", genre: \"policier\" });' '  const reponse = await demander(messages, echantillon, 100);' '  const fiche = extraireJson(reponse);' '  const trouvees = fautes(fiche, schema);' '  console.log(\"Fiche du modèle :\", JSON.stringify(fiche));' '  console.log(\"Fautes :\", trouvees.length === 0 ? \"aucune\" : trouvees.join(\", \"));' '}' '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.

Lancer le contrôle

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

Une sortie possible

LigneCe qu’elle montre
Fiche 1ok
Fiche 2pages: mauvais type
Fiche 3genre: valeur interdite
Fiche 4titre: absent, note: mauvais type
Fiche du modèle et FautesChangent à chaque exécution : une fiche du modèle, puis ses fautes ou aucune

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

Une erreur fréquente

Attention

Beaucoup pensent que « 180 » et 180 sont la même chose. Ils se ressemblent, mais un programme ne peut ni additionner ni comparer un texte comme un nombre. Contrôlez le type, pas l’apparence de la valeur.

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