14. Prompt Caching 是什么?它在什么场景下能显著降低成本?
整理 Prompt Caching 的原理、收益与适用场景。
简单回答
Prompt Caching 是缓存 Prompt 中固定部分的 Prefill 计算结果(主要是 KV Cache),后续请求如果有相同的前缀就可以直接复用,跳过重复的 Prefill 计算。这能同时降低延迟(减少 TTFT)和成本(减少 GPU 计算量和 API token 费用)。在 System Prompt 很长且多个请求共享、或者多轮对话中前缀大量重复的场景下,Prompt Caching 的收益最为显著。
详细解释
为什么 Prompt Caching 重要
很多 LLM 应用的 Prompt 结构是"大段固定前缀 + 少量变化后缀"。比如一个客服系统,每次请求的 Prompt 可能是:
System Prompt 那 3000 token 对每个请求都是一样的。如果每次请求都要重新做这 3000 token 的 Prefill,大量计算被浪费了。
Prompt Caching 的做法是:第一次请求时正常 Prefill 所有 token,但把 KV Cache 保存下来(关联到这段 Prompt 文本)。后续请求如果有相同的前缀(System Prompt 一样),直接加载已缓存的 KV Cache,只对变化的部分做增量 Prefill。
服务端的 Prefix Caching
SGLang 的 RadixAttention 和 vLLM 的 Automatic Prefix Caching(APC)都是服务端实现的 Prefix Caching 方案。
RadixAttention 用 Radix Tree(基数树)来管理所有请求的 KV Cache。基数树的每个节点代表一段 token 序列的 KV Cache,不同请求如果有共同前缀就共享相同的节点。当新请求到来时,在 Radix Tree 中查找最长匹配前缀,命中的部分直接复用,只对剩余部分做 Prefill。
vLLM 的 APC 在 PagedAttention 基础上实现——对 KV Cache 的块计算哈希值,相同哈希值的块可以被多个请求共享。不需要人工标记哪些是前缀,系统自动检测和共享。
API 层面的 Prompt Caching
Anthropic 和 OpenAI 的 API 都支持 Prompt Caching 功能。使用方式是在 API 请求中标记哪些部分是可缓存的前缀。缓存命中后,这部分 token 的计费会大幅降低(通常降低 50%~90%)。
比如 Anthropic 的 API 允许你在 system 消息上标记缓存,第一次请求时按正常价格计费并建立缓存,后续请求如果 system 消息不变,这部分 token 的计费降低 90%。
收益最大的场景
System Prompt 很长且固定——比如几千 token 的角色定义、规则、few-shot 示例。Agent 系统中的工具定义也算(几十个工具的 JSON Schema 可能占几千 token)。这些在请求之间不变,Caching 收益最大。
多轮对话——前面的对话历史在每一轮都是公共前缀。第 10 轮时 Prompt 可能有 5000 token 是历史消息,只有最新的 50 token 是变化的。Prefix Caching 可以让每轮的 Prefill 开销只有增量部分。
RAG 场景中相同 System Prompt + 不同检索结果——System Prompt 部分可以缓存,但检索结果变化后就不能缓存了。收益取决于固定部分占总 Prompt 的比例。
批量处理——对同一批数据用相同的 Prompt 模板做批量处理(如批量分类、批量提取),每个请求只有数据部分不同,Prompt 模板完全相同。
局限和注意事项
Prompt Caching 只对前缀有效。如果变化的部分在 Prompt 中间而不是末尾,中间之后的所有内容都无法使用缓存。所以 Prompt 设计时应该把固定内容放在前面,变化内容放在后面。
缓存有 TTL(过期时间)。API 层面的缓存通常在几分钟到几小时内有效(Anthropic 的是 5 分钟),如果请求间隔太长缓存就失效了。自部署的 Prefix Caching 可以根据显存情况自主管理 TTL。
缓存占用显存。服务端 Prefix Caching 需要把 KV Cache 保留在显存中,这会减少可用于服务新请求的显存。如果缓存的前缀太多,反而可能降低并发能力。需要有合理的驱逐策略(LRU 等)。
面试时可以这样答
Prompt Caching 是缓存 Prompt 中固定前缀的 KV Cache,后续请求复用,跳过重复 Prefill。收益是同时降低延迟和成本。
收益最大的场景是 System Prompt 很长且固定——比如几千 token 的角色定义加工具定义,每个请求都一样。多轮对话也有收益,因为历史消息是公共前缀。批量处理同模板不同数据的场景也很适合。
实现上有两个层面。服务端的 Prefix Caching——vLLM 的 APC、SGLang 的 RadixAttention 会自动检测和共享公共前缀。API 层面——Anthropic 和 OpenAI 都支持标记可缓存的前缀,命中后计费大幅降低。
要注意 Prompt 设计——固定内容放前面、变化内容放后面,因为只有前缀能被缓存。还要注意缓存占用显存和 TTL 过期。
常见追问
- Prompt Caching 的命中率一般能到多少?怎么提高?
- 如果 System Prompt 稍有变化(比如加了一个字),缓存会完全失效吗?
- Prefix Caching 和 KV Cache 共享(如 Beam Search 中的)有什么关系?