dsh-cot-anchor
jiewiw/dsh-cot-anchor
Injects conclusions already established in the previous reasoning block after each tool result, so the model continues from them instead of re-deriving the same conclusions.
Installer
dsh plugin --profile web add github:jiewiw/dsh-cot-anchorREADME
dsh-cot-anchor
DeepSeek Harness(DSH)插件:治一类特定的模型毛病——思考着思考,但没在推进。表现为反复重新推导已经得出的结论、把工具调用写成纯文本、原地重复同一段话、输出无意义的递增数字流。
插件做两件事:
- 结论回流:每次工具结果返回后,从最新思考中摘出已成立的结论(最多 3 条、每条 ≤ 220 字)插回上下文,下一步起手就能看到,不必重推一遍。装上默认生效。
- 生成中途打断(软切):生成过程中每 32 个字符检查一次,发现打转 / 原地重复 / 伪工具调用 / 数字流就立即切断本次请求,把已生成部分作为正常消息落盘、排好结论锚点,让回合从断点续跑——不会因为一次误判丢掉整轮工作。
它不解决一切长任务问题,只解决「单流内思考链极度冗余、结论反复重新发现」。跨步骤的折返跑(同一结论在十几步里重推)不在能力范围内,那是姊妹插件 dsh-step-governor 的职责。
快速开始
dsh plugin --profile <你的profile> add github:JiewiW/dsh-cot-anchor#v0.2.1
重启实例后设置页出现「COT 锚点」标签即生效。结论注入无需任何配置;软切需要内核支持(见兼容性)。
工作方式
模型思考 → 工具执行 → [插件] 摘出已成立的结论插回上下文 → 下一步思考
↑
只在工具边界注入
注入消息以 user 角色追加在工具结果之后、下一次请求之前,尾部追加写入会话日志,不改写已有内容,因此不会打穿前缀缓存。
成本
| 场景 | 额外成本 |
|---|---|
| 默认(结论注入开启,其余关闭) | 每个工具结果后一条短消息,上界 660 字符(3 条 × 220 字);无额外模型调用 |
| 命令执行纪律提醒 | 每轮一次、随运行时上下文快照("Current runtime context…")注入,位于记忆规则之后;单条全文固定约 380 token(字符估算),作为稳定前缀段参与上下文,不再随工具调用堆叠 |
| 开启 LLM 提炼结论(默认关) | 每个助手回合多一次小模型调用 |
| 开启打转 / 重复等判定 | 纯本地字符串计算,零 token 成本;可能增加少量回合数 |
| 开启 CoT 静默采集 | 每个助手回合留一条本地样本;默认关闭 |
注入消息会随之后续请求的上下文一同发送,因此持续占用少量上下文窗口。按中英混排估算,660 字符约合 200–500 token 量级——相对于一次工具往返的上下文可以忽略,但它在每一步都会累积。注入以尾部追加方式写入会话日志,不改写已有内容,因此不会打穿前缀缓存:除新追加的一块外,此前内容始终是稳定前缀。新追加块在其首次出现的那次请求上按未命中计费一次,此后转为缓存命中——这一点与文本是否固定无关。推理锚点每次不同,其排列顺序仅为内容组织上的一致性,不影响缓存行为(自 411cb74/v0.2.2 起命令执行纪律已改走运行时上下文快照的固定段,不再参与本次工具注入)。
在一个约 924 万 token 的真实长会话上实测:插件注入总量约占全会话 0.23%(每个注入块只在首现那一次请求按未命中计费,此后转为缓存命中)。具体分项口径见下文「实测成本占比」。
能力边界(请先读)
- 两类机制都是单步边界内的:软切只看当前一次生成流,进入下一步计数归零。治得了单流内退化,治不了跨步骤折返跑。
- 软切不减少回合步数。长任务账单的大头是「步数 × 每步膨胀的上下文重读」,步数治理请用 step-governor。
- 模型可能知道自己在空转却停不下来——实测出现过思考中自述「I'm burning turns, let me stop」之后继续生成下一条探索路线。注入的前提是模型会读且照做,自知不构成刹车。
- 软切每回合按判定类别分桶计预算 6/20/3(启发式判定 6 次、字节级确证重复 20 次、伪工具调用 3 次),总闸 29(6+20+3)。打满后启发式判定升级为终止本回合,高置信重复仍照常拦截;预算事件(
agent/soft-cut-suppressed/phase.abortTurn)在会话日志可观测。这些常量由内核定义、不由插件持有。
以下统计数据自 v0.2.1 之前的机制采集:当时命令执行纪律是随每次工具执行后剥出的独立
user消息(source.summary = cot-anchor: exec-discipline)与推理锚点同车注入。自 v0.2.1 起(并入 411cb74 迁移后),纪律不再随工具注入,而是注册为运行时上下文快照的一个固定段(每轮出现一次、位于记忆规则之后、用户唠叨之前),不再按工具条数线性堆叠;下述注入量只是旧机制的上限参照。
在一个 95 次助手请求、累计约 924 万 token 的真实长会话上按消息级口径统计(字符→token 为启发式估算,非 tokenizer 实测;任何人可在自己的 DSH 会话日志上按同口径复算:逐条统计 user/message 中 source.summary 为 cot-anchor: exec-discipline(固定纪律)与其他 cot-anchor:*(动态锚点)的文本,并对照各次助手请求 usage 的 inputTokens / cacheReadTokens):
结论:插件带来的新增输入在全会话 token 总量的 0.3% 以内。每个注入块在首现时按未命中计费一次,此后随上下文增长参与后续每一次请求。纪律块体积约占注入量五分之四,但"文本固定"不带来额外缓存收益——该占比只反映体积,不反映命中。(该占比为 v0.2.1 之前旧机制的历史数据;新版纪律块已移入运行时上下文快照固定段,不再按工具条数累计。)
兼容性与软切内核
| 能力 | 支持的 DSH 版本 |
|---|---|
| --- | --- |
| 结论注入、设置页 | 0.1.5 起全部版本 |
| 生成中途打断(软切) | 仅 0.1.5-rc.1 / rc.2 开箱可用 |
0.1.5-rc.3 起内核移除了软切所需的 agent/soft-cut 钩子,该能力会静默失效;插件在启动日志和设置页顶部明确提示当前内核是否支持——以设置页显示为准,不要凭开关是开的就认为在生效。
新版内核可用随包工具把软切机构移植回去(带版本与哈希自检,幂等、可回滚,不符自动还原):
node node_modules/dsh-cot-anchor/tools/apply-softcut-port.mjs --check # 查看状态
node node_modules/dsh-cot-anchor/tools/apply-softcut-port.mjs # 应用
移植后重启实例。完整步骤与风险见 docs/softcut-kernel-port.md。
设置
设置页「COT 锚点」共 61 项、分组展示,多数场景用默认值即可。下面只列常用项与容易误判的项;其余阈值在设置页内均有内联说明。
总开关
| 键 | 默认 | 说明 |
|---|---|---|
enableToolInject | 开 | 工具结果后注入结论锚点,本插件的主要价值,建议保持开启 |
enableSoftCut | 开 | 允许生成中途打断;内核不支持时自动无效 |
enableExecDisciplineBlock | 开 | 随锚点同车注入命令执行纪律提醒;与锚点注入共用去重节奏,关闭后锚点注入行为不变 |
五项软切判定
全部关闭时插件只做结论注入。
| 键 | 识别什么 | 注意 |
|---|---|---|
enablePseudoTool | 把工具调用写成普通文本(如 <seed:tool_call>...) | 只能识别已知文本形态 |
enableRepeat | 逐字节相同的内容反复吐出 | 换措辞的重复抓不到 |
enableChurn | 措辞不同但反复「重新分析」 | 启发式判定,遇到未闭合代码块自动让路 |
enableTransition | 「接下来我要……」类转折句 | 最容易误判:正常分阶段思考也有转折句;若频繁在正常思考中切断,先关它 |
enableNumberRunaway | 无意义递增数字流 | 要求数字流足够长(≥ 500 字符跨度等阈值) |
打断太频繁时:先关 enableTransition,其次调高判定阈值(churnMinHits 默认 18 等)。
锚点内容
| 键 | 默认 | 说明 |
|---|---|---|
minReasoningChars | 250 | 思考短于此长度不提取结论 |
maxPoints | 3 | 最多保留几条结论 |
maxPointChars | 220 | 单条结论字数上限 |
结论由规则从思考文本中摘句得到,不理解句子的语义角色,因此入池前会剔除两类无命题内容:纯话语标记句(剥掉 Actually / wait / Hmm / 其实 / 等等 等标记后实词不足 6 字符,如「Actually, wait.」「其实,等等。」)与路线意图宣告句(「the decisive route: ask the user…」)。标记词领起但带事实命题的句子(「Wait, the kernel never marks in verbose mode.」)照常保留。
注意:Wait / Actually / Hmm 等转折词在推理链中承担结构控制作用,插件不从模型输出里删除它们,只阻止它们被当成结论回灌。
LLM 提炼与 CoT 采集(默认全关)
enableLlmRefine:用一次小模型调用把整段思考压成摘要式结论,通常比规则摘句更准;provider/model 留空则跟随当前会话。enableHarvest/enableAutoAnalyze/enableLearnedPatterns:静默采集思考样本、自动归纳检测器看不见的打转形态、把学习成果用于判定。开启会在本地留存思考文本,启用前请自行评估隐私;学习模式默认有 20 轮影子期(learnedShadowRounds)防止一次误学永久改变判定。
隐私
- 结论注入与全部软切判定都在本地完成,不向任何外部服务发送数据。
- LLM 提炼开启时,思考文本会发给你指定的 provider(留空则跟随当前会话)。
- CoT 采集开启时,思考文本与工具轨迹只留存本地。
常见问题
设置页显示「当前内核没有掐断能力」 内核不提供软切钩子,结论注入不受影响。需要软切可停留在 0.1.5-rc.1/rc.2,或按上文移植。
模型好像没收到提醒
确认 enableToolInject 已开、且思考长度超过 minReasoningChars——思考过短本来就不提取。
开发
仓库根目录所有 test-*.mjs 都是独立可执行脚本(无测试框架、无 npm test),逐个 node test-*.mjs 运行,退出码 0 即通过。
许可
MIT
Plugins associés
hindsight (coding-agents)
vectorize-io/hindsight
OpenViking (dsh-memory-plugin)
volcengine/openviking
ReMe (dsh)
agentscope-ai/reme
ReMe (typescript)
agentscope-ai/reme