Prompt Caching

缓存是什么意思

大模型的接口服务商,有的会提供缓存功能,用于存储用户请求的上下文信息,以便在后续的请求中复用。这样可以减少模型计算量(省钱),提高响应速度,同时也可以提高模型的可用性和稳定性,这是什么意思?

  • 当你发送一个超长的 messages 列表时,API 服务商(如 Anthropic 或 OpenAI)并不会直接把它丢给模型,而是先对你的输入进行 哈希(Hash)计算。
  • Prefix Matching(前缀匹配): 如果你这次发送的 5000 个 Token 中,前 4500 个和 5 分钟前发送的那一轮完全一模一样,后端服务器就会发现:“嘿,这部分我刚才计算过(计算过 KV Cache)!”
  • 重用计算结果: 服务器直接从内存里调出这 4500 个 Token 产生的中间状态(KV Cache),只对新增加的 500 个 Token 进行推理。

在 API 商的视角里,Token 的成本分为两部分:

  • 计算成本(最贵): 模型要把文本转化成数学向量并进行复杂的矩阵运算。
  • 存储/读取成本(较便宜): 只是把已经算好的数据从内存里读出来。

与消息压缩有什么区别

本质区别:压缩是丢弃信息来省钱(你能记住大意,但一定丢掉了细节,比如变量名);缓存是利用重复信息来省钱。

  1. 缓存(Prompt Caching):“无损的瞬间移动” 缓存是基于 Prefix(前缀) 的键值对存储。它的逻辑是:
  • 精细度:它是 Token 级别的。只要前 NN 个 Token 没变,它就直接复用。
  • 原始数据:完全保留。模型依然能看到每一个原始字符,没有任何信息丢失。
  • 本质:它压缩的是“计算量”和“金钱成本”,而不是信息本身。
  • 局限性:缓存有“物理极限”。如果对话真的达到了 200k 甚至 1M Token,即便有缓存,模型处理起来也会变慢,且容易在长距离推理中产生“迷路”(Lost in the Middle)。
  1. 消息压缩(Context Compression):“有损的记忆提炼” 当缓存也救不了(比如上下文快爆了,或者成本太高)时,上下文压缩 才会上场。
  • 精细度:它是 语义级别的。它会把原始的 1000 行 ls 结果,替换成一句 [此处省略了 xx 目录下的文件列表,包含 main.py 等]。
  • 原始数据:永久丢失。一旦压缩完成,原始的细节就再也找不回来了。
  • 本质:它模拟的是人类的“长期记忆提炼”。你记得昨天吃了一顿大餐(压缩后的信息),但你可能忘了那盘菜里有几颗葱花(丢失的原始数据)。

缓存是让服务器“记住”它刚才算出来的 KV Cache(中间数学状态),这是一种物理意义上的保留。消息压缩是让 AI 或程序员通过逻辑“总结”出 核心意义(Summary)。这是一种语义意义上的保留。

什么是中间数学状态

缓存存的不是“理解后的文字总结”(那就成压缩了),而是矩阵运算的中间数值。

在大模型中,第 nn 个 Token 的计算,只取决于它前面的 n1n-1 个 Token。计算过程:当模型处理第 500 个 Token 时,它的注意力机制(Attention)只会向后看(Look-back)前 499 个 Token 的向量。单向依赖:第 501 个 Token 的出现,完全不会影响前 500 个 Token 已经计算出来的隐藏层状态(Hidden States)。换句话说: 在 Transformer 的自注意力层中,每一个 Token 的 K(Key) 和 V(Value) 向量一旦算出来,只要前面的输入不变,这些向量就永远不会变。这就是所谓的 KV Cache。

重特性:幂等性 这也就是为什么它能省钱: 因为服务器省下了前 500 个 Token 那些昂贵的矩阵乘法(Wq,Wk,WvW_q, W_k, W_v 映射)。

只要你改动了前缀里的任何一个字符(哪怕是一个空格),数学上的等价性就瞬间崩塌:

  • 因为 Transformer 的位置编码(Positional Encoding)会变。
  • 注意力权重会因为那个微小的改动而重新分配。
  • 此时,旧的 KV Cache 全都作废,必须全额付费重新计算。

这就是为什么我们要反复强调要保护前缀的稳定性

Temp=0还是注意力锚点

Temp=0Temp=0 时,数学确定性 = 语义唯一性。在前缀完全一致且 Temp=0Temp=0 的前提下:“从第 1 个 Token 重新生成”与“从第 501 个 Token 开始续写”,在数学和语义上会得到完全、彻底、逐字一致的结果。

不存在“重新跑一遍可能会选另一个近义词”的情况,因为模型在那个时间点看到的概率分布是由前面的 Token 矩阵决定的,而矩阵运算在同样的硬件环境下是幂等的(结果一致)。

所以对于编程和 Agent 这种任务,通常会将 Temperature 设为 0(或者极低)。

这里应该是讲偏了,temp影响的是“生成”,历史消息一旦产生,就从“生成”的输出变成“输入”了,输入的语义不会因为temp而改变。

所以缓存真正的作用是固化一些隐形约束/前提/人格/设定,因为这些不会因为你后续的多轮对话而改变,而且不需要反复把它投入计算。其它作用真不是为了怕重新计算一次会偏移,而是为了节省计算资源。当然客观上也避免了模糊注意力,所以“对注意力的影响”是远大于temp的影响的。

由于没有物理层面的“存档”,模型每次都要试图在巨大的矩阵中重新寻找“重点”。随着轮次增加,原始指令(System Prompt)的权重在 softmax 归一化过程中会被海量的历史报错和中间过程“摊薄”。

大模型工程最核心的“第一性原理”:缓存(Prompt Caching)在本质上并不是一个存储工具,而是一个“注意力锚点(Attention Anchor

怎么缓存

对输入按一定大小进行切片,比如1024,然后对切片进行哈希,作为key,值是从第一个chunk起到这一个chunk为止计算的kv矩阵,这是啥? 在 Transformer 的注意力机制 Attention(Q,K,V)=softmax(QKTdk)VAttention(Q, K, V) = \text{softmax}(\frac{QK^T}{\sqrt{d_k}})V 中,QQKKVV 分别是 Query、Key 和 Value 向量。这个计算过程是相对耗时的,因此可以通过缓存来加速。

上面说的“数学中间态”就是这个kv矩阵,新的token从这个chunk开始,一直取到最后,进行prefill,生成新的kv矩阵拼接在缓存矩阵后面,此时才开始Decoding,预测下一个token

直到此时,temp的影响才开始出现,但它影响的可能只是行文风格,语气什么的了。

总之,缓存的意思是(从头开始)到哪个位置可以不去计算,然后拼上后面的(新)内容接着计算。