Ollama: como definir o tamanho de contexto com num_ctx
Prompts longos são truncados silenciosamente no Ollama. Veja como definir num_ctx por requisição ou servidor e calcular a RAM da KV cache antes de aumentar o valor.
O que num_ctx faz e por que o seu prompt longo foi truncado
O comprimento de contexto do Ollama é o número de tokens que um modelo carregado consegue manter na memória de cada vez, e num_ctx é a opção que o define. O Ollama escolhe um valor predefinido muito inferior ao máximo anunciado pelo modelo, por isso um prompt mais longo é truncado antes de o modelo o ler. A resposta não indica que isso aconteceu.
A biblioteca de modelos do Ollama lista o Llama 3.1 8B com uma janela de contexto de 128k. Um servidor com a configuração predefinida não lhe dará esse valor. A documentação do próprio Ollama apresenta valores predefinidos diferentes em páginas diferentes: a FAQ indica 4096 tokens, a referência do Modelfile indica que num_ctx tem o valor predefinido 2048, e a página sobre o comprimento de contexto diz que o valor predefinido é escolhido com base na VRAM disponível: 4k abaixo de 24 GiB, 32k entre 24 e 48 GiB e 256k acima disso. Cada valor foi verdadeiro para alguma build. Essa divergência é a lição útil: leia o valor no seu próprio servidor em execução, em vez de confiar em qualquer página, incluindo esta.
A truncagem é silenciosa porque o modelo continua a responder, e a resposta continua a parecer bem escrita. Ela foi gerada a partir do final da sua entrada. Um resumo que não inclui a primeira metade de um documento parece indicar um modelo fraco. Normalmente, indica uma janela de contexto pequena.
Verifique o tamanho do contexto do Ollama que o servidor aplicou efetivamente
A verificação que funciona em qualquer build é prompt_eval_count, a contagem de tokens do prompt que o servidor indica ter processado. Envie mais conteúdo do que o contexto consegue armazenar. Esse número para no 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}'Esse prompt tem cerca de 18,000 palavras, muito mais do que 4096 tokens. prompt_eval_count devolve um valor próximo de 4096, e não da contagem real de tokens, porque o servidor descartou o restante. Execute novamente com "num_ctx":16384. A contagem aumenta. Se a sua build devolver um erro em vez de truncar o conteúdo, a conclusão é a mesma, mas o sinal é mais evidente.
ollama psA coluna CONTEXT, nas builds que a apresentam, contém o tamanho do contexto com que o modelo carregado está a funcionar neste momento. A coluna PROCESSOR, ao lado, mostra onde o modelo está a ser executado. 100% CPU é normal numa VPS sem GPU. Uma divisão como 30%/70% CPU/GPU numa máquina com GPU significa que os pesos e a cache já não cabem na VRAM, e um valor elevado de num_ctx é normalmente a causa.
journalctl -u ollama --no-pager | grep -i n_ctx | tail -n 5O executor de inferência apresenta o tamanho do contexto numa linha que contém n_ctx. O texto exato varia entre releases. Por isso, interprete a ausência da linha como uma alteração de nome, e não como prova de qualquer conclusão.
Quatro locais para definir num_ctx
No pedido. Envie "options": {"num_ctx": 16384} para /api/generate ou /api/chat. Esta definição tem precedência sobre todas as outras e aplica-se apenas a essa chamada. Se o valor for diferente daquele com que o modelo carregado está a ser executado, o servidor recarrega primeiro o modelo. Pode ver isso em load_duration na resposta: o valor passa de quase zero para vários segundos.
Na sessão interativa. Dentro de ollama run, introduza /set parameter num_ctx 16384. A definição mantém-se durante essa sessão.
Num Modelfile. Isto incorpora o valor num modelo com nome, para que todos os clientes o recebam sem alterações no lado do cliente.
FROM llama3.1:8b
PARAMETER num_ctx 16384ollama create llama3.1-16k -f ./Modelfile
ollama run llama3.1-16kNo servidor. OLLAMA_CONTEXT_LENGTH define o valor predefinido para todos os pedidos que não incluam o seu próprio num_ctx. Com systemd, adicione um drop-in em vez de editar o ficheiro da unidade.
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_CONTEXT_LENGTH=16384"sudo systemctl daemon-reload
sudo systemctl restart ollama
ollama psA precedência é especialmente importante ao depurar o cliente de outra pessoa. Um pedido que inclua num_ctx tem precedência sobre a predefinição do servidor. Por isso, um frontend de chat ou um agente que envie o seu próprio valor baixo pode anular silenciosamente a alteração feita no systemd. Quando apontar um agente de programação para o seu servidor Ollama, verifique o que o cliente envia antes de culpar o servidor.
Por que você não pode simplesmente definir num_ctx como o máximo do modelo
A atenção faz com que cada token observe todos os tokens anteriores. As chaves e os valores calculados para os tokens anteriores são mantidos para não serem recalculados a cada novo token. Esse armazenamento é o cache KV (cache de chave/valor). Ele é alocado para todo o num_ctx quando o modelo é carregado, e não à medida que a conversa cresce. Por isso, um contexto grande consome essa memória mesmo com um prompt de uma linha.
O tutorial da DigitalOcean sobre custos de inferência apresenta a aritmética em uma linha:
kv_bytes_per_token = 2 * layers * kv_heads * head_dim * bytes_per_valueO 2 conta as chaves e os valores separadamente. Consulte os outros números do seu próprio modelo.
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"}'O Llama 3.1 8B informa 32 camadas e 8 cabeças de chave/valor. A dimensão da cabeça é embed dividida por heads, portanto 4096 / 32 = 128 neste caso. Alguns modelos publicam esse valor diretamente como llama.attention.key_length. O cache padrão mantém valores f16, então bytes_per_value é 2, e 2 32 8 128 2 resulta em 131,072 bytes. Isso corresponde a 128 KiB de cache para cada token de contexto. Multiplique pelo tamanho do contexto e o custo deixa de ser abstrato.
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
}
]Essas 6 linhas são cálculos baseados na fórmula acima, não medições. A coluna total soma os 4.9 GB do download listado pela biblioteca Ollama para llama3.1:8b em agosto de 2026, o que corresponde a 4.6 GiB, e não inclui os buffers de computação nem o próprio processo do servidor. Considere esse valor um limite mínimo.
O importante é a proporção. Em 8k, o cache custa 1 GiB, um valor insignificante perto dos pesos. No contexto máximo de 128k do modelo, ele custa 16 GiB, mais de três vezes o tamanho dos pesos, para um total próximo de 20.6 GiB. Portanto, uma VPS de 4 GB não consegue carregar este modelo com um contexto útil. Uma VPS de 8 GB funciona confortavelmente com 8k. Uma VPS de 16 GB chega a 32k, mantendo espaço para o restante do sistema. Cada um desses limites aumenta com o tamanho dos pesos. Se você estiver comparando um modelo maior com este 8B, os mesmos cálculos feitos para a tag 27B do Qwen em uma VPS somente com CPU mostram quanto pouco sobra para o contexto entre 8 e 64 GB.
O que acontece quando o cache KV não cabe
Num VPS apenas com CPU, o processo cresce simplesmente. Monitorize-o enquanto o modelo é carregado e enquanto um pedido longo é executado.
free -m
ps -eo rss,comm --sort=-rss | head -n 5RSS (resident set size) é apresentado em kilobytes. Se o swap utilizado em free -m começar a aumentar, reduza o contexto. Um cache KV que esteja no swap faz a geração parar durante segundos por token, porque cada token novo lê todo o cache.
Se o sistema ficar completamente sem memória, o kernel escolhe o maior processo e termina-o.
sudo dmesg | grep -i "killed process"Uma linha com Out of memory: Killed process 1234 (ollama) significa que o contexto pedido não coube. O Ollama muitas vezes recusa antes de chegar a esse ponto. Nesse caso, o pedido falha com uma mensagem que indica a memória necessária e a memória disponível.
Num sistema com GPU, a falha é menos evidente. As camadas passam para a RAM do sistema, ollama ps mostra a divisão entre CPU e GPU, e o débito diminui acentuadamente. A dimensão dessa redução depende do hardware. Por isso, meça os tokens por segundo no seu próprio sistema em cada definição de contexto, em vez de confiar num valor obtido noutra máquina.
O tempo de prefill cresce mais depressa do que o prompt
Prefill é o processamento da sua entrada antes de aparecer o primeiro token de saída. Cada token do prompt atende a todos os tokens anteriores, por isso o trabalho total cresce com o quadrado do tamanho da entrada. Duplicar o prompt aumenta o tempo de espera pelo primeiro token mais do que o duplica.
A resposta inclui a medição, por isso não precisa de aceitar esse valor sem confirmação.
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)}'Execute esse comando com um prompt curto e novamente com um prompt longo. Depois, divida o número de tokens pelos segundos em cada caso. Numa VPS apenas com CPU, o prefill é normalmente a parte mais lenta de um pedido com contexto longo. Um valor de tokens por segundo obtido com um prompt curto não permite prever o desempenho nesse caso.
É com a concorrência que este problema se torna mais grave. Cada pedido servido precisa da sua própria cache. Por isso, a memória apresentada no gráfico acima é por pedido, não por servidor. Um único pedido longo pode ocupar o servidor enquanto os pedidos curtos ficam em fila. Defina OLLAMA_NUM_PARALLEL de forma deliberada e consulte quantos utilizadores concorrentes um LLM autoalojado consegue servir antes de aumentar ambos os valores em conjunto.
Recupere contexto usando uma cache menor
bytes_per_value na fórmula é uma definição que pode controlar. A FAQ do Ollama documenta OLLAMA_KV_CACHE_TYPE, com f16 como predefinição de 2 bytes, além de q8_0 com 1 byte e q4_0 abaixo desse valor. Mudar para q8_0 reduz a cache para metade, por isso a linha de 32k custa 2 GiB em vez de 4 GiB. A mesma FAQ documenta OLLAMA_FLASH_ATTENTION=1, que algumas compilações exigem antes de uma cache quantizada produzir efeito.
[Service]
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"Confirme em vez de assumir: reinicie o serviço, carregue o modelo com o mesmo num_ctx de antes e compare o RSS. O suporte depende do modelo e do backend. Se uma definição não alterar nada, essa combinação não é suportada. A documentação lista estas opções sem garantir um resultado de qualidade. Por isso, teste q4_0 com os seus próprios prompts antes de depender dela. Se estas opções são o motivo pelo qual chegou aqui, Ollama e llama.cpp expõem-nas de forma diferente.
Uma receita para escolher num_ctx
- Leia o contexto máximo do modelo, a contagem de camadas e a contagem de cabeças key/value em
/api/show. - Calcule os bytes por token com a fórmula e multiplique pelo contexto pretendido.
- Some o tamanho dos pesos, compare o resultado com a RAM livre e reserve pelo menos 1 GiB para o restante sistema.
- Defina o valor, carregue o modelo e confirme o que foi aplicado com
ollama pseprompt_eval_count. - Execute a carga de trabalho real enquanto monitoriza
free -me reduza o contexto para metade se o swap começar a ser utilizado.
A maioria das tarefas precisa de menos contexto do que é normalmente configurado. Resumir um relatório longo cabe em 16k. Um frontend de retrieval que insere cinco blocos de documentos raramente ultrapassa 8k. Um agente de programação que lê ficheiros completos é o caso que realmente precisa de 64k ou mais. Também é o caso em que deve dimensionar a máquina em função do contexto, e não o contrário. Se o próprio servidor ainda for recente, comece por uma instalação funcional do Ollama num VPS e ajuste o contexto depois de os modelos serem carregados sem erros.
FAQ
Qual é o comprimento de contexto predefinido no Ollama?
Depende da compilação e do hardware, por isso deve confirmar em vez de assumir. A FAQ do Ollama documenta 4096 tokens, a referência do Modelfile documenta um valor predefinido de num_ctx 2048, e a página sobre o comprimento de contexto documenta um valor escolhido com base na VRAM disponível: 4k abaixo de 24 GiB, 32k entre 24 e 48 GiB e 256k acima disso. Uma VPS que use apenas CPU fica no limite inferior. ollama ps mostra o contexto aplicado nas compilações que incluem essa coluna, e prompt_eval_count numa resposta da API confirma-o em todas as compilações.
Por que motivo o Ollama ignora o início do meu prompt longo?
Porque o prompt era maior do que a janela de contexto. O servidor cortou-o antes de o modelo o receber e não devolveu nenhum erro. Envie o mesmo prompt novamente com um num_ctx maior e monitorize o crescimento de prompt_eval_count na resposta. Se esse número não mudar, algo entre o cliente e o servidor está a definir num_ctx por conta própria. Isto é comum em interfaces de chat e frameworks de agentes.
Quanta RAM adicional é necessária para um num_ctx maior?
Multiplique o comprimento de contexto pelo custo da cache por token, que é 2 * layers * kv_heads * head_dim * bytes_per_value. Para o Llama 3.1 8B em f16, esse custo é 128 KiB por token. Assim, 32k tokens ocupam 4 GiB e os 128k completos ocupam 16 GiB, além dos pesos. A cache é alocada quando o modelo é carregado, por isso um num_ctx grande consome essa memória mesmo quando os prompts são curtos.
Uma janela de contexto maior torna o Ollama mais lento?
Sim, de duas formas. O trabalho de prefill cresce com o quadrado do comprimento do prompt, por isso uma entrada longa atrasa o primeiro token mais do que o seu comprimento faria prever. A cache maior também compete pela memória: num servidor com GPU, força algumas camadas a passar para a RAM do sistema; num servidor apenas com CPU, aproxima a máquina do uso de swap. Um num_ctx grande que nunca seja preenchido continua a consumir memória, embora não aumente o tempo de prefill.
Posso definir num_ctx permanentemente para um modelo?
Sim. Escreva um Modelfile que contenha FROM llama3.1:8b e PARAMETER num_ctx 16384 e execute ollama create llama3.1-16k -f ./Modelfile. Todos os clientes que solicitarem llama3.1-16k obterão esse contexto sem enviar quaisquer opções. Um pedido que contenha o seu próprio num_ctx continua a ter precedência. Portanto, isto define um valor predefinido, não um limite máximo.