Ollama : régler la longueur de contexte avec num_ctx
Ollama tronque les longs prompts avec une petite fenêtre par défaut. Réglez num_ctx par requête ou globalement, puis prévoyez la RAM du KV cache.
Fonctionnement de num_ctx et raisons pour lesquelles votre prompt long a été tronqué
La longueur de contexte d’Ollama correspond au nombre de tokens qu’un modèle chargé peut conserver en mémoire à la fois, et num_ctx est l’option qui la définit. Ollama choisit une valeur par défaut bien inférieure à la valeur maximale annoncée par le modèle. Un prompt plus long est donc tronqué avant même que le modèle ne le lise. La réponse n’indique pas que cela s’est produit.
Llama 3.1 8B est indiqué avec une fenêtre de contexte de 128k dans la bibliothèque de modèles Ollama. Un serveur avec sa configuration par défaut ne vous donnera pas cette valeur. La documentation d’Ollama indique des valeurs par défaut différentes selon les pages : la FAQ mentionne 4096 tokens, la référence Modelfile indique que num_ctx vaut par défaut 2048, et la page consacrée à la longueur de contexte indique que la valeur par défaut dépend de la VRAM disponible : 4k en dessous de 24 GiB, 32k de 24 GiB à moins de 48 GiB, et 256k à partir de 48 GiB. Chacune de ces valeurs était valable pour certaines versions. La leçon utile est donc la suivante : lisez la valeur utilisée par votre propre serveur en fonctionnement au lieu de faire confiance à une page quelconque, y compris celle-ci.
La troncature est discrète, car le modèle répond tout de même, et la réponse reste cohérente. Elle a été générée à partir de la fin de votre entrée. Un résumé qui ignore la première moitié d’un document peut donner l’impression que le modèle est peu performant. Il s’agit généralement d’une fenêtre de contexte trop petite.
Vérifier la longueur de contexte réellement appliquée par votre serveur Ollama
La vérification qui fonctionne avec toutes les versions est prompt_eval_count, c’est-à-dire le nombre de tokens du prompt que le serveur indique avoir traités. Envoyez plus de tokens que le contexte ne peut en contenir : ce nombre s’arrête alors à la limite.
sudo apt update && sudo apt install -y jq
LONG=$(python3 -c "print('the quick brown fox jumps over the lazy dog. ' * 2000)")
jq -n --arg p "$LONG" '{model:"llama3.1:8b", prompt:$p, stream:false, options:{num_ctx:4096}}' |
curl -s http://localhost:11434/api/generate -d @- |
jq '{prompt_eval_count, prompt_eval_duration}'Ce prompt contient environ 18,000 mots, soit largement plus de 4096 tokens. prompt_eval_count renvoie une valeur proche de 4096, et non du nombre réel de tokens, car le serveur a ignoré le reste. Exécutez de nouveau la commande avec "num_ctx":16384 : le nombre augmente. Si votre version renvoie une erreur au lieu de tronquer le prompt, le résultat est le même, mais le signal est plus explicite.
ollama psSur les versions qui l’affichent, la colonne CONTEXT indique la longueur de contexte utilisée actuellement par le modèle chargé. La colonne PROCESSOR, juste à côté, indique où le modèle est exécuté. 100% CPU est normal sur un VPS sans GPU. Une répartition telle que 30%/70% CPU/GPU sur une machine équipée d’un GPU signifie que les poids et le cache ne tiennent plus dans la VRAM. Une valeur augmentée de num_ctx en est généralement la cause.
journalctl -u ollama --no-pager | grep -i n_ctx | tail -n 5Le moteur d’inférence affiche la taille du contexte dans une ligne contenant n_ctx. La formulation exacte varie selon les versions. Considérez donc l’absence de cette ligne comme un changement de nom, et non comme une preuve d’un comportement particulier.
Quatre endroits où définir num_ctx
Dans la requête. Envoyez "options": {"num_ctx": 16384} à /api/generate ou /api/chat. Ce paramètre a priorité sur tous les autres et ne s’applique qu’à cet appel. Si sa valeur diffère de celle utilisée par le modèle chargé, le serveur recharge d’abord le modèle. Vous pouvez le voir dans load_duration de la réponse : la valeur passe de presque zéro à plusieurs secondes. Le même délai apparaît lorsque le modèle est resté inactif assez longtemps pour être déchargé. Une fois la taille de contexte définie, il est donc utile de laisser le modèle résident avec keep_alive.
Dans la session interactive. Dans ollama run, saisissez /set parameter num_ctx 16384. Le paramètre reste valable pendant cette session.
Dans un Modelfile. Cette méthode intègre la valeur au modèle nommé. Tous les clients l’utilisent alors sans modification côté client.
FROM llama3.1:8b
PARAMETER num_ctx 16384ollama create llama3.1-16k -f ./Modelfile
ollama run llama3.1-16kSur le serveur. OLLAMA_CONTEXT_LENGTH définit la valeur par défaut de toutes les requêtes qui ne fournissent pas leur propre num_ctx. Avec systemd, ajoutez un drop-in au lieu de modifier le fichier d’unité.
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_CONTEXT_LENGTH=16384"sudo systemctl daemon-reload
sudo systemctl restart ollama
ollama psL’ordre de priorité est particulièrement important lorsque vous déboguez le client d’une autre personne. Une requête qui contient num_ctx a priorité sur la valeur par défaut du serveur. Une interface de chat ou un agent qui envoie sa propre valeur faible peut donc annuler discrètement votre modification systemd. Lorsque vous connectez un agent de programmation à votre serveur Ollama, vérifiez ce que le client envoie avant d’incriminer le serveur.
Pourquoi vous ne pouvez pas simplement définir num_ctx sur la valeur maximale du modèle
L’attention fait lire à chaque token tous les tokens qui le précèdent. Les clés et les valeurs calculées pour les tokens précédents sont conservées afin de ne pas être recalculées pour chaque nouveau token. Ce stockage constitue le cache KV (cache key/value). Il est alloué pour toute la valeur de num_ctx au chargement du modèle, et non au fur et à mesure que la conversation s’allonge. Un contexte important consomme donc cette mémoire même avec un prompt d’une seule ligne.
Chaque couche conserve un vecteur de clé et un vecteur de valeur par tête key/value pour chaque token. Le calcul tient donc sur une ligne :
kv_bytes_per_token = 2 * layers * kv_heads * head_dim * bytes_per_valueLe 2 compte séparément les clés et les valeurs. Relevez les autres nombres dans les informations de votre propre modèle.
curl -s http://localhost:11434/api/show -d '{"model":"llama3.1:8b"}' |
jq '.model_info | {ctx: ."llama.context_length", layers: ."llama.block_count", heads: ."llama.attention.head_count", kv_heads: ."llama.attention.head_count_kv", embed: ."llama.embedding_length"}'Llama 3.1 8B indique 32 couches et 8 têtes key/value. La dimension des têtes correspond à embed divisée par heads. Ici, 4096 / 32 = 128. Certains modèles la publient directement sous le nom llama.attention.key_length. Le cache utilise par défaut des valeurs f16, donc bytes_per_value vaut 2. Le calcul 2 32 8 128 2 donne 131,072 octets. Cela représente 128 KiB de cache pour chaque token du contexte. Multipliez cette valeur par la longueur du contexte : le coût devient rapidement concret.
Les données de ce graphique
[
{
"label": "4k",
"kv_cache_gib": 0.5,
"total_ram_gib": 5.1
},
{
"label": "8k",
"kv_cache_gib": 1,
"total_ram_gib": 5.6
},
{
"label": "16k",
"kv_cache_gib": 2,
"total_ram_gib": 6.6
},
{
"label": "32k",
"kv_cache_gib": 4,
"total_ram_gib": 8.6
},
{
"label": "64k",
"kv_cache_gib": 8,
"total_ram_gib": 12.6
},
{
"label": "128k",
"kv_cache_gib": 16,
"total_ram_gib": 20.6
}
]Ces 6 lignes sont calculées à partir de la formule ci-dessus, et non mesurées. La colonne Total ajoute les 4.9 GB du téléchargement indiqué par la bibliothèque Ollama pour llama3.1:8b en octobre 2026, soit 4.6 GiB. Elle exclut les buffers de calcul et le processus du serveur. Considérez cette valeur comme un minimum.
L’ordre de grandeur est le point essentiel. À 8k, le cache coûte 1 GiB, ce qui est négligeable par rapport aux poids. Avec le contexte maximal de 128k, il coûte 16 GiB, soit plus de trois fois le poids du modèle, pour un total proche de 20.6 GiB. Un VPS de 4 GB ne peut donc pas charger ce modèle avec une longueur de contexte utile. Un VPS de 8 GB convient pour 8k. Un VPS de 16 GB atteint 32k tout en laissant de la mémoire pour le reste du serveur. Tous ces seuils augmentent avec la taille des poids. Si vous comparez un modèle plus grand à ce modèle 8B, les mêmes calculs effectués pour le tag 27B de Qwen sur un VPS utilisant uniquement le CPU montrent la faible quantité de mémoire restante pour le contexte entre 8 et 64 GB.
Ce qui se passe lorsque le cache KV ne tient pas
Sur un VPS équipé uniquement d’un CPU, le processus augmente simplement sa consommation mémoire. Surveillez-le pendant le chargement du modèle et pendant l’exécution d’une requête longue.
free -m
ps -eo rss,comm --sort=-rss | head -n 5La RSS (resident set size) est affichée en kilooctets. Si l’utilisation du swap dans free -m commence à augmenter, réduisez la taille du contexte. Un cache KV placé dans le swap ralentit la génération à plusieurs secondes par token, car chaque nouveau token lit l’intégralité du cache.
Si la machine n’a plus du tout de mémoire disponible, le kernel choisit un processus à tuer, généralement celui qui consomme le plus de mémoire.
sudo dmesg | grep -i "killed process"Une ligne contenant Out of memory: Killed process 1234 (ollama) signifie qu’Ollama est le processus choisi par le kernel, pas nécessairement celui qui a consommé toute la mémoire. Sur une machine où Ollama est le seul processus important, un contexte trop volumineux est généralement en cause. Vérifiez ce qui fonctionnait avant de réduire num_ctx. Ollama refuse souvent de poursuivre avant d’en arriver là. La requête échoue alors avec un message indiquant la mémoire demandée et la mémoire disponible.
Sur une machine équipée d’un GPU, l’échec est moins visible. Des couches sont déportées vers la RAM système, ollama ps affiche la répartition entre le CPU et le GPU, et le débit chute fortement. L’ampleur de cette baisse dépend du matériel. Mesurez donc le nombre de tokens par seconde sur votre propre machine pour chaque taille de contexte au lieu de vous fier à une valeur mesurée sur une autre machine.
Le temps de préremplissage augmente plus vite que la longueur du prompt
Le préremplissage correspond au traitement de votre entrée avant l’apparition du premier token de sortie. Chaque token du prompt est mis en relation avec tous les tokens qui le précèdent. La charge totale augmente donc avec le carré de la longueur de l’entrée. Doubler la longueur du prompt fait plus que doubler l’attente avant le premier token.
La réponse contient la mesure. Vous n’avez donc pas à l’accepter sans vérification.
jq -n --arg p "$LONG" '{model:"llama3.1:8b", prompt:$p, stream:false, options:{num_ctx:16384}}' |
curl -s http://localhost:11434/api/generate -d @- |
jq '{tokens: .prompt_eval_count, prefill_seconds: (.prompt_eval_duration/1000000000)}'Exécutez-le avec un prompt court, puis avec un prompt long, et divisez le nombre de tokens par le nombre de secondes dans chaque cas. Sur un VPS dépourvu de GPU, le prefill est généralement l’étape la plus lente d’une requête avec un long contexte. Une mesure en tokens par seconde obtenue avec un prompt court ne permet donc pas de prévoir ses performances. Lorsque le prefill dépasse le délai d’attente configuré en amont, le prompt long renvoie généralement délai d’expiration du contexte dépassé au lieu d’une réponse. Identifiez donc la couche qui a abandonné avant de réduire le contexte.
C’est avec la concurrence que le problème est le plus important. Chaque requête traitée a besoin de son propre cache. La mémoire indiquée dans le graphique ci-dessus est donc utilisée par requête, et non par serveur. Une seule requête longue peut monopoliser la machine pendant que les requêtes courtes attendent derrière elle. Définissez OLLAMA_NUM_PARALLEL volontairement, puis consultez combien d’utilisateurs simultanés un LLM auto-hébergé peut servir avant d’augmenter les deux valeurs en même temps.
Récupérer de la mémoire de contexte avec un cache plus petit
bytes_per_value dans la formule est un paramètre que vous contrôlez. La FAQ d’Ollama documente OLLAMA_KV_CACHE_TYPE, avec f16 comme valeur par défaut, q8_0 à environ la moitié de la mémoire de f16, et q4_0 à environ un quart. La valeur exacte de q8_0 est légèrement supérieure à la moitié : llama.cpp stocke chaque bloc de 32 valeurs sous la forme de 32 valeurs d’un octet plus un facteur d’échelle de deux octets, soit 34 octets contre 64 pour f16. Passer à q8_0 ramène donc la ligne de 32k à environ 2.1 GiB au lieu de 4 GiB. La quantification des poids libère de la mémoire de l’autre côté du même budget, et le tag GLM qui tient réellement sur un VPS est détaillé quantification par quantification si vous préférez faire ce compromis. La même FAQ précise que le cache n’est quantifié que lorsque Flash Attention est activé, et documente OLLAMA_FLASH_ATTENTION=1 pour forcer son activation.
[Service]
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"Vérifiez au lieu de supposer : redémarrez le service, chargez le modèle avec le même num_ctx qu’auparavant, puis comparez la RSS. La prise en charge dépend du modèle et du backend. Si un paramètre ne change rien, votre combinaison n’est donc pas prise en charge. Le type de cache est une option globale : tous les modèles du serveur l’utilisent. Concernant la qualité, la FAQ indique que q8_0 n’a généralement pas d’effet perceptible, tandis que q4_0 entraîne une perte de précision plus importante, surtout avec de grandes tailles de contexte. Testez donc q4_0 avec vos propres prompts avant de vous y fier. Si ces paramètres sont la raison de votre recherche, Ollama et llama.cpp les exposent différemment.
Une méthode pour choisir num_ctx
- Relevez dans
/api/showle contexte maximal du modèle, le nombre de couches et le nombre de têtes key/value. - Calculez le nombre d’octets par token avec la formule, puis multipliez-le par la taille de contexte souhaitée.
- Ajoutez la taille des poids, comparez le total à la RAM disponible et gardez au moins 1 GiB pour le reste du serveur.
- Définissez la valeur, chargez le modèle, puis vérifiez la valeur appliquée avec
ollama psetprompt_eval_count. - Exécutez votre charge réelle en surveillant
free -m, puis divisez le contexte par deux si le swap commence à être utilisé.
La plupart des tâches nécessitent moins de contexte qu’on ne leur en attribue. Le résumé d’un rapport volumineux tient dans 16k. Une interface de retrieval qui insère cinq extraits de documents dépasse rarement 8k. Un agent de programmation qui lit des fichiers entiers est le cas qui nécessite réellement 64k ou plus. C’est aussi dans ce cas qu’il faut dimensionner la machine en fonction du contexte, et non l’inverse. Si le serveur est encore récent, commencez par une installation Ollama fonctionnelle sur un VPS et ajustez le contexte une fois que les modèles se chargent correctement.
FAQ
Quelle est la longueur de contexte par défaut dans Ollama ?
Elle dépend du build et du matériel. Vérifiez-la au lieu de partir du principe qu’elle est fixe. La FAQ d’Ollama indique 4096 tokens, tandis que la référence Modelfile indique une valeur par défaut de num_ctx de 2048. La page consacrée à la longueur de contexte indique, quant à elle, une valeur choisie selon la VRAM disponible : 4k en dessous de 24 GiB, 32k de 24 GiB à moins de 48 GiB, et 256k à partir de 48 GiB. Un VPS utilisant uniquement le CPU se situe dans la plage basse. ollama ps affiche le contexte appliqué sur les builds qui possèdent cette colonne, et prompt_eval_count dans une réponse API le confirme sur tous les builds.
Pourquoi Ollama ignore-t-il le début de mon long prompt ?
Parce que le prompt dépassait la fenêtre de contexte. Le serveur l’a donc tronqué avant que le modèle ne le voie, sans renvoyer d’erreur. Renvoyez le même prompt avec un num_ctx plus grand et surveillez l’augmentation de prompt_eval_count dans la réponse. Si cette valeur ne change pas, un élément situé entre vous et le serveur définit lui-même num_ctx. C’est fréquent avec les interfaces de chat et les frameworks d’agents.
De quelle quantité de RAM supplémentaire un num_ctx plus grand a-t-il besoin ?
Multipliez la longueur du contexte par le coût du cache par token, qui est de 2 * layers * kv_heads * head_dim * bytes_per_value. Pour Llama 3.1 8B en f16, cela représente 128 KiB par token. 32k tokens coûtent donc 4 GiB, et 128k tokens complets coûtent 16 GiB en plus des poids. Le cache est alloué lors du chargement du modèle. Un num_ctx élevé consomme donc cette mémoire même si vos prompts restent courts.
Une fenêtre de contexte plus grande ralentit-elle Ollama ?
Oui, de deux façons. Le travail de prefill augmente avec le carré de la longueur du prompt. Une longue entrée retarde donc le premier token davantage que sa longueur ne le laisse penser. Le cache plus grand consomme aussi de la mémoire : sur une machine équipée d’un GPU, il force le déplacement de couches vers la RAM système ; sur une machine utilisant le CPU, il rapproche la machine de l’utilisation du swap. Un num_ctx élevé que vous n’utilisez jamais consomme tout de même cette mémoire, mais n’augmente pas le temps de prefill.
Puis-je définir num_ctx de manière permanente pour un modèle ?
Oui. Écrivez un Modelfile contenant FROM llama3.1:8b et PARAMETER num_ctx 16384, puis exécutez ollama create llama3.1-16k -f ./Modelfile. Chaque client qui demande llama3.1-16k utilise ce contexte sans envoyer d’options. Une requête contenant son propre num_ctx reste prioritaire. Cette valeur définit donc une valeur par défaut, et non une limite maximale.