DeepSeek Harness 模型接入排查:确定性 400、API key 冲突与思考复读失能
把 DeepSeek Harness(DSH)接到第三方模型或中转站之后,最容易踩的往往不是模型质量,而是三类「配置与元信息对不上」的问题:确定性的超窗 400、自动压缩静默失效、以及看起来像模型变傻的思考复读。 具体来说:pi-ai 在约束输出上限时用启发式估算填满窗口、只留固定 4096 的安全余量,于是工具输出这类被低估的内容会让「输入+输出」确定性地超过窗口;profile 里为第三方路由声明的 contextWindow 没有汇入模型信息解析链,导致依赖它的自动压缩直接中止、而界面把超窗误报成「额度已用尽」;停止原因映射里一次无条件的溢出判断,会把已经成功完成的 Codex 回答也判成上下文超限。除此之外还有三件纯配置问题:手工新增的 DeepSeek provider 与内置模型共用同一把密钥(引用名按 provider 名派生)、中转模型默认不支持图片(能力需要显式声明)、以及中文思考下 reasoning 通道自我复制把会话拖死(现有复读守卫对 reasoning 通道是盲的)(#9712、#9230、#9022、#9759、#9133、#9524)。
DeepSeek Harness 确定性 400:窗口声明与输出上限对不上
一句话结论:这不是「偶尔超一点」,而是每次都会超——因为输出上限是按估算值贴到窗口上限的,只留了 4096 这么小一段安全余量。 症状是走 pi-ai 路由时确定性收到 400 CONTEXT_WINDOW_EXCEEDED,且输入加输出正好等于窗口加一(#9712)。
DeepSeek Harness 机制一:固定 4096 余量 + 低估工具输出
据社区从发布产物逐字复核:clampMaxTokensToContext 会用本地启发式估算已用 token,让「输入 + 输出」尽量贴近窗口上限,只剩一个固定的安全余量;而估算函数(ceil(字符数 / 3.5) 一类)优先复用最近一次助手响应的用量,其后内容按字符数粗估,工具输出恰好落在被低估的区间里。讨论中算过本案例的低估量:实际比估算多 1.59%~2.42%(#9712)。
DeepSeek Harness 机制二:把 maxTokens 声明成窗口的 90% 会放大它
如果 profile 里把 maxTokens 声明成窗口的九成,压缩阈值会被压到一个很小的值(讨论中给出的量级是约 39K),于是「压缩过晚 + 输出预留过大」叠加,更容易溢出(#9712)。
DeepSeek Harness 四步处置
- 先确认是「贴窗口」而不是「历史太长」:把同一段历史换到一个窗口更大的模型上试,若立刻正常,说明是「输入+输出贴上限」这一类(#9712)。
- 收窄输出上限:给该路由/模型显式压
maxTokens,别让它贴到窗口(#9712):
providers:
<provider>:
modelOverrides:
<model>:
maxTokens: 32768
- 别把
maxTokens声明成窗口的九成:留出与压缩阈值相匹配的余量(#9712)。 - 把压缩提前:调小
headroomTokens、让thresholdRatio更保守,避免等你撞上溢出再压(#9712)。 - 验证:重放同样的对话轮,预期不再 400;若仍报,检查是不是声明窗口本身大于上游真实限制(见下一条)。
DeepSeek Harness 机制三:声明的 contextWindow 没进解析链 → 压缩失效 + 误报额度
一句话结论:contextWindow 你写了,但它没有汇入模型信息解析链;压缩去解析时拿到未定义值,直接抛配置错误、压缩中止,请求原样发出去被网关按超窗拒掉,界面却把它显示成「额度已用尽」。 症状是「明明手填了窗口,自动压缩完全不生效」(#9022)。
据报告者实测与社区逐行核对调用点:压缩的压力路径调用模型信息解析拿到 info.context === undefined,随后抛 TargetPressureConfigError,压缩中止;于是「必须手填」与「手填无效」并存(#9022)。
处置步骤:
- 确认判据:错误串里出现
TargetPressureConfigError,且 UI 文案是「额度已用尽」而网关返回的是超窗(两条信息不一致)(#9022)。 - 应急:手动执行
/compact(手动路径不受这条影响)(#9022)。 - 缓解:给该路由补上能让解析链拿到的窗口信息(例如走一层声明齐备的路由配置),或使用压缩目标守卫类插件在压缩被拒后改投更大窗口路由。
- 看文案分流:遇到「额度已用尽」先分辨是不是超窗的错文,避免按「充值」方向排查(#9022)。
DeepSeek Harness 机制四:已完成的 Codex 回答被误判超限
一句话结论:停止原因映射里那次「是否上下文溢出」的判断是无条件的,于是把「正常 stop、但累计输入超过目录声明窗口」的响应也判成溢出,覆盖了服务端的成功终态。 症状是「回答明明成功完成,却报上下文超限」(#9230)。
处置步骤:
DeepSeek Harness 配置类:密钥共用、图片能力未声明
一句话结论:这两条都不是 bug,而是「配置的默认推导规则」不符合直觉——密钥按 provider 名派生的引用名解析,图片能力必须显式声明。(#9759、#9133)
DeepSeek Harness 手工 provider 与内置共用密钥
据社区逐行核对源码:引用名派生规则是 deriveKeyRef(provider),即 provider 名大写加 _API_KEY;手工路由命名为 deepseek 就生成 DEEPSEEK_API_KEY,与内置(引用名同为 DEEPSEEK_API_KEY)逐字相同,而凭据是按引用名解析的(#9759)。
- 确认:改手工 provider 的密钥后,内置 DeepSeek 模型的密钥也跟着变——即为本条的指纹(#9759)。
- 修法一(推荐):把手工路由改名为
deepseek-alt之类,派生出的引用名自然分开。 - 修法二:显式把该 provider 的密钥引用改成
DEEPSEEK_MANUAL_API_KEY,再分别填写两把密钥。 - 要知道这是正当用法:同端点多路由共用 key 在 DSH 里是合法的,所以这不算缺陷,只是命名引导不足(#9759)。
DeepSeek Harness 中转模型不支持图片
- 确认:给该模型发图时被系统直接限制,而模型确实支持图片输入(#9133)。
- 修法:在该模型对应的配置行补上输入模态声明:
- patch:
id: <模型行的 id>
config:
input: [text, image]
- 验证:重开会话后发送一张图片,预期不再被拦(#9133)。
- 记住它是声明式的:即使上游支持,没声明也会被拦——所以「模型文档说支持图片」不构成排查依据。
DeepSeek Harness 思考复读:模型侧退化 + 守卫对 reasoning 盲
一句话结论:中文思考时 reasoning 通道会退化成「最短独立句」的自我复制(好。/ Go.),严重时整块约 99% 是同一个字、会话失能;而现有的两个流式复读守卫都对 reasoning 通道是盲的,所以拦不住。 换成 pro 档思考即消失(#9524)。
据讨论核对现状后认可的判据:倾向在模型/档位侧(flash 系容易塌缩锁定,pro 档「用而不塌」);而 llm/stream 上的两个复读守卫,一个按设计忽略 reasoning 通道,另一个需要连续多次停滞才反应,对「纯思考空转」不覆盖(#9524)。
DeepSeek Harness 四步处置
- 用可量化判据确认,而不是凭感觉:统计 reasoning 块尾的单字占比与最长重复片段长度;讨论中给出的量级是单字率 ≥30%、重复片段 ≥3 且排除标点时即可判定(#9524)。
- 装针对 reasoning 通道的守卫插件:
@argszero/cordis-plugin-thinking-loop-guard(0.2.0 起新增了「思考期间打断」的能力,period-1 的内容重复也会触发)(#9524):
npm i @argszero/cordis-plugin-thinking-loop-guard
- 换档位或锁语言:换到 pro 档思考,或把思考语言锁成英文,两者都能显著降低复读概率(#9524)。
- 验证:复现原来的长中文思考任务,预期不再出现「整块同字」;同时观察守卫是否给出打断记录(#9524)。
DSH插件 排查注意事项
这一族看起来杂,但可以用一句话分流:报错是「超窗/额度」就去查窗口与输出上限;报错是「模型不支持」就去查能力声明;没有报错只是变傻就去查思考通道。 九条要点:
- 确定性 400 优先怀疑输出上限,而不是历史太长(#9712)。
- 别把
maxTokens声明成窗口的九成:它会把压缩阈值一起压小(#9712)。 - 「手填
contextWindow但不生效」是已知缺口:解析链没汇入,不是你没写对(#9022)。 - 「额度已用尽」可能其实是超窗:文案与实际原因不一致,别照着充值方向排查(#9022)。
- 成功的回答不该被判超限:看到这种矛盾,直接定到停止原因映射的误判(#9230)。
- 密钥引用名按 provider 名派生:与内置同名就会共用,改名是最省事的解法(#9759)。
- 图片能力是声明式的:上游支持不等于 DSH 放行(#9133)。
- 思考复读先量化再处理:单字率与重复片段长度是可测的,不必靠主观判断(#9524)。
- 修复状态如实:窗口声明未汇入解析链、停止原因误判这两条属核心侧且讨论所指版本未修;密钥共用与图片声明是配置问题(改名或补声明即可);思考复读偏向模型侧,用户侧靠守卫插件与换档缓解。
接第三方模型时排查成本高,往往是因为「插件 + 配置 + 模型元信息」三层叠在一起。如果你想先把插件这一层看清,与其在各处手敲命令,不如用 DSH Plugin Hub 这类可视化插件市场:已安装列表、装卸历史与系统日志集中在一处,先把「环境里到底挂了什么」确认下来。

来源:Discussion #9712、Discussion #9230、Discussion #9022、Discussion #9759、Discussion #9133、Discussion #9524。
常见问题
DeepSeek Harness 每次都确定性 400 超窗,是因为输出上限按启发式估算填满窗口、只留了固定 4096 的安全余量。pi-ai 在把 max_tokens 约束到上下文窗口时,用本地启发式估算已用 token 并让「输入+输出」贴到窗口上限,工具输出这类内容会被低估,于是确定性溢出。另外如果 profile 把 maxTokens 声明成窗口的九成,自动压缩阈值也会被压得极低,进一步放大问题。
DeepSeek Harness 手填 contextWindow 却不生效,是因为这条路由声明的 contextWindow 没有汇入模型信息解析链。压缩的压力路径会去解析模型信息,拿到的是未定义,于是直接抛配置错误、压缩中止,请求原样发出去被网关按超窗拒掉;而界面文案把这种情况显示成额度用尽,与实际原因不符。手动 /compact 不受影响,可先用它应急。
DeepSeek Harness 把已完成的 Codex 回答报成超限,是停止原因映射时误判。适配器在映射停止原因时无条件做了一次「是否上下文溢出」的启发式判断,而该判断把「正常停止但累计输入超过目录声明窗口」的响应也当成溢出,覆盖了服务端的成功终态。修法方向是只在显式溢出或零输出的长度截断时才判溢出。
DeepSeek Harness 手工 provider 与内置共用密钥,是因为密钥引用名是按 provider 名派生的:DERIVE 规则是 provider 大写加 _API_KEY,你手工路由命名成 deepseek 就生成 DEEPSEEK_API_KEY,与内置的引用名逐字相同,而凭据是按引用名解析的。把手工路由改名为 deepseek-alt,或显式把它的密钥引用改成 DEEPSEEK_MANUAL_API_KEY,两者即可分开。
DeepSeek Harness 发图被拦,是因为该模型在 profile 补丁里没有声明图像输入能力。在该模型对应的配置行里补上 input: [text, image] 即可;这一步是配置层声明,不是模型能力检测的结果,所以即使上游确实支持图片,不声明也会被 DSH 拦住。
相关术语
- clampMaxTokensToContext
- clampMaxTokensToContext 是 pi-ai 里把输出上限约束到上下文窗口的函数,它用本地启发式估算已用 token,并让输入与输出之和尽量贴近窗口上限,只保留一个固定大小的安全余量。工具输出等内容的估算偏低会直接导致确定性溢出。— https://github.com/deepseek-ai/deepseek-harness/discussions/9712
- resolveModelInfo
- resolveModelInfo 是 DeepSeek Harness 用来解析某个路由对应模型元信息(例如上下文窗口、输出上限)的函数,压缩与压力判断都依赖它。第三方路由声明的 contextWindow 若没有汇入这里,依赖它的自动压缩就会拿不到值而中止。— https://github.com/deepseek-ai/deepseek-harness/discussions/9022
- deriveKeyRef
- deriveKeyRef 是 DeepSeek Harness 里根据 provider 名派生凭据引用名的规则,形如把 provider 名大写后拼上 _API_KEY。由于凭据按引用名解析而非按 provider 分段,手工路由若与内置 provider 同名,就会共用同一把密钥。— https://github.com/deepseek-ai/deepseek-harness/discussions/9759
- input: [text, image]
- input 是模型配置里声明该模型可接受哪些输入模态的字段,取值为 text 与 image 的组合。它是声明式配置而非运行时探测:不声明 image 时,即使上游支持图片输入,Harness 也会在有图片的请求上直接限制。— https://github.com/deepseek-ai/deepseek-harness/discussions/9133
来源
- #9712 — pi-ai 用估算值把 max_tokens 填满窗口(固定 4096 余量),导致确定性超窗 400· deepseek-ai(GitHub Discussions)
- #9230 — Completed Codex responses are misclassified as context overflow above the catalog window· deepseek-ai(GitHub Discussions)
- #9022 — pi-ai 路由声明的 contextWindow 未进入 resolveModelInfo,导致自动压缩静默失效、超限被误报为额度已用尽· deepseek-ai(GitHub Discussions)
- #9759 — Manually added DeepSeek provider shares the same API key as the built-in DeepSeek model· deepseek-ai(GitHub Discussions)
- #9133 — 使用 chatgpt 中转过程中发现的不支持图片并且可稳定复现的 bug· deepseek-ai(GitHub Discussions)
- #9524 — 思考通道(reasoning)退化:中文思考下最短独立句自我复制,flash 系易发· deepseek-ai(GitHub Discussions)