Prompt 缓存
Prompt 缓存复用的是相同前缀的 KV 计算,所以它只认「从头开始逐字相同」:稳定内容放前面、易变内容放后面、缓存断点打在前缀末尾,TTL 内命中才省钱。任何改写前缀的动作(压缩、动态工具集、时间戳)都会击穿缓存,缓存友好是 prompt 设计的一条硬约束。
也叫:prompt 缓存 · prompt caching · 前缀缓存 · 缓存断点 · cache breakpoint · TTL
原理拆解出自 T1-4
缓存层级
tools → system → messages,改上层废下层;两把刀都动最下层缓存前缀 ①
tools · 工具定义顺序一变就失效
② 末尾单独一个断点
system · 系统提示词让它能在压缩中幸存
③ 清理与压缩都动这里
messages · 历史对话 + 工具结果
压缩发生时
会话前缀作废新摘要要重新写入一次
system 那段照常读它自己有断点,活下来了
缓存的四个数(记不住就抄)
| 项 | 数值 | 读法 |
|---|---|---|
| 写入溢价 | 5 分钟约 1.25 倍原价;1 小时约 2 倍 | 写进去要先贵一次 |
| 命中 | 约 0.1 倍原价,并免费续期 | 续期从请求开始时刻算起 |
| 最小可缓存长度 | 512 / 1024 / 2048 / 4096 token,按模型不同 | 不到门槛不缓存,且不报错 |
| 回溯窗口 | 20 个 block | 一轮加太多 block,会把上次写入推出去 |
压缩流程:输入 token 数达阈值触发 → 生成一段摘要块 → 摘要块之前的内容全部作废 → 从摘要继续。阈值默认 15 万,最低只能设到 5 万 —— 这个下限本身就是官方在说:不要频繁小压。用量要跨所有迭代汇总,只看顶层字段会算漏账。
和解只需要一个断点:在系统提示词末尾单独打一个缓存断点,压缩发生时那段缓存仍然有效、照常读取,只有新生成的摘要需要作为新内容写入一次 —— 长系统提示词因此可以跨多次压缩一直活着。
隐形失效项才是排查噩梦:工具定义顺序变了、某些语言序列化时 JSON 键顺序不稳定、图片增删、思考或 effort 配置变动、
tool_choice 变化 —— 内容看着一模一样,缓存就是不命中。 ┌──────────── 上下文窗口 ────────────┐
│ tools │ system │ 历史 + 工具结果 │
└───┬───────┬────────────┬───────────┘
│ │ │
改这里 │ 改这里 │ 改这里 │
▼ ▼ ▼
┌───────────────────────────────────┐
│ 缓存前缀层级:tools → system → messages │
│ 改上层 → 下层全部失效 │
└───────────────────────────────────┘
▲ ▲
│ │
清理会动这里 压缩会动这里压缩的机制(截至 2026-08 已经是一等公民 API)
流程是:按输入 token 数达到阈值触发 → 生成一段摘要块 → 摘要块之前的内容全部作废 → 从摘要继续。几个必须知道的细节:
- 阈值默认 15 万 token,最低只能设到 5 万。 这个下限本身就是官方在告诉你:不要频繁小压。
- 压缩是一次额外采样,单独计费。 用量要跨所有迭代汇总,只看顶层的输入输出 token 字段会算漏账。
- 自定义摘要指令是「完全替换」,不是追加。 这是最容易踩的坑——你只写了「重点保留代码片段」,就等于把默认提示里「保留状态、下一步、已有结论」全删了。
- 可以在压缩后暂停,让你把最近几条消息原样接在摘要后面,避免刚说完的关键信息立刻被摘要走样。
- 带工具时压缩可能失败:模型在摘要那一步跑去调工具了,返回一个空摘要。解法是在指令里明确写「这一步只写文本,不要调用任何工具」。
- 摘要用的是同一个模型,不能换个便宜的来做。
缓存的机制
- 层级
tools → system → messages,改上层废下层; - 写入只发生在断点处,读取时向前回溯,回溯窗口是 20 个 block。这意味着一轮加太多 block,会把上一次的写入推出窗口,明明内容没变也命中不了;
- 有最小可缓存长度门槛,按模型不同为 512 / 1024 / 2048 / 4096 token 不等。不到门槛不缓存,且不报错——两个缓存字段都是 0 就是这种情况;
- 计费:5 分钟写入约 1.25 倍原价、1 小时写入约 2 倍,命中约 0.1 倍;命中会免费续期,续期从请求开始时刻算起(生成耗时也算在寿命里);
- 常见的隐形失效项:工具定义顺序变了、某些语言序列化时 JSON 键顺序不稳定、图片增删、思考或 effort 配置变动、
tool_choice变化。
压缩与缓存怎么和解(这是本篇最值钱的一段)
「压缩会击穿缓存」这个说法要说得更精确:击穿的是会话前缀,不是全部。
官方给的解法是:在系统提示词末尾单独打一个缓存断点。这样压缩发生时,系统提示词那段缓存仍然有效、照常读取,只有新生成的摘要需要作为新内容写入一次。长系统提示词因此可以跨多次压缩一直活着。
再配合「少次大压」,整笔账就清楚了:
一次压缩的固定开销 = 额外采样(读入约 T 个 token)
+ 摘要写入缓存
+ 会话前缀重建
压缩次数 ↑ → 固定开销 × 次数 ↑,同时信息经多次转述失真 ↑
所以阈值应尽量贴近窗口上限,而不是"勤快地小压"。以上节选自T1-4 上下文预算:压缩、清理与 prompt 缓存的三方博弈,读全文能看到前后语境。
延伸阅读
考这个知识点的题1 道
会连带问到14 道
- Q1-01Token 是什么?为什么说上下文窗口是大模型应用的第一约束?
- Q1-02大模型是怎么生成下一个字的?自回归生成和 KV Cache 是什么关系?
- Q1-04system prompt 和 user prompt 有什么区别?为什么指令要放 system?
- Q1-08说说你常用的 Prompt 技巧;few-shot 什么时候有效、什么时候反而有害?
- Q1-11什么是上下文工程?它和提示词工程是什么关系?
- Q1-13多轮历史越来越长你怎么压缩?compaction 时什么必须保真?
- Q3-13上下文快满了:滑动窗口 / 摘要压缩 / 重要性过滤怎么选?压缩丢了关键决定怎么办?
- Q3-23Agent 每轮都调大模型,太贵太慢,成本和延迟怎么优化?
- Q5-06一次多轮 Agent 请求的 trace 里应该记哪些东西?
- Q6-02vLLM 为什么快?PagedAttention、continuous batching 解决什么?
- Q6-07语义缓存是什么?什么场景省大钱、什么场景会答错话?
- Q6-09应用 token 成本突然涨了 3 倍,怎么排查和治理?
- Q7-02给 AI 编程工具喂上下文有什么讲究?为什么整仓塞进去反而更差?
- Q8-09你的方案预算砍一半,先砍什么?