Observabilité de l'IA : journaux, invites, appels d'outils et coût

DEV - 12/06
Voici une fonction de cinq lignes. Il appelle un LLM, enregistre la réponse, la renvoie. fonction asynchrone...

Voici une fonction de cinq lignes. Il appelle un LLM, enregistre la réponse, la renvoie.

fonction asynchrone demander (question : chaîne) { const res = attendre openai.responses.create ({ modèle : "o4-mini", entrée : question }); console.log("réponse:", res.output_text); renvoyer res.output_text ; }
Entrer en mode plein écran Quitter le mode plein écran

Cela compile. Il passe les tests. Il est expédié. Et cela vous coûtera discrètement quatre chiffres par mois avant que quiconque ne le remarque, car rien dans ce journal ne vous indique que le modèle a brûlé 8 000 jetons de raisonnement cachés pour produire une réponse de 40 jetons.

C’est la lacune sur laquelle porte cet article. Les appels AI ne sont pas des appels HTTP classiques. L'état intéressant n'est pas le corps de réponse - ce sont les messages que vous avez envoyés, les outils choisis par le modèle, les jetons qu'il a consommés (visibles et autres) et les dollars qui ont été retirés du budget. Si votre histoire d'observabilité est « nous enregistrons la réponse », vous pilotez un avion avec une seule jauge et cette jauge est l'altimètre.

Parlons de ce qu'il faut réellement capturer.

Les quatre signaux qui comptent

Chaque système d’IA a les mêmes quatre dimensions qui méritent d’être instrumentées, et la plupart des équipes n’en suivent qu’une ou deux :

  1. Journaux - la paire requête/réponse, l'erreur, la latence. Les trucs ennuyeux que l'APM traditionnel couvre déjà.
  2. Invites : le texte réel entré et le texte réel sorti. Y compris les invites système, les définitions d’outils et l’historique.
  3. Appels d'outils : quel outil le modèle a choisi, avec quels arguments, ce qui est revenu, dans quel ordre, avec quelles tentatives.
  4. Coût : jetons d'entrée, jetons de sortie, jetons mis en cache, jetons de raisonnement, modèle et prix par million de jetons pour chacun. Multiplié par utilisateur, par fonctionnalité, par demande.

Si vous perdez l'un de ces éléments, vous travaillerez à l'aveugle sur un axe différent du problème. Perdez le signal de coût et vous vous réveillez avec un message Slack de la finance. Perdez le signal d'appel de l'outil et vous ne pouvez pas savoir pourquoi votre agent a continué à réserver le mauvais vol. Perdez le signal d'invite et une régression de prod devient un jeu de devinettes. Perdez les journaux simples et vous ne savez même pas que l'appel a eu lieu.

La bonne nouvelle : en 2026, il existera enfin une norme pour capturer les quatre. La mauvaise nouvelle : la plupart des équipes roulent toujours les leurs et manquent la moitié du terrain.

Logs : que capturer et pourquoi "200 OK" est un mensonge

Commencez par la couche ennuyeuse. Chaque appel LLM mérite une ligne de journal structurée avec au minimum :

  • Horodatage, ID de demande, ID de trace parent.
  • Fournisseur (ouvert,anthropique,base, votre propre passerelle), nom du modèle, version du modèle si vous l'avez.
  • Point de terminaison ou opération (chat.achèvements,réponses,messages).
  • Latence - à la fois horloge murale et délai d'obtention du premier jeton si vous diffusez.
  • Statut HTTP, classe d'erreur, corps de l'erreur.
  • Raison de fin (arrêt,longueur,appels_outils,contenu_filter).

Ce dernier est le piège. Un 200 de l'API ne signifie pas "le modèle a répondu à la question". UNfinish_reasondelongueursignifie que la réponse a été tronquée au milieu de la phrase.contenu_filtersignifie que le système de sécurité a bloqué la sortie.appels_outilssignifie que le modèle vous demande de faire un travail et que la conversation n'est pas terminée. Si votre suivi compte les 200 comme succès, vous comptez les troncatures et les refus comme des victoires.

Le cas du streaming est une affaire à part entière. Une réponse diffusée en continu peut renvoyer un HTTP 200, émettre une demi-phrase, puis mourir avec une interruption de connexion. La vérification « cet appel a-t-il réussi » doit avoir lieu à la fin du flux, et non au niveau des en-têtes. Capturez également le nombre d'octets et le nombre de morceaux - une réponse partielle arrivée en trois morceaux au lieu de quarante vous indique que le modèle est mort prématurément, et la latence jusqu'au premier jeton aura fière allure même si l'utilisateur n'a rien d'utile.

Le délai d'obtention du premier jeton est le nombre de latence qui est en corrélation avec la vitesse perçue par l'utilisateur. La durée totale est importante pour la facturation et la planification de la capacité, mais un utilisateur qui voit le premier jeton en 600 ms et le dernier jeton en 8 s ressent une application rapide. Un utilisateur qui attend 4 secondes avant que quelque chose n'apparaisse n'apparaît pas, même si la durée totale est plus courte.

Invites : capturez ...
[Courte citation de 8% de l'article original]

Loading...