Ollama num_predict 怎么限制输出长度
Ollama 的 num_predict 只限制输出 token 数量。本文说明 Modelfile、options 和 /set parameter 三种设置位置,解释最近设置为何覆盖其他设置,以及如何读取响应中的 done_reason。
Ollama 中的 num_predict
num_predict 是 Ollama 中用于限制模型单次响应最多生成多少个 token 的选项。它只统计输出 token,因此不会将提示词计入限制。模型达到该上限后,会立即停止生成,有时会在单词中间停止;此时响应中的 done_reason 会设置为 length。
这就是该功能的全部内容。难点在于,Ollama 提供了 3 个可设置此值的位置,并且距离请求最近的设置优先。几乎所有“num_predict 不起作用”的报告,原因都是某一层设置静默覆盖了另一层设置。
num_predict 不是 num_ctx
在 Ollama 中,这两个选项比其他任何选项都更容易混淆,而这种混淆会浪费实际的调试时间。
num_ctx表示模型可以读取多少内容。它是上下文窗口的大小,用于容纳提示词以及当前为止生成的全部内容。增大该值会消耗更多内存,因为模型为这些令牌保留的键值缓存会随窗口增大。为硬件确定 num_ctx 大小是另一项独立工作,也有其自身的故障模式。
num_predict表示模型可以写入多少内容。它是停止规则,不是资源分配。增大该值主要增加墙钟时间,而不是 RAM 用量,并且不会预先预留内存。
两者会在一个地方产生联系。生成的令牌会在生成后进入上下文窗口,因此回复可能因为窗口已填满而停止,而不是因为达到上限而停止。Ollama 在这两种情况下都会报告 length,因此区分两者的数字是 eval_count,下文将进一步介绍。
使用 Modelfile 一次设置
Modelfile 会将该值写入您创建的模型。创建文件:
FROM qwen3:8b
PARAMETER num_ctx 8192
PARAMETER num_predict 512然后构建模型,并读取构建结果:
ollama create qwen3-capped -f Modelfile
ollama show --parameters qwen3-cappedollama show --parameters 会逐行输出每个已存储参数及其值。如果输出中缺少 num_predict,说明该模型未内置上限,此时使用 Ollama 自身的默认值。ollama show --modelfile qwen3-capped 会输出完整定义,这也是复制现有模型随附参数的最快方法。
如果您希望每个调用方都继承某个值,应在这一层设置它。如果您希望该值成为最终值,则不应在这一层设置,因为它并不是最终值。
在 options 对象中为每个请求单独设置
每个生成端点都接受一个 options 对象,num_predict 放在该对象中:
curl http://localhost:11434/api/generate -d '{
"model": "qwen3:8b",
"prompt": "Explain what a reverse proxy does.",
"stream": false,
"options": { "num_predict": 128 }
}'/api/chat 使用含义相同的 options 键。此处设置的值仅对当前调用生效,不影响其他调用。这是工具使用的层级:聊天前端、脚本、SDK 封装器或编码代理。无论界面是否显示相应输入框,它们都会发送一个 options 对象。
使用 /set parameter 在单个会话中设置
在 ollama run 中,交互式会话设置的选项会在本次会话的剩余时间内生效:
>>> /set parameter num_predict 256
>>> /show parameters/show parameters 会显示会话在您发送下一条消息时将发送的内容,因此这是确认更改是否生效的最快方法。该值会一直保留,直到您输入 /bye。如需保留这些设置,/save qwen3-capped 会将当前会话(包括参数)写入为一个新模型。在此处进行的任何 /set 都不会影响其他客户端。
哪个设置生效,以及为什么看起来没有生效
优先级顺序很简单。随请求发送的选项优先级最高。模型的 Modelfile 中的 PARAMETER num_predict 行会在请求未提供值时作为回退设置。如果两者都没有设置,则使用 Ollama 的内置默认值。
/set parameter 不是第三条规则。交互式会话是 API 客户端,因此您在那里设置的值会作为该请求的 options 发送。这正是它会覆盖该会话 Modelfile 设置的原因。
现在说明这个问题导致的故障。您添加 PARAMETER num_predict 512,重新构建模型,但回复仍然会生成数千个 token。该设置确实存在,ollama show --parameters 可以证明这一点。但每个请求都会覆盖它,因为客户端会发送自己的 options 对象,其中包含客户端自己的数值。这个数值通常是您几个月前在设置界面中输入后忘记的。ollama show 读取已存储的模型。它无法显示通过 HTTP 到达的内容。
使用一条命令验证服务器端行为。发送一个会生成较长回复的请求,将上限强制设为较低值,然后读取两个字段:
curl -s http://localhost:11434/api/generate -d '{
"model": "qwen3-capped",
"prompt": "Describe the Linux boot process in detail.",
"stream": false,
"options": { "num_predict": 32 }
}' | jq '.done_reason, .eval_count'该命令应输出 "length" 和 32。如果缺少 jq,请先使用 sudo apt install -y jq 安装。返回 "length" 和 32 表示服务器遵循了该选项,而您的应用发送了不同的设置。要查看服务器对请求的记录,请在环境中设置 OLLAMA_DEBUG=1 后重启服务器,并在应用与服务器通信时监控 journalctl -u ollama -f。
负值,以及不应照抄的数字
num_predict也接受负值,但这些值表示哨兵值,而不是计数。一个负值表示“不限制,继续生成”。另一个负值表示“填充剩余上下文”。截至 August 2026,Ollama Modelfile 参考文档将默认值列为 -1,表示无限生成;同一表格的早期版本还曾将 -2 列为填充上下文的值。
请将这些内容视为依赖版本的行为,因为相关定义发生过变化。在该条目于 2024 年末修正之前,参考文档长期将默认值记为 128,因此许多指南仍在重复旧数字。请阅读与您实际运行版本对应的 Modelfile 参数参考,然后使用上文的 eval_count 检查确认行为。您在自己的主机上验证过的值,比从任何地方(包括本文)读到的值更可靠。
仅 CPU VPS 上,输出长度为何是主要成本
生成分为两个阶段,且两者的速度差异很大。提示词 token 会批量计算,一次处理多个。输出 token 则逐个生成,每个 token 都需要完整遍历一次模型权重。在仅使用 CPU 的 VPS 上,这个过程受内存带宽限制,因此生成一个 token 的成本远高于处理一个提示词 token。
请求不使用流式输出,相关数值会直接显示:
"prompt_eval_count": 26,
"prompt_eval_duration": 107345000,
"eval_count": 237,
"eval_duration": 4289432000时长单位为纳秒。在这段数据中,26 个提示词 token 用时约 0.1 秒,237 个输出 token 用时约 4.3 秒。需要注意,这段数据来自 Ollama API 文档中的示例响应,并非某台特定服务器的测量结果。您自己的生成速度是将 eval_count 除以 eval_duration 后换算为秒;在调整其他设置前,先测量您自己硬件上的每秒 token 数很有价值。该速度不仅取决于机器,也取决于模型。因此,如果主要成本来自较长的回答,选择针对快速解码构建的模型,例如VPS 上的 Nemotron 3.5 Lightning,可以减少原本需要通过设置较低上限来限制的等待时间。
剩下的只需计算即可。在每秒生成 8 个 token 的情况下,生成一个 2,000 token 的回答会让机器持续工作超过 4 分钟,而模型并不知道您只想要一个段落。有些模型还会进入循环,不断重复某个短语,直到外部条件停止生成。如果不设置上限,这个请求会持续占用一个 CPU 核心,直到上下文窗口耗尽。num_predict用于限制生成长度。对于小型自托管 Ollama VPS,这点尤其重要,因为一个长请求可能占满整台机器。
截断输出通常是达到上限,而不是模型损坏
这些症状看起来像模型故障:回答在句子中间停止;JSON 无法解析,因为结尾的大括号始终没有出现。人们通常会立即归咎于模型或量化。请先读取响应。
done_reason 表示答案直接回答了问题。stop 表示模型自行完成了生成,原因可能是输出了序列结束标记,或匹配了 stop 选项中的某个字符串。length 表示生成因空间不足而被截断。看到 length 时,请将 eval_count 与上限进行比较:两者完全相同,表示 num_predict 停止了生成;如果前者更小,则表示上下文窗口先耗尽了。
使用流式传输时,这些字段会出现在最后一个数据块中,也就是包含 "done": true 的数据块。许多客户端库会丢弃这个数据块,只将文本交给代码。因此,在应用中,同样的截断看起来没有原因,而在 curl 下却很明显。如果库隐藏了这些字段,请使用 curl 发送一次请求,以确认服务器实际返回的内容。
还有一点可以避免浪费整个下午。提高 num_predict 不会让模型生成更多内容,只会提高上限。如果回答在 200 个 token 后以 done_reason 和 stop 结束,说明模型认为自己已经完成生成;提高上限不会改变结果。带有 stop 的简短回答是提示词问题。带有 length 的简短回答是上限问题。
选择数值
- 对于交互式聊天,可以不设上限,并按 Ctrl+C 停止失控的回复。因为您始终在查看屏幕。
- 对于任何脚本任务,都应设置上限。在循环中进行不设上限的生成,会导致本应运行十分钟的批处理任务直到第二天早上仍未结束。
- 对于结构化输出,应将上限设置为高于预期最大有效文档的值,然后将
done_reasonoflength视为硬错误并重试,不要解析返回的部分内容。 - 对于编码代理,应在代理自身的配置中设置该值,因为代理会在每次请求中发送自己的选项。将编码代理指向 Ollama介绍了这些设置的位置。
上限按 token 计算,而不是按单词或字符计算,因此不要估算。先在不设上限的情况下生成一个有代表性的回答,读取 eval_count,再将限制设置为明显高于该值的数值。不同模型系列的分词方式不同,因此适用于 Llama 模型的值,可能会截断来自同一 VPS 上的 Qwen 3 模型的相同回答。
FAQ
num_ctx 和 num_predict 有什么区别?
num_ctx 是上下文窗口的大小,用于设置模型可以读取的内容:提示词以及截至当前已生成的所有内容。它会增加内存开销,因为键值缓存会随之增长。num_predict 设置模型在一次响应中最多可以写入的 token 数量。它主要增加耗时,而不是内存开销,并且不会预先分配空间。生成的 token 会同时计入这两个值,因此响应可能因任一限制而提前结束。
为什么我的 num_predict 设置似乎没有生效?
因为随请求发送的值会覆盖模型中存储的值。将 PARAMETER num_predict 512 写入 Modelfile,然后通过聊天前端或代码代理使用该模型时,客户端会发送自己的 options 对象,其中的数值优先。ollama show --parameters 仍会显示您设置的值,因为它读取的是模型中存储的值,看不到通过 HTTP 到达的内容。使用 "options": {"num_predict": 32} 发送一个带有 curl 的请求,并检查返回的 eval_count 是否为 32。如果是,则说明服务器本身运行正常,接下来应在应用程序中继续排查。
如何判断输出是否因 num_predict 而被截断?
使用 "stream": false 发送请求,然后读取 done_reason。值为 stop 表示模型自行完成了生成。值为 length 表示可用空间已耗尽。然后将 eval_count 与您的上限比较:如果两者完全相同,说明是 num_predict 停止了生成;如果 eval_count 更小,说明上下文窗口先被填满。使用流式传输时,这两个字段都会在最后一个数据块中随 "done": true 返回,但许多客户端库会在您的代码读取前将其丢弃。
num_predict 的默认值是多少?
请从您自己的安装中读取该值,不要依赖文章中的信息。截至 August 2026,Ollama Modelfile 参考文档将默认值列为 -1,表示生成不受限制;该条目在 2024 年底经过修正,此前多年一直记录为 128。负值表示特殊标记,而不是数量;同一张表的旧版本还曾列出 -2,表示填满剩余上下文。请查看适用于您版本的 Modelfile 参数参考,然后使用 ollama show --parameters 和一个 curl 请求进行确认。
提高 num_predict 会让模型生成更长的回答吗?
不会。它只会移除上限。如果回答以 done_reason 结束,并且 stop,说明模型认为生成已经完成;提高上限不会改变结果。这种情况下,长度取决于提示词:要求特定结构、指定章节数量,或明确详细程度。只有当 done_reason 返回 length 时,才应提高 num_predict。