SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 已更新 2026-10-04

Ollama num_ctx 怎麼設定?避免提示詞遭截斷

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 欄會顯示目前載入模型所使用的 context length。旁邊的 PROCESSOR 欄會顯示模型的配置位置。VPS 沒有 GPU 時,100% CPU 屬於正常情況。在配備 GPU 的伺服器上,如果顯示 30%/70% CPU/GPU 之類的分割配置,表示權重與 cache 已無法一併放入 VRAM,而提高 num_ctx 通常就是原因。

journalctl -u ollama --no-pager | grep -i n_ctx | tail -n 5

inference runner 會在包含 n_ctx 的行中顯示 context size。不同 release 的確切文字可能不同,因此找不到該行時,應先視為名稱變更,而不是據此判定其他結論。

設定 num_ctx 的 4 個位置

在請求中。 將 "options": {"num_ctx": 16384} 傳送至 /api/generate 或 /api/chat。這會覆寫所有其他設定,且只套用至該次呼叫。如果此值與已載入模型目前使用的值不同,伺服器會先重新載入模型。你可以在回應的 load_duration 中看到這點:數值會從接近 0 跳升至數秒。模型閒置足夠時間而卸載時,也會出現相同的等待時間。因此,確定 context size 後,建議透過 keep_alive 讓模型常駐。

在互動工作階段中。 在 ollama run 內輸入 /set parameter num_ctx 16384。此設定只會持續該工作階段。

在 Modelfile 中。 這會將值寫入具名模型,因此所有 client 都會取得該設定,無須在 client 端變更。

FROM llama3.1:8b
PARAMETER num_ctx 16384
ollama create llama3.1-16k -f ./Modelfile
ollama run llama3.1-16k

在伺服器上。 OLLAMA_CONTEXT_LENGTH 會為未攜帶自有 num_ctx 的所有請求設定預設值。在 systemd 下,請新增 drop-in,而不要編輯 unit file。

sudo systemctl edit ollama.service
[Service]
Environment="OLLAMA_CONTEXT_LENGTH=16384"
sudo systemctl daemon-reload
sudo systemctl restart ollama
ollama ps

在除錯其他人的 client 時,優先順序尤其重要。攜帶 num_ctx 的請求會覆寫伺服器預設值,因此 chat 前端或 agent 若自行傳送較小的值,可能會悄悄抵銷你的 systemd 變更。當你將 coding agent 指向 Ollama 伺服器時,請先確認 client 傳送的內容,再判斷問題是否出在伺服器。

為何不能直接將 num_ctx 設為模型上限

Attention 會讓每個 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 後,這項成本就不再只是抽象數字。

ChartLlama 3.1 8B at f16: KV cache and total RAM by context length, in GiB
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 context 時,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 標籤的相同計算結果,能顯示在 8 到 64 GB 記憶體之間,weights 能為 context 留下的空間有多麼有限。

KV cache 無法容納時會發生什麼事

在僅使用 CPU 的 VPS 上,程序會持續增加記憶體用量。模型載入期間以及執行長時間請求時,請監控其狀態。

free -m
ps -eo rss,comm --sort=-rss | head -n 5

RSS(常駐集大小)會以 KB 顯示。如果 free -m 中的已用 swap 開始增加,請縮小 context。KV cache 若位於 swap 中,生成速度會降至每個 token 停頓數秒,因為每個新 token 都必須讀取整個 cache。

如果主機的記憶體完全耗盡,核心會選擇記憶體用量最大的程序並將其終止。

sudo dmesg | grep -i "killed process"

若出現 Out of memory: Killed process 1234 (ollama) 的行,表示你要求的 context 無法容納。Ollama 通常會在達到這個階段前拒絕請求,接著顯示錯誤訊息,列出所需記憶體與可用記憶體。

在 GPU 主機上,失敗情況較不明顯。部分 layer 會溢出至系統 RAM,ollama ps 會顯示 CPU 與 GPU 的分配情形,吞吐量也會大幅下降。下降幅度取決於硬體,因此請在每個 context 設定下,測量你自己的主機每秒可處理的 token 數,不要直接採用其他機器的數值。

Prefill 時間成長速度高於 prompt 長度

Prefill 是在第一個輸出 token 出現前,處理輸入內容的工作。每個 prompt token 都會關注它之前的所有 token,因此總工作量會隨輸入長度的平方增加。prompt 長度加倍時,等待第一個 token 的時間會超過 2 倍。

回應中會提供測量結果,因此不必直接相信這項說法。

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)}'

使用短 prompt 執行一次,再使用長 prompt 執行一次,然後分別以 token 數除以秒數。在僅使用 CPU 的 VPS 上,對長上下文請求而言,prefill 通常是最慢的階段,而根據短 prompt 取得的每秒 token 數,無法預測長 prompt 的表現。若 prefill 時間超過前方任何一層設定的 timeout,長 prompt 通常會回傳 context deadline exceeded,而不是答案。因此,應先找出是哪一層放棄請求,再縮短上下文。

Concurrency 會讓這個問題最嚴重。每個處理中的請求都需要自己的 cache,因此上方圖表中的記憶體用量是以每個請求計算,而不是以每台伺服器計算;一個長請求可能占用整台主機,使短請求排在後面等待。請審慎設定 OLLAMA_NUM_PARALLEL,並先閱讀 一台自架 LLM 能服務多少個並行使用者,再同時提高這兩個數值。

以較小的快取換回可用記憶體

bytes_per_value 是由您控制的設定。Ollama 的 FAQ 說明了 OLLAMA_KV_CACHE_TYPE,其中 f16 是預設值 2 bytes,另有 1 byte 的 q8_0,以及更低的 q4_0。改用 q8_0 會讓快取縮小一半,因此 32k 那列的成本會從 4 GiB 降至 2 GiB。量化權重則能從同一份記憶體預算的另一側釋放空間;如果您比較願意採用這種取捨,實際能在 VPS 上運作的 GLM 標籤 會逐一說明各種量化方式。相同的 FAQ 也說明 OLLAMA_FLASH_ATTENTION=1;部分建置版本需要先設定它,量化快取才會生效。

[Service]
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"

不要直接假設設定有效,請進行確認:重新啟動服務,以與先前相同的 num_ctx 載入模型,然後比較 RSS。支援情況取決於模型與後端,因此設定沒有造成任何變化,表示您的組合不在支援範圍內。文件列出這些選項,但未保證品質結果;請先使用您自己的提示測試 q4_0,再依賴它。如果您是因為這些控制項才來到這裡,Ollama 與 llama.cpp 提供這些設定的方式不同。

設定 num_ctx 的方法

  1. 從 /api/show 讀取模型的最大上下文長度、層數及 key/value head 數量。
  2. 使用公式計算每個 token 所需的位元組數,再乘以所需的上下文長度。
  3. 加上權重大小,與可用 RAM 比較,並至少保留 1 GiB 給伺服器的其他工作。
  4. 設定數值並載入模型,再使用 ollama ps 和 prompt_eval_count 確認實際套用的設定。
  5. 執行實際工作負載並監控 free -m。如果 swap 開始使用,將上下文長度減半。

大多數工作所需的上下文都比使用者設定的短。摘要整理長篇報告時,16k 通常已足夠。會貼入五個文件片段的檢索前端,很少會超過 8k。需要讀取完整檔案的程式碼代理,才是真正需要 64k 或更大上下文的情況。這種情況也應該以上下文需求來規劃機器,而不是反過來。如果伺服器本身仍是新建的,請先從 可正常運作的 VPS 上的 Ollama 安裝 開始,等模型能正常載入後再調整上下文。

FAQ

Ollama 的預設 context length 是多少?

這取決於建置版本與硬體,因此應查證,不要直接假設。Ollama FAQ 記載為 4096 tokens,Modelfile reference 記載 num_ctx 預設值為 2048,而 context length 頁面記載的預設值則依可用 VRAM 決定:低於 24 GiB 時為 4k,24 至 48 GiB 時為 32k,高於 48 GiB 時為 256k。僅使用 CPU 的 VPS 會落在較小的範圍。對於包含該欄位的建置版本,ollama ps 會列出實際套用的 context;API 回應中的 prompt_eval_count 則可在所有建置版本中確認該值。

為什麼 Ollama 會忽略長 prompt 的開頭?

因為 prompt 長度超過 context window,伺服器會在模型讀取前截斷內容,而且不會回傳錯誤。使用較大的 num_ctx 再次傳送相同 prompt,並觀察回應中的 prompt_eval_count 是否增加。如果該數值沒有變化,表示用戶端與伺服器之間的某個元件自行設定了 num_ctx。這種情況常見於聊天前端與 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,因此較大的 num_ctx 即使 prompt 持續很短,也會佔用相應的記憶體。

較大的 context window 會讓 Ollama 變慢嗎?

會,原因有兩個。Prefill 工作量會隨 prompt 長度的平方增加,因此較長的輸入會讓第一個 token 的產生時間,延遲幅度超過輸入長度所直觀顯示的程度。較大的 cache 也會與其他用途競爭記憶體:在 GPU 主機上,會使部分 layers 移入 system 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。帶有自訂 num_ctx 的 request 仍會優先套用,因此這是設定預設值,而不是設定上限。