Ollama : régler la longueur de contexte avec num_ctx
Ollama tronque les longs prompts avec une fenêtre par défaut limitée. Réglez num_ctx par requête ou pour le serveur, puis prévoyez la RAM du KV cache.
Ce que fait num_ctx et pourquoi votre long prompt a été tronqué
La longueur de contexte d’Ollama correspond au nombre de tokens qu’un modèle chargé peut garder en mémoire à un instant donné. num_ctx est l’option qui la définit. Ollama choisit une valeur par défaut bien inférieure au maximum annoncé par le modèle. Un prompt plus long est donc tronqué avant même que le modèle ne le lise. La réponse ne vous indique pas que cela s’est produit.
Llama 3.1 8B est indiqué avec une fenêtre de contexte de 128k tokens dans la bibliothèque de modèles Ollama. Un serveur avec la configuration par défaut ne vous donnera pas cette longueur. La documentation d’Ollama indique des valeurs par défaut différentes selon les pages : la FAQ parle de 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 précise que la valeur par défaut dépend de la VRAM (mémoire vidéo) disponible : 4k sous 24 GiB, 32k de 24 à 48 GiB et 256k au-delà. Chacune de ces valeurs était correcte pour un build donné. C’est la leçon utile : lisez la valeur utilisée par votre propre serveur en fonctionnement au lieu de faire confiance à une page, y compris celle-ci.
La troncature passe inaperçue parce que le modèle répond quand même et que sa réponse reste cohérente. Il l’a rédigée à partir de la fin de votre entrée. Un résumé qui ignore la première moitié d’un document donne l’impression que le modèle est peu performant. La cause est généralement une fenêtre de contexte trop courte.
Vérifier la longueur de contexte qu’Ollama a réellement appliquée sur votre serveur
La vérification qui fonctionne sur tous les builds est prompt_eval_count, c’est-à-dire le nombre de tokens du prompt que le serveur indique avoir traités. Envoyez plus de contenu 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, donc 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 supprimé le reste. Exécutez de nouveau la commande avec "num_ctx":16384 : le nombre augmente. Si votre build renvoie une erreur au lieu de tronquer le contenu, le constat est le même, mais le signal est plus explicite.
ollama psLa colonne CONTEXT, sur les builds qui l’affichent, contient la longueur de contexte actuellement utilisée par le modèle chargé. La colonne PROCESSOR, à côté, indique où le modèle s’exécute. 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 num_ctx augmentée 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 sur une ligne contenant n_ctx. La formulation exacte change selon les releases. Considérez donc l’absence de cette ligne comme un changement de nom, et non comme une preuve.
Quatre endroits pour 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 s’applique uniquement à 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 entières.
Dans la session interactive. Dans ollama run, saisissez /set parameter num_ctx 16384. Le paramètre reste valable pendant cette session.
Dans un Modelfile. La valeur est intégrée à un 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 pour chaque requête qui ne contient pas son 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 psLa priorité des paramètres est particulièrement importante 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. Un frontend de chat ou un agent qui envoie lui-même une petite valeur peut donc annuler discrètement votre modification systemd. Lorsque vous connectez un agent de codage à 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 consulter à chaque token tous les tokens précédents. 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 clé/valeur). Il est alloué pour l’ensemble de num_ctx lors du 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.
Le tutoriel de DigitalOcean sur le coût de l’inférence présente le calcul en 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 caractéristiques 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 layers et 8 heads key/value. La dimension des heads correspond à embed divisé par heads, donc 4096 / 32 = 128 ici. Certains modèles la publient directement sous le nom llama.attention.key_length. Le cache par défaut stocke 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 ce nombre par la longueur du contexte et le coût devient concret.
The data behind this chart
[
{
"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 du total ajoute les 4.9 GB du téléchargement indiqué par la bibliothèque Ollama pour llama3.1:8b en août 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 à côté des poids. À la longueur maximale de 128k du modèle, il coûte 16 GiB, soit plus de trois fois la taille des poids, pour un total proche de 20.6 GiB. Un VPS de 4 GB ne peut donc pas charger ce modèle avec un contexte utile. Un VPS de 8 GB est à l’aise à 8k. Un VPS de 16 GB atteint 32k tout en conservant de la mémoire pour le reste du système. Chacun de ces seuils augmente 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 utilisant uniquement le CPU, le processus augmente simplement. Surveillez-le pendant le chargement du modèle et 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 le swap utilisé dans free -m commence à augmenter, réduisez le contexte. Un cache KV placé dans le swap ralentit fortement la génération, jusqu’à plusieurs secondes par token, car chaque nouveau token lit l’intégralité du cache.
Si la machine arrive complètement à court de mémoire, le kernel sélectionne le plus gros processus et le tue.
sudo dmesg | grep -i "killed process"Une ligne contenant Out of memory: Killed process 1234 (ollama) signifie que le contexte demandé ne tient pas en mémoire. Ollama refuse souvent la requête avant d’en arriver là. La requête échoue alors avec un message indiquant la mémoire nécessaire et la mémoire disponible.
Sur une machine équipée d’un GPU, l’échec est moins visible. Des layers sont transférés dans 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 obtenue sur la machine de quelqu’un d’autre.
Le temps de prefill augmente plus vite que le prompt
Le prefill correspond au traitement de votre entrée avant l’apparition du premier token de sortie. Chaque token du prompt doit prendre en compte tous les tokens qui le précèdent. La charge totale augmente donc avec le carré de la longueur de l’entrée. Si vous doublez la longueur du prompt, l’attente avant le premier token est multipliée par plus de 2.
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 cette commande avec un prompt court, puis avec un prompt long. Divisez ensuite le nombre de tokens par le nombre de secondes dans chaque cas. Sur un VPS utilisant uniquement le CPU, le prefill est généralement la partie 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 la prévoir.
C’est avec la concurrence que ce problème est le plus marqué. Chaque requête traitée a besoin de son propre cache. La mémoire indiquée dans le graphique ci-dessus est donc consommé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 de manière réfléchie et 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 du 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 à 2 octets, puis q8_0 à 1 octet et q4_0 en dessous. Passer à q8_0 divise le cache par deux : la ligne de 32k coûte donc 2 GiB au lieu de 4 GiB. La même FAQ documente OLLAMA_FLASH_ATTENTION=1, que certains builds exigent avant qu’un cache quantifié soit pris en compte.
[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 pas prise en charge. La documentation répertorie ces options sans garantir le résultat en matière de qualité. 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, son nombre de couches et son 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 de travail réelle en surveillant
free -m, puis divisez le contexte par 2 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 long rapport tient dans 16k. Une interface de recherche 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 le cas où vous devez dimensionner la machine en fonction du contexte, et non l’inverse. Si le serveur est encore récent, commencez par une installation fonctionnelle d’Ollama 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 donc la valeur au lieu de partir d’une supposition. La FAQ d’Ollama indique 4096 tokens, la documentation de référence du Modelfile indique une valeur num_ctx par défaut de 2048, et la page consacrée à la longueur de contexte indique une valeur par défaut calculée selon la VRAM disponible : 4k sous 24 GiB, 32k de 24 à 48 GiB, et 256k au-delà. Un VPS limité au CPU utilise généralement la valeur la plus basse. ollama ps affiche le contexte appliqué dans les builds qui incluent cette colonne, et prompt_eval_count dans une réponse d’API le confirme avec 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 reçoive, sans renvoyer d’erreur. Renvoyez le même prompt avec une valeur num_ctx plus élevée et surveillez l’augmentation de prompt_eval_count dans la réponse. Si cette valeur ne change pas, un composant entre votre client et le serveur définit lui-même num_ctx. C’est fréquent avec les interfaces de chat et les frameworks d’agents.
Combien de RAM supplémentaire un num_ctx plus élevé nécessite-t-il ?
Multipliez la longueur de contexte par le coût du cache par token, soit 2 * layers * kv_heads * head_dim * bytes_per_value. Pour Llama 3.1 8B en f16, ce coût est de 128 KiB par token. 32k tokens nécessitent donc 4 GiB, et 128k tokens nécessitent 16 GiB supplémentaires aux poids du modèle. Le cache est alloué lors du chargement du modèle. Une valeur num_ctx élevée 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 ne le laisse penser sa longueur. Le cache plus volumineux entre aussi en concurrence pour la mémoire : sur une machine équipée d’un GPU, il pousse des couches vers la RAM système ; sur une machine équipée d’un CPU, il augmente le risque de swap. Une valeur num_ctx élevée que vous n’utilisez jamais consomme tout de même la 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. Tous les clients qui demandent llama3.1-16k utilisent ce contexte sans envoyer d’options. Une requête qui contient sa propre valeur num_ctx reste prioritaire. Cette configuration définit donc une valeur par défaut, et non une limite maximale.