深挖技术 · Agent 工程 · 成本优化

DeepSeek 前缀缓存拆解:Agent 怎么把输入成本压到 1/30

整理:AI 情报看板 | 日期:2026-09-02 | 素材:叶小钗《DeepSeek Harness 源码拆解》+ DeepSeek 官方 Context Caching 文档交叉核实

同样是 100 万 token 的输入,DeepSeek v4-flash 高峰时段:缓存命中 0.10 元,未命中 3.00 元——差价 30 倍。对纯聊天的普通应用,这个差距往往感知不到;但只要你的 Agent 不是「一问一答」,而是每完成一个指令要跑十几轮工具调用的多轮 Agent,这个差价就会直接变成账单上的「惊喜」。

原因很朴素:Agent 每走一步,都要把「系统提示 + 工具说明 + 聊天记录 + 刚拿到的工具结果」整体重发一遍;为了让 Agent「有记忆」,这些消息还是累加发送的——模型推理了几轮,前面的内容就跟着重发几遍。上下文越长、轮次越多,输入 token 的膨胀越夸张,缓存命中率对总成本的影响就越致命。

DeepSeek Harness(DeepSeek 官方 Agent 框架,本板块 8/16、8/22 已做过两期深度分析)在实测中把缓存命中率做到了 99%。它没有黑魔法,靠的是一套可复制的工程纪律。这篇文章把它的源码思路拆开,并对照 DeepSeek 官方缓存文档核实每一处规则——结论是:缓存优化不是调参,是消息组装架构。

一、先算账:30 倍价差是怎么落进账单的

DeepSeek 官方定价(每百万 token,元):

计费项v4-flash 空闲v4-flash 高峰v4-pro 空闲v4-pro 高峰
输入 · 缓存命中0.050.100.150.30
输入 · 缓存未命中1.503.004.509.00
输出4.509.0013.5027.00

注意:不管是空闲/高峰、flash/pro,命中价与未命中价的比例恒为 1:30。所以实际输入单价可以这样算:

实际输入单价 = 命中率 × 命中价 + (1 − 命中率) × 未命中价

以 v4-flash 高峰价(命中 0.10 / 未命中 3.00)为例:

命中率100 万输入 token 实际价格相当于全未命中的
0%3.000 元100%
90%0.390 元13%
99%0.129 元4.3%
关键洞察:从 90% 提到 99%,只多了 9 个百分点,输入费用却从 0.390 元降到 0.129 元——又砍掉约三分之二。缓存优化的收益不是线性的,而是「越接近 100% 越陡峭」。Agent 一天跑几万次请求时,这个差距直接决定盈亏。输出 token 不受影响,仍按输出价计费。

二、缓存在缓存什么:prefill 与 KV cache

要理解缓存规则,先理解 LLM 推理的两个阶段:

DeepSeek 的「Context Caching」把请求输入部分的 KV 状态存到硬盘:当下一个请求的开头与之前完全一致时,服务端直接加载这份 KV 状态,跳过绝大部分 prefill 计算。可以理解为——模型读完上下文后留下了一份「计算结果存根」,下次遇到完全相同的开头,直接从硬盘取回,省掉重复计算。

官方口径(api-docs.deepseek.com/guides/kv_cache):缓存默认开启、对所有用户生效,无需改代码;命中与否在响应 usage 里用两个字段体现:prompt_cache_hit_tokens(命中的输入 token 数)与 prompt_cache_miss_tokens(未命中的),二者相加即本次输入 token 总数。缓存是尽力而为(best-effort),不承诺 100% 命中;缓存构建需要数秒,闲置后数小时到数天自动清除。

三、官方命中规则:三条持久化 + 一个硬约束

DeepSeek 的磁盘缓存(受滑动窗口注意力机制影响)与常规前缀缓存有一个关键差异:缓存按「前缀单元」整块存储和匹配,后续请求必须完整匹配某个已持久化的单元才能命中。官方文档给出三条持久化时机:

  1. 请求边界持久化:每次请求在「用户输入结束处」和「模型输出结束处」各产生一个缓存前缀单元。例:第一轮 A+B,第二轮 A+B+C → 完整匹配 A+B 单元,命中。
  2. 公共前缀检测持久化:系统发现多次请求有公共前缀时,会把它单独持久化为一个单元。例:先发 A+B、再发 A+C(本轮无法命中 A+B),但系统检测出公共前缀 A 并单独保存;第三次发 A+D → 命中 A。
  3. 固定 token 间隔持久化:对长输入/长输出,按固定 token 间隔切出单元,避免长前缀因永远到不了「结束位置」而完全无法缓存。
硬约束——从头匹配:匹配从请求的第一个 token 开始。中间有一段相同、开头不同,中间那段也用不上旧缓存。例:上一轮 A+B+C+D+E,下一轮 A+B+X+D+E——能复用的只有 A+B,从 X 开始即使 D、E 与上轮完全一样,也无法续用旧缓存。这是理解一切缓存优化技巧的总纲。

四、Agent 弄丢缓存的四种典型姿势

理论上多轮 Agent 是前缀缓存的最佳受益者——每轮在上一轮末尾追加内容,可复用前缀只会越来越长。但实际开发中命中率经常惨不忍睹,根因都是同一个:框架在调模型前重新组装了一次请求,而「组装」悄悄改变了开头。四种最常见的姿势:

① 系统提示每轮都在变

把当前时间、当前目录、权限状态、随机 ID 等动态信息直接拼进系统提示。系统提示位于请求最前面,任何一处变化都会截断整个缓存。这是最常见、杀伤力最大的一种。

② 工具列表顺序不稳定

上一轮工具顺序 read, bash, edit,下一轮变成 bash, edit, read——工具没变、Schema 没变,但序列化后的 token 顺序变了。若工具说明位于大量历史消息之前,这一变,后面整段缓存全部作废。

③ 每轮重新整理历史消息

发送前重排消息顺序、重新序列化 XML/JSON、改写之前的消息。程序看来「意思没变」,但多一个空格、字段顺序变化、重新序列化都会产生新的 token 序列,进而产生新的前缀。

④ 请求参数在后台悄悄变化

因额度/超时自动切换模型或服务商、插件运行时动态改参数或注入一段系统提示——只要这些变化最终影响了请求头、系统提示或工具定义,就形成一条新前缀。

理想状态一句话:发过的内容尽量不动,新的、容易变化的内容不断往尾部追加。会话越长,可复用前缀越长——缓存命中率应当随会话进行「越用越高」,而不是天天在 0% 附近徘徊。

五、DeepSeek Harness 的五步保前缀法

DeepSeek Harness 是插件化 Agent 框架:系统提示、工具、运行环境都由插件提供。插件一多,怎么保证前缀稳定?Harness 的思路是:缓存数据存在 DeepSeek 服务端,Harness 不管缓存本身,只管让自己发出去的相邻两轮请求拥有相同开头。实现分五步:

第 1 步:稳定内容与可变内容分开登记

插件把内容交给统一登记处,Harness 组装时统一决定谁在前、按什么顺序。源码里分了四类入口:系统提示 section()、工具 tools()、可变状态 context()、模型名/工作目录等填充值 variable()。判断标准只有一个:这项内容在会话运行期间会不会变。当前工作目录虽属环境信息,但同一会话内基本不变,就留在系统提示里。

第 2 步:每轮按同一套规则排序

每轮重新取出可见内容,按固定规则组装:系统提示按登记编号排列,工具未指定位置则按名称排序。顺序稳定本身就是为了避开「内容相同、顺序变了」这种毫无必要的缓存杀手。模型名、工作目录等动态值在此时写入系统提示;参数名写错或取不到值,Harness 在请求发出前直接报错,不带着脏前缀出门。

第 3 步:可变状态追加到历史末尾

沙箱模式、审批策略、子 Agent 权限这类「影响模型当下能做什么」的内容,会整理成一份运行状态快照(runtime context)。每轮开始时与上一轮比较:相同则不重复发送;变了则生成一条新消息追加到会话末尾;上一轮有、本轮清空了,也追加一条「清空消息」告知模型旧状态失效。这一步对缓存最关键——变化只发生在尾部,前面的 system、tools、历史消息原封不动,下一轮长前缀照常可复用。

第 4 步:请求参数与内容一并记日志

模型名、温度、最大输出长度等调用参数连同系统提示、工具列表一起写入会话日志:首次调用写完整记录,之后只有真正变化才新增变化记录。缓存命中率哪天突然下降,翻日志就能定位「哪一轮出现了新记录、模型/提示/工具/参数改了什么」。

第 5 步:每次从同一份日志还原请求,并冻结核对

每次调用模型,Harness 按日志顺序取回用户消息、模型回答、工具结果,与记录在 request header 里的系统提示/工具/参数合并成完整请求。组装好后请求被冻结——发送插件只能查看、不能临时改一句系统提示或换工具;发送前还会从日志取回消息逐项比对,对不上就报错阻止发送。模型返回后,回复追加进同一份日志。下一轮从头还原,中间没有改动,上一轮完整请求自然成为下一轮的开头。

五步的本质:前三步解决「前缀长什么样」(稳定前置、可变后置、排序固定),后两步解决「前缀会不会被悄悄改掉」(日志留痕 + 发送前核对冻结)。Harness 把「缓存命中」从玄学变成了可审计的工程纪律——命中率下跌不再是黑盒,翻日志就能找到元凶。

六、自检清单:自己写 Agent 时照着查

核心口诀:旧内容不改,新内容后加。逐项检查:

  1. 系统提示的各段内容有固定名字、固定顺序(不要动态拼接)。
  2. 当前时间、随机编号、环境状态放到消息尾部,绝不进系统提示。
  3. 工具按名称或明确配置排序,工具参数的字段顺序也要稳定(序列化时固定 key 顺序)。
  4. 历史消息只追加、少重排少改写——「重新格式化」等于亲手废掉自己的缓存。
  5. 模型、服务商、参数变化时留下明确记录(日志里可审计)。
  6. 上下文压缩时,尽量保留前面仍可复用的内容——截断也是改变前缀。

七、延伸:前缀稳定是 Agent 框架的「隐形架构」

这篇文章的价值不止于省几十块钱。把视野拉高一层:「把动态内容沉到尾部」正在成为 Agent 框架的标准架构共识——OpenAI、Anthropic 等主流平台的 prompt caching 文档里,最佳实践第一条几乎都是「保持系统提示稳定、把易变内容放后面」。谁在框架层面把这条纪律做成了默认行为(而不是交给开发者自觉),谁就在长会话、高频工具调用的场景里天然拥有成本优势。

回头看本板块 8/16《DeepSeek Harness 深度分析》与 8/22《Harness 双雄》讲的「Agent 底座之争」——缓存命中率其实是被低估的第四维竞争维度:模型能力、生态、价格之外,同样的模型价格表,底座框架不同,跑同样任务的真实账单可能差一个数量级。对自研 Agent 平台来说,这不是「能省则省」的优化项,而是架构期就要定死的设计决策。

参考来源

· 叶小钗:《DeepSeek Harness 源码拆解:1/30 的输入价,99% 的缓存命中率》(2026-09-02,本文素材来源)
· DeepSeek API Docs:Context Caching(磁盘缓存机制、持久化时机、命中规则、usage 字段)
· DeepSeek API 定价页(v4-flash / v4-pro 输入命中/未命中/输出三档计费)
· 本板块:DeepSeek Harness 深度分析 · 开源 Agent 底座(2026-08-16)
· 本板块:Harness 时代——龙虾之死与双雄并立 · Agent 底座之争终局推演(2026-08-22)

免责声明:本文定价数据与缓存规则取自 DeepSeek 官方定价页及 Context Caching 官方文档(2026-09-02 访问),并引用「叶小钗」公众号对 DeepSeek Harness 源码的拆解分析;公式演算(0.99×0.10+0.01×3.00=0.129 元)为基于官方价格的独立核算,仅供参考,不构成任何成本或投资建议。
← 主页