DeepSeek Harness 会话标题不更新:maxOutputTokens 64 被思考吃光
标题停在首条消息的截断文本上,通常不是模型不会起标题,而是标题请求的输出预算被思考吃光了。 内置标题插件复用主对话模型单独发一次请求,max_tokens 是思考与正文的共用额度;强制思考模型先把额度写满,正文为空,插件随后在 max-tokens 分支抛错并只打一条 warn,界面上什么也看不到(Discussion #10129)。
讨论中的复现环境是 0.2.1-rc.2 的桌面版,源码定位由社区核对给出。版本不同,行号可能有偏移,判断依据以配置项和 warn 文案为准,不要只认行号。
DeepSeek Harness 会话标题为什么几乎不更新:64 是思考加正文的总预算
64 这个数字不在插件源码里,而在 bundle 的补丁配置里,这决定了它属于今天就能改的配置问题。 社区核对源码给出的链路是四步:
packages/session/session-title-llm/src/index.ts:84把maxOutputTokens声明为z.number().step(1).min(1).required(),是 required 且没有默认值。packages/experimental/session-titles-bundle/cordis.patch.yml:10-11给了maxInputBytes: 4096与maxOutputTokens: 64,插件照单全收。- 强制思考模型把 64 个 token 全用在 reasoning 上,
finish_reason变成length,content为空。 session-title-llm在:202的 max-tokens 分支抛出title output reached maxOutputTokens,该错误只在 catch 里 warn,不写会话事件流。
据讨论里的实测对照:max_tokens=64 时 reasoning_tokens=64、正文为空;调到 1024 时 reasoning_tokens=139、标题正常;1024 且不带思考档位时 reasoning_tokens=0、总 token 只有 9。这组数字说明 64 不是「五个词的标题够了」,而是默认了模型不思考。
DeepSeek Harness 三步确认问题在标题额度,而不是模型能力
先用可观测证据把「模型不行」排除掉,再动配置。 三步都能在本地完成:
- 新建一个会话,只发一条消息,完成两轮对话后看侧栏标题。预期结果:标题仍是首条消息的截断文本,没有任何错误提示。
- 打开当前 profile 的
cordis.patch.yml,搜session-titles,确认同一段里有maxOutputTokens: 64。预期结果:能看到 64 与 4096 两个值,说明生效的是 bundle 补丁而非插件默认值。 - 用同一模型手动发一次带
max_tokens: 64与思考档位的请求,记录finish_reason与reasoning_tokens。预期结果:finish_reason=length、reasoning_tokens=64、content为空,与标题插件的失败路径完全一致。
三步都对上,就不用再怀疑模型或网络,问题在额度。
DSH插件路径一:用 cordis.patch.yml 提高 maxOutputTokens
这是改动最小、见效最快的一条路,只影响标题请求,不动主对话模型。 操作步骤:
- 找到 bundle 补丁里 session-titles 那一段,记下它的插件 id。预期结果:得到一个可被用户层 patch 命中的 id。
- 在用户层
cordis.patch.yml里按同一 id 增加覆盖块,把额度写大,同时重申maxInputBytes:
#按 bundle 补丁里的同一 id 覆盖,config 整块替换
- id: <session-titles 对应的插件 id>
config:
maxInputBytes: 4096
maxOutputTokens: 1024
- 保存后重载 profile,新建一个会话并对话两轮。预期结果:侧栏出现模型生成的短标题,而不是首条消息的截断文本。
- 回看会话事件流,确认不再出现
title output reached maxOutputTokens。预期结果:warn 消失,标题请求正常结束。
注意这条路的边界:补丁不深合并,漏写 maxInputBytes 会把 4096 变成未设置;已经写入兜底标题的存量会话不会自动重算,因为兜底标题不作为后续请求的锚点。
DeepSeek Harness 路径二:让标题请求不思考
这条路的思路是让 64 个 token 全部留给正文,但据讨论它不能只靠配置完成。 现状是标题插件复用主对话模型、思考档位写死取列表第一项,显式的关闭项会在发请求前被删掉,服务端对 off 返回 400 与错误码 11150(据讨论,报告者实测)。可行做法有两条:
- 给标题单独配一个不强制思考的小模型。预期结果:同样的 64 额度下
reasoning_tokens=0,标题能正常返回;这需要插件侧支持标题模型与主对话模型分开配置。 - 改插件让思考档位可配置,或允许在标题请求里保留 off。预期结果:请求不再被强制加上思考档位,
content非空。 - 改完后用路径一里的第 3 步复测一次。预期结果:
finish_reason=stop,正文非空,标题更新。
如果不想改代码,这条路走不通,直接用路径一或路径三。
DeepSeek Harness 路径三:改用本地截断标题
不调用模型就没有额度问题,代价是标题只反映首条消息。 适合标题只用来区分会话、不需要语义概括的场景:
- 在用户层 patch 里禁用 session-titles 那一行(按当前宿主的 patch schema 写
disabled)。预期结果:重启后不再发标题请求,日志里也没有标题相关 warn。 - 确认侧栏标题回落到首条消息的截断文本。预期结果:新会话标题稳定、可预测,但不会随对话变化。
- 如果截断文本太长或带换行,自己写一个小插件在会话创建时生成本地标题,只做空白折叠与定长截断。预期结果:标题长度统一,且完全不消耗 token。
这条路的取舍很直接:零成本、零失败,但失去了语义标题。多会话并行、靠标题找会话的人,还是建议走路径一;要换第三方标题插件的话,先在 DSH Plugin Hub 核对兼容版本。
DeepSeek Harness 三条路怎么选,以及改完看什么
新会话优先路径一,插件开发者优先路径二,只求稳定可读选路径三。 收尾检查按顺序做:
- 改完配置后重启一次 profile,而不是只刷新页面。预期结果:补丁重新加载,旧进程里的 64 不再生效。
- 新建会话验证标题生成。预期结果:两轮内出现语义标题。
- 发一条长消息把输入推过 4096 字节,再对话一轮。预期结果:如果标题停止更新,说明撞的是
maxInputBytes而不是额度,需要按路径三或改输入策略处理。
据讨论,这三个问题(额度太小、超限直接抛、失败静默)是相互独立的缺陷,调大额度只解决第一个。想彻底稳定,输入侧要改成取最近若干条并截断,失败要能在界面上看见。
三条路的差异可以直接对照:
| 路径 | 改动位置 | 生效范围 | 主要限制 |
|---|---|---|---|
| 提高额度 | 用户层 cordis.patch.yml | 仅标题请求 | 长会话仍会撞 4096 字节 |
| 关掉思考 | 插件代码或换标题模型 | 仅标题请求 | 据讨论不能只改配置 |
| 本地截断 | 禁用插件或自写插件 | 全部会话 | 标题没有语义 |
如果只是想让新会话马上有标题,路径一足够;如果还想让超长会话也不掉标题,必须同时处理输入裁剪,单靠调额度会在会话变长后回到原点。
不管走哪条,都建议顺手补一条可观测的验证:删掉现有标题后再触发一次标题请求,看会话事件流里有没有对应的成功记录。没有记录就说明失败仍然静默,这条链路的修复只做了一半。
来源:Discussion #10129、deepseek-ai/deepseek-harness。会话标题只是症状之一,更多排查入口见 DSH 故障排查。
常见问题
DeepSeek Harness 的标题请求输出预算被思考吃光了。标题插件把 maxOutputTokens 设成 64,而 max_tokens 是思考加正文的总预算,强制思考模型会先把 64 个 token 全部用在 reasoning 上,正文为空后走 max-tokens 分支抛错,错误只打 warn,所以界面上看不到任何提示。
DeepSeek Harness 能恢复新会话的标题生成。用户层 cordis.patch.yml 按同一插件 id 覆盖 maxOutputTokens 即可,但补丁是 config 整块替换、不深合并,必须同时重申 maxInputBytes。已经落盘的兜底标题不会自愈,存量会话要等下一次成功请求才会改写。
据讨论,DeepSeek Harness 标题插件的思考档位写死取列表第一项,发请求前会把显式的关闭项删掉,而服务端对 off 返回 400 与错误码 11150。所以这条路不能靠改配置完成,要么换一个不强制思考的模型给标题,要么改插件代码让思考档位可配。
DeepSeek Harness 标题在长会话里仍会停止更新,因为 maxInputBytes 默认 4096 字节,标题插件每次把全部用户消息重新发一遍,输入单调增长,超限直接抛错而不是裁剪。额度调到 1024 只是止血,长会话要真正稳定,得把输入策略改成只取最近若干条并截断。
相关术语
- maxOutputTokens(输出额度)
- maxOutputTokens 是一次模型请求允许生成的 token 总预算,思考与正文共用这一份额度,不是正文单独的预算。— https://github.com/deepseek-ai/deepseek-harness/discussions/10129
- max-tokens 分支
- max-tokens 分支是标题插件在 finish 原因为 length 时走的失败路径,会抛出 title output reached maxOutputTokens,并且只在 catch 里记一条 warn。— https://github.com/deepseek-ai/deepseek-harness/discussions/10129
- cordis.patch.yml
- cordis.patch.yml 是 DSH 用来覆盖插件配置的补丁文件,按插件 id 命中后对 config 做整块替换,不做字段级深合并,因此覆盖时必须重申同块内的其他字段。— https://github.com/deepseek-ai/deepseek-harness/discussions/10129
- 兜底标题
- 兜底标题是标题插件在模型请求失败时写入会话记录的首条消息截断文本,它被当作正式标题落盘,也不作为下一次请求的锚点。— https://github.com/deepseek-ai/deepseek-harness/discussions/10129
来源
- deepseek-harness Discussion #10129:内置会话标题插件几乎从不更新,输出额度 64 被思考吃光· deepseek-ai(GitHub Discussions)
- deepseek-ai/deepseek-harness 官方仓库· GitHub