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

Relire le SQL écrit par un modèle

Après cette leçon: Je peux relire la requête d’un modèle et dire si elle répond à la question posée.

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

La requête du modèle répond-elle à la question ?

Relire du SQL écrit par un modèle, c’est comparer la requête à la question avant de lui faire confiance. Une requête peut tourner sans erreur et répondre à une autre question.

Le module 4 enseigne les jointures et les regroupements. Cette leçon relit le SQL qu’un modèle a écrit pour une question, et cherche ses trois défauts les plus fréquents.

À la fin de cette leçon

Remarque

Je peux relire la requête d’un modèle et dire si elle répond à la question posée.

Mots clés

MotCe que ça veut direExemple
Clauseune partie d’une requête, comme WHERE
Filtreun test qui ne garde que certaines lignesrendu = 0
Doublonune même valeur comptée plusieurs fois
DISTINCTgarde chaque valeur une seule foisCOUNT(DISTINCT membre_id)
Colonne de jointurela colonne sur laquelle on apparie deux tables

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

Lire la question avant la requête

Listez d’abord ce que demande la question. Quelles lignes comptent ? Attend-on un nombre, une liste ou une seule valeur ? Faut-il compter chaque chose une seule fois ?

Lisez ensuite la requête clause par clause. FROM et JOIN disent d’où viennent les lignes, WHERE en garde une partie et SELECT dit ce qui revient.

Exemple détaillé : morceaux de question et clauses

La question ditLa requête a besoin deClause
au mois 3mois = 3WHERE
membres différentsDISTINCT membre_idSELECT
combienCOUNTSELECT
titresune jointure de prets vers livres sur livre_idFROM et JOIN

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

Trois défauts fréquents chez un modèle

Compter des doublons : COUNT(membre_id) compte Amina deux fois si elle a emprunté deux fois. Un filtre oublié : la requête compte tous les prêts, pas seulement ceux encore dehors.

La mauvaise jointure : prets.id = livres.id apparie le prêt 3 au livre 3 juste parce qu’ils portent le même numéro. La jointure doit passer par prets.livre_id.

Exemple détaillé : faux et juste

QuestionMorceau fauxMorceau juste
Membres différents au mois 3COUNT(membre_id)COUNT(DISTINCT membre_id)
Livres encore dehorsPas de WHEREWHERE rendu = 0
Titres empruntés par le membre 2ON p.id = l.idON p.livre_id = l.id

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

Une erreur courante

Attention

Beaucoup pensent qu’une requête qui tourne sans erreur répond à la question. Une erreur veut seulement dire que le SQL est cassé. Une mauvaise jointure ou un filtre oublié tournent sans bruit et donnent une réponse fausse.

É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 grille de relecture, partie 1

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander, sqlDe } = require(\"./model\");' 'const questions = [' '  { q: \"Combien de membres différents ont emprunté un livre au mois 3 ?\", besoins: [\"DISTINCT\", \"mois = 3\"],' '    a: \"SELECT COUNT(membre_id) FROM prets WHERE mois = 3\",' '    b: \"SELECT COUNT(DISTINCT membre_id) FROM prets WHERE mois = 3\" },' '  { q: \"Combien de livres sont encore dehors ?\", besoins: [\"rendu = 0\"],' '    a: \"SELECT COUNT(*) FROM prets\",' '    b: \"SELECT COUNT(*) FROM prets WHERE rendu = 0\" },' '  { q: \"Quels titres le membre 2 a-t-il empruntés ?\", besoins: [\"livre_id\", \"membre_id = 2\"],' '    a: \"SELECT l.titre FROM prets p JOIN livres l ON p.id = l.id WHERE p.membre_id = 2\",' '    b: \"SELECT l.titre FROM prets p JOIN livres l ON p.livre_id = l.id WHERE p.membre_id = 2\" },' '];' > relire.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 grille de relecture, partie 2

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function tasser(sql) { return sql.toUpperCase().split(/\s+/).join(\" \").trim(); }' 'function relire(sql, besoins) {' '  const texte = tasser(sql);' '  const defauts = besoins.filter(function (n) { return texte.indexOf(tasser(n)) < 0; })' '    .map(function (n) { return \"manque \" + n; });' '  if (/ON \w+\.ID = \w+\.ID\b/.test(texte)) defauts.push(\"jointure id sur id\");' '  return defauts.length ? defauts.join(\", \") : \"semble juste\";' '}' >> relire.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 grille de relecture, partie 3

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  questions.forEach(function (x, i) {' '    console.log((i + 1) + \" \" + x.q);' '    console.log(\"  A : \" + relire(x.a, x.besoins));' '    console.log(\"  B : \" + relire(x.b, x.besoins));' '  });' '  const schema = \"prets(id, livre_id, membre_id, mois, rendu)\nmembres(id, nom)\nprets.membre_id -> membres.id\";' '  const systeme = \"Répondez par une seule requête SELECT pour SQLite, et rien d’autre.\";' '  const echantillon = \"SELECT COUNT(DISTINCT membre_id) FROM prets WHERE mois = 3;\";' '  const reponse = await demander([{ role: \"system\", content: systeme },' '    { role: \"user\", content: schema + \"\nQuestion : \" + questions[0].q }], echantillon, 120);' '  const sql = sqlDe(reponse.texte);' '  console.log(\"le modèle a écrit : \" + sql);' '  console.log(\"  relecture : \" + relire(sql, questions[0].besoins));' '}' 'main();' >> relire.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 la grille de relecture

Commande
docker exec -w /home/node/project agent node relire.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
A : manque DISTINCTQuestion 1, la candidate A compte des doublons
A : manque rendu = 0Question 2, la candidate A n’a pas de filtre
A : manque livre_id, jointure id sur idQuestion 3, la candidate A joint sur la mauvaise colonne
B : semble justeChaque candidate B passe la relecture
le modèle a écrit : ...La requête du modèle pour la question 1, relue de la même façon, ou un échantillon enregistré

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.