Vizion Web
IA & LLM

Streaming SSE

Définition

Server-Sent Events. Protocole qui permet d'afficher les tokens du LLM au fur et à mesure de leur génération côté client, plutôt qu'attendre la réponse complète. Améliore drastiquement le ressenti utilisateur.

Comment ça marche

Un LLM génère ses réponses token par token, à un rythme de quelques dizaines à quelques centaines de tokens par seconde selon le modèle. Sans streaming, le serveur attend la fin de la génération pour tout renvoyer d'un bloc, ce qui peut prendre 5 à 30 secondes pour une réponse longue. En streaming SSE (Server-Sent Events), chaque token est poussé au navigateur dès qu'il est produit côté fournisseur, à travers la connexion HTTP ouverte. Le navigateur écoute le flux et met à jour l'interface au fil de l'eau. La latence du premier token (TTFT) reste la même, mais le temps perçu jusqu'à la première information utile chute massivement.

Pourquoi SSE plutôt qu'autre chose

SSE est un protocole HTTP unidirectionnel : le serveur pousse des messages au client sur une seule connexion ouverte, sans que le client ait besoin de répondre. C'est plus simple que WebSocket (qui ouvre un canal bidirectionnel et demande plus d'infrastructure) et parfaitement adapté au streaming de génération. SSE traverse les proxies HTTP standards, fonctionne avec les CDN, ne demande aucune configuration spéciale. Le format est trivial : des lignes data: <token>\n\n séparées par des doubles sauts de ligne. C'est devenu le standard de fait pour toute interface conversationnelle, depuis que ChatGPT l'a popularisé.

L'impact sur l'expérience perçue

L'utilisateur voit la réponse se construire à l'écran comme dans ChatGPT. Même si le temps total ne change pas (parfois il augmente légèrement à cause du overhead), l'attente perçue chute fortement : la première lettre arrive en moins d'une seconde, on commence à lire immédiatement, et le reste se construit pendant qu'on lit. C'est la différence entre une UX qui paraît rapide et une UX qui paraît bloquée. Sur les benchmarks utilisateur, le streaming améliore la satisfaction de 30 à 50% sans aucun gain de performance brute. Pour toute interface conversationnelle, c'est devenu non négociable.

Implémentation côté Next.js

Sur Next.js, on expose une route API qui renvoie un ReadableStream. Le SDK OpenAI fournit stream: true sur les appels, le SDK Anthropic gère également le streaming nativement. Vercel AI SDK simplifie tout : useChat et useCompletion côté client, streamText côté serveur, avec gestion des erreurs, des outils et de la concurrence. Côté serveur Edge ou Node, on convertit le stream du fournisseur en réponse HTTP avec content-type text/event-stream et cache-control: no-cache. Côté client, on consomme avec EventSource ou les hooks fournis par AI SDK. Quelques dizaines de lignes suffisent pour un chat fonctionnel.

Les pièges à éviter

Trois pièges classiques. La gestion des erreurs mid-stream : si le fournisseur déconnecte au milieu de la génération, on doit détecter l'erreur et l'afficher proprement sans casser l'UI. La gestion des tools : pendant un tool call, le streaming s'interrompt, on doit gérer plusieurs phases de stream (texte, tool call, texte). Les buffers intermédiaires : certains hébergeurs (Heroku, anciens setups Nginx) buffrent les réponses HTTP par défaut, ce qui annule le streaming ; on force le streaming avec les bons headers (X-Accel-Buffering: no). Et le timeout : sur Vercel Edge, les fonctions sont limitées dans le temps, on configure max-duration pour permettre des générations longues.

Quand l'utiliser

Le streaming s'impose pour toute UI conversationnelle où l'utilisateur attend une réponse longue : chat, agent qui raisonne, génération de contenu, transformation de texte. À l'inverse, pour des appels où on a besoin de la réponse complète avant d'agir (extraction structurée, classification, tool call sans interaction), le streaming n'apporte rien et complexifie inutilement le code. Pour les usages de type batch ou pipeline serveur-à-serveur (génération de descriptions produits, résumé de documents en masse), on garde un appel synchrone classique. Le streaming est un outil d'UX, pas un outil d'orchestration.