缓存:AI 账单的隐形折扣
KV Cache 和语义缓存都是同一招:算过的别再算。拖动命中率滑块实时看账单变化——Harness 核心篇成本优化的底层原理
本页解决的问题
先给结论「缓存:AI 账单的隐形折扣」要解决的关键问题是什么?
KV Cache 和语义缓存都是同一招:算过的别再算。拖动命中率滑块实时看账单变化——Harness 核心篇成本优化的底层原理
让这个结论先证明自己值得留下。 把这一页当成决策工具,而不是需要背下来的定义。把概念连到一个真实任务、一个可观察结果,以及一个能改变你判断的失败上。
写下一个问题:试完这个方法后,你能用什么证据回答它?
结论听起来很完整,却没有检查最关键的假设。
你算过一次「37 × 89 = 3293」,第二天有人又问你 37 × 89 等于几——你会重新列竖式吗?不会,你直接报答案。缓存就是电脑的这种「直接报答案」:把算过的结果按 key 存进上一课的哈希表,下次遇到同样的 key,一步直达取结果。哈希表管「存哪、怎么找」,缓存管「什么值得存」。两课合起来才是完整的「空间换时间」。
大模型每生成一个字,都要「回头看」前面所有 token,给每个 token 算一份注意力的中间结果。关键在于:只要前缀一模一样,这些中间结果就一模一样——那第二轮对话还重算它干嘛?下面每个小方块是一个 token,先点「播放第一轮」,再点「播放第二轮」。留意第二轮里绿色方块出现的速度:它们没有被计算,是直接从缓存取的。
第一轮对话
系统提示词 + 问题①,每个 token 都要从零计算第二轮对话
前缀(系统提示词 + 第一轮全部内容)一字没变第二轮的计算量对比(方块数 = 要算的 token 数)
KV Cache 省的是「同一段开头」,还有一种更狠的:同样的问题,答案整个都别再算。客服机器人每天被问 1 万次「怎么退货」,问法五花八门但意思相同——把「意思」当 key(用向量相似度判断,第十课细讲),命中就直接返回存好的答案,一次模型调用都不用发。拖动命中率滑块,留意月账单的变化。
⚠️ 但是——退货政策改了怎么办?
缓存里还躺着按旧政策生成的标准答案,机器人会一本正经地拿它继续回答十天半个月,比不缓存错得更稳定、更理直气壮。所以工程师常说:缓存最难的不是存,是知道什么时候作废(术语叫「缓存失效」,计算机科学两大难题之一)。常见做法:给缓存设个保质期(比如 24 小时过期)、或者政策一更新就主动清掉相关条目。设计任何缓存前先想好这一步,否则省下的钱会用客诉还回来。
「算过的别再算」这一招无处不在,下面四个你天天在享受的东西,本质上是同一个结构。
KV Cache
大模型推理的标配:前缀 token 的注意力中间结果只算一次。没有它,长对话根本跑不动。
语义缓存
把「问题的意思」当 key,相似提问直接复用答案。高频客服场景能砍掉一大半调用费。
浏览器缓存
图片、样式文件下载一次就存本地,第二次打开网页秒开——你刷网页快,一半功劳是它的。
CDN
把内容提前存到离你最近的机房,全国用户都像访问本地服务器。缓存 + 地理位置,还是那一招。
「先想一个日常场景」为什么要看操作
「你算过一次「37 × 89 = 3293」,第二天有人又问你 37 × 89 等于几——你会重新列竖式吗?不会,你直接报答案。」把结构落到了一个具体动作。这里真正要比较的不是名词谁更高级,而是数据如何被放置,以及最常发生的操作需要走多远。
读懂结构,要同时看访问方式和变化方式
「大模型每生成一个字,都要「回头看」前面所有 token,给每个 token 算一份注意力的中间结果。关键在于: 只要前缀一模一样,这些中间结果就一模一样 ——那第二轮对话还重算它干嘛?下面每个小方块是一个 token,先点「播放第一轮」,再点「播放第二轮」。」揭示了一个容易被忽略的取舍:按位置读取、按键查找、从两端进出、插入新元素和遍历关系,适合的组织方式并不相同。一个结构在某个操作上很快,不代表它在所有操作上都快。
- 缓存 = 算过的别再算 :结果按 key 存进哈希表,下次直达取——上一课的结构在这一课开始赚钱
- KV Cache 认前缀 :固定内容放提示词开头、会变的放末尾,缓存命中率直接决定账单
- 语义缓存更狠 :意思相同的提问连模型都不调,高频场景省钱效果按命中率线性放大
把规模和更新频率一起算进去
实践时可以把「把内容提前存到离你最近的机房,全国用户都像访问本地服务器。」当作边界提醒:先写下数据量、最常用的操作和允许的延迟,再看 AI 给出的结构是否真的匹配。
从「先想一个日常场景」走到「交互 1 · KV Cache:同一段开头别算两遍」
「先想一个日常场景」先把问题落在「你算过一次「37 × 89 = 3293」,第二天有人又问你 37 × 89 等于几——你会重新列竖式吗?不会,你直接报答案。 缓存就是电脑的这种「直接报答案」 :把算过的结果按 key 存进上一课的哈希表,下次遇到同样的 key,一步直达取结果。哈希表管「存哪、怎么找」,缓存管「什么值得存」。两课合起来才是完整的「空间换时间」」上;到了「交互 1 · KV Cache:同一段开头别算两遍」,讨论继续推进到「大模型每生成一个字,都要「回头看」前面所有 token,给每个 token 算一份注意力的中间结果。关键在于: 只要前缀一模一样,这些中间结果就一模一样 ——那第二轮对话还重算它干嘛?下面每个小方块是一个 token,先点「播放第一轮」,再点「播放第二轮」。 留意 第二轮里绿色方块出现的速度:它们没有被计算,是直接从缓存取的」。两段连起来,重点就不只是记住一个结论,而是看清它成立所依赖的条件。
把这条判断带到下一个场景
遇到一个新的数据结构时,不要从定义开始背。先写出最频繁的操作,再估计数据量和更新方式,最后检查结构是否让这三个条件同时成立。
- 「先想一个日常场景」:你算过一次「37 × 89 = 3293」,第二天有人又问你 37 × 89 等于几——你会重新列竖式吗?不会,你直接报答案。 缓存就是电脑的这种「直接报答案」 :把算过的结果按 key 存进上一课的哈希表,下次遇到同样的 key,一步直达取结果。哈希表管「存哪、怎么找」,缓存管「什么值得存」。两课合起来才是完整的「空间换时间」
- 「交互 1 · KV Cache:同一段开头别算两遍」:大模型每生成一个字,都要「回头看」前面所有 token,给每个 token 算一份注意力的中间结果。关键在于: 只要前缀一模一样,这些中间结果就一模一样 ——那第二轮对话还重算它干嘛?下面每个小方块是一个 token,先点「播放第一轮」,再点「播放第二轮」。 留意 第二轮里绿色方块出现的速度:它们没有被计算,是直接从缓存取的
- 「最后的要点」:验收视角 :看到「每次请求都重新调用模型 / 重新计算」的设计,就该问一句「这里为什么不缓存?」
最后的「最后的要点」把讨论落到「验收视角 :看到「每次请求都重新调用模型 / 重新计算」的设计,就该问一句「这里为什么不缓存?」」。回看这条线索时,最值得保留的是:当输入、规模或风险改变,哪些判断需要重新做一遍。
✅ 这一课想和你分享的
- 缓存 = 算过的别再算:结果按 key 存进哈希表,下次直达取——上一课的结构在这一课开始赚钱
- KV Cache 认前缀:固定内容放提示词开头、会变的放末尾,缓存命中率直接决定账单
- 语义缓存更狠:意思相同的提问连模型都不调,高频场景省钱效果按命中率线性放大
- 缓存三问:存什么(值得复用的结果)、存哪(内存 / 磁盘 / 离用户近的地方)、何时作废(最难的一问)
- 验收视角:看到「每次请求都重新调用模型 / 重新计算」的设计,就该问一句「这里为什么不缓存?」
我把这篇文章里的一个判断改写成了今天可以验证的小实验。比记住结论更有用的是,知道下一步要观察什么。
读完以后我先回头找它成立的条件,而不是直接把方法搬进项目。这个顺序让后面的取舍清楚很多。
如果把这个判断放到真实工作里,最先需要补的约束是什么?我想知道从阅读到第一次实践之间,哪一步最值得先做。
还没有这篇文章的讨论。