Que faire quand une fonction d’IA échoue
Un incident est un moment où une fonction fait du tort aux utilisateurs ou à l’entreprise, par exemple de faux remboursements ou une adresse divulguée. Conduire un incident, c’est le repérer, limiter les dégâts, le corriger et en tirer une leçon.
Enregistrer des traces aide à retrouver une panne. Cette leçon emploie ces enregistrements pour conduire l’incident.
À la fin de cette leçon
Remarque
Je peux conduire un incident d’IA et en tirer une leçon.
Mots clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Incident | un moment où une fonction fait du tort aux utilisateurs | |
| Chronologie | les événements dans l’ordre, avec leur heure | |
| Gravité | le sérieux de l’incident, de 1 à 3 | 2 |
| Atténuer | limiter les dégâts avant d’avoir corrigé la cause | |
| Revue | une réunion pour comprendre ce qui a laissé passer l’incident |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Commencez par une chronologie tirée des traces
Rangez chaque événement dans l’ordre du temps, même si les enregistrements arrivent dans un autre ordre. Chaque ligne dit quand, qui et quoi.
Calculez ensuite deux nombres. Le délai de détection va du début au premier signe. Le délai de rétablissement va du début à la correction.
Exemple détaillé : une consigne qui rembourse à tort
| Minute | Qui | Événement | Ce que cela donne |
|---|---|---|---|
| 0 | livraison | Nouvelle consigne en ligne | Le début |
| 25 | support | Premier signalement d’un client | Délai de détection : 25 |
| 31 | astreinte | Incident déclaré | Le travail commence |
| 40 | astreinte | Ancienne consigne rétablie | Les dégâts s’arrêtent |
| 52 | supervision | Remboursements revenus à zéro | Délai de rétablissement : 52 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
La gravité décide qui fait quoi
Écrivez la règle de gravité avant un incident. La gravité 1 : des données privées sont montrées, ou la moitié des utilisateurs ou plus sont touchés. La gravité 2 : dix pour cent ou plus. Au-dessous, c’est 3.
Chaque gravité a une courte liste d’actions, et chaque action a un rôle : responsable, correcteur ou communication. Les rôles évitent que tous fassent la même tâche.
Exemple détaillé : gravité et actions
| Gravité | Quand | Actions |
|---|---|---|
| 1 | Données privées, ou 50 pour cent ou plus | Prévenir le propriétaire, revenir en arrière, informer les utilisateurs, tenir une revue |
| 2 | 10 à 49 pour cent | Revenir en arrière, informer l’équipe, tenir une revue |
| 3 | Moins de 10 pour cent | Noter dans le journal |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une erreur courante
Attention
Beaucoup pensent qu’une revue doit trouver qui a fait l’erreur. Les gens cachent alors des faits la fois suivante. Demandez ce qui, dans le système, a laissé passer l’erreur : pas de canari, pas d’alerte, une règle que personne ne contrôlait. Écrivez des rôles dans la revue, jamais le nom d’une personne.
É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 le script de l’incident, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander } = require(\"./model\");' 'const evenements = [' ' { a: 31, qui: \"astreinte\", sorte: \"declare\", quoi: \"incident déclaré\" },' ' { a: 0, qui: \"livraison\", sorte: \"debut\", quoi: \"nouvelle consigne en ligne\" },' ' { a: 52, qui: \"supervision\", sorte: \"resolu\", quoi: \"remboursements revenus à zéro\" },' ' { a: 25, qui: \"support\", sorte: \"detecte\", quoi: \"premier signalement d’un client\" },' ' { a: 40, qui: \"astreinte\", sorte: \"attenue\", quoi: \"ancienne consigne rétablie\" },' '];' > incident.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 script de l’incident, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function premier(sorte) { return evenements.filter(function (e) { return e.sorte === sorte; })[0].a; }' 'function gravite(pourcent, prive) {' ' if (prive || pourcent >= 50) return 1;' ' return pourcent >= 10 ? 2 : 3;' '}' 'const tries = evenements.slice().sort(function (x, y) { return x.a - y.a; });' >> incident.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 script de l’incident, partie 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' tries.forEach(function (e) { console.log(\"minute \" + e.a + \" \" + e.qui + \" : \" + e.quoi); });' ' console.log(\"délai de détection : \" + (premier(\"detecte\") - premier(\"debut\")) + \" minutes\");' ' console.log(\"délai de rétablissement : \" + (premier(\"resolu\") - premier(\"debut\")) + \" minutes\");' ' console.log(\"gravité : \" + gravite(18, false));' ' const q = \"En une phrase courte, pourquoi une revue d’incident nomme-t-elle des rôles et non des personnes ?\";' ' const echantillon = \"Les gens cachent leurs erreurs quand on les accuse, alors que la revue doit trouver ce que le système a laissé passer.\";' ' const reponse = await demander([{ role: \"user\", content: q }], echantillon, 60);' ' console.log(\"le modèle dit : \" + reponse.texte);' '}' 'main();' >> incident.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 le rapport d’incident
docker exec -w /home/node/project agent node incident.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.
Ce que le Run affiche
| Ligne | Ce qu’elle montre |
|---|---|
| minute 0 livraison : nouvelle consigne en ligne | Cinq événements, triés par minute |
| délai de détection : 25 minutes | Le premier signalement moins le début |
| délai de rétablissement : 52 minutes | Le retour à zéro moins le début |
| gravité : 2 | Pour 18 pour cent touchés, sans données privées |
| le modèle dit : ... | Une phrase du labo. Un échantillon enregistré si aucun modèle ne répond |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.