前言
决定一个 coding agent 烧不烧钱的,不是模型单价,是缓存命中率。
听着反直觉。我拿 DeepSeeker-Code 跑了一天实测,把账单和 token 拆开看了,结论就是这个。这篇文章就把这笔账彻底算明白:一天烧了多少 token、花了几个钱、为什么这么便宜------以及最关键的,这便宜不是天上掉的,是工程上一处处保出来的。
(上一篇聊了整体的设计取舍,没看过的可以先翻翻:DeepSeeker-Code 的设计哲学。这篇算它的续集,专门讲"省钱"这件事。)
一、先上账单:一小时到底烧了多少
模型是 deepseek-v4-flash,时段取 16:00~17:00 这一小时,期间高强度使用:


发文提示:上面两张图是本地路径,发布到掘金时请手动上传替换。
整理成表格:
| 项目 | 数值 |
|---|---|
| 时段 | 16:00 ~ 17:00(一小时) |
| 总 token | 25,682,801 |
| 输入(命中缓存) | 24,094,336 |
| 输入(未命中缓存) | 1,393,449 |
| 输出 | 195,016 |
| 该时段消费 | ¥2.26 |
2568 万 token,两块两毛六。这就是一小时高强度 agent 使用的全部成本。
三个数字最关键:缓存命中率 94.5% 、输出只占总量的 0.76% 、一小时两块二。下面一个个拆。
二、agent 是"输入怪兽":成本几乎全在输入上
先看一个反直觉的点:输出只有 19.5 万 token,输入却有 2548 万------输入是输出的 130 倍。
为什么?因为 agent 不是聊天。聊天是你一句我一句,上下文轻飘飘。agent 每完成一轮"推理→调工具→拿到结果",下一轮推理时,它要把整个上下文重新发给模型一遍:系统提示词、工具表、之前的全部对话、工具返回的结果。干十轮活,系统提示词和工具表就被重发了十次。
所以 agent 的成本结构天然畸形:输出(模型生成的内容)是少数,输入(反复重发的上下文)是大头。这一小时 99.2% 的成本都在输入上。
而好消息是------缓存只对输入生效。
三、缓存救了命:命中单价只有未命中的十分之一
DeepSeek 有个机制叫上下文缓存(context caching):你上一轮发过的上下文,模型会在一段时间内缓存住;下一轮只要前缀一样、没变,这部分就直接走缓存,单价大约只有正常输入的十分之一。
回头看那 94.5% 的命中率:2548 万输入 token 里,有 2409 万命中了缓存,按十分之一的白菜价计费;只有 139 万是冷数据,走全价。
这能省多少?算笔账。假设未命中输入的单价是 p,那命中部分就是 p/10:
- 有缓存时,输入费用 ≈ 2409 万 × (p/10) + 139 万 × p,折算下来约等于 380 万 × p
- 如果一点缓存都没有,全部走全价:2548 万 × p
有缓存让输入费用降到了约七分之一,砍掉了将近 85%。 这就是为什么 2568 万 token 才花两块二------大头被缓存按一折吃掉了。
要是没有这层缓存红利,同一小时的输入费用要翻近 7 倍。一天、一周累计下来,差距是成百上千的。
四、命中率不是白来的:工程上怎么"保住"前缀缓存
讲到这里,肯定有人想:那缓存命中率高,不是 DeepSeek 自己的事吗,跟你写 agent 有什么关系?
关系大了。缓存命中有个硬前提:上下文的前缀必须跟上次一模一样。 前缀哪怕差一个字,从那个位置往后全算未命中。
所以问题来了------agent 每轮都在往上下文里塞新东西(新的工具结果、新的对话)。要是不讲究,系统提示词今天改一段、明天插一条,或者压缩时机不对把前面的内容动了,缓存"啪"就断了,94.5% 的命中率瞬间归零,账单立刻翻几倍。
DeepSeeker-Code 为了保住这个前缀,做了几件要紧的约束:
第一,系统提示词绝对稳定。 消息列表的第一条永远是系统提示词,而且只往后追加内容,绝不重排、绝不在前面插东西。无论第几轮,它的前缀都纹丝不动------这是缓存命中的地基。
第二,压缩看缓存的脸色。 上下文快满了要压缩,可压缩本身会把缓存打穿(因为内容变了)。所以我的压缩时机是动态的:缓存命中率高的时候,宁可多撑一会儿、接着吃缓存红利,不轻易动手;命中率低的时候,反正要重新算,不如早点压缩。这条直接把"该不该压缩"和"缓存健不健康"绑在了一起。
第三,摘要槽、工具表位置固定。 哪些内容放第一个、哪些放第二个,都有固定位置,不在结构上做无谓的调整。位置一固定,前缀就稳定,缓存就稳。
说白了,这一整套都是在"灵活"和"稳定"之间反复选稳定。每一次为了缓存友好而放弃的灵活,省下来的都是真金白银。
五、代价是什么
为缓存做的这些优化,不是没有代价:
代价一,约束多。 系统提示词结构不能随便动,想加个新功能、调个提示词顺序,都得掂量会不会伤到前缀。灵活性被牺牲了不少。
代价二,绑死 DeepSeek。 这套"前缀稳定 + 缓存感知压缩"是照着 DeepSeek 的缓存脾气调的。换一个缓存策略不同的模型,这套功夫得推倒重来。又是一个"用通用性换针对性"的取舍。
代价三,打穿时的兜底。 缓存总有失效的时候(长时间不用、或某次不得不大改前缀)。这时候靠的是另一套------用每轮真实 token 用量校准本地估算,保证压缩时机不靠猜,避免缓存一旦断了、费用失控还浑然不知。
诚实讲,缓存这把刀,握好了省钱,握不好就是一堆看不见的约束和耦合。但权衡下来,对高频使用的本地 agent,这笔账太划算了。
结语
聊到这,那句话就落地了:agent 的省钱逻辑,本质就是让重复上下文走缓存。
模型给缓存这个能力,是给了一颗种子;能不能长成 94.5% 的命中率、能不能把账单压到两块二,全看你在工程上为它留了多少土。系统提示词别乱动、压缩看缓存脸色、消息结构求稳------这些不起眼的约束,才是省钱的真正功臣。
本地运行、DeepSeek 的缓存红利、加上一处处为缓存做优的工程------这套组合下来,才有了一小时高强度使用两块二的真实成本。比起按调用次数或订阅费计费的云端方案,这笔账我看着是舒服的。
项目已经开源:github.com/xknk/deepSe...,欢迎来看看、提提 issue。觉得这套省钱思路有点意思,点个 star 就是对我最大的鼓励。
总结
- agent 是输入怪兽:一小时 2568 万 token 里,输出只占 0.76%,输入是输出的 130 倍------成本几乎全在反复重发的上下文上;
- 缓存是省钱核心:命中缓存的单价只有未命中的约十分之一,94.5% 的命中率把输入费用砍掉了将近 85%;
- 命中率是保出来的:系统提示词绝对稳定、压缩看缓存脸色、消息结构求稳,这些约束是 94.5% 的真正来源;
- 代价是约束和耦合:灵活性被牺牲、跟 DeepSeek 绑死、还要备一套打穿时的兜底,但权衡下来划算。