dsh-cache-miss
English
DSH 网页插件:提示缓存被破坏、一次请求要重算整段上下文时,在那一轮的第一条 assistant 回复下方递一张黄色罚单——重算了多少、多花了多少钱、是谁破坏了前缀。
装它不需要配置,也不需要改变任何习惯。它只在命中被破坏时说话,其余时间安静。
缓存未命中提示
安装
dsh plugin --profile web add dsh-cache-miss
重启 dsh web(或硬刷新正在运行的 GUI)以加载 client bundle。和所有插件一样,装卸会改动前缀,所以别在正在干活的长会话里装。
要求核心 0.1.7-rc.2 及以上(工具目录变化时那条 "Tool added" 提示从这一版才有)。更老的核心上黄线照旧出现,只是工具名会一直写出来,不再有人替你省那两个字。
那行黄字
一轮 Agent 对话是 assistant -> tool -> assistant -> tool ...。该轮第一次模型调用正是提示缓存可能已过期、需要整段重新 prefill(重建缓存)的时机;同轮后续调用通常命中刚重建的缓存。DSH 的 token 统计在输入框下方,产物文件行在轮尾;这一行补的是 miss 发生的那一处。
Cache miss after 3m idle · 182k tokens re-billed (turn ~$0.027) · 0.8k cached · ttft 2.1s ↑ · (tools changed) · session used (~$2.90)
idle —— 距上一轮结束的空闲时长。
re-billed —— 这次请求未命中、被重算的输入 token。
cached —— 同一次 prefill 里命中缓存的部分,让"重算 vs 命中"一目了然。
(turn ~$…) / (step ~$…) —— 被重建的那部分上下文大约多少钱:轮首 miss 标 turn(整段重建),轮中 miss 标 step(只有该步改动的前缀);两者都发生就直接给合计。
ttft —— 首 token 时延;箭头示意重建通常更慢。
(system prompt changed) / (tools changed) / (config changed) —— 核心给出的前缀变更分类,写成人话。系统提示、工具目录、请求 config 都属于前缀,任一处变了,之后全部重算。分类由核心判定,插件只转述;config changed 是插件在同一份规范化 config 上比出来的补充项。
(tools changed: +preset_ops) —— 工具目录动了哪个工具。只在别处看不到时写名字:成员增删核已经在聊天里另起一行 "Tool added: …",这里就不重复;同名换定义(~edit)没有那行,所以永远写出来。名字超过 2 个只给计数(+8 -1),完整清单在控制台。
session used (~$…) —— 会话累计,used 标明这是累计而不是本次。
同一行会带浏览器本地时间戳写进控制台,每个 step 只写一次。~ 明示估算;金额是美元单价,不做汇率换算。
它只做一件事
- 只出现在对话里:不新增页面、侧栏或按钮,内容长在它该在的位置。
- 只算 prompt 的钱:页面显示的是未命中输入与缓存读的金额,输出 token 不在这个口径里。
- 只用 usage 里的计数:token 数、缓存命中量、时延;不读消息正文,不上传任何东西。
- 走公开接口:conversation-node 与 slot,纯前端,卸掉不留痕。
缓存与花费
命中缓存与未命中的输入 token,单价差 30–50 倍(models.dev 2026-10 价目,美元 / 1M token):
| 模型 | 未命中输入 (input) | 命中缓存 (cache_read) | 倍数 |
|---|
deepseek-v4-flash | 0.15 | 0.003 | 50× |
deepseek-v4-pro | 0.66 | 0.022 | 30× |
重算 448k token 按 flash 是 ~$0.067,命中只要 ~$0.0013。prompt 的省钱全靠命中率,而命中率由前缀决定:DeepSeek 的前缀缓存要求从第一个 token 起逐字节一致,系统提示、工具目录、请求 config 任意一处变动,变化点之后全部按未命中计费。
实测(145 份会话日志、15,580 次请求、568 次 miss)里重算的金额大致这么分:前缀变更(工具目录或 config)占 41%,轮首空闲过期占 17%,压缩重写历史占 10%,系统提示占 8%,另有 22% 在日志里查不到任何原因(工具、config、系统提示、压缩都没动,间隔中位数 9 秒)——那是服务端侧的事,客户端拿不到证据。
所以能省的钱只有四处:
- 别在长会话里装卸插件:工具目录和系统提示都进前缀,下一次请求全部重算。
- 切 provider / 模型 / reasoningEffort 之后别指望命中:那是另一个缓存命名空间。
- 正在进行的长会话,继续用比新开便宜——理由不只是缓存(虽然它确实还在),而是新会话得把任务、约束、试错结论、你纠正过的那些理解重新说一遍,模型还要重新磨合:解释原因、纠正新的歧义,这些都要 token,也要时间。缓存只是这笔账里顺带的那部分。
- 少改会进入前缀的内容(项目说明、系统提示类文本)。
关于 /compact:什么时候划算
/compact 不是免费动作。它由两笔支出组成:摘要调用本身(把历史读一遍、写一份摘要),以及压缩后第一次请求的重建。之后每步才省下"压掉那截上下文"的缓存价。
记 A = 压缩前上下文,B = 压缩后上下文,S = 摘要输出 token,U = 压缩后第一次请求未命中 token,M_c = 摘要调用自己未命中 token。压缩之后还要跑多少个模型调用才回本:
N = ⌊ (A + 49·M_c + 49·U + 200·S) / (A − B) ⌋ + 1
49 和 200 是价目比,不是魔法数:49 = 未命中/命中 − 1,200 = 输出/命中。flash 是 0.15/0.003/0.6 → 50/200;换成 pro 的 0.66/0.022/1.98 就是 30/90,同一个式子代进去即可。
判断划不划算,看三件事:
一、你还跑得够久吗——这个能算,不用猜。 上下文长回原样要 (A − B) / g 步,g 是它每步涨多少 token(几百到一千几)。而一次压缩通常丢掉几十万 token,所以回本窗口往往在百步以上。除非你把刚聊过的内容压掉、之后又几乎不动,这个条件很少成为阻碍。
二、压得狠不狠,决定成本的全部。 把上式按 r = B/A 改写:N ≈ (1 + 49r + 200·S/A) / (1 − r)。r 越小回本越快——r = 0.1 是十几步,r = 0.4 就是四十几步。所以:
- 阶段结束时压(读完一批文件、跑完一次排查,接下来那批内容作废)→ r 很小,回本快;
- 等上下文满了自动压(核心在窗口 80% 触发)→ 那时大半内容还在用,保留量大,r 最差。
三、摘要调用自己会不会命中缓存——这一项算不出来,只能认。 它不是"把你刚读过的东西再读一遍":请求由被折叠的那段历史加一段摘要指令构成,前缀跟对话的前缀不是一回事,日志里也不落盘。所以哪怕这段对话刚才一直在命中,摘要调用仍可能整段重算;反过来也一样。命中时约 $0.002,冷跑 $0.02–0.09,差一个数量级——这一项的不确定性大于前两项之和。
结论:按钱算,压缩几乎总能回本;按体验算,它买的是上下文空间。 需要空间时压,挑一个内容大量作废的时刻压,别把它当成省钱手段。
计价口径
金额只算 prompt(未命中输入 + 命中缓存读),不含 output token。单价取自 models.dev 的 DeepSeek 价目,按它的美元单价显示,~ 明示估算,实际扣费以官方账单为准。
随包快照只作离线兜底;实时价目按需取、24 小时有效:过期后下次加载刷新一次,模型切换时刷新一次,遇到快照里查不到的模型也刷新一次——所以调价和新模型都不用等插件发版。取不到(离线、请求失败)就继续用手上的价目;匹配不到就只省略金额,不编价格。峰谷/节假日这类分时价是单一供应商的定价策略,插件不写死。
/compact 那次摘要调用不是 assistant step,不在插件的统计口径里(核心单独记录),所以 session used 不含它——而它经常是整场会话里单笔最贵的一次调用。
已知限制
- TTFT 是
step/start 到首个非空 token 增量的墙钟间隔;任一侧落在载入窗口之外时不显示。
- 每个 assistant step 都会走一遍节点,但命中不渲染,所以命中的轮次没有可见行。
- 从未上报过缓存字段的 provider 只给一次灰色提示
Provider reports no cache fields,不做启发式猜测;一旦该 provider 出现过缓存字段,之后缺字段就按全量未命中处理。
- 插件只统计 prompt 上的花费,不含输出 token;它读 usage 里的计数,不读你的消息内容。
最后
本插件没有仪表盘,也没有广告。只在缓存命中被破坏时向你递一张罚单。如果它帮你省下了糊涂钱,欢迎给个 Star ⭐️,或者不点也没关系,它依然会安静地工作。
dsh plugin --profile web add dsh-cache-miss