Back to deblo
deblo

Streaming SSE : réponses IA en temps réel dans SvelteKit

20+ types d'événements, quiz intégrés, téléchargements de fichiers, déductions de crédits et progression des outils -- le tout diffusé en temps réel via Server-Sent Events.

Juste A. Gnimavo (Thales) & Claude | March 26, 2026 4 min deblo
EN/ FR/ ES
deblossestreamingsveltekittemps-réelopenrouter

Par Thales & Claude -- CEO & AI CTO, ZeroSuite, Inc.

La différence entre un bon produit IA et un excellent se mesure souvent en millisecondes. Pas le temps de réponse total -- les utilisateurs attendront 10 ou 20 secondes pour une réponse réfléchie à une question complexe -- mais le temps entre l'appui sur « Envoyer » et l'apparition du premier caractère. Cet intervalle est la zone morte où les utilisateurs se demandent si l'application est cassée.

Deblo élimine cette zone morte grâce au streaming par Server-Sent Events (SSE). La réponse de l'IA commence à apparaître en moins de 500 millisecondes, caractère par caractère, pendant que le backend la génère encore. Mais le streaming de Deblo va bien au-delà du simple texte : nous diffusons 20+ types d'événements incluant quiz intégrés, fichiers téléchargeables, mises à jour de crédits, progression d'exécution d'outils, annotations de citations et liens de paiement -- le tout via une seule connexion SSE.

Pourquoi SSE plutôt que WebSocket

Nous avons choisi SSE pour trois raisons spécifiques :

  1. Le streaming unidirectionnel est tout ce dont nous avons besoin. L'utilisateur envoie un message (un POST HTTP classique), et l'IA diffuse la réponse.
  2. Meilleur support des pare-feu et proxies. SSE fonctionne sur HTTP/1.1 ou HTTP/2 standard. En Afrique, où beaucoup d'utilisateurs sont derrière des proxies opérateurs, c'est crucial.
  3. Déploiement et débogage plus simples. Les connexions SSE apparaissent dans les DevTools du navigateur comme une requête standard.

20+ types d'événements

Chaque événement SSE est un objet JSON préfixé par les lignes event: et data:. Les types d'événements incluent : content (texte principal), quiz (question à choix multiples intégrée), file (fichier généré téléchargeable), tool_start/tool_end (exécution d'outils), credit_update (crédits déduits), suggestions (puces de réponse rapide), bonus_credits (crédits bonus attribués), annotations (citations URL), reasoning (chaîne de pensée), heartbeat (keep-alive toutes les 15 secondes) et done (flux terminé).

Le pattern de streaming backend

Le backend produit les événements SSE depuis un générateur asynchrone. Le pattern de base pour le streaming augmenté par les outils : le LLM diffuse des tokens de texte comme événements content, et quand il décide d'appeler un outil, le serveur émet tool_start, exécute l'outil, puis émet tool_end. C'est du SSE-dans-SSE : nous recevons un flux SSE d'OpenRouter et le ré-émettons comme un flux SSE vers le frontend, en transformant et enrichissant les événements au passage.

Le frontend : streamChat() avec 42+ paramètres

La fonction frontend streamChat() est le hub central pour toute communication SSE. Elle utilise fetch avec getReader() plutôt que l'API EventSource du navigateur, car EventSource ne supporte que les requêtes GET, mais notre endpoint de chat est un POST. La gestion du buffer est critique : les événements SSE peuvent être répartis sur plusieurs appels read(), surtout sur les connexions mobiles lentes.

Un quiz arrive en plein streaming

L'une des fonctionnalités distinctives de Deblo est les quiz intégrés. L'IA peut, à tout moment pendant sa réponse, insérer une question à choix multiples que l'élève doit répondre avant que la conversation continue. Quand le frontend reçoit cet événement, il rend un composant QuizWidget intégré dans la bulle de message de l'assistant.

Visualisation de la progression des outils : ProcessingSteps

Quand l'IA utilise des outils, l'utilisateur voit une chronologie en temps réel de ce qui se passe. C'est le composant ProcessingSteps, qui rend une chronologie verticale avec des indicateurs d'état animés pour chaque invocation d'outil. Chaque outil passe par trois phases : loading (animation spinner), completed (icône statique), ou error (X rouge).

Ce que nous avons appris sur le streaming

  1. La gestion du buffer n'est pas optionnelle. Les événements SSE répartis sur les paquets TCP sont la norme.
  2. Les heartbeats empêchent les timeouts des proxies. Sans événements keep-alive périodiques, les proxies inverses fermeront les connexions inactives après 30-60 secondes.
  3. Le typage des événements vaut la complexité. Avoir 20+ types d'événements distincts semble du sur-engineering, mais chaque type active une fonctionnalité UI spécifique.
  4. Désactivez le buffering à chaque couche. L'en-tête X-Accel-Buffering: no, Cache-Control: no-cache et la classe StreamingResponse de FastAPI gèrent la plupart de cela, mais il faut vérifier de bout en bout.

Le streaming est une de ces fonctionnalités où la complexité d'implémentation est invisible pour l'utilisateur. Quand ça marche, l'IA parle tout simplement. Les caractères apparaissent fluidement, les outils s'exécutent visuellement, les quiz surgissent en ligne. L'utilisateur ne pense jamais au SSE ou au parsing d'événements. Il voit juste un tuteur qui répond instantanément.


Ceci est l'article 7 de 20 dans la série « Comment nous avons construit Deblo.ai ».

Share this article:

Responses

Write a response
0/2000
Loading responses...

Related Articles

Thales & Claude deblo

Le Step Zero ne suffisait pas : comment valider un constructeur sans valider le runtime a fait tomber toutes les sessions vocales de Déblo l’heure où nous avons livré le streaming caméra temps réel

La phase 14 a livré Déblo Eyes — streaming caméra temps réel via LiveKit vers Gemini Live native audio. Le premier deploy a fait tomber toutes les sessions vocales en production en quatre-vingt-dix secondes parce que notre Step 0 avait validé le constructeur sans exercer le runtime. Le build log de comment Déblo a eu des yeux, ce qu’un pré-vol incomplet a coûté, et quels points de polish ont été livrés ou reportés.

33 min May 20, 2026
debloclaude-opus-4.7claude-codegemini-live +25
Thales & Claude deblo

Le tiret cadratin qui a tué la production : comment un slogan marketing dans un header HTTP a fait tomber le chat de Déblo pendant 24 heures

Deux jours avant la soumission App Store, tout le produit chat de Déblo s’est cassé silencieusement. Pas de spinner, pas de toast, aucune erreur dans l’UI — juste un silence radio. L’incident de 24 heures se résumait à un seul « é » dans la valeur d’un header HTTP qui levait une UnicodeEncodeError avant qu’aucune requête vers OpenRouter ne quitte le backend. Post-mortem d’une fausse hypothèse, d’une trace Sentry, et d’un fix de six lignes qui a débloqué le lancement.

30 min May 19, 2026
debloclaude-opus-4.7claude-codeincident +19
Thales & Claude deblo

Six heures, d’une page blanche à la review Apple — Comment nous avons soumis Déblo à l’App Store, en direct

Marche à marche en direct de la soumission de Déblo à l’App Store iOS en six heures : ce que les validateurs d’Apple ont rejeté (un superscript Unicode), ce que nous avons corrigé (un Promotional Text gaspillé sur des marques tierces), et les rouages de l’ASO iOS que presque tout le monde rate.

30 min May 13, 2026
debloclaude-opus-4.7claude-codeapp-store +16