本机跑 Ollama,喂一份长文档让它总结,它答得挺顺,但你发现它完全没提文档前半段的内容;或者多轮对话聊到后面开始「失忆」、前后矛盾。这不是模型笨,是 Ollama 默认上下文窗口小得离谱——很多模型标称 128K,Ollama 默认只给 2048 token,超出的部分被静默丢掉,而且不会报错提醒你。
先确认是不是被截断了
最直观的办法看 prompt_eval_count:发一段明显超过默认窗口的长文本,让接口返回这个值。
curl http://localhost:11434/api/generate -d '{
"model": "llama3.1:8b",
"prompt": "在这里粘一段约 18000 词的文档",
"options": { "num_ctx": 4096 },
"stream": false
}' | python3 -c "import sys,json;print(json.load(sys.stdin)['prompt_eval_count'])"
如果返回接近 4096 而不是真实 token 数,说明被截了。把 num_ctx 调到 16384 再跑,数字会明显涨上去。
三种调大上下文的方法
| 方式 | 作用范围 | 适合 |
|---|---|---|
| 请求里 options.num_ctx | 单次请求 | 临时任务 / 测试上限 |
| Modelfile 写 PARAMETER | 用模型名调用即生效 | 长文档/代码固定用 |
| OLLAMA_CONTEXT_LENGTH 环境变量 | 服务端所有请求 | 统一调大省心 |
方式①单次优先级最高:
import requests
requests.post("http://localhost:11434/api/generate", json={
"model": "llama3.1:8b",
"prompt": long_doc,
"options": {"num_ctx": 16384},
"stream": False,
})
方式②写进 Modelfile 固化一个新模型:
FROM llama3.1:8b
PARAMETER num_ctx 16384
ollama create llama3.1-16k -f ./Modelfile
ollama run llama3.1-16k
方式③改全局默认(systemd 用 drop-in 改,别动原 unit):
sudo systemctl edit ollama
# 写入
[Service]
Environment="OLLAMA_CONTEXT_LENGTH=16384"
之后 sudo systemctl daemon-reload && sudo systemctl restart ollama。
代价:显存随上下文线性涨
| num_ctx | 显存占用(llama3.1:8b Q4) | 速度 |
|---|---|---|
| 2048 | ~5.6 GB | ~47 tok/s |
| 8192 | ~6.9 GB | ~44 tok/s |
| 16384 | ~8.8 GB | ~39 tok/s |
| 32768 | ~11.9 GB,OOM 风险 | ~31 tok/s |
7-8B 的 Q4 模型,8K 几乎免费,16K 在 12G 显存上稳,32K 要 16G+ 或换更小量化。别一上来就拉满 128K,速度掉一半还容易 OOM。笔记本 8G 显存别缩 ctx,把 num_batch 调小到 128 更稳。
长文还断?再看 num_predict
有时不是输入被截,是输出被砍——回答到一半没了。那是 num_predict(最大生成 token)太小。请求里加 "num_predict": 4096,并开 "stream": true 边生边收,避免一次性大响应超时。
踩坑实录
用 Ollama 跑代码助手,让它改一个 600 行的文件,它只动了文件尾巴、前半段逻辑全忽略。查 ollama ps 的 CONTEXT 列才发现模型只加载了 2048 token。本地 llama3.1 标称 128K,但默认 2048。在 Modelfile 里写死 PARAMETER num_ctx 16384 重建模型后,前后逻辑才对上。后来养成习惯:长文档/长代码任务一律显式带 num_ctx,别赌默认。
常见问题
Q1:为什么标称 128K 实际只有 2048?
Ollama 默认按可用显存给保守值,不同版本默认值还不一致(文档里 2048 / 4096 都出现过)。以你自己 ollama ps 显示的 CONTEXT 列为准,别信文档页。
Q2:RAG 检索内容很长也被截?
是。检索回来的 chunks 拼进 prompt 后同样受 num_ctx 限制。除了调大窗口,更要控制 chunk 数量(3-5 个、每块 200-300 token)并加 reranker,否则塞再多也没用,模型还是只看到尾部。
Ollama 这类本地大模型排障,关键是用接口返回的真实数值说话。更多 AI 与运维实操笔记,欢迎来 fenij.com 交流。