Streaming LLM : définition, frames et marqueur de fin
Le streaming LLM consiste à recevoir une réponse de modèle petit à petit au lieu d’attendre la fin complète. C’est utile pour afficher rapidement le début d’une réponse ou alimenter une interface de chat. Ollama documente le streaming de son API et indique aussi comment le désactiver.
Frame, token et texte
Ne confondez pas les niveaux. Une frame HTTP ou SSE est un morceau transporté. Elle peut contenir un fragment de texte, un token, plusieurs tokens ou une métadonnée. Votre code doit assembler le contenu utile et attendre le marqueur de fin avant de considérer la réponse terminée.
Pourquoi c’est pratique
L’utilisateur voit que le modèle travaille. Pour un long texte, cela améliore l’expérience. Pour un traitement machine strict, le streaming complique parfois la validation JSON. Dans ce cas, désactivez-le ou validez seulement après réception complète.
Erreur fréquente
Beaucoup de scripts déclenchent une action dès qu’un morceau contient un mot attendu. C’est risqué : le modèle peut corriger la phrase ensuite. Attendez le signal de fin, puis parsez la réponse finale.
Bon usage
Chat humain : streaming activé. Extraction structurée : streaming désactivé ou buffer complet. Logs : conservez la réponse finale plutôt que chaque fragment si vous voulez rejouer ou auditer.
Implémentation robuste
Le client doit accumuler les fragments dans un buffer, gérer les lignes vides, ignorer les événements non textuels si l’API en envoie, puis fermer proprement au marqueur final. Si la connexion coupe au milieu, marquez la réponse comme incomplète. Ne sauvegardez pas une réponse partielle comme si elle était validée.
Interface utilisateur
Dans une interface, affichez le flux pour rassurer l’utilisateur, mais gardez les boutons d’action sensibles désactivés tant que la réponse n’est pas terminée. Pour un agent qui déclenche des outils, le streaming doit rester visuel : la décision d’action doit se faire sur une réponse complète et validée.
Stockage
Pour l’audit, stockez la réponse finale et les métadonnées utiles : modèle, heure, prompt, statut terminé ou interrompu. Stocker chaque fragment est rarement utile hors debug et peut rendre les logs illisibles.
Cas JSON
Pour du JSON strict, demandez une réponse non streamée quand c’est possible. Sinon, bufferisez toute la réponse, retirez les marqueurs éventuels, puis parsez une seule fois. Parser fragment par fragment crée des faux échecs.
Découpage réseau et découpage du message
Un morceau reçu sur le réseau peut s’arrêter au milieu d’une ligne JSON. À l’inverse, une lecture réseau peut contenir plusieurs événements. Le parseur doit reconstituer les messages selon le protocole annoncé par l’API, par exemple des objets JSON séparés par des retours à la ligne, et non supposer qu’une lecture égale un token.
La présence d’un début de réponse réduit l’attente perçue, pas nécessairement le temps total de calcul. Mesurez séparément le délai jusqu’au premier fragment et celui jusqu’à la fin si vous comparez des configurations. Un flux interrompu reste incomplet même si le texte affiché paraît grammaticalement terminé.