故障排查 / 输出质量怪

模型“回”了但内容是空的 / 只蹦出几个字就断(思考模型)

本站未复现 改写 影响:llama.cpp / Ollama / 任何把思考与正文共用一份输出预算的推理栈 全版本(思考型模型通用行为) · Windows / Linux / macOS

报错原文

{"choices":[{"message":{"content":""},"finish_reason":"length"}]}
{"response":"","thinking":"Okay, the user is asking for...","done_reason":"length"}

这段字符串可以直接粘到 站内搜索 或外部搜索引擎里找。

现象

调用没报错、状态码正常,但返回的正文是空的,或只蹦出「Based」这种一两个字就断了。尤其发生在思考/推理型模型上(Qwen3 的 -thinking 变体、DeepSeek-R1 类、任何会先写思考块再答的模型):reasoning / thinking / reasoning_content 字段里一大段思考,正文却是空的。重试时好时坏——短问题正常、一换长一点的题就空。

原因

思考模型在给出可见答案前,会先生成一段隐藏的推理(reasoning)。关键在于:这段推理和正文**共用同一份输出 token 预算**(llama.cpp 的 n_predict、Ollama 的 num_predict、OpenAI 兼容端点的 max_tokens),而模型不会给正文留余量。推理一旦把预算吃光,生成就在第一个可见字之前停了。响应本身格式完好、也算“成功”(HTTP 200、无 error),所以很容易被当成“模型坏了 / 不肯回答”。其实有三种状态:① 空(推理吃掉 100% 预算,一个字都没剩下)② 截断(答案开了头被切半)③ 完整(finish_reason=stop)——只有②看起来像“正常但不对劲”,①最容易被误判为故障。

按这个顺序处理

  1. 先把输出预算抬到思考模型“想完再说话”够用:思考模型 max_tokens / num_predict 至少给到 2048,复杂推理 4096 起。参照系:llama.cpp 官方讨论里一台本地 RTX 3000 实测,问「2+2」光内部思考就烧掉约 420 token,可见答案只有 “four” 一个词——预算卡在 50 必然空。
  2. 不需要深度思考的场景,直接关思考(省 token、省时间):llama.cpp 用 --reasoning-budget 给思考单独封顶(用完强制收尾、正文照常出,不会把正文截断);Ollama 用**原生 /api/chat 顶层参数** `think:false` 关闭。
  3. 注意 Ollama 的 OpenAI 兼容端点 /v1 会**忽略** think 参数(0.30 起 `reasoning_effort:"none"` 才生效)——这是最坑的一个不对称:同一个模型走 /api/chat 能关思考,走 /v1 关不掉、照样烧预算出空回复。你的客户端如果强制走 /v1,就发 `reasoning_effort:"none"`。
  4. 别把空回复当成“模型的回答”:代码里判 `finish_reason=="length" && content 为空` 时,去读 reasoning_content / thinking 字段。预算被思考吃光时,思考是满的、答案是空的——读那个字段一眼就能看出这是预算问题、不是配置或权重坏了,也就不会去瞎改量化/模板。
  5. 别用一个全局 max_tokens 默认值同时伺候思考模型和普通模型:一个够思考模型想完还答的预算,喂普通模型是浪费;一个贴普通模型的预算,留思考模型一句都说不出来。按模型分开设默认值。

怎么确认解决了

同一条“问 2+2”,把 max_tokens 从触发空回复的小值抬到 2048/4096(或用上面方法关掉思考)后重跑:正文有内容、finish_reason 变成 stop,且「思考字段长度 + 正文长度」不再逼近预算上限。

来源与可信度

条目性质依据公开事实与社区普遍报告,用本站自己的话重写(未搬运任何他人文章段落)
是否已在本站机器复现否——请把这条当线索而不是结论

输出质量怪 · 其他条目

输出乱码、复读、突然说另一种语言上下文一长就开始答非所问
回到故障排查首页查容量是否本来就不够上传实测数据
这条内容有帮助吗?