exploring-ai-failures

Par posthog · skills

Identifier les points de défaillance d'une application IA/LLM en production et faire émerger les patterns d'échec à partir de traces réelles. À utiliser quand quelqu'un veut comprendre ce qui ne va pas avec une fonctionnalité IA, trouver et catégoriser les modes de défaillance, trier les erreurs, ou investiguer des problèmes de qualité (mauvaises réponses, instructions ignorées, hallucinations, mauvais usage des outils) — « qu'est-ce qui échoue dans mon agent », « faire ressortir les patterns d'erreur », « pourquoi les réponses sont mauvaises », « trouver les modes de défaillance courants », « que dois-je corriger en priorité ». Couvre le périmètre d'un cas d'usage, la recherche de traces défaillantes selon le signal le plus adapté au contexte (erreurs de code, valeurs aberrantes de métriques, découpage par type de trace, revue manuelle, pics d'eval existants, clustering), et leur lecture débouchant sur une taxonomie des défaillances classée par priorité.

npx skills add https://github.com/posthog/skills --skill exploring-ai-failures

Exploration des défaillances de l'IA

La chose la plus précieuse que tu puisses faire avec le trafic d'IA en production est d'examiner les endroits où il échoue et de nommer les motifs. Le hic : la plupart des défaillances sont silencieuses. Le modèle retourne une réponse propre — HTTP 200, aucune exception — qui est fausse, hors sujet, ignore une instruction ou détourne l'usage d'un outil. Celles-ci ne lèvent jamais d'erreur, et ce sont généralement les défaillances qui méritent l'attention.

Donc cette compétence concerne la détection des défaillances (bruyantes et silencieuses), la lecture de celles-ci, et leur regroupement en un ensemble hiérarchisé de modes de défaillance sur lesquels tu peux agir : corriger un prompt, signaler un bug, prioriser le travail, ou transformer le mode principal en eval automatique (creating-online-evaluations).

Tout ce qui suit sert une activité irréductible : la lecture de vraies traces. Les requêtes ne font que dire quelles traces ouvrir — ce ne sont jamais la réponse. Si tu rapportes une liste de problèmes sans avoir ouvert les traces, tu as décrit la minorité bruyante (les choses qui lèvent des erreurs) et tu as raté le travail.

C'est bottom-up : les modes de défaillance émergent de vraies traces, non d'une liste de métriques génériques décidées à l'avance. Pour lire une seule trace en détail, appuie-toi sur exploring-llm-traces ; pour un regroupement émergent à grand volume, exploring-llm-clusters.

Outils

Outil Objectif
posthog:query-llm-traces-list Lister les traces candidates — filtrer par erreur, trier par métrique, limiter par type
posthog:query-llm-trace Lire une trace en entier pour voir ce qui s'est vraiment mal passé
posthog:execute-sql Trouver les valeurs aberrantes de métrique, découvrir la taxonomie des traces, compter les modes de défaillance
posthog:llma-evaluation-list Trouver les evals existants dont les défaillances pourraient révéler un nouveau mode
posthog:generate-app-url Construire un lien profond qualifié par région et projet vers une trace ou liste

Les requêtes détaillées pour chaque stratégie ci-dessous se trouvent dans references/finding-traces.md. Le schéma complet des événements $ai_* (et la division events vs ai_events pour le contenu lourd comme $ai_input/$ai_output_choices) se trouve dans exploring-llm-traces/references/events-and-properties.md.

Collaborer avec l'utilisateur

Collabore sur le périmètre et les priorités — pas sur la question de faire le travail. Affine avec l'utilisateur dès le départ : quelle fonctionnalité ou cas d'usage ? ont-ils déjà observé quelque chose de mauvais ? y a-t-il un signal à suivre (un pouce vers le bas, un ticket, une métrique qui semble bizarre) ? Une fois le périmètre défini, va lire des traces et reviens avec des modes de défaillance documentés — ne t'arrête pas pour demander la permission avant la lecture ; cette lecture est l'activité centrale, pas un suivi optionnel à proposer. Quand l'utilisateur ne sait pas ce qu'il faut chercher, pilote la boucle ci-dessous et explique le raisonnement en chemin ; garde l'enseignement optionnel.

Étape 1 — Limiter à un seul cas d'usage

Les applications ont une taxonomie de types de traces, et chacun échoue différemment — un chat d'assistance hallucine une politique, un résumeur omet des points clés, un agent boucle ou détourne l'usage d'un outil. Évaluer ou analyser les combiner ensemble dilue le signal. Choisis-en un, puis trouve son filtre (un préfixe $ai_trace_id, une propriété de fonctionnalité, un modèle). Si l'utilisateur ne sait pas comment son trafic se divise, découvre d'abord la taxonomie (requête dans references/finding-traces.md).

Étape 2 — Choisir quelles traces lire

Ce sont des façons de sélectionner quelles traces ouvrir — pas des réponses en soi. Les requêtes (comptes d'erreurs, agrégats de métriques) te disent où regarder ; ce ne sont jamais la sortie. Choisis en fonction du contexte et des signaux que tu as, et combine-les :

  • Erreurs de code ($ai_is_error) — le balayage le moins cher et le signal le moins représentatif : il ne détecte que les exceptions et les défaillances d'API, pas les défaillances de qualité silencieuses qui importent le plus. Utilise-le pour attraper quelques traces à lire, pas comme un décompte des « problèmes ». Légèrement plus utile pour les pipelines de sortie structurée ou d'appel d'outil, où certaines défaillances remontent comme des erreurs d'analyse/schéma.
  • Valeurs aberrantes de métrique — trie par jetons de sortie/entrée, longueur de message, coût, ou latence et ouvre les extrêmes. La longueur qui s'emballe, la troncature, la surcharge de contexte, et les boucles se regroupent aux queues.
  • Une seule tranche de type de trace — réduis à une seule sorte de requête pour que les traces que tu lis partagent une taxonomie.
  • Échantillon stratifié — quand tu n'as pas de signal spécifique (le cas courant), tire un lot mélangé entre tranches et résultats et lis-le. C'est la méthode par défaut, non le repli.
  • Pics d'eval existant — quand les evals tournent déjà, un saut dans les défaillances d'une eval te pointe vers les traces à lire (llma-evaluation-list + execute-sql sur les événements $ai_evaluation).
  • Clustering — à grand volume, laisse les regroupements émerger pour choisir des traces représentatives à lire ; voir exploring-llm-clusters.

Le piège. C'est tentant de faire un GROUP BY sur les messages d'erreur, produire un tableau hiérarchisé, et arrêter. Ce tableau est la minorité bruyante — les défaillances qui lèvent une exception. Les défaillances qui importent pour la plupart des produits d'IA se terminent avec HTTP 200 et n'apparaissent que quand un humain lit la trace. Un classement construit à partir de comptes d'erreur ou de métrique que tu n'as jamais lus n'est pas le livrable — c'est un pointeur vers ce qu'il faut lire ensuite. Si une requête pour des défaillances silencieuses revient vide ou maladroite, c'est un signal de lire des traces, pas d'abandonner et de rapporter les bruyantes.

Étape 3 — Lire un lot (c'est le travail)

Ouvre et lis vraiment les traces que tu as sélectionnées — prévois environ 20–30 pour un cas d'usage. Lis chacune avec query-llm-trace, dont l'unique argument obligatoire est traceId ; la valeur à passer est l'id de la trace du résultat query-llm-traces-list. Cette étape n'est pas optionnelle, et rien ne la remplace. Tu ne peux pas trouver les défaillances silencieuses avec GROUP BY ou en cherchant dans les sorties "refusal" / "sorry", parce que tu ne connais pas encore les motifs à chercher — la lecture c'est comment tu les découvres. Un proxy SQL intelligent qui retourne rien n'est pas la preuve que les défaillances n'y sont pas ; ça signifie que tu dois lire.

Pour chaque trace, note en langage courant ce qui s'est mal passé — et écris le timestamp du premier événement de la trace à côté de la note (il est là dans la trace que tu viens de lire, et dans le createdAt de query-llm-traces-list). Ce timestamp et l'ID de trace sont tout ce qu'il te faut pour construire un lien profond résolvable à l'étape 4, donc le capturer maintenant t'épargne un second aller-retour plus tard.

Quand une trace échoue dans une chaîne, enregistre la première chose qui s'est cassée — la défaillance racinaire cause généralement les symptômes en aval, et la corriger les efface. Groupe tes notes en quelques modes de défaillance nommés ("ignore le filtre de date", "invente une politique", "omet la deuxième question") ; une deuxième passe peut aider à regrouper tes notes, mais examine les regroupements toi-même. Continues à lire jusqu'à ce que les nouvelles traces cessent de montrer de nouveaux modes (des dizaines de traces, pas des milliers — arrête quand ça devient silencieux).

Étape 4 — Hiérarchiser, lier, et remettre à l'utilisateur

Hiérarchise les modes que tu as trouvés en lisant, grossièrement par leur fréquence dans ton échantillon — quelques-uns dominent généralement. Présente une courte liste hiérarchisée de modes de défaillance nommés. Pour chaque mode, inclus un ou deux liens profonds de traces d'exemple de ton propre chef — n'attends pas d'être demandé, et ne fais pas demander à l'utilisateur.

Tu as lu ces traces, mais tu peux en mal lire une — une trace qui ressemble à une hallucination peut être correcte en contexte, et certaines de celles que tu signales seront toi qui mal comprends la trace, pas une vraie défaillance. Donc ne présente pas la liste comme un fait établi. Donne à l'utilisateur un couple de liens d'exemple par mode, demande-lui d'ouvrir les liens, puis demande quel mode il veut viser ensuite.

(Une liste assemblée à partir de messages d'erreur ou de comptes de métrique que tu n'as jamais lus est le sous-ensemble bruyant, pas ceci — retourne à l'étape 3.)

Quand il y a peu à regarder

Si le cas d'usage est nouveau ou peu volumineux et que tu ne peux pas trouver assez de défaillances : élargis d'abord la fenêtre de temps ou relâche la tranche ; puis test de charge avec des entrées qui sondent délibérément les contraintes qui t'importent (cas limites, entrées longues ou ambiguës, formulation adversariale) ; ou génère un petit ensemble synthétique sur les dimensions qui importent (type de requête × scénario utilisateur), exécute-le à travers le système, et lis ces traces. Traite les résultats synthétiques comme un bootstrap, pas la vérité de base — ils ne sont pas fiables pour les domaines à enjeux élevés ou de niche.

Construire des liens d'interface utilisateur

query-llm-trace retourne une _posthogUrl pour la trace qu'il a lue, donc remets celle-ci au lieu de composer ta propre. Construis un lien toi-même seulement pour une trace dont tu as un id mais que tu n'as pas ouverte, et alors seulement avec posthog:generate-app-url — ne compose jamais à la main l'hôte ou le préfixe /project/<id>/. L'url doit être un modèle de catalogue canonique ; passe les ids concrets via params, jamais en les inlinant dans le chemin.

  • Liste de traces : generate-app-url {url: "/ai-observability/traces"} (puis filtre ton cas d'usage)
  • Trace unique : generate-app-url {url: "/ai-observability/traces/{id}", params: {id: "<trace_id>"}}

Aucun lien de trace ne porte de timestamp, donc ajoute ?timestamp=<url_encoded_timestamp> à l'URL que tu remets — la page de trace la lit pour résoudre les traces anciennes, et aucun outil ne peut l'exprimer.

Les liens générés se résolvent vers l'hôte de région correct et le préfixe de projet (par exemple https://us.posthog.com/project/<id>/ai-observability/traces/<trace_id>), donc un utilisateur pas déjà sur le projet cible atterrit quand même au bon endroit.

Conseils

  • Lire est le travail, pas la dernière étape. Les agrégats, les comptes d'erreurs, et les scores sont des indices pour quelles traces ouvrir — jamais un substitut. Lis un premier lot avant de rapporter quoi que ce soit, et ne demande pas la permission de le faire.
  • Ne sur-pondère pas les erreurs. $ai_is_error est le signal le plus bruyant mais le moins intéressant ; les défaillances qui valent ton temps se terminent généralement sans une.
  • Les stratégies de découverte sont un menu pour choisir les traces à lire, pas un pipeline et pas la réponse. Choisis en fonction du contexte, combine librement, et ne force pas un ordre.
  • Un cas d'usage à la fois. Les différents types de traces ont des taxonomies de défaillances différentes — les mélanger brouille le résultat.
  • Fréquence plutôt que complétude. L'objectif est les modes qui arrivent le plus, pas chaque défaillance concevable.
  • La sortie est une liste hiérarchisée de modes de défaillance nommés à partir des traces que tu as lues — cet artefact est ce qui rend l'étape suivante (corriger, prioriser, ou eval) évidente.
  • Remets des exemples liés, puis laisse l'utilisateur diriger. Ne t'arrête pas à un tableau catégorique. Donne un ou deux liens de trace résolubles par mode sans y être incité, demande à l'utilisateur d'en regarder un couple.

Compétences connexes

  • creating-online-evaluations — transformer un mode de défaillance hiérarchisé en eval qui tourne en continu
  • exploring-llm-clusters — comparer le comportement entre clusters au lieu de lire les traces une par une
  • exploring-llm-traces — la mécanique de lecture de trace sur laquelle cette compétence s'appuie

Skills similaires