Ilustración editorial para Streaming de respuestas de IA: cómo mostrar progreso sin ejecutar datos o acciones antes de tener una salida válida
Imagen generada con gpt-image-2.5-sunburst para InferamaSource ↗
01

Un fragment visible n’est pas une sortie exploitable

Une interface peut afficher du texte au fil de sa réception depuis un modèle tout en maintenant une frontière stricte entre ce texte et l’état du système. Cette frontière importe, car un delta de streaming indique seulement qu’une partie d’une génération a été reçue. Il ne prouve ni que le message est terminé, ni que son sens ne changera pas, ni qu’un objet structuré est complet, ni qu’un appel d’outil contient des arguments valides.

La latence perçue et la validité sont deux propriétés différentes. Le streaming peut réduire le délai jusqu’au premier fragment et fournir à l’utilisateur des signaux d’activité utiles. Mais le résultat qui déclenche une opération doit respecter des exigences supplémentaires : réception d’une terminaison non ambiguë, assemblage complet, validation syntaxique et sémantique, rattachement à une génération précise et, lorsque le risque le justifie, confirmation humaine. Une application qui confond ces niveaux peut créer des enregistrements incomplets, indexer des affirmations ensuite retirées ou exécuter deux fois une action après une interruption.

Il est préférable de traiter ce qui est affiché pendant la transmission comme une projection provisoire. Elle peut être utile pour la lecture, la révision et l’annulation, mais doit être identifiée comme un brouillon. L’état métier, lui, doit dériver d’une représentation finale contrôlée par le serveur ou par un composant de confiance. Cette règle s’applique aux assistants conversationnels, à l’extraction documentaire, à la génération de code, à l’automatisation administrative et aux agents utilisant des outils.

Les API des fournisseurs n’emploient pas toutes les mêmes noms d’événements et n’offrent pas exactement les mêmes garanties. Certaines documentent des événements incrémentiels, des identifiants de réponse et un événement de fin ; d’autres décrivent des états d’exécution ou un signal de résultat. L’intégration doit reposer sur le contrat concret de l’API retenue et ne jamais déduire qu’une sortie est complète parce qu’aucun trafic n’est arrivé pendant quelques secondes.

02

Concevoir une machine à états explicite

La manière la plus claire d’empêcher que l’interface devienne un canal d’exécution consiste à modéliser le cycle de vie de chaque génération. L’identifiant interne de la génération doit être créé avant l’ouverture de la connexion et associé, lorsqu’il existe, à l’identifiant renvoyé par le fournisseur. Il doit aussi être lié à la session, à l’utilisateur ou au principal autorisé, à la version du prompt ou de la configuration appliquée et à l’opération métier demandée.

Le premier état est reçu : un événement est arrivé avec des métadonnées de transport, mais son contenu n’a pas encore été accepté. Il passe ensuite dans un tampon provisoire, où il est conservé selon le numéro de séquence ou la position définie par le protocole. Le client peut lire ce tampon pour afficher un brouillon. Si le flux livre des parties de plusieurs éléments, tels que du texte, un raisonnement non exposé et des arguments d’outil, il faut maintenir des tampons distincts par élément et par type.

Lors de l’assemblage, le consommateur transforme les fragments en une représentation candidate complète : texte final, objet structuré ou requête d’outil. Cette étape n’est pas une validation. Par exemple, le fait qu’une concaténation puisse être interprétée comme du JSON ne prouve pas qu’elle ne contient que les champs autorisés, que les valeurs appartiennent aux plages acceptables ou que l’utilisateur a autorisé l’action qui en résulte.

Une sortie ne devient validée qu’après vérification de l’événement terminal ou de l’état final documenté, de l’ordre et de l’intégrité des événements nécessaires, du schéma attendu et des règles métier. Résultat confirmé signifie en outre que le système a persisté la version validée avec une clé stable et enregistré la décision. Action exécutée est un état ultérieur, et non un synonyme de validée : il exige une politique d’autorisation, une clé d’idempotence et une preuve de son résultat.

Les états terminaux alternatifs méritent un traitement spécifique. Annulée indique que l’utilisateur ou le système a demandé l’arrêt de l’expérience ; incomplète indique qu’une partie indispensable manque ou que le fournisseur a signalé une fin non satisfaisante ; échouée représente une erreur traitable ; expirée indique qu’il n’est plus sûr de reprendre. Aucun de ces états ne doit promouvoir le tampon provisoire au rang de résultat final.

Transition recommandée pour une génération

  1. 01Créer une génération interne et enregistrer la finalité de l’opération.
  2. 02Recevoir les événements et vérifier qu’ils appartiennent à la génération attendue.
  3. 03Trier ou dédupliquer les événements avant de les ajouter aux tampons provisoires.
  4. 04N’afficher que la projection provisoire autorisée par l’interface.
  5. 05Après le signal terminal documenté, assembler la représentation candidate.
  6. 06Valider l’intégrité, le schéma, les règles métier et l’autorisation.
  7. 07Persister une version confirmée et immuable de la sortie validée.
  8. 08S’il existe un outil, demander une confirmation lorsque cela s’applique et exécuter avec une clé d’idempotence.
03

Déterminer ce qui peut être affiché, enregistré, indexé ou exécuté

La politique ne doit pas dépendre uniquement du fait que le contenu paraît raisonnable. Elle doit dépendre de son état et de la catégorie de flux. Un chat informatif peut tolérer que la personne voie un brouillon clairement signalé. Une extraction qui alimente une base de connaissances exige une version finale avant l’indexation. Un outil qui crée une réservation, envoie une communication ou modifie des droits nécessite des contrôles supplémentaires, même si ses arguments ont déjà passé une validation de schéma.

Conserver de la télémétrie de transport n’équivaut pas à persister la sortie comme contenu métier. Il peut être légitime de retenir un journal minimal d’événements reçus afin de diagnostiquer les interruptions et de réconcilier les sessions, dans le respect des politiques applicables de confidentialité et de conservation. Cela doit être distingué du stockage du texte partiel comme réponse approuvée. De même, un journal ne doit pas transformer des secrets, des données personnelles ou des instructions potentiellement sensibles en une copie dépourvue de contrôles.

L’indexation appelle une décision particulièrement prudente. Des fragments partiels peuvent contenir une conclusion intermédiaire qui disparaît à la fin de la réponse. Les indexer entraîne la récupération future de matière non confirmée et complique l’explication de ce qu’une personne a vu et de la version que le système a adoptée. Indexez la version validée, avec son identifiant de génération et de version, et permettez le retrait ou le remplacement auditable de cette version.

Matrice de décision par état

ÉtatAfficher à la personnePersister comme résultatIndexerExécuter une action externe
Événement reçuPas nécessairement ; vérifier d’abord l’appartenance et le formatNonNonNon
Tampon provisoireOui, comme brouillon avec une annulation disponibleUniquement des traces techniques minimales si la politique l’autoriseNonNon
Objet assembléÉventuellement, toujours comme provisoirePas comme résultat confirméNonNon
Sortie validéeOui, comme résultat finalOui, avec version et identifiantOui, si le flux l’exigePas encore par défaut
Résultat confirméOuiOuiOui, le cas échéantUniquement si la politique d’action l’autorise
Action exécutéeOui, avec état et justificatif disponibleOui, consigner la décision et le résultatSans objetDéjà réalisée ; ne pas répéter sans idempotence
04

Consommer le transport sans supposer que les paquets sont des messages

Dans un flux reposant sur des événements envoyés par le serveur, le protocole définit la formation des événements et prévoit les reconnexions. Le transport utilise du texte encodé en UTF-8 et la limite d’un paquet réseau ne correspond pas à la limite d’un caractère, d’une ligne d’événement ou d’un objet JSON. Le consommateur doit donc utiliser un décodeur incrémentiel et un analyseur d’événements ; il ne doit pas convertir chaque lecture d’octets en chaîne indépendante en supposant qu’elle contient un événement complet.

Après reconstruction d’un événement de protocole, il reste à interpréter le contrat de l’API. Un texte peut arriver sous forme de deltas ; les arguments d’un appel de fonction peuvent être répartis ; les éléments de sortie peuvent être entrelacés. Le consommateur doit regrouper selon les identifiants documentés, par exemple la génération, l’élément ou l’index de sortie, et appliquer les numéros de séquence lorsqu’ils sont disponibles. Une arrivée répétée ne doit ni dupliquer des caractères, ni créer deux objets, ni provoquer une seconde exécution.

La fermeture de la connexion ne constitue pas davantage une preuve suffisante de succès. La connexion peut être fermée par une annulation, un proxy, un délai maximal ou une erreur. Seuls le signal terminal et l’état documenté par le fournisseur permettent de classer la génération comme terminée, incomplète ou échouée. Si cette preuve manque, l’état correct est incertain ou incomplet, et la promotion comme l’exécution sont bloquées.

Toutes les API ne fournissent pas de somme de contrôle, de version finale ou de mécanisme de reprise. Lorsqu’un identifiant de réponse et un curseur de séquence existent, conservez-les avec le dernier événement accepté. Dans le cas contraire, une reconnexion peut nécessiter la création d’une nouvelle génération du point de vue métier. Il n’est pas sûr de déduire que deux séquences semblables sont la même réponse à partir de leur seul contenu.

05

Appel d’outils : complet ne signifie pas autorisé

Les appels d’outils méritent une barrière indépendante, car ils transforment du texte généré en effets en dehors du modèle. Le fait que le nom d’une fonction ou une partie de ses arguments apparaisse ne constitue pas une requête exécutable. Les arguments doivent être accumulés jusqu’au signal de fin correspondant, convertis en représentation structurée et validés selon un schéma strict. Les champs inconnus, les conversions implicites et les valeurs hors politique doivent être rejetés ou imposer une nouvelle interaction.

La validation de schéma est nécessaire, mais insuffisante. Un outil de transfert peut recevoir un montant correctement formaté tout en dépassant une limite, sans autorisation, ou à destination d’un bénéficiaire non autorisé. Les règles métier doivent être exécutées dans le service qui contrôle l’action, et pas seulement dans le client qui affiche la conversation. Pour les opérations importantes, une confirmation utilisateur doit présenter une description stable de l’action dérivée des arguments déjà validés.

L’exécution doit porter une clé d’idempotence calculée ou attribuée par le serveur. Cette clé doit être liée à l’intention confirmée, non à chaque nouvelle tentative réseau. Avant de réessayer, l’exécuteur consulte le registre des opérations afin de déterminer si cette clé possède déjà un résultat. Cela importe, car HTTP avertit qu’il est dangereux de réessayer une opération non idempotente lorsqu’il est impossible de savoir si la requête d’origine a déjà été appliquée.

Le résultat de l’outil doit lui aussi être réconcilié. Si le fournisseur externe accepte l’opération mais que la réponse est perdue, l’état n’est pas « non exécutée » : il est inconnu jusqu’à la consultation d’un identifiant d’opération ou l’application d’une procédure de compensation. Concevoir ce cas dès le départ évite qu’un bouton de nouvelle tentative devienne un ordre dupliqué.

Contrôles pour un outil externe

ÉtapeContrôle minimalRésultat en cas d’échec
Arguments partielsAccumuler par identifiant d’appel ; ne pas les interpréter pour exécuterConserver le brouillon ou l’écarter
Arguments completsValider le JSON, le schéma et les champs autorisésRejeter l’appel
IntentionAppliquer l’autorisation, les limites et les règles métierBloquer et expliquer le motif
ConfirmationLa demander lorsque la politique de risque l’exigeNe pas créer l’ordre externe
ExécutionUtiliser une clé d’idempotence et consigner la tentativeConsulter l’état avant de réessayer
Réponse externeConserver l’identifiant et un résultat vérifiableMarquer comme état inconnu ou en attente de réconciliation
06

Interruptions, annulations, reprise et expérience produit

En cas d’interruption, l’application doit préserver la distinction entre ce qui a été vu et ce qui a été confirmé. Elle peut laisser le brouillon visible avec un avertissement d’interruption, proposer une nouvelle tentative ou tenter une reprise lorsque le protocole et le fournisseur le permettent. En cas de reprise, elle doit demander ou traiter uniquement les événements postérieurs au dernier curseur confirmé et dédupliquer toute répétition. Si la continuité ne peut être prouvée, il est préférable de démarrer une nouvelle génération et de l’identifier comme telle.

L’annulation par l’utilisateur requiert deux opérations distinctes : cesser d’afficher ou de demander davantage de contenu, puis décider du traitement du travail déjà démarré. Annuler l’abonnement n’implique pas nécessairement que le fournisseur ait arrêté le calcul. Le système doit consigner la demande d’annulation, empêcher les promotions ultérieures non souhaitées et traiter tout événement arrivant après elle selon une politique définie. Une action externe déjà envoyée exige une consultation ou une compensation, et non une supposition fondée sur la fermeture de l’interface.

Du point de vue produit, les indicateurs doivent communiquer l’activité sans promettre l’achèvement. Un curseur de saisie, un état « génération en cours » et une option d’arrêt conviennent au brouillon. Une étiquette telle que « résultat prêt » doit être réservée à la sortie validée. Si l’édition du brouillon est permise, l’édition humaine doit créer une branche ou une version distincte : elle ne doit pas être confondue avec la réponse confirmée par le système.

La restauration d’une session doit permettre d’expliquer ce qui s’est produit. Conservez le lien entre la génération, les événements acceptés, le dernier curseur, la version validée et, s’il y en a une, l’opération externe. Cette traçabilité n’exige pas de stocker indéfiniment tout le texte ; le niveau de détail doit être adapté à la sensibilité des données et aux obligations de conservation.

Réponse à une déconnexion

  1. 01Marquer la transmission comme interrompue sans déclarer de succès.
  2. 02Conserver le dernier identifiant ou curseur accepté et l’état des tampons.
  3. 03Tenter une reprise uniquement à l’aide du mécanisme documenté par le fournisseur.
  4. 04Dédupliquer les événements au moyen de la séquence, de l’identifiant d’événement, ou des deux.
  5. 05Exiger à nouveau un signal terminal valide avant de valider la sortie.
  6. 06S’il n’existe pas de continuité démontrable, clôturer comme incomplète et proposer une nouvelle génération.
  7. 07Bloquer tout outil en attente jusqu’à reconstruction et validation d’une intention complète.
07

Télémétrie et tests avant le déploiement

Les métriques doivent dissocier la rapidité perçue de la correction. Enregistrez le délai jusqu’au premier fragment, le délai jusqu’à la terminaison, le délai jusqu’à la validation et, dans les flux avec outils, le délai jusqu’à la confirmation et à l’exécution. Enregistrez aussi les abandons, les annulations, les reconnexions, les événements écartés comme doublons, les générations incomplètes et les écarts entre le contenu provisoire et la version confirmée. Ces signaux permettent de détecter si une amélioration visuelle masque une dégradation de la complétude.

N’utilisez pas le texte intégral comme unique base d’observabilité. Un identifiant de génération, l’identifiant fournisseur lorsqu’il existe, la séquence, le type d’événement, les transitions d’état et les motifs de rejet suffisent généralement à examiner de nombreux incidents. Lorsqu’il est nécessaire de conserver du contenu pour l’audit, appliquez des contrôles d’accès, une minimisation et une politique explicite de conservation.

Les tests de chaos doivent intervenir à chaque frontière, et pas seulement en déconnectant avant le premier jeton. Simulez des coupures au milieu d’un caractère multioctet, entre des lignes d’événement, au sein du JSON, après des arguments d’outil apparemment complets et juste avant le signal terminal. Simulez des renvois d’événements, des changements d’ordre lorsque le contrat ne les interdit pas, des réponses terminales d’erreur, des annulations tardives et la perte de la réponse du système externe. Le critère essentiel est qu’aucun scénario ne transforme un contenu incomplet en résultat confirmé ni ne déclenche une seconde action pour la même finalité.

Comme vérification de déploiement, contrôlez que le client ne détient pas d’identifiants permettant d’exécuter directement des actions sensibles ; que la validation est centralisée ; que le stockage d’idempotence survit à des redémarrages raisonnables ; et que les tableaux de bord distinguent une génération abandonnée d’une action confirmée. Consultez également les parcours internes Apprendre, Comparer et Découvrir afin d’aligner cette décision d’intégration sur les modèles et capacités du produit.

Questions ouvertes

  • La disponibilité d’identifiants de séquence, de curseurs de reprise et d’événements terminaux non ambigus varie selon les API et leurs versions.
  • La possibilité de reprendre une transmission et le comportement face aux événements répétés doivent être vérifiés dans le contrat propre au fournisseur.
  • Les règles imposant une confirmation humaine dépendent du risque de l’outil, de l’autorisation de l’utilisateur et des politiques de chaque organisation.
  • La conservation des tampons, des traces et du contenu confirmé doit être définie selon la sensibilité des données et les exigences applicables.
08

Poursuivre l’exploration

08

Sources consultées

03

Corrections et transparence

Si vous repérez une information incorrecte ou obsolète, envoyez-nous la page et la source à vérifier.

Proposer une correction