免费POC, 零成本试错
AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


我要投稿

Prompt caching 技术是如何实现 1 折的推理成本优化的?

发布日期:2026-02-12 22:42:14 浏览次数: 1513
作者:Baihai IDP

微信搜一搜,关注“Baihai IDP”

推荐语

揭秘Prompt Caching技术如何实现惊人的90%成本优化,深入解析KV矩阵复用的核心原理。

核心内容:
1. Transformer注意力机制中Key-Value矩阵的计算原理与复用逻辑
2. OpenAI与Anthropic两种缓存策略的对比分析
3. 实际测试中观察到的延迟降低与成本优化效果

杨芳贤
53AI创始人/腾讯云(TVP)最具价值专家

编者按:你是否曾好奇过,那些声称能将长文本输入成本降低90%、延迟减少85%的"Prompt Caching"技术,背后究竟缓存了什么?是简单的文本复用,还是某种更深层的计算优化?

我们今天为大家带来的文章,作者的核心观点是:Prompt Caching的本质并非简单的文本字符串缓存,而是对Transformer注意力机制中Key-Value(KV)矩阵计算结果的复用,通过避免重复计算注意力权重来实现成本削减与性能提升。

文章的重点内容包括:第一,从Tokenizer到Embedding再到Transformer的完整技术拆解,帮助读者建立对LLM内部数据流的直觉认知;第二,对注意力机制(Attention)的数学原理进行深入浅出的阐释,详细展示了Query、Key、Value矩阵的计算过程以及Softmax权重分配机制;第三,揭示了"KV Caching"的核心实现逻辑——通过缓存历史token的K、V投影矩阵,使模型在增量生成时只需计算最新token,而非重新处理整个上下文;第四,对OpenAI与Anthropic两种缓存策略的对比分析,指出自动路由与显式控制之间的权衡,以及Temperature等采样参数对缓存机制的零影响。

作者 | Sam Rose

编译 | 岳





撰写本文时,OpenAI 和 Anthropic 的 API 中,缓存的 input token 单价仅为普通 input token 的十分之一。

Anthropic 甚至声称[1],prompt caching 能将长 prompt 的延迟“最高降低 85%”。而在实际测试中,我发现对于足够长的 prompt,这一说法确实成立。我向 Anthropic 和 OpenAI 各发送了数百次请求,注意到在所有 input token 均被缓存的情况下,首 token 延迟(time-to-first-token latency)出现了明显下降。

image.png

缓存 token(cached token)到底是什么玩意儿? 

这背后究竟发生了什么,让服务商能给 input token 打出 1 折的超低折扣?他们在各次请求之间到底保存了什么?这可不是简单地把响应结果存下来,等收到相同 prompt 时再复用 —— 通过 API 就能很容易地验证这一点并未发生。随便写个 prompt,连续发送十几次,你会发现即使使用情况栏(usage 部分)显示 input token 已被缓存,每次得到的回复仍然各不相同。

我对大模型厂商文档中的解释[2-3]并不满意 —— 它们虽能很好地说明如何使用 prompt caching,却巧妙地避开了“究竟缓存了什么”这个核心问题。于是我决定深入探究,一头扎进 LLM 工作原理的“兔子洞”,直到彻底搞明白服务商究竟缓存了哪些精确的数据、这些数据的用途,以及它们如何让每个人的 LLM 请求都变得更快速、更便宜。

读完本文,你将……

  • 在更深层次上理解 LLM 的工作原理

  • 对“LLM 的运作方式”建立新的直觉认知

  • 弄明白究竟哪些二进制数据被缓存了,以及它们如何降低你的 LLM 请求成本


01

LLM 架构

本质上,LLM 就是一个巨大的数学函数:输入一串数字,并输出一个数字。在 LLM 内部,存在着一个由数十亿个精心设计的运算构成的巨型图结构,负责将这些输入数字转化为输出数字。

这个由海量数学运算构成的巨型图结构大致可分为 4 个部分。

image.png

图中的每个节点都可以看作一个函数,接收输入并产生输出。输入会以循环方式不断馈入 LLM,直到遇到某个特殊的输出值指示其停止。用伪代码表示大致如下:

prompt ="What is the meaning of life?";

tokens = tokenizer(prompt);
while(true){
 embeddings = embed(tokens);
for([attention, feedforward] of transformers){
 embeddings = attention(embeddings);
 embeddings = feedforward(embeddings);
}
 output_token = output(embeddings);
if(output_token === END_TOKEN){
break;
}
 tokens.push(output_token);
}

print(decode(tokens));

尽管以上描述已大幅简化,但现代 LLM 的核心代码行数之少仍让我感到意外。

Sebastian Raschka[4] 用 PyTorch 从零实现了多个开源模型,还产出了大量高质量的教学材料 —— 如果你喜欢本文,大概率也会喜欢他的内容。以当前领先的开源模型之一 Olmo 3 为例,其核心代码仅数百行[5]

Prompt caching 发生在 Transformer 的“attention(注意力机制)”中。接下来我们将按顺序逐步拆解 LLM 的工作原理,直到抵达这一环节。这意味着,我们的旅程得从 tokens 说起。


02

Tokenizer(分词器)

image.png

在 LLM 处理你的 prompt(提示词)之前,必须先将其转换为它能理解的表示形式。这个过程分为两步,由 tokenizer 和 embedding 共同完成。为什么要这么做,要到讲 embedding 时才能完全明晰,现在请先耐心了解 tokenizer 的作用。

Tokenizer 会将你的 prompt 拆成多个小片段,并为每个唯一的片段分配一个整数 ID,称为"token"。例如,GPT-5 对 prompt "Check out ngrok.ai" 的分词结果如下:

image.png

该 prompt 已被拆分为数组 [“Check”, " out", " ng", “rok”, “.ai”],并转换为 tokens [4383, 842, 1657, 17690, 75584]。相同的 prompt 始终生成相同的 tokens。tokens 也是区分大小写的 —— 因为大小写能传递语义信息。例如,首字母大写的 "Will" 更可能是人名,而小写的 "will" 则更可能是助动词。

为什么不直接按空格或字符分割?

这其实是个相当深刻的问题,细讲起来足以让本文篇幅翻倍。简短而不尽兴的答案是:这是一种权衡。若想深入理解,Andrej Karpathy 有一期从零实现 tokenizer 的精彩视频(https://www.youtube.com/watch?v=zduSFxRajkE)对于 prompt caching 而言,只需知道:tokenization 的作用就是把文本变成数字。

Tokens 是 LLM 输入与输出的基本单位。当你向 ChatGPT 提问时,回复会随着每次 LLM 迭代完成而逐个 token 流式返回。服务商这么做,是因为生成完整回复可能需要数十秒,而一旦 token 生成就立即返回,能让交互体验更流畅自然。

我们来问一个 LLM 领域的经典问题,亲眼看看这个过程:

image.png

Prompt tokens 输入,✨ AI 魔法发生 ✨,输出一个 token,循环往复。这个过程称为“inference(推理)”。注意:每个输出 token 都会在下一轮迭代前被追加到 input prompt 中。LLM 需要全部上下文才能给出高质量回答 —— 如果只输入原始 prompt,它会反复尝试生成答案的第一个 token。如果只输入已生成的回答部分,它会立刻忘记问题本身。因此,每一轮迭代都必须将完整的 prompt 加上已生成的回答内容重新输入 LLM。

那个 199999 <END> token 是什么?

这个推理过程总得有个终点。LLM 拥有多种“特殊”token,其中之一就是标志着响应结束的 token。在 GPT-5 的分词器中,这就是 token 199999。这只是 LLM 终止生成过程的多种方式之一:你也可以通过 API 指定最大生成 token 数,服务商还可能基于安全策略设定其他终止规则。

此外还有用于标记对话消息起止的特殊 token —— 正是这些 token 让 ChatGPT、Claude 等聊天模型能分辨一条消息何时结束、下一条何时开始。

关于 tokenizer(分词器)的最后一点:它们种类繁多!ChatGPT 使用的 tokenizer 与 Claude 不同,甚至 OpenAI 自家的不同模型也使用不同的 tokenizer。每种 tokenizer 都有自己独特的文本切分规则。如果你想直观比较不同 tokenizer 的分词效果,可以试试 tiktokenizer[6]

认识了 tokens 之后,接下来我们聊聊 embeddings。


03

Embedding

image.png

经过 tokenizer 处理后的 tokens,现在进入 embedding 阶段。要理解 embedding,不妨先思考模型的目标是什么。

人类用代码解决问题时,会编写接收输入、产生输出的函数,比如华氏转摄氏:

function fahrenheitToCelsius(fahrenheit){
return((fahrenheit -32)*5)/9;
}

我们可以把任意数字传入 fahrenheitToCelsius,并能获得正确结果。但假如我们面对一个问题,却不知道背后的公式呢?假如我们只有下面这张神秘的输入-输出对照表:

(我并不指望你能认出这个函数 —— 不过,如果你把截图贴进 ChatGPT,它能立刻识别出来。)

当我们知道每个输入对应的正确输出,却不知道产生这种对应关系的函数时,就可以“训练”一个模型来学习这个函数。做法是:给模型提供一块“画布” —— 那个由海量数学运算构成的巨型图结构,然后不断调整这个图结构,直到模型收敛到正确的函数。每次更新图结构后,我们都将输入数据喂进去,观察输出数据与目标的差距。反复迭代,直到结果足够接近目标。这就是训练的本质。

事实证明,在训练文本生成模型时,能够识别两个句子是否“相似”会很有帮助。但“相似”具体指什么?它们可能同样悲伤、幽默或发人深省;也可能在长度、节奏、语气、语言、词汇或结构上相近。描述句子相似性的方式有无数维度,而两个句子可能在某些维度上相似,在另一些维度上则不然。

Tokens 本身只是简单的整数编号,没有任何“维度”信息;而 embeddings 则是高维向量,承载了丰富的语义和结构信息。

Embedding 是一个长度为 n 的数组,代表 n 维空间中的一个位置。如果 n=3,embedding 可能是 [10, 4, 2],表示三维空间中 x=10、y=4、z=2 的坐标点。在 LLM 训练过程中,每个 token 会被随机分配一个起始位置,随后训练过程会不断微调所有 token 的位置,直到找到能产生最佳输出的排列方式。

Embedding 阶段的第一步,就是查表获取每个 token 对应的 embedding。用伪代码表示大概是这样:

// Created during training, never changes during inference.
const EMBEDDINGS = [...];
 
function embed(tokens) {
 return tokens.map(token => {
 return EMBEDDINGS[token];
 });
}

于是,我们把 tokens(整数数组)转换成了 embeddings(数组的数组,即“矩阵”)。

image.png

image.png

tokens [75, 305, 284, 887] 被转换为一个由 3 维 embeddings 构成的矩阵。

Embedding 的维度越多,模型可用于比较句子的“角度”就越多。我们刚才一直在用 3 维 embeddings 举例,但当前主流模型的 embedding 维度通常是几千维,最大的甚至超过 10,000 维。

为了说明更高维度的价值,下面我展示了 8 组彩色形状,它们最初位于一维空间中 —— 挤在一条直线上,杂乱无章,难以理解。但随着维度增加,你就能清楚地看到存在 8 个不同的、相关的组别。

image.png

image.png

image.png

三维是我这里能提供的视觉示例的极限,至于几千维的空间能表达什么,就得靠你发挥想象力了。

Embedding 阶段还有最后一件事要做。在获取 token 的 embedding 后,会将该 token 在 prompt 中的位置信息编码进 embedding 中。我没有深入研究这一机制的具体实现方式,只知道它对 prompt caching 的工作方式影响不大,但如果没有这一步,LLM 就无法判断 prompt 中 tokens 的先后顺序。

更新一下前面的伪代码,假设存在一个叫 encodePosition 的函数,它接收 embeddings 和位置信息,并返回嵌入了位置编码的新 embeddings。

const EMBEDDINGS =[...];
 
// Input: array of tokens (integers)
function embed(tokens){
// Output: array of n-dimensional embedding arrays
return tokens.map((token, i)=>{
 const embeddings = EMBEDDINGS[token];
return encodePosition(embeddings, i);
});
}

总而言之,embeddings 是 n 维空间中的点,你可以将其视为它们所代表文本的语义含义。在训练过程中,每个 token 都会在该空间中移动,靠近其他语义相似的 token。维度越多,LLM 对每个 token 的表示就越复杂、越细腻。

至此,tokenizer 和 embedding 阶段所做的全部工作,都是为了把原始文本转换成 LLM 能处理的形式。接下来,我们来看看这些数据进入 transformer 阶段后会发生什么。


04

Transformer

image.png

Transformer 阶段的核心任务,就是接收 embeddings 作为输入,并在 n 维空间中对它们进行调整。它通过两种方式实现这一点,而我们只关注第一种:attention(注意力机制)。我们暂不讨论 “Feedforward” 层或输出阶段(至少在这篇文章中👀)。

Attention 机制的作用,是帮助 LLM 理解 prompt 中各个 token 之间的关系 —— 具体做法是让每个 token 能够影响其他 token 在 n 维空间中的位置。它通过加权组合 prompt 中所有 token 的 embeddings 来实现这一点。输入是整个 prompt 的 embeddings,输出则是一个新的 embedding,它是所有输入 embeddings 的加权组合。

举个例子,如果 prompt 是 “Mary had a little”,被分词为四个 token:Mary、had、a、little,那么 attention 机制可能会决定,在生成下一个 token 时,模型会认为:

  • “Mary” 最重要(63%)(译者注:因为整个句子的主语是 Mary,后续内容很可能围绕她展开)

  • “had” 和 “a” 次之(16% 和 12%)(译者注:它们是语法结构的一部分,但语义信息较弱)

  • “little” 也有一定作用(9%)(译者注:它修饰后面的名词)

然后,它会把所有 token 的 embeddings 分别乘以对应的权重,然后把结果加在一起,得到一个融合后的向量。这正是 LLM 判断“在当前上下文中,每个 token 应该被关注多少”的方式。

这是目前为止整个流程中最复杂、最抽象的部分。我会先用伪代码展示它,然后再看看 embeddings 在经过这一过程时是如何被变换的。我本想让这一部分的数学内容少一些,但这里很难避免一些数学运算。别担心,你能行的,我相信你。

Attention 中的大部分计算都是矩阵乘法。对于本文而言,你只需知道:输出矩阵的形状由两个输入矩阵的形状决定,输出的行数等于第一个输入矩阵的行数,列数等于第二个输入矩阵的列数。

image.png

理解了这一点,我们来看一个简化版的注意力机制如何计算分配给每个 token 的权重。在以下代码中,我用 * 表示矩阵乘法。

// Similar to EMBEDDINGS from the pseudocode
// earlier, WQ and WK are learned during 
// training and do not change during inference.
//
// These are both n*n matrices, where n is the
// number of embedding dimensions. In our example
// above, n =3.
const WQ =[[...],[...],[...]];
const WK =[[...],[...],[...]];

// The input embeddings look like this:
//[
//[-0.1,0.1,-0.3],// Mary
//[1.0,-0.5,-0.6],// had
//[0.0,0.8,0.6],// a
//[0.5,-0.7,1.0]// little
//]
function attentionWeights(embeddings){
 const Q = embeddings * WQ;
 const K = embeddings * WK;
 const scores = Q * transpose(K);
 const masked = mask(scores);
return softmax(masked);
}

接下来,让我们看看 embedding 在流经这个函数时是如何变化的。

等等,WQ 和 WK 变量到底是什么?

还记得我之前说过,每个 token 的 embedding 最初都被随机分配了一个位置,然后在训练过程中不断微调,直到模型找到一个良好的排列状态吗?

WQ 和 WK 也是类似的。它们是 n×n 的矩阵(n 即 embedding 维度),在训练开始时被赋予随机值,随后也在训练中被不断调整,以帮助模型收敛到一个更优的解。

任何在训练过程中被调整的数,都被称为“模型参数”。embedding 向量中的每个浮点数,以及 WQ、WK 矩阵中的每个数值,都是一个参数。当你听说某个模型有“1750 亿参数”时,指的就是这些数字。

至于 WQ 和 WK 到底代表什么,我们其实并不完全清楚。随着模型训练收敛,它们最终会变成某种对 embedding 的变换方式,有助于模型生成更好的输出。它们内部可能在做任何事情 —— 而如何解释这些矩阵的含义,目前仍是一个开放且活跃的研究方向。

要得到 Q 和 K,我们分别将 embeddings 与 WQ 和 WK 相乘。WQ 和 WK 的行数和列数始终等于 embedding 的维度(本例中为 3)。这里我为 WQ 和 WK 选取了随机值,并将结果四舍五入到小数点后两位以便阅读。

image.png

得到的 Q 矩阵有 4 行 3 列。4 行是因为 embeddings 矩阵有 4 行(每个 token 一行),3 列是因为 WQ 有 3 列(每个 embedding 维度一列)。

K 的计算完全相同,只是将 WQ 换成 WK。

image.png

Q 和 K 都是输入 embedding 到新的 n 维空间的"投影"。它们不是原始的 embedding,但由原始 embeddings 推导而来。

然后,我们将 Q 和 K 相乘。我们对 K 进行“转置”,也就是沿对角线翻转,使得得到的矩阵是一个方阵,其行数和列数都等于输入提示词中的 token 数量。

image.png

这些 scores 表示每个 token 对下一个生成 token 的重要程度。左上角的数值 -0.08,代表 “Mary” 对 “had” 的重要性。再往下一行的 -0.10,则代表 “Mary” 对 “a” 的重要性。在展示完矩阵运算后,我会用图示更直观地说明这一点。接下来的所有操作,都是为了将这些 scores 转换为可用于混合 embeddings 的权重。

这个 score 矩阵的第一个问题是:它允许未来的 token 影响过去的 token。在第一行,我们唯一知道的词是"Mary",所以它应该是唯一对生成"had"有贡献的词。第二行也是如此,我们知道"Mary"和"had",所以只有这两个词应该对生成"a"有贡献,依此类推。

为了解决这个问题,我们对矩阵应用一个三角形掩码(triangular mask),将未来 token 对应的位置置零。不过,我们并不是真的设为 0,而是设为负无穷(negative infinity) —— 原因稍后解释。

image.png

第二个问题是,这些 scores 是任意的数值。如果它们能变成一个每行之和等于 1 的概率分布,对我们来说会更有用。这正是 softmax 函数的作用。softmax 具体如何运作的细节并不重要 —— 它比简单的“将每个数字除以该行总和”稍复杂一点,但结果是一样的:每行之和为 1,且每个数字都在 0 和 1 之间。

image.png

为了解释为什么用负无穷,下面是一个 softmax 的代码实现:

function softmax(matrix){
return matrix.map(row =>{
 const exps = row.map(=> Math.exp(x));
 const sumExps = exps.reduce((a, b)=> a + b,0);
return exps.map(exp => exp / sumExps);
});
}

它并不是简单地把每个数加起来再除以总和,而是先对每个数值取 Math.exp,也就是计算 e^x。如果我们用 0 代替负无穷,Math.exp(0) === 1,这些被屏蔽的位置仍然会产生非零权重。而 Math.exp(-Infinity) 是 0,这正是我们想要的。

下面的图片展示了提示词"Mary had a little"的 attention 权重示例。

这些权重与上面的计算结果不匹配,因为我是从 Transformer Explained 网站[7]上运行的 GPT-2 模型中提取的。所以这些是一个真实模型(尽管是老模型)的真实权重。

image.png

第一行只有"Mary",因此Mary对"had"的生成的贡献是100%。然后在第二行,"Mary"贡献了79%,而"had"贡献了21%用于生成"a",以此类推。LLM 认为这个句子中最重要的词是 “Mary”,这一点并不意外——从每一行中 “Mary” 都拥有最高权重就能看出。如果我让你补全"Jessica had a little"这个句子,你不太可能选择"lamb"。

接下来就只剩下对 token embeddings 进行加权混合了,谢天谢地,这一步比计算权重要简单得多。

// Learned during training, doesn't change 
// during inference. This is also an n*n matrix,
// where n is the number of embedding dimensions.
const WV =[[...],[...],...];
 
function attention(embeddings){
 const V = embeddings * WV;
// This is the `attentionWeights` function from
// the section above. We're wrapping it in
// this `attention` function.
 const weights = attentionWeights(embeddings);
return weights * V;
}

image.png

为什么不直接混合原始 embeddings?

当我们通过 Q 和 K 相乘得到 attention 权重时,我们完全是在衡量 token 之间的相关性。Embeddings 编码了 token 的各种语义信息 —— 某一维可能表示“颜色”,另一维表示“大小”,再一维表示“礼貌/粗鲁程度”,等等。而权重是通过相似度来判断哪些 token 更相关。

WV 的作用,则是让模型决定在混合时保留哪些维度的信息。

以句子 “Mary had a little” 为例,这里关于 “Mary” 最重要的信息是“人名”。模型在训练中可能也学到了很多关于 “Bloody Mary(血腥玛丽鸡尾酒)” 或 “Mary Queen of Scots(苏格兰女王玛丽)” 的知识,但这些与这首童谣无关,如果带入后续计算反而会引入噪声。因此,WV 允许模型在混合 embeddings 之前,先过滤掉不相关的特征。

接着,我们将生成的权重与 V 相乘,输出一组新的 embeddings:

image.png

Attention 机制的最终输出,就是这个输出矩阵的最后一行。通过 attention 过程,前面所有 token 的上下文信息都被融合进了这一行。但要注意:为了得到最后一行,前面所有行都必须被计算出来。

总而言之,输入是一组 embeddings,输出是一个新的 embedding。Attention 机制通过大量精细的数学运算,按照训练中学到的 WQ、WK 和 WV 矩阵所决定的重要性比例,将各个 token 的信息进行了加权融合。正是这一机制,让 LLM 能够理解在其上下文窗口中“什么内容重要,以及为什么重要”。

现在,我们终于掌握了讨论 caching 所需的一切知识。

当然,Attention 还有更多技术细节

我在本文展示的是一个简化版的 attention,目的是突出与 prompt caching 最相关的核心部分。实际中的 attention 机制更为复杂。如果你希望深入了解更多技术细节,我推荐 3blue1brown 关于 attention 的视频[8]


05

Prompt caching

我们再来看一遍上面的网格,但这次会展示在推理循环中每生成一个新 token 时,它是如何逐步填充的。

image.png

每次生成新 token 时,都会将其追加到输入中,并重新完整处理整个 prompt。但仔细观察:之前计算出的权重从未改变。第二行始终是 0.79 和 0.21,第三行始终是 0.81、0.13、0.06。我们其实在不断重复大量不必要的计算。如果你刚刚才处理完 “Mary had a”,那么在生成下一个 token 时,对 “Mary had a little” 中前三个 token 的大部分矩阵运算其实是冗余的 —— 而这正是 LLM 推理循环的默认行为。

通过以下两个改动,就能避免这些重复计算:

  • 在每次迭代中缓存 K 和 V 矩阵。

  • 只将最新 token 的 embeddings 输入模型,而不是整个 prompt。

现在我们再次走一遍矩阵运算过程,但这一次:前 4 个 token 的 K 和 V 矩阵已被缓存,我们只传入一个新 token 的 embeddings。

是的,又要面对矩阵运算了,抱歉!不过内容和之前基本一致,我们会快速过一遍。

计算新的 Q 时,输出只有一行。WQ 和之前一样,没有变化。

image.png

接着,计算新的 K 也同样只输出一行,而 WK 也和之前一样保持不变。

image.png

但随后我们将这一新行追加到前一次迭代缓存的 4 行 K 矩阵之后:

image.png

于是现在我们拥有了提示词中所有 token 的 K 矩阵,但我们只需要计算它的最后一行。

我们继续以这种方式来获取新的 score:

image.png

以及新的的 weights:

image.png

全程我们只计算必需的部分,完全不需要对旧值进行任何重新计算。获取 V 的新一行时也是同样的做法:

image.png

然后将其追加到我们缓存的 V 中:

image.png

最后,我们将新的权重与新的 V 相乘,得到最终的新 embeddings:

image.png

我们只需要这单独一行新的 embedding。得益于缓存的 K 和 V,先前所有 token 的上下文信息都已被融入其中。

被缓存的数据是 embeddings * WK 和 embeddings * WV 的结果,也就是 K 和 V。因此,提示词缓存通常被称为"KV caching"。

image.png

就是这样,上面那些 K 和 V 矩阵,就是服务提供商保存在他们巨大数据中心里的 1 和 0,用来给我们提供一折的 token 成本和更快的响应。

服务提供商在请求发出后,会将每个提示词的这些矩阵保留 5-10 分钟,如果你发送一个以相同提示词开头的新请求,他们就会复用缓存的 K 和 V,而不是重新计算它们。缓存匹配不需要完全一致 —— 即使新 prompt 只和缓存中的某一部分开头相同,也可以复用那部分已缓存的计算结果,而不必整个 prompt 完全匹配。

OpenAI 和 Anthropic 的缓存机制截然不同。OpenAI 完全自动处理,会尽可能尝试将请求路由到缓存条目。在我的实验中,通过发送请求然后立即重发,缓存命中率约为 50%。考虑到长上下文窗口的首字节延迟(time-to-first-byte)可能很长,这种自动缓存可能导致性能表现不稳定。

Anthropic 则赋予你更多控制权,让你决定何时缓存以及缓存多久。你需要为这项特权付费,但在我进行的实验中,当我们要求 Anthropic 缓存某个提示词时,他们会 100% 地将请求路由到缓存条目。因此,如果你的应用涉及长上下文窗口,并且需要可预测的延迟,Anthropic 可能是更合适的选择。

等等,那 temperature 这些参数会影响提示词缓存吗?

LLM 提供商提供了多种参数来控制模型输出的随机性,常见的有 temperature、top_p 和 top_k。这些参数都作用于推理循环的最后一步,即模型根据它为词表中每个 token 分配的概率来选取 token。这发生在 attention 机制产生最终 embedding 之后,因此提示词缓存不受这些参数影响。你可以随意调整它们,而不用担心导致缓存的提示词失效。

致谢

为了学习撰写本文所需的全部知识,我如饥似渴地阅读了大量优质内容,以下是我认为对我最有帮助的:

  • Build a Large Language Model (From Scratch)[9] by Sebastian Raschka[10].

  • Neural Networks: Zero to Hero[11] by Andrej Karpathy[12].

  • Neural Networks video course[13] by 3blue1brown[14].

  • Transformer Explainer[15] by Aeree Cho[16] et al.

如果你喜欢这篇文章,你一定会喜欢这些资源。

END

本期互动内容 🍻

按照文中逻辑,缓存本质是拿内存换计算。当你处理10万Token以上的超长上下文时,有没有估算过KV Cache的内存占用成本 vs 重新计算的API成本?在什么临界点你会选择放弃缓存?

文中链接

[1]https://claude.com/blog/prompt-caching

[2]https://docs.claude.com/en/docs/build-with-claude/prompt-caching

[3]https://platform.openai.com/docs/guides/prompt-caching

[4]https://magazine.sebastianraschka.com/

[5]https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/13_olmo3/standalone-olmo3.ipynb

[6]https://tiktokenizer.vercel.app/

[7]https://poloclub.github.io/transformer-explainer/

[8]https://www.youtube.com/watch?v=eMlx5fFNoYc

[9]https://www.oreilly.com/library/view/build-a-large/9781633437166/

[10]https://sebastianraschka.com/

[11]https://www.youtube.com/watch?v=VMj-3S1tku0&list=PLAqhIrjkxbuWI23v9cThsA9GvCAUhRvKZ

[12]https://karpathy.ai/

[13]https://www.youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi

[14]https://www.youtube.com/@3blue1brown

[15]https://poloclub.github.io/transformer-explainer/

[16]https://aereeeee.github.io/

本文经原作者授权,由 Baihai IDP 编译。如需转载译文,请联系获取授权。

原文链接:

https://ngrok.com/blog/prompt-caching/

微信图片_20250707174120.png

AI 及大模型技术分享交流群

干货分享,联系小助手入群

53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

添加专属顾问

回到顶部

加载中...

扫码咨询