
不是存答案,而是存「计算进度」:KV Cache 为什么能省钱?
KV Cache 缓存的不是答案,而是模型处理上下文时产生的中间计算结果。从这一句出发,解释改动前文为什么会让缓存失效、换模型为什么要重新付费,以及它和上下文压缩之间的取舍。
TL;DR
「命中缓存,计费就会少很多」「切换模型,花费会更多哦」,这两句提示指向的是同一件事。 KV Cache 存的既不是答案也不是记忆,而是模型在预填充阶段读完输入后产生、并会在后续生成中反复使用的中间计算结果。 由此推出三件事:缓存只能复用从开头开始连续相同的那一段,所以改动前文会让其后的计算全部作废; 缓存属于生成它的那个具体模型,所以中途换模型要把整段历史重新算一遍; 而上下文压缩专门在改写前缀,于是它和缓存复用之间存在一个必须权衡的取舍。
目录
开篇
做 Agent 产品的时候,大概都听过这句话:
命中缓存,计费就会少很多。
用 AI 产品的时候,可能也会看到这样的小提示:
如果切换模型,花费会更多哦~
这两句话其实指向同一件事:KV Cache 可以改变一次请求要花多少钱。
第一次听到 KV cache 可能会下意识地觉得必须先把 Transformer、注意力机制、矩阵运算都搞明白,才有资格理解它。但如果只是想在做产品时把它用对,完全不需要这些术语。
下面可以从我们听到最多的那个问题开始:
为什么同一段上下文,第一次交给大模型处理比较贵,再次使用却能便宜很多?难道是模型把答案提前存好了吗?🤔
不是这样的。
KV Cache 缓存的是模型处理这些内容时产生的中间计算结果。下一次遇到相同的开头,系统可以直接复用这些结果,不必从头再算。
接下来解决的每一件事:为什么改动前面的内容会让缓存失效、为什么换模型就要重新付费、它和上下文压缩是什么关系,都是从这一句推出来的。👇
模型「读一遍」并不便宜
首先我们平时和大模型聊天,它为什么会一直记得前面说过的话?这个我在之前的文章中有写到~(一定要先理解这个原理才能理解下面的内容🌟)深度解析 Memory 本质(在第二部分:记忆的本质)
人读一份一百页的资料需要花时间理解,大模型也一样。
模型在收到一段文字后,它不能直接开始回答。它需要先处理所有输入,理解每句话之间的关系:
- 这句话是谁说的?
- 它和前面的要求有什么关系?
- 哪些信息比较重要?
- 当前问题应该参考哪些内容?
这个「阅读和理解输入」的过程需要大量计算。
一段几百字的对话可能不明显,但在编程、办公助手这种长程任务 Agent 中,输入经常包含:
- 几十轮聊天记录
- 大量代码
- 文件内容
- 搜索结果
- 命令执行日志
一轮请求可能包含几万甚至几十万字。
如果每次请求都从头计算一遍,这会浪费大量时间和算力。
于是,KV Cache 出现了。👇
KV Cache:把已经算过的部分保存下来
大模型在收到一段文字之后,不能马上给出回答。它需要先处理整段输入,通过大量计算建立各部分内容之间的关系,再在这些计算结果的基础上生成回复。
而且,后面的计算会受到前面内容的影响。
即,大模型处理一次请求,可以粗略分成两个阶段:
- 处理输入,建立对上下文的计算结果;
- 根据这些结果生成回答。
第一阶段也叫预填充。KV Cache 主要节省的就是这一阶段中重复发生的计算。
可以把这个第一阶段想象成一张很长的电子表格。表格中有一百行公式,后面每一行都需要参考前面的结果。
第 1 行 → 计算结果 1第 2 行 → 计算结果 2……第 100 行 → 计算结果 100第一次打开表格时,电脑需要把一百行全部计算一遍。
如果我们只在末尾新增第 101 行,前面一百行完全没有变化,电脑就不必从头重算,只需要读取以前保存的结果,再计算新增的一行。
👉 KV Cache 保存的,就是大模型在阅读和理解已有内容时产生、并会在后续生成中反复使用的一部分中间计算结果。
它不是对原文的摘要,也不是模型对过去的记忆,而是模型服务替它保存下来的计算结果。
顺便说一句:为什么叫 KV Cache 呢?
KV 中的 K 和 V,分别来自两个英文单词:
- K:Key
- V:Value
它们是模型处理上下文时产生、并会在后续生成中反复使用的两组内部数据。
不理解背后的数学公式没关系~只要记住:
KV Cache 保存的不是聊天记录、摘要或者最终答案,而是模型处理上下文时产生的部分中间计算结果。
所以,可以把 KV Cache 简单理解为:
大模型的上下文计算缓存。
把这个过程放到真实对话中看,就更容易理解了~👇
第一次请求是:
你是一名编程助手。项目使用 Go。数据库使用 MySQL。请帮我设计用户表。
第二次请求是:
你是一名编程助手。项目使用 Go。数据库使用 MySQL。请帮我设计用户表。接下来再帮我设计订单表。
第二次请求的开头与第一次完全相同,只在末尾增加了一个新问题。
这时,模型服务就可以直接复用前面那部分已经保存的计算结果,只处理新增加的内容。这就是所谓的「缓存命中」。
连续对话特别适合使用 KV Cache,正是因为每一轮通常都可以理解为:
上一轮的全部内容 + 本轮新增内容
👉 前面的聊天历史保持不变,新的消息不断追加在末尾,因此已经完成的计算可以被反复复用。
但如果我们把原来的「项目使用 Go」改成「项目使用 Python」,情况就不一样了。👇
这时,后面几句话可能就需要根据 Go 和 Python 这两个不同编程语言的特点,去重新理解。从发生变化的位置开始,后续计算结果通常都不能继续使用。(因为模型理解输入的方式是计算,而这个计算过程就是和上面比喻的表格一样,前后相互关联着。)
所以,KV Cache 并不要求整次请求从头到尾都与上一次完全相同,但它通常只能复用:
从开头开始,连续保持相同的那一部分内容。
不过,拥有相同的开头还不够。KV Cache 是某个具体模型计算出来的结果,因此能否复用,还与当前使用的是不是同一个模型有关。👇
为什么换了模型,花费通常会增加?
前面提到,聊天过程中只要上下文的开头保持不变,模型服务就可能复用之前保存的计算结果,只处理后来新增的内容。
但这些缓存并不只由聊天内容决定,它还属于生成它的具体模型。
不同模型使用不同的参数和计算方式。即使读取完全相同的聊天记录,产生的中间计算结果通常也不一样:
模型 A:聊天历史 → 模型 A 的缓存模型 B:同一段聊天历史 → 模型 B 的缓存因此,模型 B 通常不能直接使用模型 A 生成的缓存。
如果在聊天途中切换模型,可能出现这样的过程:
- 切换前:模型 A 已有缓存 → 主要处理本轮新增内容
- 刚切换到模型 B:模型 B 没有对应缓存 → 需要重新处理整段聊天历史
- 继续使用模型 B:模型 B 已经建立自己的缓存 → 后续请求又可以复用相同的上下文前缀
这就是为什么聊天进行到一半时切换模型,花费往往会突然增加:聊天记录虽然没有消失,但新模型需要重新处理它。
那如果后来又切回模型 A,能不能重新使用原来的缓存呢?🤔
有可能,但也不能保证。还要看旧缓存是否仍然存在、是否已经过期,以及请求开头是否仍然完全一致等等。
所以,缓存能否复用,需要两件事同时成立:请求的开头没有变化,以及处理它的还是同一个模型。可以这样记:
聊天历史属于这段对话,但缓存属于处理它的那个具体模型。
不过,这里就有一个矛盾。KV Cache 能省钱,前提是前面的内容一直保持不变。但在真实的 Agent 产品里,有一件事专门在做相反的事情:上下文压缩。👇
上下文压缩与 KV cache
KV Cache,是在缓存模型处理上下文时产生的中间计算结果,回到前面说过的两个阶段,它只参与第一阶段:处理输入,完全不参与生成答案。
所以,即使前面的聊天记录命中了缓存,模型仍然需要根据本轮新增的问题生成回答。同一段历史后面接上不同的问题,当然会得到不同的答案;即使问题完全相同,由于生成过程可能存在随机性,两次回答也不一定一模一样。
如果输入完全相同,读取此前保存的中间计算结果,与重新计算这部分内容,理论上应该得到相同的效果。KV Cache 没有删除原始信息,也没有重新改写上下文,它只是让相同的内容不必重复计算。
这也是 KV Cache 和上下文压缩最重要的区别:
- KV Cache 是「相同的内容不重复算」
- 上下文压缩是「把原来的内容变短以后再算」
👉 KV Cache 通常是无损复用,而上下文压缩会删减、截断或总结历史信息,因此可能遗漏细节。
下面重点讨论一下最常见的摘要式压缩:👇
假设一段对话原本是:
A + B + C + D + E + F系统保留最近的 E、F,把前面的内容整理成「摘要 1」:
摘要 1 + E + F随后,对话又产生了 G、H、I:
摘要 1 + E + F + G + H + I在正常聊天阶段,前面的内容没有变化,只是在末尾不断增加新消息,因此已有缓存可以持续复用。
但当系统再次压缩时,就需要在两种方式之间选择。
(1)第一种方式是保留旧摘要,只压缩后来新增的历史:
摘要 1 + 摘要 2 + H + I👉 这种方式能够保留更稳定的输入前缀,有利于继续复用旧缓存。但随着压缩次数增加,摘要会越来越多,内容之间也可能出现重复、过时甚至矛盾。
(2)第二种方式是把旧摘要和新增历史重新整理成一份统一摘要:
摘要 2 + H + I👉 这样可以删除过时信息、合并重复内容,并让上下文长期保持简洁一致。不过,「摘要 1」变成「摘要 2」以后,输入前缀发生了变化,压缩后的对话就需要重新计算并建立新的缓存。
但是,(这里有个小分支)这难道就意味着之前的缓存完全浪费了吗?
不一定。🙂↔️
如果压缩系统设计得当,那么生成新摘要的请求这里就可以用到 KV cache 了~系统只需要继续处理新增内容和压缩指令,再生成新的摘要。
但是,(回到主线)新摘要替换旧内容以后,主对话模型处理请求就不能用之前的缓存了,因为「摘要 1」已经变成「摘要 2」,从变化的位置开始,旧缓存通常不能继续用于压缩后的对话。
整个过程可以概括为:
- 正常对话:前文不变,末尾增加消息 → 持续命中缓存
- 生成摘要:利用未变化的前缀生成新摘要 → 旧缓存仍可能降低压缩成本
- 摘要替换:新摘要改变了输入前缀 → 重新建立缓存
- 继续对话:新摘要保持不变,末尾增加消息 → 再次持续命中缓存
所以,摘要管理和缓存复用之间存在一个取舍:
- 保留所有旧摘要,缓存更加稳定,但上下文会越来越杂乱;
- 定期合并旧摘要,会暂时损失部分缓存,但上下文更加简洁一致。
👉 实际系统可能采用增量摘要、定期合并,或者两者结合。无论选择哪一种,核心目标都是在缓存成本、上下文长度和信息完整性之间取得平衡。
最后
KV Cache 是模型服务保存下来的中间计算结果。相同的上下文再次出现时,系统可以直接复用这些结果,只计算新增的内容。
但它不是完全免费,因为读取缓存、新增内容和生成答案仍然需要资源。
它也不是在缓存答案,更不是模型突然拥有了长期记忆。
完整过程可以概括为:
- 第一次请求:处理全部内容 → 产生中间计算结果 → 保存可复用结果 → 生成回答
- 后续请求:读取已有计算结果 → 处理新增内容 → 生成新回答
所以,「缓存命中为什么更便宜」的真正答案是:
因为大模型不必重新完成已经做过的计算。存储和读取依然有成本,但通常远低于重新调用 GPU 计算整段上下文的成本。
核心结论
标注「判断」「假设」的是我的看法而非事实;标注「已推翻」的保留在这里,不删除。
引用本文
晨旭,《不是存答案,而是存「计算进度」:KV Cache 为什么能省钱?》,晨光里的AI,2026-09-07
[晨旭:《不是存答案,而是存「计算进度」:KV Cache 为什么能省钱?》](https://chenxu.xin/writing/kv-cache-why-cheaper)带进你的 AI 继续追问
这篇文章有一份干净的 Markdown 原文,可以直接交给任何模型读,不用复制粘贴。