问题描述
- opencode 1.4.11
- oh-my-openagents 3.17.4
- llama.cpp + qwen3.5 35B/qwen3.6 35B
- 任务处理有时候会中断并答复:Assistant response prefill is incompatible with enable_thinking
- 不折腾了,reasoning = off
尝试
- 修改opencode.json
- "enable_thinking": true 无效
- "assistant_prefill": false 无效
- bunx oh-my-opencode doctor --fix 没有这个命令
- llama.cpp config.ini
- reasoning = on/off/auto 无效
- chat-template-kwargs = {"enable_thinking":false} 无效
- llama ini里增加 --chat-template-file "/models/google-gemma-4-31B-it-interleaved.jinja",好像有效果,观察
根源
Response Prefill (响应预填充)
llama.cpp HTTP 服务器默认开启 prefill-assistant 特性:当对话历史的最后一条消息来自助手时,llama.cpp 会自动预填充助手的响应前缀,以复用 KV 缓存、加速后续生成。这一机制的设计目标是优化多轮对话的响应速度,但在思考模式下会触发底层逻辑冲突。 具体而言,当模型处于思考模式时,其输出会先产生 `` 标签包裹的思维链,再输出正式回答;而预填充机制会提前写入助手响应的固定前缀,这会打断思维链的生成流程,甚至导致模型输出格式混乱。因此 llama.cpp 从代码层面严格禁止两者同时启用。Enable Thinking / Reasoning (思维链输出)
Qwen3.5 系列模型(含 27B 版本)支持思考模式(Thinking Mode) :模型会在生成最终回答前,先产生一段用 ... 标签包裹的思维链,用于拆解问题、逻辑推理或自我验证。这一特性默认开启,旨在提升复杂任务(如代码生成、数学推理)的准确性,官方也提供了明确的参数开关 enable_thinking 用于切换模式 opencode
Qwen3.5 27B 默认开启思考模式,llama.cpp 默认开启 prefill-assistant,而 OpenCode 未对这两个默认参数做任何调整, 这就导致三者的默认配置形成了冲突的 “完美风暴”。长期观察的解决方案
chat-template-file = D:\OS\gguf\Qwen3.5-122B-A10B-chat_template.jinja reasoning = off # 推理模式总开关:on/off/auto 不会重复生效 reasoning-budget = 0 # 推理预算token: 0 不推理,-1无限制, xxx具体token数量 chat-template-kwargs = {"enable_thinking":false} # 对话模板参数,思维链/thinking 功能
Trae的分析
这样的方式,是否真的能解决冲突,让opencode调用毫无问题?
1. 你现在这套“关 reasoning + reasoning-budget + chat-template-kwargs enable_thinking=false”的思路, 大概率可以把冲突压下去 ,前提是:OpenCode 发到 llama.cpp 的请求最终确实会走到这个模板参数(也就是 enable_thinking 不会被请求体里覆盖为 true)。 但从“彻底根治”的角度看, 最稳的是直接在 llama.cpp server 侧关掉 prefill-assistant ,因为报错本质就是 llama.cpp 明确禁止 prefill-assistant 与 enable_thinking 同时启用。llama.cpp server 有专门参数: --no-prefill-assistant (默认是开启 prefill)来源: llama.cpp tools/server README 。 结论建议: - 要“OpenCode 调用毫无问题” :优先把 --no-prefill-assistant 加到 server 启动参数(或写进 preset/ini 等价项,如果你的版本支持),再保留你现在的 thinking/reasoning 关闭作为双保险。 - 仅靠你现在后面三个开关 :通常也能好,但仍可能在“OpenCode 某次请求显式打开 enable_thinking / 使用了另一份模板”时复发。这样的设定是否会大幅降低性能?
- 关闭 thinking/reasoning:通常不会降低吞吐,反而更快 。原因很简单:少生成一段思维链 token,输出更短、上下文更干净。 - 关闭 prefill-assistant:可能带来小幅性能损失,但通常不大 。prefill 的收益只在“对话历史最后一条消息来自 assistant(而且客户端又继续发请求)”这种场景明显;OpenCode 的任务式调用很多时候最后一条是 user/tool 侧输入,prefill 的收益本来就有限。 所以整体上更可能是: 稳定性显著提升,性能小幅变化(多数场景几乎无感) ,代价主要在极少数“连续 assistant 结尾的多轮续写”场景。OpenCode + llama.cpp + Gemma4 / Qwen3.5 最佳实践(可落地的配置策略)
- 服务端统一兜底(推荐) :在 OpenCode 专用的 llama.cpp 实例上,直接加 --no-prefill-assistant 。这一步能把“prefill vs thinking”这一类冲突从机制上消掉。 - Qwen3.5 单独策略 (更关键): - 如果你追求稳定 + 兼容:保持 chat-template-kwargs = {"enable_thinking":false} ,并把 reasoning=off / 或 reasoning-budget=0 作为一致化策略(不同版本字段行为可能略有差异,但目标是“不要产出 链”)。 - 如果你确实想用 thinking:建议 不要给 OpenCode 用同一个 server ;单独起一个“prefill 可开、thinking 可开”的交互聊天实例,把 OpenCode 走的实例固定为“thinking 关 + no-prefill-assistant”。 - Gemma4 策略 (相对简单):Gemma 系列一般不依赖 Qwen 那套 enable_thinking 机制;它更多是“模板是否正确、采样与上下文是否合理”。Gemma 用 OpenCode 时,重点是模板文件匹配模型、以及别把上下文/输出搞到过长导致任务变慢。你现在的模板文件指定方式是对的。 - 验证是否彻底解决(建议你做一次自测) :用同一套 server,刻意构造“最后一条消息是 assistant”的对话再请求一次(这是最容易触发 prefill 的条件)。如果加了 --no-prefill-assistant ,应当不再可能出现那条报错;如果没加,只靠 enable_thinking=false,也应当不会报错,但更依赖“请求没有把 enable_thinking 打回去”。