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

Ingénierie du contexte pour agents LLM

Après cette leçon: Je peux choisir ce qui entre dans la fenêtre à chaque étape, lui donner un budget et dire quoi retirer d’abord.

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

Choisir ce que le modèle voit

L’ingénierie du contexte consiste à décider ce qui entre dans la fenêtre du modèle à chaque étape d’une exécution d’agent. La fenêtre est finie, donc chaque partie est un choix.

Un agent qui garde tous les fichiers et tous les résultats d’outils peut remplir sa fenêtre en quelques étapes. Les instructions utiles sont alors noyées sous des sorties dont personne n’a besoin.

À la fin de cette leçon

Remarque

Je peux choisir ce qui entre dans la fenêtre à chaque étape, lui donner un budget et dire quoi retirer d’abord.

Mots clés

MotCe que ça veut dire
Fenêtre de contextetout ce que le modèle lit en un appel
Budgetle plus grand nombre de jetons qu’une fenêtre peut contenir
Épingléune partie qu’on ne retire jamais
Résultat d’outilce qu’un outil a affiché, renvoyé au modèle
Mémoiredes notes gardées entre les exécutions et chargées au début
Ordre de retraitles parties qui partent d’abord quand la fenêtre est pleine

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

Une fenêtre est faite de parties

Chaque appel envoie des parties dans un ordre fixe. Les instructions disent qui est l’agent et ce qu’il peut faire. La mémoire garde des notes durables. Les fichiers sont ce sur quoi il travaille. Les résultats d’outils sont ce que ses outils ont affiché. L’historique est la conversation jusqu’ici.

Le module « Construire des agents » explique comment la mémoire est stockée. Ici, la question est seulement de savoir combien en tient.

Que retirer en premier

Donnez un budget à toute la fenêtre et retirez des parties jusqu’à ce qu’elle tienne. Retirez d’abord ce qui coûte le moins à reconstruire. Un vieux résultat d’outil peut être redemandé. Un fichier peut être relu. La mémoire est plus lente à refaire.

Ne retirez jamais les instructions. Épinglez le fichier en cours de modification. Arrêtez de retirer dès que la fenêtre tient, car chaque retrait de trop fait perdre quelque chose.

Ordre de retrait d’un agent de code

PartieRetiréePourquoi
Résultats d’outilsD’abord, les plus anciens en premierL’outil peut tourner de nouveau
FichiersEnsuite, sauf s’ils sont épinglésLe fichier peut être relu
MémoireEn troisièmeLes notes sont plus lentes à refaire
HistoriqueEn dernierIl contient ce que la personne a demandé
InstructionsJamaisSans elles, l’agent n’a plus de règles

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

Une erreur courante

Attention

Beaucoup coupent par le début, en retirant les plus anciens messages quel que soit leur contenu. Les instructions partent alors en premier. Retirez selon ce qu’est une partie, pas selon son âge.

É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 constructeur de fenêtre, partie 1

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander } = require(\"./model\");' 'const BUDGET = 58;' '// Ici un jeton est un mot. Un vrai tokeniseur compte autrement.' 'function taille(texte) { return texte.split(\" \").length; }' 'const parties = [' '  { genre: \"instructions\", nom: \"regles\", texte: \"Vous êtes un assistant de code. Modifiez seulement les fichiers montrés. Dites ce que vous avez changé.\" },' '  { genre: \"memoire\", nom: \"notes\", texte: \"Le projet utilise des tabulations. Les tests sont dans tests. Lancez-les avant chaque commit.\" },' '  { genre: \"fichier\", nom: \"app.py\", epingle: true, texte: \"def total(articles): return sum(articles) # additionne les prix du panier\" },' '];' > contexte1.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 constructeur de fenêtre, partie 2

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'parties.push({ genre: \"resultat_outil\", nom: \"essai 1\", texte: \"3 reussis 1 echoue test_total attendu 12 obtenu 10 dans tests slash test_app\" });' 'parties.push({ genre: \"resultat_outil\", nom: \"essai 2\", texte: \"4 reussis 0 echoue\" });' 'parties.push({ genre: \"fichier\", nom: \"lisezmoi\", texte: \"Un petit script de boutique qui calcule le prix des paniers et imprime un recu.\" });' 'const ORDRE = [\"resultat_outil\", \"fichier\", \"memoire\"];' 'function total(liste) {' '  let somme = 0;' '  for (const p of liste) somme = somme + taille(p.texte);' '  return somme;' '}' >> contexte1.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 constructeur de fenêtre, partie 3

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function assembler(toutes, budget) {' '  const gardees = toutes.slice();' '  const retirees = [];' '  for (const genre of ORDRE) {' '    for (const p of toutes) {' '      if (total(gardees) <= budget) break;' '      if (p.genre === genre && p.epingle === undefined) {' '        gardees.splice(gardees.indexOf(p), 1);' '        retirees.push(p.nom);' '      }' '    }' '  }' '  return { gardees: gardees, retirees: retirees, utilises: total(gardees) };' '}' >> contexte1.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 constructeur de fenêtre, partie 4

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  const f = assembler(parties, BUDGET);' '  console.log(\"budget \" + BUDGET + \", utilisé \" + f.utilises);' '  for (const p of parties) {' '    console.log((f.gardees.includes(p) ? \"gardé   \" : \"retiré  \") + p.genre + \" \" + p.nom + \" \" + taille(p.texte));' '  }' '  const corps = f.gardees.slice(1).map(function (p) { return p.nom + \" : \" + p.texte; }).join(\" | \");' '  const question = corps + \" | Quel fichier modifiez-vous en premier ? Une phrase.\";' '  const messages = [{ role: \"system\", content: f.gardees[0].texte }, { role: \"user\", content: question }];' '  const reponse = await demander(messages, \"Je modifie app.py en premier, car le test qui échoue porte sur total.\", 40);' '  console.log(\"modèle : \" + reponse.texte);' '}' 'main();' >> contexte1.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 et voir ce qui est retiré

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

Des mots tiennent lieu de jetons

Une vraie fenêtre se compte en jetons, avec le tokeniseur du modèle. Ici un mot vaut un jeton, donc chaque étudiant affiche les mêmes tailles. L’idée reste la même : additionner les parties et comparer à une limite.

Le Run fait un court appel avec ce qui est gardé. Sans modèle, il affiche un échantillon enregistré.

Une sortie possible

LigneCe qu’elle montre
budget 58, utilisé 56La fenêtre tient maintenant
gardé instructions regles 17Les instructions ne sont jamais retirées
retiré resultat_outil essai 1 13Le plus ancien résultat d’outil part en premier
retiré resultat_outil essai 2 4Le retrait s’arrête dès que ça tient
gardé fichier lisezmoi 15Aucun fichier n’a été retiré, le lisezmoi reste
modèle : ...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.