它不改变模型说什么,只改变模型说得多快、算得多便宜。对 Akke 这种「一天上万次 LLM 调用」的业务,这是直接和成本表挂钩的东西。
大模型(DeepSeek、GPT、Claude 都一样)生成文字是 自回归(autoregressive) 的——一次只吐一个 token(约等于一个字/词),然后把这个新字接到后面,再预测下一个:
输入: 这个客户 意向 第1步: 这个客户 意向 → 很 第2步: 这个客户 意向很 → 高 第3步: 这个客户 意向很高 → , ...
关键点:每预测下一个字,模型都要"回头看"前面所有的字。这就是问题的根源。
模型理解每个字时,会把它转换成两样东西,叫 Key(K) 和 Value(V)——你可以粗暴理解成"这个字的索引标签 + 内容摘要"。预测下一个字时,新字要去和前面每一个字的 K/V 比对一遍,才知道该说什么。
如果不缓存,会发生这种事:
| 生成第几个字 | 要重新计算的字数 |
|---|---|
| 第 1 个 | 算 1 个字的 K/V |
| 第 2 个 | 把前 2 个字的 K/V 全部重算 |
| 第 3 个 | 把前 3 个字的 K/V 全部重算 |
| 第 100 个 | 把前 100 个字的 K/V 全部重算 |
前面那些字根本没变,K/V 也不会变,却被一遍遍重算。生成 N 个字,计算量是 N² 量级——回复越长越离谱。这就是纯粹的重复劳动。
既然每个字的 K/V 算出来就不再变,那就第一次算完直接存进显存。下一个字只需要:
于是每生成一个字的计算量从「重算前面全部」降成「只算新的 1 个」。N² 的重复劳动 → N 的线性工作量。
一句话比喻:
不做笔记的人,每翻到新一页都要把前面整本书重读一遍才敢往下看;
做了笔记(KVCache)的人,翻到新一页只读这一页,前面的内容瞄一眼笔记就行。
读得越厚,差距越大。
笔记得有地方放。KVCache 存在 GPU 显存里,上下文越长、缓存越大。它的大小大致正比于:
缓存大小 ≈ 上下文token数 × 模型层数 × 维度 × 2(K和V)
实际后果,对工程有两个直接含义:
KVCache 用显存换速度。 Akke 自己不部署模型(走 OpenRouter / DeepSeek 托管),这部分由供应商承担——但它决定了长上下文为什么更贵、更慢,这点会传导到我们的账单。
Akke 的 AI 主要花在两处:① 海量评论的意向分析、② 对高意向客户的多轮自动养客对话。KVCache 在这两处的价值完全不同,要分开看。
每天 6000+ 抓取任务,意向分析要被调用成千上万次。每一次的 prompt 长这样:
[系统提示词:你是全屋定制行业的获客分析助手,判断意向等级...] ← 每次都一样 [few-shot 示例:几条标注好的样例评论] ← 每次都一样 [本次要分析的评论正文] ← 只有这里在变
前面那一大段「系统提示词 + few-shot 示例」每次调用一字不差地重复。模型为它算的 KVCache 也完全一样——却被每次调用从头重算一遍,纯纯浪费。
Prompt Caching(提示词缓存)就是把 KVCache 产品化:供应商把这段固定前缀的 KVCache 在它那边存住,下次同样的前缀直接命中缓存,不重算、按大幅折扣计费。DeepSeek、OpenRouter 这类都支持(DeepSeek 称之为上下文硬盘缓存)。
举个示意性例子(具体折扣以当前官方定价为准,需上线前核对):
一条 prompt 假设 1000 token 是固定前缀、50 token 是变动的评论。当这条链路一天跑上万次,省下的就是前缀部分约 95% 的输入成本。
- 不命中缓存:每次都为 1050 token 付"全价输入费"。
- 命中缓存:1000 token 的固定前缀只按缓存价(通常是零头),只有 50 token 付全价。
养客是和客户多轮聊,对话历史越聊越长。每生成一句回复,模型都要"回看"全部历史。
| 名词 | 大白话 |
|---|---|
| token | 模型眼里的一个"字/词单位" |
| 自回归生成 | 一次吐一个 token,循环往复 |
| K / V(Key/Value) | 每个 token 的"索引标签 / 内容摘要",比对用 |
| KVCache | 把算过的 K/V 存起来复用的缓存 |
| Prompt Caching | KVCache 的产品化:缓存固定前缀,命中后按折扣计费 |
| 上下文(context) | 这次喂给模型的全部输入文字 |
| 显存 | GPU 的内存,KVCache 住在这里 |