Ollama: come impostare num_ctx e il contesto massimo
Ollama può troncare i prompt lunghi senza avviso: imposta num_ctx per richiesta o server e calcola la RAM della cache KV prima di aumentarlo.
Che cosa fa num_ctx e perché il prompt lungo è stato troncato
La lunghezza del contesto di Ollama è il numero di token che un modello caricato può mantenere in memoria contemporaneamente; num_ctx è l'opzione che la imposta. Ollama sceglie un valore predefinito molto inferiore al massimo dichiarato dal modello, quindi un prompt più lungo viene troncato prima che il modello possa leggerlo. La risposta non indica che questo sia accaduto.
Llama 3.1 8B è indicato con una finestra di contesto di 128k nella libreria dei modelli di Ollama. Un server con la configurazione predefinita non ti fornirà questo valore. La documentazione di Ollama indica valori predefiniti diversi in pagine diverse: le FAQ indicano 4096 token, il riferimento a Modelfile indica che num_ctx ha come valore predefinito 2048, mentre la pagina sulla lunghezza del contesto afferma che il valore predefinito viene scelto in base alla VRAM disponibile (memoria video): 4k sotto 24 GiB, 32k da 24 a 48 GiB e 256k oltre tale soglia. Ciascuna di queste indicazioni era corretta per una determinata build. La lezione utile è questa: leggi il valore dal server in esecuzione, invece di fidarti di una pagina qualsiasi, inclusa questa.
La troncatura non è evidente perché il modello risponde comunque e la risposta mantiene una buona leggibilità. Tuttavia, viene generata a partire dalla parte finale dell'input. Un riepilogo che ignora la prima metà di un documento può sembrare il risultato di un modello poco efficace. Di solito la causa è una finestra di contesto ridotta.
Verificare la lunghezza del contesto applicata dal server Ollama
Il controllo che funziona su qualsiasi build è prompt_eval_count, cioè il numero di token del prompt che il server dichiara di aver elaborato. Invia un prompt più lungo della capacità del contesto: il numero si arresta in corrispondenza del 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}'Questo prompt contiene circa 18,000 parole, quindi supera ampiamente 4096 token. prompt_eval_count restituisce un valore vicino a 4096 anziché vicino al numero effettivo di token, perché il server ha scartato il resto. Eseguilo di nuovo con "num_ctx":16384: il conteggio aumenta. Se la tua build restituisce un errore invece di troncare il prompt, il risultato indica la stessa condizione, ma in modo più evidente.
ollama psLa colonna CONTEXT, nelle build che la visualizzano, contiene la lunghezza del contesto con cui il modello caricato è attualmente in esecuzione. La colonna PROCESSOR adiacente indica dove è posizionato il modello. 100% CPU è normale su un VPS senza GPU. Una suddivisione come 30%/70% CPU/GPU su un sistema con GPU indica che i pesi e la cache non entrano più nella VRAM; un valore num_ctx più elevato è la causa abituale.
journalctl -u ollama --no-pager | grep -i n_ctx | tail -n 5Il runner di inferenza stampa la dimensione del contesto in una riga contenente n_ctx. La formulazione esatta cambia tra le release, quindi considera una riga mancante come un possibile cambio di nome, non come una prova conclusiva.
Quattro punti in cui impostare num_ctx
Nella richiesta. Invia "options": {"num_ctx": 16384} a /api/generate o /api/chat. Questa impostazione ha la precedenza su tutte le altre e si applica solo a quella chiamata. Se il valore è diverso da quello utilizzato dal modello caricato, il server ricarica prima il modello. Questo è visibile in load_duration nella risposta: il valore passa da quasi zero a diversi secondi. Lo stesso tempo di attesa si verifica quando il modello è rimasto inattivo abbastanza a lungo da essere scaricato. Dopo aver scelto la dimensione del contesto, conviene quindi mantenere il modello residente con keep_alive.
Nella sessione interattiva. In ollama run, digita /set parameter num_ctx 16384. L'impostazione resta valida per la sessione corrente.
In un Modelfile. Il valore viene incorporato in un modello con nome. Ogni client lo utilizza senza modifiche lato client.
FROM llama3.1:8b
PARAMETER num_ctx 16384ollama create llama3.1-16k -f ./Modelfile
ollama run llama3.1-16kSul server. OLLAMA_CONTEXT_LENGTH imposta il valore predefinito per ogni richiesta che non contiene un proprio num_ctx. Con systemd, aggiungi un drop-in invece di modificare il file dell'unità.
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_CONTEXT_LENGTH=16384"sudo systemctl daemon-reload
sudo systemctl restart ollama
ollama psLa precedenza è particolarmente importante quando esegui il debug del client di un altro utente. Una richiesta che contiene num_ctx ha la precedenza sul valore predefinito del server. Di conseguenza, un'interfaccia di chat o un agent che invia autonomamente un valore ridotto può annullare senza segnalarlo la modifica apportata con systemd. Quando configuri un coding agent per usare il tuo server Ollama, controlla quale valore invia il client prima di attribuire il problema al server.
Perché non puoi semplicemente impostare num_ctx al valore massimo del modello
L'attention fa in modo che ogni token consideri tutti i token precedenti. Le key e le value calcolate per i token precedenti vengono conservate, così non devono essere ricalcolate per ogni nuovo token. Questa memoria è la KV cache (key/value cache). Viene allocata per l'intero num_ctx quando il modello viene caricato, non quando la conversazione cresce. Per questo un contesto ampio consuma memoria anche con un prompt di una sola riga.
Il tutorial di DigitalOcean sui costi dell'inferenza riporta il calcolo in una sola riga:
kv_bytes_per_token = 2 * layers * kv_heads * head_dim * bytes_per_valueIl 2 conta separatamente key e value. Ricava gli altri numeri dal modello che utilizzi.
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 indica 32 layer e 8 key/value head. La dimensione della head è embed divisa per heads, quindi qui 4096 / 32 = 128; alcuni modelli la pubblicano direttamente come llama.attention.key_length. La cache predefinita usa valori f16, quindi bytes_per_value è 2. Il calcolo 2 32 8 128 2 restituisce 131,072 byte. Sono 128 KiB di cache per ogni singolo token del contesto. Moltiplicando questo valore per la lunghezza del contesto, il costo diventa concreto.
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
}
]Le 6 righe sono calcolate con la formula precedente, non misurate. La colonna del totale aggiunge i 4.9 GB del download indicato dalla libreria Ollama per llama3.1:8b nell'agosto 2026, pari a 4.6 GiB, ed esclude i buffer di calcolo e il processo del server. Consideralo un valore minimo.
Il punto è l'andamento. Con 8k, la cache costa 1 GiB, un valore trascurabile rispetto ai pesi. Con il contesto completo di 128k, costa 16 GiB, oltre il triplo dei pesi, per un totale di circa 20.6 GiB. Un VPS da 4 GB non può quindi caricare questo modello con un contesto utile. Un VPS da 8 GB gestisce comodamente 8k. Un VPS da 16 GB arriva a 32k, lasciando memoria per il resto del sistema. Tutte queste soglie aumentano insieme alla dimensione dei pesi. Se stai valutando un modello più grande rispetto a questo 8B, gli stessi calcoli applicati al tag Qwen da 27B su un VPS con sola CPU mostrano quanta poca memoria resta per il contesto tra 8 e 64 GB.
Cosa succede quando la cache KV non entra
Su una VPS con la sola CPU, il processo cresce semplicemente. Monitoralo durante il caricamento del modello e mentre viene eseguita una richiesta lunga.
free -m
ps -eo rss,comm --sort=-rss | head -n 5RSS (resident set size) viene visualizzato in kilobyte. Se lo swap utilizzato in free -m inizia ad aumentare, riduci il contesto. Una cache KV che risiede nello swap rallenta la generazione fino a diversi secondi per token, perché ogni nuovo token legge l’intera cache.
Se il sistema esaurisce completamente la memoria, il kernel seleziona il processo più grande e lo termina.
sudo dmesg | grep -i "killed process"Una riga con Out of memory: Killed process 1234 (ollama) indica che il contesto richiesto non entrava nella memoria disponibile. Ollama spesso rifiuta la richiesta prima di arrivare a questo punto; in tal caso la richiesta non riesce e il messaggio indica quanta memoria era necessaria rispetto a quella libera.
Su un sistema con GPU il problema è meno evidente. I layer vengono trasferiti nella RAM di sistema, ollama ps mostra la suddivisione tra CPU e GPU e la velocità di elaborazione diminuisce nettamente. L’entità del calo dipende dall’hardware, quindi misura i token al secondo sul tuo sistema per ogni impostazione del contesto, invece di affidarti a un valore ottenuto su una macchina diversa.
Il tempo di prefill cresce più rapidamente del prompt
Il prefill è il lavoro eseguito sull'input prima che venga visualizzato il primo token di output. Ogni token del prompt presta attenzione a tutti i token che lo precedono, quindi il lavoro complessivo cresce con il quadrato della lunghezza dell'input. Raddoppiare il prompt fa aumentare il tempo di attesa per il primo token di oltre il doppio.
La risposta contiene la misurazione, quindi non devi accettare questo dato senza verificarlo.
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)}'Esegui la richiesta con un prompt breve e poi ripetila con uno lungo. In entrambi i casi, dividi il numero di token per i secondi impiegati. Su una VPS con sola CPU, il prefill è generalmente la fase più lenta nelle richieste con contesto lungo. Un valore di token al secondo calcolato su un prompt breve non consente di prevederne le prestazioni. Se il prefill supera il timeout configurato nel livello che lo precede, il prompt lungo restituisce in genere scadenza del contesto superata invece di una risposta. Prima di ridurre il contesto, individua quindi quale livello ha interrotto l'operazione.
Il problema è più evidente con la concorrenza. Ogni richiesta gestita richiede una propria cache, quindi la memoria indicata nel grafico precedente è riferita alla singola richiesta, non al server, e una richiesta lunga può occupare tutte le risorse della macchina mentre le richieste brevi restano in coda. Imposta OLLAMA_NUM_PARALLEL deliberatamente e consulta quanti utenti simultanei può gestire un LLM self-hosted prima di aumentare entrambi i valori contemporaneamente.
Ridurre il contesto con una cache più piccola
bytes_per_value nella formula è un'impostazione sotto il tuo controllo. Le FAQ di Ollama documentano OLLAMA_KV_CACHE_TYPE, con f16 come valore predefinito a 2 byte, oltre a q8_0 a 1 byte e q4_0 al di sotto di questo valore. Passare a q8_0 dimezza la cache, quindi la riga da 32k costa 2 GiB invece di 4 GiB. La quantizzazione dei pesi libera memoria dall'altro lato dello stesso budget, e il tag GLM che entra davvero in una VPS viene analizzato quantizzazione per quantizzazione se preferisci questo compromesso. La stessa FAQ documenta OLLAMA_FLASH_ATTENTION=1, che alcune build richiedono prima che una cache quantizzata diventi effettiva.
[Service]
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"Verifica invece di dare per scontato: riavvia il servizio, carica il modello allo stesso num_ctx di prima e confronta l'RSS. Il supporto dipende dal modello e dal backend, quindi un'impostazione che non cambia nulla indica che la tua combinazione non è supportata. La documentazione elenca queste opzioni senza garantire un risultato in termini di qualità, quindi prova q4_0 con i tuoi prompt prima di farvi affidamento. Se sei arrivato qui a causa di queste impostazioni, Ollama e llama.cpp le espongono in modo diverso.
Una procedura per scegliere num_ctx
- Leggi il contesto massimo del modello, il numero di layer e il numero di head key/value da
/api/show. - Calcola i byte per token con la formula, quindi moltiplica il risultato per il contesto desiderato.
- Aggiungi la dimensione dei pesi, confronta il totale con la RAM libera e lascia almeno 1 GiB per il resto del server.
- Imposta il valore, carica il modello e verifica il valore applicato con
ollama pseprompt_eval_count. - Esegui il carico di lavoro reale monitorando
free -me dimezza il contesto se lo swap inizia a essere utilizzato.
La maggior parte dei carichi di lavoro richiede meno contesto di quanto venga assegnato. La sintesi di un report lungo rientra in 16k. Un front end di retrieval che inserisce cinque blocchi di documenti supera raramente 8k. Un agente di coding che legge file interi è il caso che richiede realmente 64k o più. In questo caso devi dimensionare la macchina in base al contesto, non il contrario. Se il server è ancora nuovo, parti da un'installazione funzionante di Ollama su un VPS e ottimizza il contesto dopo aver verificato che i modelli vengano caricati correttamente.
FAQ
Qual è la lunghezza predefinita del contesto in Ollama?
Dipende dalla build e dall'hardware, quindi è necessario verificare invece di dare per scontato un valore. Le FAQ di Ollama indicano 4096 token, mentre il riferimento Modelfile documenta un valore predefinito num_ctx pari a 2048. La pagina sulla lunghezza del contesto documenta invece un valore predefinito scelto in base alla VRAM disponibile: 4k sotto 24 GiB, 32k da 24 a 48 GiB e 256k oltre questo limite. Una VPS che usa soltanto la CPU rientra nel valore più basso. ollama ps stampa il contesto applicato nelle build che includono quella colonna, mentre prompt_eval_count in una risposta API lo conferma in ogni build.
Perché Ollama ignora l'inizio del mio prompt lungo?
Perché il prompt era più lungo della finestra di contesto. Il server lo ha quindi troncato prima che il modello potesse riceverlo e non ha restituito alcun errore. Invia di nuovo lo stesso prompt con un valore num_ctx maggiore e osserva la crescita di prompt_eval_count nella risposta. Se quel numero non cambia, un componente tra il client e il server sta impostando direttamente num_ctx. Questo comportamento è comune nei front end per chat e nei framework per agenti.
Quanta RAM aggiuntiva richiede un valore num_ctx maggiore?
Moltiplica la lunghezza del contesto per il costo della cache per token, che è 2 * layers * kv_heads * head_dim * bytes_per_value. Per Llama 3.1 8B a f16 il costo è 128 KiB per token. Di conseguenza, 32k token richiedono 4 GiB e l'intero contesto da 128k richiede 16 GiB aggiuntivi rispetto ai pesi. La cache viene allocata quando il modello viene caricato, quindi un valore num_ctx elevato consuma quella memoria anche se i prompt rimangono brevi.
Una finestra di contesto più ampia rende Ollama più lento?
Sì, in due modi. Il lavoro di prefill cresce con il quadrato della lunghezza del prompt, quindi un input lungo ritarda il primo token più di quanto suggerisca la sua lunghezza. Inoltre, la cache più grande compete per la memoria: su un sistema con GPU sposta alcuni layer nella RAM di sistema, mentre su un sistema con sola CPU porta la macchina più vicino all'uso della swap. Un valore num_ctx elevato che non viene mai utilizzato per intero consuma comunque memoria, anche se non aumenta il tempo di prefill.
Posso impostare in modo permanente num_ctx per un modello?
Sì. Scrivi un Modelfile contenente FROM llama3.1:8b e PARAMETER num_ctx 16384, quindi esegui ollama create llama3.1-16k -f ./Modelfile. Ogni client che richiede llama3.1-16k utilizza quel contesto senza inviare opzioni. Una richiesta che contiene il proprio num_ctx ha comunque la precedenza, quindi questa impostazione definisce un valore predefinito, non un limite massimo.