Une recherche ne suffisait pas
La recherche agentique, c’est un agent qui décide de chercher de nouveau quand les premiers résultats ne répondent pas à la question. C’est utile parce qu’une vraie question demande souvent deux regards : le premier trouve le sujet, le second le détail.
Quelqu’un demande combien de temps il reste bloqué. La première recherche trouve les règles du mot de passe, pas la durée de blocage. L’agent cherche encore.
À la fin de cette leçon
Remarque
Je peux laisser un agent chercher plus d’une fois, avec une règle d’arrêt et une limite, et évaluer ses réponses sur des questions connues.
Mots clés
| Mot | Ce que ça veut dire |
|---|---|
| Recherche agentique | une recherche que l’agent peut répéter et changer |
| Règle d’arrêt | la condition qui met fin à la boucle de recherche |
| Limite de recherches | le plus de recherches qu’une question peut utiliser |
| Rappel | la part des sources nécessaires qui ont été trouvées |
| Réponse étayée | une réponse dont les sources ont vraiment été trouvées |
| Vu | les sources trouvées jusqu’ici |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
La recherche est un outil réutilisable
Un agent fonctionne en boucle, avec un budget d’étapes. Ici l’outil de la boucle est la recherche. L’agent cherche, lit ce qui revient, puis répond ou cherche de nouveau avec une nouvelle requête.
Deux points demandent du soin. La boucle doit se terminer. Et la réponse finale doit s’appuyer sur ce qui a vraiment été trouvé.
Trois façons de s’arrêter
On s’arrête quand l’agent répond. On s’arrête quand une recherche n’apporte rien de nouveau, car chercher encore avec les mêmes mots n’aidera pas. On s’arrête à une limite de recherches, fixée par le coût et le temps.
Notez pourquoi la boucle s’est arrêtée : répondu, arrêté, limite ou pas de réponse. La raison dit quoi corriger.
Exemple détaillé : trois parcours de la même question
| Parcours | Recherches | Fin | Étayé |
|---|---|---|---|
| Bon | 2 | répondu | oui |
| Bloqué | 2 | arrêt, rien de nouveau | non |
| Limite de 1 | 1 | arrêt, limite | non |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Vérifiez que la réponse a des sources
Une réponse liste ses sources. Elle est étayée seulement si chaque source fait partie des pages que les recherches ont rendues. Une source que l’agent n’a jamais vue est inventée.
Mesurez aussi le rappel : parmi les pages dont une question a besoin, combien les recherches ont-elles trouvées ? Évaluez les deux sur des questions aux sources connues.
Une erreur courante
Attention
Beaucoup pensent qu’un agent qui cite une source l’a utilisée. Une citation n’est que du texte. Vérifiez que chaque identifiant cité a été rendu par une recherche de ce parcours, sinon une source inventée passe pour une vraie.
Écrire l’assistant du modèle, partie 1
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
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 la boucle de recherche, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander } = require(\"./model\");' 'const index = {' ' \"règles de mot de passe\": [\"p2\", \"p1\"],' ' \"durée de blocage\": [\"p3\"],' ' \"réinitialiser mot de passe\": [\"p1\"],' '};' 'const docs = { p1: \"Réinitialisez votre mot de passe depuis la page de connexion.\", p2: \"Un mot de passe contient dix lettres.\", p3: \"Après cinq mots de passe faux, le compte est bloqué quinze minutes.\" };' > agentique1.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 boucle de recherche, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function lancer(etapes, max) {' ' const vus = [];' ' let n = 0;' ' for (const e of etapes) {' ' if (\"reponse\" in e) {' ' const ok = e.sources.length > 0 && e.sources.every(function (p) { return vus.includes(p); });' ' return \"répondu, étayé : \" + (ok ? \"oui\" : \"non\");' ' }' ' if (n === max) return \"arrêt : limite de \" + max + \" recherche(s)\";' ' n++;' ' const trouves = index[e.recherche] || [];' ' const neufs = trouves.filter(function (p) { return vus.includes(p) === false; });' ' neufs.forEach(function (p) { vus.push(p); });' ' console.log(\" recherche \" + n + \" : \" + e.recherche + \" -> \" + (trouves.join(\" \") || \"rien\") + \", nouveau \" + neufs.length);' ' if (neufs.length === 0) return \"arrêt : rien de nouveau\";' ' }' ' return \"pas de réponse\";' '}' >> agentique1.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 boucle de recherche, partie 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const bon = [{ recherche: \"règles de mot de passe\" }, { recherche: \"durée de blocage\" }, { reponse: \"Quinze minutes.\", sources: [\"p3\"] }];' 'const bloque = [{ recherche: \"réinitialiser mot de passe\" }, { recherche: \"réinitialiser mot de passe\" }, { reponse: \"Pas sûr.\", sources: [\"p1\"] }];' 'console.log(\"bon parcours :\"); console.log(lancer(bon, 3));' 'console.log(\"parcours bloqué :\"); console.log(lancer(bloque, 3));' 'console.log(\"parcours limité :\"); console.log(lancer(bon, 1));' 'async function main() {' ' const texte = \"Question : combien de temps suis-je bloqué. La première recherche a trouvé : \" + docs.p2 + \" Écrivez une meilleure requête de 5 mots au plus. Répondez par la requête seule.\";' ' const reponse = await demander([{ role: \"user\", content: texte }], \"durée de blocage du compte\", 20);' ' console.log(\"un modèle suggère :\", reponse.texte.trim());' '}' 'main();' >> agentique1.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 les trois boucles
docker exec -w /home/node/project agent node agentique1.jsAffiché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.
Ceci est une maquette
La boucle suit des étapes enregistrées, donc chaque étudiant voit les mêmes trois parcours. Un vrai agent choisit ses étapes, et l’appel au modèle ne fait ici que suggérer une requête, que le Run affiche sans la suivre.
L’index compte trois entrées. Un vrai index est la recherche hybride que vous avez construite, avec le filtre de la leçon 5.
Ce que le Run affiche
| Parcours | Dernière ligne |
|---|---|
| bon parcours | répondu, étayé : oui |
| parcours bloqué | arrêt : rien de nouveau |
| parcours limité | arrêt : limite de 1 recherche(s) |
| suggestion du modèle | Une sortie possible : durée de blocage du compte |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.