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

Construire un chatbot qui fonctionne

Après cette leçon: Je peux réunir état, coupe, message system, flux et sources dans un seul chatbot.

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

Assembler les cinq parties

Un chatbot qui fonctionne réunit cinq parties dans une seule boucle. Il garde un état, le coupe, suit un message system, envoie sa réponse en flux et montre ses sources. C’est difficile, car chaque partie marche seule, et les bogues apparaissent là où elles se rejoignent.

Le chatbot d’une bibliothèque répond à trois questions de suite. Il doit se souvenir de la première, rester dans son budget et citer une source à chaque fois.

À la fin de cette leçon

Remarque

Je peux réunir état, coupe, message system, flux et sources dans un seul chatbot.

Mots-clés

MotCe que ça veut dire
Boucle de chatles étapes répétées pour chaque message de l’utilisateur
Tourun message de l’utilisateur et la réponse qui lui correspond
Historiquetous les messages du chat jusqu’ici
Budgetle plus de jetons que vous choisissez d’envoyer
Replice que fait le bot quand aucun modèle ne répond

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

Un tour utilise les cinq parties

Chaque tour suit les mêmes étapes. Chargez l’historique. Ajoutez le message de l’utilisateur. Coupez ce que vous allez envoyer. Appelez le modèle. Contrôlez la réponse. Enregistrez l’historique.

Écrivez ces étapes dans une seule fonction, tour. Le chat n’est alors que cette fonction appelée encore et encore.

Exemple travaillé : les étapes d’un tour

ÉtapeDe la leçonCe qui se passe
Charger et ajouterGarder une conversationLe message de l’utilisateur rejoint la liste de la session
CouperCouper un historiqueLes vieux messages sont laissés de côté pour cet appel
Message et sourcesMessage system, CitationsLe message system contient les règles et les sources numérotées
Appeler et contrôlerCitationsOn vérifie que la réponse n’a pas de repère sans source
Flux et enregistrementRéponse en fluxLes morceaux vont à la page, l’historique est enregistré

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

Garder n’est pas envoyer

L’historique garde tous les messages. L’appel n’envoie que ce qui tient dans le budget. Couper ne change donc jamais le dossier. Cela change un appel.

Vous pouvez aussi changer le budget plus tard, et une personne peut toujours lire le chat entier.

Prévoir un modèle qui ne répond pas

Parfois aucun modèle ne répond : l’IA est coupée, le crédit du jour est épuisé ou le réseau tombe. Un repli est un message clair qui le dit, pour que le chat ne reste pas bloqué et ne plante pas.

Dans ce labo, chaque Run affiche alors un échantillon enregistré, annoncé comme tel. Un vrai produit montrerait son propre avis.

Une erreur fréquente

Attention

Beaucoup pensent qu’un chatbot est fini quand la démonstration marche. Une démonstration pose des questions gentilles. Essayez des questions pénibles, un très long chat et aucun modèle du tout. Comptez les jetons que coûte un chat avant que d’autres l’utilisent.

É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 chatbot, partie 1

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const fs = require(\"fs\");' 'const { demander } = require(\"./model\");' 'const BUDGET = 180; // jetons pour le message system et l’historique ensemble' 'const SOURCES = [' '  \"Les adhérents peuvent emprunter jusqu’à six livres pour trois semaines.\",' '  \"Un livre rendu en retard coûte dix centimes par jour.\",' '  \"La bibliothèque ouvre à neuf heures et ferme à dix-sept heures en semaine.\",' '];' > robot6.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 chatbot, partie 2

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function jetons(m) { return Math.ceil(m.content.length / 4) + 4; }' 'function total(liste) {' '  return liste.reduce(function (somme, m) { return somme + jetons(m); }, 0);' '}' 'function messageSysteme() {' '  const numerotees = SOURCES.map(function (t, rang) { return \"[\" + (rang + 1) + \"] \" + t; }).join(\" \");' '  const regle = \"Vous êtes l’assistant de la bibliothèque. Répondez en deux phrases au plus, avec ces sources seulement. Écrivez le numéro de la source entre crochets après chaque fait. Si elles ne le disent pas, répondez : Je ne sais pas. \";' '  return { role: \"system\", content: regle + numerotees };' '}' >> robot6.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 chatbot, partie 3

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function couper(historique, systeme) {' '  const gardes = historique.slice();' '  while (total([systeme].concat(gardes)) > BUDGET && gardes.length > 1) gardes.shift();' '  return gardes;' '}' 'function reperesFaux(reponse) {' '  const faux = [];' '  const motif = /\[(\d+)\]/g;' '  let m = motif.exec(reponse);' '  while (m) {' '    if (Number(m[1]) < 1 || Number(m[1]) > SOURCES.length) faux.push(m[1]);' '    m = motif.exec(reponse);' '  }' '  return faux;' '}' >> robot6.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 chatbot, partie 4

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function tour(etat, texte, echantillon) {' '  etat.historique.push({ role: \"user\", content: texte });' '  const systeme = messageSysteme();' '  const envoyes = couper(etat.historique, systeme);' '  const detenus = etat.historique.length;' '  const reponse = await demander([systeme].concat(envoyes), echantillon, 70);' '  etat.historique.push({ role: \"assistant\", content: reponse });' '  fs.writeFileSync(\"chat.json\", JSON.stringify(etat, null, 1));' '  console.log(\"Vous : \" + texte);' '  console.log(\"Bot : \" + reponse);' '  console.log(\"  envoyé \" + envoyes.length + \" sur \" + detenus + \" messages, faux repères : \" + reperesFaux(reponse).length);' '}' >> robot6.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 chatbot, partie 5

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  const etat = { historique: [] };' '  // Échantillons enregistrés, utilisés seulement si aucun modèle ne répond.' '  await tour(etat, \"Combien de livres puis-je emprunter ?\", \"Vous pouvez emprunter six livres pour trois semaines [1].\");' '  await tour(etat, \"Et combien coûte un retard ?\", \"Un livre en retard coûte dix centimes par jour [2].\");' '  await tour(etat, \"Quand fermez-vous le vendredi ?\", \"La bibliothèque ferme à dix-sept heures en semaine [3].\");' '  console.log(\"Enregistré : \" + etat.historique.length + \" messages dans chat.json\");' '}' 'main();' >> robot6.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.

Tenir un chat de trois tours

Commande
docker exec -w /home/node/project agent node robot6.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 peut montrer
Vous et BotTrois questions, chacune avec une courte réponse qui peut citer une source
envoyé n sur menvoyé 1 sur 1, puis 3 sur 3, puis 5 sur 5 ou moins. Les réponses enregistrées donnent 4 sur 5
faux repèresLe plus souvent 0. Un nombre au-dessus de 0 veut dire que la réponse cite une source qui n’existe pas
EnregistréEnregistré : 6 messages dans chat.json

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.