~/tools / Faire tourner un LLM local sur votre serveur / Ollama Stream Reader
Ollama Stream Reader — Recollez un stream Ollama et voyez sa vitesse et sa raison d'arrêt
Collez une réponse en streaming d'Ollama, de /api/chat, /api/generate ou du /v1/chat/completions compatible OpenAI, et l'outil recolle les morceaux en texte complet, en thinking et en appels d'outils. Il indique pourquoi le modèle s'est arrêté, à quelle vitesse il a généré et traité le prompt, et si le stream a été coupé, et vous donne le message de l'assistant à ajouter à la requête suivante. Rien ne quitte votre navigateur.
Comment enregistrer un stream avec curl
-N désactive la mise en tampon de curl, et > stream.txt enregistre le stream dans un fichier. Remplacez le modèle et le message par les vôtres.
curl -sN http://localhost:11434/api/chat -d '{"model":"qwen2.5:7b","messages":[{"role":"user","content":"Hello"}]}' > stream.txt
curl -sN http://localhost:11434/v1/chat/completions -H "Content-Type: application/json" -d '{"model":"qwen2.5:7b","stream":true,"stream_options":{"include_usage":true},"messages":[{"role":"user","content":"Hello"}]}' > stream.txtLu comme un stream /api/chat (un objet JSON par ligne).
Résumé
- Modèle
- qwen2.5:7b
- Raison de l'arrêt
- stop
- Chunks
- 7
- Tokens générés
- 7
- Vitesse de génération
- 10.4 tokens/s
- Tokens du prompt
- 35
- Vitesse du prompt (tokens qui n'étaient pas dans le cache)
- 64.1 tokens/s
- Temps de chargement du modèle
- 4.923 s
- Temps total
- 6.310 s
- Du premier au dernier chunk
- 0.675 s
Texte
Hello, nice to meet.
Message de l'assistant pour la requête suivante
Ajoutez-le à messages, suivi des résultats des appels d'outils, s'il y en a.
{
"role": "assistant",
"content": "Hello, nice to meet."
}eval_count compte aussi les tokens des appels d'outils, qui ne sont pas envoyés comme texte. Dans notre test, un appel d'outil est arrivé dans un seul chunk avec eval_count 20.
La documentation d'Ollama indique que prompt_eval_duration ne couvre que les tokens du prompt qui n'étaient pas dans le cache. La vitesse du prompt affichée ici ne divise que ces tokens. Toutes les durées sont en nanosecondes ; dans la forme OpenAI, les timings sont en millisecondes entières.
Dans la forme compatible OpenAI, les nombres de tokens ne sont envoyés qu'avec stream_options.include_usage, dans un chunk supplémentaire avant data: [DONE]. Si le stream est coupé, ce chunk n'arrive pas.
Formats d'après la documentation d'Ollama sur le streaming et l'usage et son code source (v0.40.15), vérifiés avec de vrais streams d'Ollama 0.40.11 le 2026-11-07. Ollama : Streaming
Tout se fait dans votre navigateur. L'outil ne se connecte à rien.
Ollama envoie ses réponses en streaming par défaut. /api/chat et /api/generate envoient un objet JSON par ligne (newline-delimited JSON) : chaque ligne porte quelques caractères de la réponse, et la dernière ligne a done à true et porte les nombres de tokens et les durées, en nanosecondes. Le /v1/chat/completions compatible OpenAI ne fait du streaming que lorsque stream vaut true. Il envoie alors des server-sent events : des lignes qui commencent par data:, un chunk à part avec un delta vide et le finish_reason, et data: [DONE] à la fin. Les nombres de tokens n'arrivent que si la requête définit stream_options.include_usage, dans un chunk supplémentaire avec une liste choices vide, et Ollama y ajoute un objet timings. Cet outil lit les trois formes, y compris la sortie de curl -i avec ses en-têtes HTTP, recolle content, thinking (reasoning dans la forme OpenAI) et les appels d'outils, et liste ce qui ne va pas : un stream sans ligne done ou sans [DONE] a été coupé ; une ligne {"error": …} signifie qu'Ollama s'est arrêté sur une erreur après avoir commencé à envoyer ; done_reason length signifie que num_predict ou max_tokens a été atteint. La vitesse de génération est eval_count divisé par eval_duration. Pour le prompt, la documentation d'Ollama indique que prompt_eval_duration ne couvre que les tokens du prompt qui n'étaient pas dans le cache, donc l'outil ne divise que ces tokens par cette durée. Dans la forme OpenAI, le timings.prompt_per_second d'Ollama divise tous les tokens du prompt, y compris ceux du cache, par ce temps. Dans notre test, il a indiqué 360.8 tokens par seconde pour un prompt dont 34 tokens sur 35 venaient du cache et dont le seul token restant a pris 97 ms. Les appels d'outils dans la forme OpenAI peuvent arriver en morceaux qui partagent un index, donc l'outil recolle les arguments par index ; Ollama lui-même envoie chaque appel d'outil en entier, dans un seul chunk. Nous avons vérifié l'outil avec de vrais streams d'Ollama 0.40.11 avec qwen2.5:7b, et les formats avec la documentation et le code source d'Ollama.
Le cœur de cet outil est open source, sous licence MIT. github.com/seigo5555/toolkitbox-lib/src/ollama-stream.ts
Cas d'usage
- Voir la réponse entière d'une requête en streaming faite avec curl, au lieu de la lire morceau par morceau, un par ligne
- Savoir si un stream a été coupé, s'est arrêté à la limite de longueur ou s'est terminé sur une erreur
- Mesurer la vitesse de génération et de traitement du prompt d'un modèle sur votre machine ou votre serveur
Utilisation
- Lancez votre requête avec curl -sN et enregistrez la sortie dans un fichier, ou copiez ce que votre programme a reçu.
- Collez le stream entier. L'outil détecte s'il vient de /api/chat, /api/generate ou /v1/chat/completions.
- Lisez les problèmes et les chiffres, et copiez le texte ou le message de l'assistant pour la requête suivante.
FAQ
Pourquoi n'y a-t-il pas de nombres de tokens dans mon stream de /v1/chat/completions ?
Dans la forme compatible OpenAI, les nombres ne sont envoyés que lorsque la requête définit stream_options à {"include_usage": true}. Ils arrivent alors dans un chunk supplémentaire avec une liste choices vide, juste avant data: [DONE]. /api/chat et /api/generate les mettent toujours sur la dernière ligne.
Pourquoi la vitesse du prompt est-elle si différente de timings.prompt_per_second ?
La documentation d'Ollama indique que prompt_eval_duration ne couvre que les tokens du prompt qui n'étaient pas dans le cache. Le timings.prompt_per_second d'Ollama divise tous les tokens du prompt, y compris ceux du cache, par cette durée, donc il paraît bien plus rapide quand le cache a servi. L'outil ne divise que les tokens qui n'étaient pas dans le cache.
Le modèle a appelé un outil mais eval_count vaut 20. Où sont ces tokens ?
Le texte d'un appel d'outil n'est pas envoyé comme content ; Ollama le transforme en tool_calls et l'envoie dans un seul chunk. Les tokens sont quand même générés et comptés. Dans notre test, un appel d'outil avec un argument est arrivé dans un seul chunk avec eval_count 20.
Pourquoi /api/chat indique-t-il stop quand le modèle a appelé un outil ?
/api/chat garde done_reason à stop. Le endpoint compatible OpenAI remplace stop par tool_calls dans finish_reason lorsqu'un appel d'outil a été envoyé.
Que faire du message de l'assistant ?
La documentation d'Ollama note qu'il faut recoller les morceaux du stream pour conserver l'historique de la conversation, ce qui compte surtout pour les appels d'outils. Ajoutez le message à messages, ajoutez le résultat de chaque appel d'outil comme un message avec le rôle tool, et envoyez la requête suivante.
Mes données sont-elles envoyées quelque part ?
Non. Le stream est lu dans votre navigateur. Les commandes curl ne sont que du texte à exécuter vous-même.
Articles liés
- Surveiller la mémoire d'Ollama sur un petit VPSVoir ce qu'Ollama garde en mémoire, combien de temps et quels réglages changent cela : ollama ps, keep_alive et les limites, d'après la FAQ officielle.
- Connecter Dify à Ollama sur votre propre VPSFaites tourner Dify sur votre propre VPS avec Ollama comme modèle : installation, champs du plugin, problème d'adresse dans Docker et embeddings, d'après la documentation officielle.
- Lancer un LLM local sans PC coûteux : guide du débutant pour utiliser un VPSPas de PC puissant ? Louez un VPS et faites tourner un petit LLM local depuis votre navigateur : six étapes, de l'estimation de la mémoire à un écran de discussion protégé, avec les limites indiquées honnêtement.