Ollama num_ctx 設定與 context length 調整
Ollama 預設 context window 可能只有 2048 或 4096 tokens,長提示詞會遭截斷。了解如何在每次請求或伺服器端設定 num_ctx,並先估算 KV cache 的 RAM 需求。
num_ctx 的作用,以及長提示詞為何被截斷
Ollama 的 context length 是載入的模型一次可在記憶體中保存的 token 數量,而 num_ctx 是設定此值的選項。Ollama 選用的預設值遠低於模型宣告的最大值,因此較長的提示詞會在模型讀取前就被截斷。回應內容不會告訴你這件事已經發生。
Ollama 模型庫將 Llama 3.1 8B 列為支援 128k context window。但標準伺服器不會提供這麼大的值。Ollama 的官方文件在不同頁面列出不同的預設值:FAQ 表示為 4096 tokens,Modelfile reference 表示 num_ctx 的預設值為 2048,而 context length 頁面表示預設值會依可用的 VRAM(video RAM)選定:低於 24 GiB 時為 4k,24 至 48 GiB 時為 32k,高於 48 GiB 時為 256k。這些說法各自在某些版本中成立。這項差異帶來的實用教訓是:請從自己正在執行的伺服器讀取實際值,不要相信任何頁面,包括本頁。
截斷不易察覺,因為模型仍會回答,而且回答讀起來仍然合理。只是它是根據你輸入內容的尾端撰寫的。遺漏文件前半部的摘要看起來像是模型能力不足。通常真正的原因是 context window 太小。
確認伺服器實際套用的 Ollama context length
適用於任何 build 的檢查方式是 prompt_eval_count,也就是伺服器回報已處理的 prompt token 數量。傳送超過 context 可容納的內容後,該數值會停在限制值。
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}'該 prompt 約有 18,000 個單字,遠超過 4096 個 token。因此,prompt_eval_count 回傳的數值會接近 4096,而不是接近實際 token 數量,因為伺服器捨棄了其餘內容。使用 "num_ctx":16384 再次執行後,計數會上升。如果你的 build 回傳錯誤,而不是截斷內容,這仍表示相同的結果,只是訊號更明顯。
ollama ps在會列印該欄位的 build 中,CONTEXT 欄位會顯示目前載入的 model 實際使用的 context length。旁邊的 PROCESSOR 欄位會顯示 model 的配置位置。沒有 GPU 的 VPS 通常會顯示 100% CPU。在 GPU 主機上,如果顯示類似 30%/70% CPU/GPU 的分割,表示 weights 加上 cache 已無法完整放入 VRAM;通常原因是提高了 num_ctx。
journalctl -u ollama --no-pager | grep -i n_ctx | tail -n 5inference runner 會在包含 n_ctx 的行中列印 context size。不同 release 的確切文字可能不同,因此找不到該行時,應先視為名稱變更,而不是據此判定任何結果。
設定 num_ctx 的 4 個位置
在請求中。 將 "options": {"num_ctx": 16384} 傳送至 /api/generate 或 /api/chat。這會優先於其他所有設定,且只套用於該次呼叫。如果此值與目前載入模型所使用的值不同,伺服器會先重新載入模型。你可以在回應的 load_duration 中看到這點:數值會從接近 0 跳升至數秒。模型閒置足夠時間而卸載時,也會出現相同的等待時間。因此,確定內容大小後,建議讓模型常駐。
在互動工作階段中。 在 ollama run 內輸入 /set parameter num_ctx 16384。此設定只會持續到該工作階段結束。
在 Modelfile 中。 這會將值寫入具名模型,因此所有用戶端都會取得該設定,無須在用戶端修改。
FROM llama3.1:8b
PARAMETER num_ctx 16384ollama create llama3.1-16k -f ./Modelfile
ollama run llama3.1-16k在伺服器上。 OLLAMA_CONTEXT_LENGTH 會為未帶有自訂 num_ctx 的所有請求設定預設值。使用 systemd 時,請新增 drop-in,不要直接編輯 unit 檔案。
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_CONTEXT_LENGTH=16384"sudo systemctl daemon-reload
sudo systemctl restart ollama
ollama ps進行其他用戶端的疑難排解時,優先順序尤其重要。帶有 num_ctx 的請求會優先於伺服器預設值,因此聊天前端或 agent 若自行傳送較小的值,會在未明確提示的情況下覆寫你所做的 systemd 變更。當你將程式碼 agent 指向 Ollama 伺服器時,請先確認用戶端傳送的內容,再判斷問題是否出在伺服器。
為什麼不能直接將 num_ctx 設為模型上限
注意力機制會讓每個 token 查看它之前的所有 token。較早 token 計算出的 keys 和 values 會被保留,因此產生新 token 時不必重新計算;這個儲存區就是 KV cache(key/value cache)。模型載入時,系統會為整個 num_ctx 配置 KV cache,而不是隨對話增長,因此即使提示只有一行,較大的 context 仍會占用相應的記憶體。
DigitalOcean 的推論成本教學用一行列出計算方式:
kv_bytes_per_token = 2 * layers * kv_heads * head_dim * bytes_per_value其中的 2 代表 keys 和 values 分開計算。其他數值請從你使用的模型取得。
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 使用 32 個 layers 和 8 個 key/value heads。head dimension 是 embed 除以 heads,因此本例為 4096 / 32 = 128;部分模型會直接將其發布為 llama.attention.key_length。預設 cache 儲存 f16 值,因此 bytes_per_value 為 2,而 2 32 8 128 2 的結果是 131,072 bytes。這表示 context 中的每個 token 都需要 128 KiB 的 cache。乘上 context length 後,成本就不再只是抽象數字。
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
}
]這些 6 列是根據上述公式計算得出,不是實測值。總計欄加上 Ollama library 在 August 2026 為 llama3.1:8b 列出的 4.9 GB 下載大小,也就是 4.6 GiB;但不包含 compute buffers 和 server process 本身。請將此數值視為最低需求。
重點在於成長幅度。context 為 8k 時,cache 只需 1 GiB,與 weights 相比幾乎可忽略。模型使用完整 128k 時,cache 需要 16 GiB,超過 weights 的 3 倍,總計接近 20.6 GiB。因此,4 GB VPS 無法在任何實用的 context 下載入此模型。8 GB VPS 在 8k context 下足夠使用。16 GB VPS 可達到 32k,並為主機的其他工作保留空間。這些門檻都會隨 weights 增加而提高;如果你要將更大的模型與這個 8B 比較,請參考 Qwen 在僅使用 CPU 的 VPS 上的 27B tag 的相同計算,即可看出在 8 到 64 GB 的記憶體範圍內,weights 能為 context 留下的空間有多有限。
KV cache 無法容納時的情況
在僅使用 CPU 的 VPS 上,程序會持續增加記憶體用量。在模型載入期間及執行長時間請求時監控它。
free -m
ps -eo rss,comm --sort=-rss | head -n 5RSS(常駐集大小)會以 KB 顯示。如果 free -m 中的 swap 使用量開始增加,請降低 context 設定。放在 swap 中的 KV cache 會讓生成每個 token 停頓數秒,因為每個新 token 都會讀取整個 cache。
如果伺服器的記憶體完全耗盡,kernel 會選擇記憶體用量最大的程序並將其終止。
sudo dmesg | grep -i "killed process"如果出現 Out of memory: Killed process 1234 (ollama) 這一行,表示你要求的 context 無法容納。Ollama 通常會在到達這一步前拒絕請求,然後顯示錯誤訊息,列出所需記憶體與當時可用的記憶體。
在使用 GPU 的伺服器上,失敗情況較不明顯。部分 layers 會溢出到系統 RAM,ollama ps 會顯示 CPU 與 GPU 的分配情況,而吞吐量會大幅下降。下降幅度取決於硬體,因此請在每個 context 設定下測量自己伺服器每秒可生成的 token 數量,不要直接採用其他機器的數據。
Prefill 速度成長快於提示詞長度
Prefill 是在第一個輸出 token 出現前,對輸入內容執行的處理。每個提示詞 token 都會注意它之前的每個 token,因此總處理量會隨輸入長度的平方成長。提示詞長度加倍時,等待第一個 token 的時間會超過原本的兩倍。
回應中會提供測量結果,因此不必直接相信這項說法。
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)}'使用短提示和長提示各執行一次,然後分別用 token 數除以秒數。在僅使用 CPU 的 VPS 上,對長上下文請求而言,prefill 通常是最慢的階段;以短提示測得的每秒 token 數,無法預測長提示的效能。prefill 若超過前方任何一層設定的 timeout,長提示通常會回傳 上下文期限已超過,而不是答案。因此,縮短上下文前,先確認是哪一層先放棄要求。
並行處理會讓這個問題更加明顯。每個處理中的請求都需要自己的快取,因此上方圖表中的記憶體用量是以每個請求計算,而不是以伺服器計算。單一長請求可能長時間占用整台主機,讓短請求在後方排隊。請審慎設定 OLLAMA_NUM_PARALLEL,並先閱讀一台自架 LLM 可服務多少並行使用者,再同時提高這兩個數值。
Buy context back with a smaller cache
bytes_per_value in the formula is a setting you control. Ollama's FAQ documents OLLAMA_KV_CACHE_TYPE, with f16 as the default at 2 bytes, plus q8_0 at 1 byte and q4_0 below that. Moving to q8_0 halves the cache, so the 32k row costs 2 GiB instead of 4 GiB. Quantising the weights frees memory from the other side of the same budget, and the GLM tag that actually fits a VPS is worked through quantisation by quantisation if that is the trade you would rather make. The same FAQ documents OLLAMA_FLASH_ATTENTION=1, which some builds want before a quantised cache takes effect.
[Service]
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"Confirm rather than assume: restart the service, load the model at the same num_ctx as before, and compare RSS. Support depends on the model and on the backend, so a setting that changes nothing means your combination is not covered. The documentation lists these options without promising a quality result, so test q4_0 against your own prompts before you rely on it. If these knobs are the reason you are here, Ollama and llama.cpp expose them differently.
選擇 num_ctx 的做法
- 從
/api/show讀取模型的最大 context、層數及 key/value head 數量。 - 使用公式計算每個 token 所需的位元組數,再乘以所需的 context。
- 加上權重大小,與可用 RAM 比較,並至少保留 1 GiB 給伺服器的其他工作。
- 設定數值並載入模型,再使用
ollama ps和prompt_eval_count確認實際套用的設定。 - 執行實際工作負載,同時監控
free -m;如果開始使用 swap,請將 context 減半。
大多數工作所需的 context 都比使用者設定的少。摘要長篇報告時,16k 通常已足夠。檢索前端貼入五個文件片段時,很少會超過 8k。會讀取完整檔案的 coding agent 才是真正需要 64k 以上的情況;在這種情況下,應依 context 規模配置機器,而不是反過來。如果伺服器本身仍是新建的,請先從 在 VPS 上完成可運作的 Ollama 安裝 開始,等模型能正常載入後再調整 context。
FAQ
Ollama 的預設 context length 是多少?
這取決於 build 與硬體,因此請查證,不要直接假設。Ollama 的 FAQ 記載為 4096 tokens,Modelfile reference 記載 num_ctx 預設值為 2048,而 context length 頁面記載的預設值會依可用 VRAM 選擇:低於 24 GiB 時為 4k,24 到 48 GiB 時為 32k,高於 48 GiB 時為 256k。僅使用 CPU 的 VPS 會落在較小的範圍。具備該欄位的 build 可透過 ollama ps 顯示實際套用的 context;API 回應中的 prompt_eval_count 則可在所有 build 上證明實際值。
為什麼 Ollama 會忽略長 prompt 的開頭?
因為 prompt 長度超過 context window,伺服器會在模型看到之前截斷 prompt,而且不會回傳錯誤。使用較大的 num_ctx 重新傳送相同 prompt,並監看回應中的 prompt_eval_count 是否增加。如果該數值沒有變化,表示你與伺服器之間的某個元件自行設定了 num_ctx;chat 前端與 agent framework 常有這種情況。
較大的 num_ctx 需要多少額外 RAM?
將 context length 乘以每個 token 的 cache 成本,即 2 * layers * kv_heads * head_dim * bytes_per_value。以 f16 的 Llama 3.1 8B 為例,每個 token 需要 128 KiB,因此 32k tokens 會額外耗用 4 GiB,而完整的 128k 則會在 weights 之外額外耗用 16 GiB。模型載入時會配置 cache,因此即使 prompt 始終很短,較大的 num_ctx 仍會耗用這些記憶體。
較大的 context window 會讓 Ollama 變慢嗎?
會,原因有兩個。Prefill 工作量會隨 prompt 長度的平方增加,因此長輸入會讓第一個 token 的延遲超出單純依長度估算的結果。較大的 cache 也會爭用記憶體:在 GPU 主機上,部分 layers 會被推送到系統 RAM;在 CPU 主機上,則會使系統更接近使用 swap。即使從未填滿,較大的 num_ctx 仍會耗用記憶體,但不會增加 prefill 時間。
我可以為單一模型永久設定 num_ctx 嗎?
可以。建立包含 FROM llama3.1:8b 與 PARAMETER num_ctx 16384 的 Modelfile,然後執行 ollama create llama3.1-16k -f ./Modelfile。所有要求使用 llama3.1-16k 的 client 都會套用該 context,無須傳送任何 options。若 request 自行附帶 num_ctx,仍會優先採用該值,因此這是預設值,而不是上限。