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

Vérifier le SQL d’un modèle en le lançant

Après cette leçon: Je peux vérifier la requête d’un modèle en la lançant sur des données à la réponse connue.

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

Lancer la requête sur une réponse connue

Vérifier du SQL en le lançant, c’est essayer la requête d’un modèle sur un petit jeu de données. Vous en avez calculé la réponse à la main. La relecture attrape certains défauts ; le lancement attrape ceux qui ont l’air justes sur la page.

Le module 43 vérifie la requête d’une personne par ses lignes. Cette leçon vérifie les candidates d’un modèle, et se demande si les données séparent le juste du faux.

À la fin de cette leçon

Remarque

Je peux vérifier la requête d’un modèle en la lançant sur des données à la réponse connue.

Mots clés

MotCe que ça veut dire
Réponse connuele résultat calculé à la main
Candidateune requête proposée comme réponse
Lignes du résultatce qu’une requête renvoie
Jeu d’essaide petites données fixes gardées pour vérifier
Distinguerdonner des résultats différents au juste et au faux

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

Comparer les lignes à une réponse connue

Calculez la réponse à la main sur un petit jeu d’essai. Neuf prêts, cela se compte sur papier. Lancez ensuite chaque candidate et comparez ses lignes aux vôtres.

Il y a trois verdicts. Réussi veut dire que les lignes concordent. Mauvaises lignes veut dire qu’elle a tourné et donné autre chose. Erreur veut dire que SQLite l’a refusée.

Exemple détaillé : réponses connues de la médiathèque

QuestionCalculé à la mainRéponse connue
Membres différents au mois 3Prêts 1 à 4 : Amina, Amina, Bruno, Chloé3
Livres encore dehorsLes prêts 3, 5, 6, 8 et 9 ont rendu = 05
Titres empruntés par le membre 2Prêts 3, 6 et 8 : livres 3, 4 et 5Carte de la pluie, Moteurs tranquilles, Sept Bouilloires

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

L’ordre compte seulement s’il est demandé

Une liste de titres dans n’importe quel ordre répond à « quels titres ». Comparez des copies triées des deux listes : un autre ordre passe quand même.

Si la question dit « le plus récent d’abord », l’ordre fait partie de la réponse. Comparez alors les lignes exactement comme elles viennent.

Les données doivent séparer le juste du faux

Demandez combien de prêts du mois 5 sont encore dehors. Les deux prêts du mois 5 sont dehors : une requête sans filtre sur rendu donne aussi 2.

Ce jeu d’essai ne sépare pas les deux requêtes. Ajoutez une ligne qui les sépare, comme un prêt rendu au mois 5, et vérifiez de nouveau.

Une erreur courante

Attention

Beaucoup pensent qu’une candidate qui réussit sur des données d’essai est juste. Elle est juste pour ces données-là. Vérifiez que le jeu d’essai donne une autre réponse à la requête fausse probable, puis faites confiance à la réussite.

É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;' '}' '// Une réponse peut entourer la requête d’un bloc délimité : on garde l’intérieur.' 'function sqlDe(texte) {' '  const morceaux = texte.split(String.fromCharCode(96).repeat(3));' '  const dedans = (morceaux.length > 2 ? morceaux[1] : texte).trim();' '  return dedans.toLowerCase().startsWith(\"sql\") ? dedans.slice(3).trim() : dedans;' '}' > 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, sqlDe };' >> 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 base de la médiathèque, partie 1

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { DatabaseSync } = require(\"node:sqlite\");' '// Une médiathèque inventée : six livres, quatre membres, neuf prêts.' 'const LIVRES = [[1, \"Le Phare des oranges\", 2019], [2, \"Port de verre\", 2021], [3, \"Carte de la pluie\", 2015],' '  [4, \"Moteurs tranquilles\", 2023], [5, \"Sept Bouilloires\", 2018], [6, \"Au nord de midi\", 2022]];' 'const MEMBRES = [[1, \"Amina\"], [2, \"Bruno\"], [3, \"Chloé\"], [4, \"Driss\"]];' '// id, livre_id, membre_id, mois, rendu (1 rendu, 0 encore dehors)' 'const PRETS = [[1, 1, 1, 3, 1], [2, 2, 1, 3, 1], [3, 3, 2, 3, 0], [4, 1, 3, 3, 1], [5, 1, 1, 4, 0],' '  [6, 4, 2, 4, 0], [7, 2, 3, 4, 1], [8, 5, 2, 5, 0], [9, 2, 4, 5, 0]];' > mediatheque.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 base de la médiathèque, partie 2

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function remplir(db, table, lignes) {' '  const marques = lignes[0].map(function () { return \"?\"; }).join(\", \");' '  const inserer = db.prepare(\"INSERT INTO \" + table + \" VALUES (\" + marques + \")\");' '  lignes.forEach(function (ligne) { inserer.run(...ligne); });' '}' 'function ouvrir(fichier) {' '  const db = new DatabaseSync(fichier || \":memory:\");' '  db.exec(\"CREATE TABLE livres (id INTEGER PRIMARY KEY, titre TEXT, annee INTEGER)\");' '  db.exec(\"CREATE TABLE membres (id INTEGER PRIMARY KEY, nom TEXT)\");' '  db.exec(\"CREATE TABLE prets (id INTEGER PRIMARY KEY, livre_id INTEGER REFERENCES livres(id), \"' '    + \"membre_id INTEGER REFERENCES membres(id), mois INTEGER, rendu INTEGER)\");' '  remplir(db, \"livres\", LIVRES);' '  remplir(db, \"membres\", MEMBRES);' '  remplir(db, \"prets\", PRETS);' '  return db;' '}' 'module.exports = { ouvrir };' >> mediatheque.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 vérification, partie 1

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander, sqlDe } = require(\"./model\");' 'const { ouvrir } = require(\"./mediatheque\");' 'const db = ouvrir();' 'function lignesDe(sql) {' '  try {' '    return db.prepare(sql).all().map(function (r) { return JSON.stringify(Object.values(r)); }).sort();' '  } catch (erreur) { return null; }' '}' 'function verifier(sql, attendu) {' '  const obtenu = lignesDe(sql);' '  if (obtenu === null) return \"erreur\";' '  const voulu = attendu.map(function (r) { return JSON.stringify(r); }).sort();' '  return obtenu.join(\"|\") === voulu.join(\"|\") ? \"réussi\" : \"mauvaises lignes \" + obtenu.join(\" \");' '}' > verifier.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 vérification, partie 2

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const P = \"SELECT COUNT(*) FROM prets WHERE \";' 'const T = \"SELECT l.titre FROM prets p JOIN livres l ON \";' 'const cas = [' '  { attendu: [[3]], sql: [\"SELECT COUNT(membre_id) FROM prets WHERE mois = 3\",' '    \"SELECT COUNT(DISTINCT membre_id) FROM prets WHERE mois = 3\",' '    \"SELECT COUNT(DISTINCT membre) FROM prets WHERE mois = 3\"] },' '  { attendu: [[5]], sql: [\"SELECT COUNT(*) FROM prets\", P + \"rendu = 0\", P + \"rendu = 1\"] },' '  { attendu: [[\"Carte de la pluie\"], [\"Moteurs tranquilles\"], [\"Sept Bouilloires\"]],' '    sql: [T + \"p.id = l.id WHERE p.membre_id = 2\", T + \"p.livre_id = l.id WHERE p.membre_id = 2\",' '      T + \"p.livre_id = l.id WHERE p.membre_id = 2 ORDER BY l.titre DESC\"] },' '  { attendu: [[2]], sql: [P + \"mois = 5 AND rendu = 0\", P + \"mois = 5\"] },' '];' >> verifier.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 vérification, partie 3

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  cas.forEach(function (c, i) {' '    c.sql.forEach(function (sql, j) { console.log((i + 1) + \"abc\"[j] + \" : \" + verifier(sql, c.attendu)); });' '  });' '  db.exec(\"UPDATE prets SET rendu = 1 WHERE id = 8\");' '  console.log(\"une fois le prêt 8 rendu, la réponse à 4 vaut 1 :\");' '  cas[3].sql.forEach(function (sql, j) { console.log(\"4\" + \"ab\"[j] + \" : \" + verifier(sql, [[1]])); });' '  db.exec(\"UPDATE prets SET rendu = 0 WHERE id = 8\");' '  await direct();' '}' >> verifier.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 vérification, partie 4

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function direct() {' '  const q = \"prets(id, livre_id, membre_id, mois, rendu)\nQuestion : Combien de membres différents ont emprunté un livre au mois 3 ?\";' '  const echantillon = \"SELECT COUNT(DISTINCT membre_id) FROM prets WHERE mois = 3;\";' '  const reponse = await demander([{ role: \"system\", content: \"Répondez par une seule requête SELECT pour SQLite, et rien d’autre.\" },' '    { role: \"user\", content: q }], echantillon, 120);' '  const sql = sqlDe(reponse.texte);' '  console.log(\"le modèle a écrit : \" + sql);' '  console.log(\"  vérifiée sur des données connues : \" + verifier(sql, [[3]]));' '}' 'main();' >> verifier.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 chaque candidate sur des données connues

Commande
docker exec -w /home/node/project agent node --experimental-sqlite --no-warnings verifier.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
1a : mauvaises lignes [4]Amina comptée deux fois
1c : erreurAucune colonne ne s’appelle membre
2c : mauvaises lignes [4]Les livres revenus ont été comptés
3a : mauvaises lignes ["Au nord de midi"] ["Carte de la pluie"]La jointure id sur id
3c : réussiUn autre ordre réussit quand même
4a : réussi et 4b : réussiLes données ne les séparent pas
4b : mauvaises lignes [2], une fois le prêt 8 renduUne nouvelle ligne les sépare

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.