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

Messages système, utilisateur et assistant

Après cette leçon: Je peux construire la liste de messages que prend un appel à un modèle de langage.

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

Un appel prend une liste de messages

Un appel de discussion à un modèle de langage prend une liste de messages. Chaque message a un rôle et un texte. Le modèle lit toute la liste, puis écrit le message suivant.

C’est important, car un modèle ne retient rien d’un appel à l’autre. Une discussion qui semble avoir de la mémoire est un programme qui renvoie les anciens messages à chaque fois.

À la fin de cette leçon

Remarque

Je peux construire la liste de messages que prend un appel à un modèle de langage.

Mots clés

MotCe que ça veut direExemple
Messageun tour de la discussion : un rôle et un texte
Rôlel’auteur d’un messageuser
Message systèmela consigne qui règle le comportement du modèle
Historiqueles messages précédents, renvoyés à chaque appel
Corps de la requêtele JSON qu’un programme envoie avec un appel

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

Un message, c’est un rôle et un texte

Un message est un objet à deux clés. role dit qui parle et content contient les mots.

Il existe trois rôles. Le message system règle le comportement du modèle. Un message user est ce que dit la personne. Un message assistant est ce que le modèle a dit plus tôt.

Le corps de la requête d’un appel

Code: node
{
  "model": "lab",
  "max_tokens": 60,
  "messages": [
    { "role": "system", "content": "Vous répondez en une seule phrase courte." },
    { "role": "user", "content": "Qu’est-ce qu’une variable en programmation ?" }
  ]
}

Envoyer un appel au modèle du labo

Commande
docker exec -w /home/node/project agent node -e '/* Le corps de la requête : un nom de modèle, une limite de réponse et une liste de messages. */ const corps = { model: "lab", max_tokens: 60, messages: [ { role: "system", content: "Vous répondez en une seule phrase courte." }, { role: "user", content: "Qu’est-ce qu’une variable en programmation ?" } ] }; (async () => { try { const url = (process.env.AI_URL || "http://ai:4000") + "/v1/chat/completions"; const reponse = await fetch(url, { method: "POST", body: JSON.stringify(corps), headers: { "content-type": "application/json", authorization: "Bearer lab" } }); if (!reponse.ok) throw new Error("HTTP " + reponse.status); const donnees = await reponse.json(); console.log("Réponse du modèle : " + donnees.choices[0].message.content); } catch (erreur) { console.log("Aucun modèle n’a répondu (" + erreur.message + ")."); console.log("Exemple enregistré : Une variable garde une valeur que le programme peut changer."); } })();'

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.

Le modèle ne retient rien entre deux appels

Chaque appel est isolé. Le modèle ne voit que les messages de cet appel.

Pour tenir une conversation, votre programme garde une liste. Après chaque réponse, il y ajoute la question et la réponse. À l’appel suivant, il renvoie l’historique, avec la nouvelle question à la fin.

Écrire le fichier d’aide labo.js

Commande
docker exec -w /home/node/project agent node -e 'require("fs").writeFileSync("labo.js", ["// labo.js, partie 1 : l’endroit unique qui envoie un appel au modèle du labo.", "const base = process.env.AI_URL || \"http://ai:4000\";", "", "async function envoyer(corps, delai) {", "  return fetch(base + \"/v1/chat/completions\", {", "    method: \"POST\",", "    headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },", "    body: JSON.stringify({ model: \"lab\", ...corps }),", "    signal: AbortSignal.timeout(delai || 30000),", "  });", "}"].join("\n") + "\n")'

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.

Ajouter la demande avec un exemple enregistré

Commande
docker exec -w /home/node/project agent node -e 'require("fs").appendFileSync("labo.js", ["", "// Partie 2 : demander une fois. Si le modèle ne peut pas répondre, rendre l’exemple enregistré.", "async function demander(corps, exemple) {", "  try {", "    const reponse = await envoyer(corps);", "    if (!reponse.ok) throw new Error(\"HTTP \" + reponse.status);", "    const donnees = await reponse.json();", "    return { etiquette: \"Réponse du modèle\", texte: donnees.choices[0].message.content, donnees: donnees };", "  } catch (erreur) {", "    return { etiquette: \"Exemple enregistré\", texte: exemple, note: erreur.message };", "  }", "}", "", "module.exports = { envoyer, demander };"].join("\n") + "\n")'

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.

Demander avec l’historique, puis sans

Commande
docker exec -w /home/node/project agent node -e 'const labo = require("./labo.js"); const consigne = { role: "system", content: "Répondez en une phrase courte." }; const historique = [ { role: "user", content: "Je m’appelle Samir." }, { role: "assistant", content: "Enchanté, Samir." } ]; const question = { role: "user", content: "Comment je m’appelle ?" }; (async () => { const avec = await labo.demander({ max_tokens: 30, messages: [consigne, ...historique, question] }, "Vous vous appelez Samir."); console.log("Avec l’historique, " + avec.etiquette + " : " + avec.texte); const sans = await labo.demander({ max_tokens: 30, messages: [consigne, question] }, "Je ne connais pas votre nom."); console.log("Sans lui, " + sans.etiquette + " : " + sans.texte); console.log("Messages envoyés à chaque appel : " + [consigne, ...historique, question].length + " et " + [consigne, question].length); })();'

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 erreur fréquente

Attention

Beaucoup pensent que le modèle se souvient de l’appel précédent. Ce n’est pas le cas. Le second appel, sans historique, ne pouvait pas connaître le prénom. Pour que le modèle s’en serve, mettez-le dans les messages que vous envoyez.

Exemple travaillé : ce que chaque appel portait

AppelMessages envoyésCe que le modèle peut savoir
Avec l’historiquesystem, user, assistant, user (4)Le prénom Samir
Sans luisystem, user (2)Rien sur Samir

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

L’ordre des messages compte

Mettez le message système en premier. Ensuite, les tours alternent : user, assistant, user, et ainsi de suite. Le dernier message vient de l’utilisateur, car c’est à lui que le modèle répond.

La plupart des API de modèles refusent une liste qui rompt cet ordre, ou donnent des réponses étranges. Vérifiez l’ordre dans votre code avant d’envoyer.

Pour aller plus loin : changer le message système

Ouvrez le Run de l’historique et remplacez la consigne par « Répondez en anglais ». Relancez-le.

Notez ce qui a changé et ce qui n’a pas changé. Puis dites en une phrase pourquoi la consigne devait figurer dans les messages envoyés.

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