Prompt Caching 是怎么工作的?

---
title: "Prompt Caching 是怎么工作的?"
author: "Amit Shekhar"
source_url: "https://outcomeschool.com/blog/how-does-prompt-caching-work"
published_at: "2026-06-09T00:00:00.000Z"
fetched_at: "2026-07-01T23:01:23Z"
updated_at: "2026-07-02T01:45:26Z"
language: "zh"
review_status: "draft"
---

# Prompt Caching 是怎么工作的?

![How does Prompt Caching work?](https://outcomeschool.com/static/images/blog/how-does-prompt-caching-work.png)

在这篇文章里,我们会学习 Prompt Caching 是怎么工作的。我们还会看到为什么需要它、它在大语言模型内部到底怎么运作,以及它在 AI 助手和 agent 这类真实系统里会用在哪里。

我们会讲这些内容:

- 什么是 prompt
- 简单回顾一下 LLM 如何读取 prompt
- 什么是 Prompt Caching
- 为什么需要 Prompt Caching
- Prompt Caching 的核心思路
- 精确前缀规则
- cache write、cache read 和 TTL
- 应该把什么放进缓存
- Prompt Caching 的好处
- 真实世界里的 Prompt Caching

我是 **Amit Shekhar**,[Outcome School](https://outcomeschool.com) 创始人。我教过并辅导过很多开发者,他们靠自己的努力拿到了高薪技术岗位;我也帮助过许多科技公司解决各自独特的问题,并创建过很多被顶级公司使用的开源库。我热衷于通过开源、博客和视频分享知识。

我在 Outcome School 教 [AI and Machine Learning](https://outcomeschool.com/program/ai-and-machine-learning)。

我们开始吧。

## 什么是 prompt

在讨论 Prompt Caching 之前,我们必须先理解什么是 prompt。

**prompt 就是我们发送给大语言模型的文本。**

大语言模型,也就是 LLM,是 ChatGPT、Claude 这类工具背后的技术。我们给它一段文本,它会返回一段文本。

简单说,prompt 就是我们输入进去的全部内容。模型读取我们的 prompt,然后写出回复。

假设我们正在构建一个客服助手。我们发送给模型的文本通常包含几个部分:

- 一组告诉模型该如何表现的指令,比如“你是一家鞋店礼貌的客服代表。”
- 也许还有一份很长的鞋类退货政策文档。
- 用户实际提出的问题,比如“买了 40 天以后还能退鞋吗?”

所有这些文本合在一起,就是 prompt。

这里有一点很重要。指令和政策文档对每个用户来说都是一样的。只有用户的问题会变化。我们很快还会回到这一点,因为它正是 Prompt Caching 的核心。

## 简单回顾一下 LLM 如何读取 prompt

要理解 Prompt Caching,我们必须先理解 LLM 读取 prompt 时的一件事。

当我们发送 prompt 时,模型并不是按完整单词来读取它。模型会先把文本拆成一些叫作 **token** 的小片段。token 是一小块文本,大致可以是一个词,也可以是词的一部分。比如 `support` 这样的短词通常是一个 token,而 `returning` 这样的长词往往会被拆成两个 token。

于是,prompt 就变成了一串 token。

我们有一篇详细介绍 [Byte Pair Encoding(BPE)](https://outcomeschool.com/blog/bpe-in-llms)的文章,解释了这种 token 切分是怎么工作的。

接下来,模型会逐个处理这些 token,并为每个 token 建立内部理解。模型在写出回复的第一个词之前,需要先读取整个 prompt,并处理其中每个 token;这个第一步叫作 **prefill**。

简单说,prefill 就是模型读取并消化整个 prompt。

在 prefill 过程中,模型会为每个 token 计算一些内部值并把它们存起来。这些存下来的值保存在一个叫作 [**KV cache**](https://outcomeschool.com/blog/kv-cache-in-llms) 的东西里。

我们用大白话理解一下 KV cache。模型读取每个 token 时,会为这个 token 创建一小份摘要,有点像是在记录这个 token 在前文上下文里意味着什么。KV cache 就是所有这些记录的集合,每个 token 对应一组记录。模型需要这些记录来写回复,并且在生成每个新词时也会反复复用它们。

这里要记住一个关键点:

**为一个很长的 prompt 构建 KV cache 是实打实的工作。模型必须逐个 token 做大量计算。**

所以,如果我们的 prompt 有 5,000 个 token,模型在写出任何内容之前,就必须先为这 5,000 个 token 全部做完这项工作。prompt 越长,prefill 这一步花的时间和钱就越多。

有了这层基础,我们就可以理解真正的问题了。

## 什么是 Prompt Caching

现在我们已经知道模型如何读取 prompt,接下来理解 Prompt Caching。

**Prompt Caching 是一种技术:模型会保存它已经为 prompt 中重复部分做过的工作,这样下次就可以复用这些保存下来的工作,而不是全部重做一遍。**

简单说,Prompt Caching 的意思就是:重活做一次,以后直接复用。

“cache”这个词的意思很简单:找一个地方把东西存起来,以后需要时可以快速拿到,不用从头再做。

把它和前面讲的内容连起来看。模型做的“重活”,就是在 prefill 阶段构建 KV cache。Prompt Caching 会保存 prompt 中重复部分对应的 KV cache。下一次我们发送一个以同样重复部分开头的 prompt 时,模型会加载已经保存的 KV cache,跳过所有重复计算。

所以,Prompt Caching 的核心,是复用 prompt 开头重复部分对应的内部计算结果。

接下来的问题是:我们为什么需要它?继续看。

## 为什么需要 Prompt Caching

回到前面的鞋店客服助手例子。

每个用户都会发送一个问题。但别忘了,每个问题都会和相同的指令、相同的长退货政策文档一起发送。用户的问题很短,但指令和文档很长。

也就是说,模型会为每个用户、每条消息,一遍又一遍地读取同样的长指令和同样的长文档。

为了方便理解,我们给它加一点数字。假设:

- 指令和政策文档一共有 5,000 个 token。
- 用户的问题有 50 个 token。

用户每问一次,模型都要对 5,050 个 token 做 prefill。其中 5,000 个 token 和上一次完全相同,只有 50 个 token 是新的。

这很浪费。模型正在对 5,000 个完全没变的 token 做重复的重活。

这会带来两个实际问题:

- **慢。** 一遍又一遍处理 5,000 个 token,会增加用户看到回复之前的延迟。
- **贵。** 我们付费通常取决于模型处理了多少 token。每次都重新处理同样的 5,000 个 token,就意味着我们在为同一份工作反复付钱。

在真实应用里,这个问题会变得更严重。想想那些很长的系统指令、大型文档,以及每次请求都会带上的大量示例。我们反复发送同一大块文本,模型也不断重复做同样的工作。

于是,Prompt Caching 就派上用场了。

## Prompt Caching 的核心思路

我们一步一步理解它的核心思路。

前面说过,在 prefill 过程中,模型会构建 KV cache,也就是为每个 token 生成内部记录。Prompt Caching 做的是一个简单但很有用的动作。

**它会保存 prompt 中固定、重复部分的 KV cache。下一次请求如果以同样的部分开头,模型就加载已经保存的 KV cache,从那里继续处理,跳过重复计算。**

我们沿用前面的例子走一遍。

**第 1 步:** 用户发送第一个问题。prompt 是 5,000 个 token 的指令和文档,再加上 50 个 token 的问题。模型会对全部 5,050 个 token 做 prefill,并构建 KV cache。在这个过程中,它会保存前 5,000 个 token 的 KV cache,因为我们标记了这部分可以缓存。

**第 2 步:** 新用户发送了另一个问题。prompt 仍然是相同的 5,000 个 token 的指令和文档,只是后面接了一个新的 50 个 token 的问题。现在,模型不需要再为前 5,000 个 token 重做计算,而是直接加载它们已经保存的 KV cache。它只需要为新的 50 个 token 做新计算。

也就是说,模型直接跳到了缓存部分结束的位置,从那里继续往下处理。它不会把已经理解过的 5,000 个 token 再浪费时间处理一遍。

下面用一个简单图示说明:

```text
WITHOUT prompt caching (every request):

[ 5,000 tokens: instructions + document ]  +  [ 50 tokens: question ]
        process all of this again                process this
        (slow, costly, repeated)                 (new work)


WITH prompt caching (after the first request):

[ 5,000 tokens: instructions + document ]  +  [ 50 tokens: question ]
        load from cache (fast, cheap)             process this
        skip the heavy work                       (new work)
```

问题解决了。模型现在只需要对重复部分做一次重活。

如果想深入理解 LLM 内部机制和 KV Cache,可以看看 Outcome School 的 [AI and Machine Learning Program](https://outcomeschool.com/program/ai-and-machine-learning)。

## 精确前缀规则

这里有一条非常重要的规则必须理解,因为大多数错误都出在这里。

**Prompt Caching 基于匹配前缀工作。缓存部分必须位于 prompt 的开头,并且必须逐字符完全一致。**

先理解一下 **prefix** 这个词。prefix 指的是某个东西的开头部分。在我们的场景里,缓存部分就是 prompt 的开头,也就是用户问题之前的那部分。

只有新的 prompt 开头和已缓存 prompt 的开头完全相同时,模型才能复用缓存。一旦文本出现不同,缓存从那个位置开始就不再有用了。

可以把它想成下面这样:

```text
Cached prompt:    You are a polite support agent. Return window is 30 days.
New prompt:       You are a polite support agent. Return window is 45 days.
                  |--------------- matches exactly ---------------|
                                   read from cache
                                                                  ^ differs from here, so this part is redone
```

这里可以看到,两段 prompt 在某个位置之前完全相同,所以前面匹配的部分可以从缓存中读取。从第一个不同的 token 开始,前缀就不再匹配,因此模型必须重新计算之后的所有内容。

这里一定要特别小心:

**只要 prompt 前面很早的位置有一个字符变化,这个变化之后的缓存就全都失效。**

举个例子。假设我们在指令最顶部加了一行“今天的日期是 2026-06-07”。这行每天都会变。因为它位于 prompt 最开头,所以每天的前缀都不一样。昨天构建的缓存,今天就复用不了了。模型必须重新做所有工作。

这是一个非常常见的错误。我们无意中把会变化的东西放在 prompt 顶部,比如当前日期、随机 ID 或用户名。这个很小的变化会悄悄破坏整个缓存。

所以要记住的规则很简单:

**把稳定部分放在前面,把变化部分放在最后。**

如果 prompt 的开头保持不变,缓存就能继续工作。如果开头一直变化,缓存就毫无用处。别急,我们马上会看到哪些部分应该保持稳定,以及应该把它们放在哪里。

**给你一个小提示**

无论你在哪个技术领域工作,都应该熟悉这些主题:

- LLM
- RAG
- MCP
- Agent
- Fine-tuning
- Quantization

我们把它们整理进了一个视频:

[AI Engineering Explained: LLM, RAG, MCP, Agent, Fine-Tuning, and Quantization](https://www.youtube.com/watch?v=lnfWvX66FUk)

不用现在停下来去看——先收藏,等有时间再看。未来的你会感谢现在的你。

现在,我们回到主题。

## cache write、cache read 和 TTL

接下来理解两个简单术语:cache write 和 cache read。

**cache write 发生在第一次。** 也就是模型处理重复部分,并把它的 KV cache 保存下来。我们是在第一次把结果写入缓存。

**cache read 发生在之后。** 也就是后续请求复用已经保存的 KV cache,而不是重新计算。我们是在从缓存里读取。

把它和成本联系起来看,这里就很有意思了。

cache write 的成本会比普通处理稍高一点,因为模型不仅要完成计算,还要把结果存起来。粗略理解,cache write 的成本大约是这部分普通价格的 1.25 倍。

但 cache read 非常便宜。从缓存读取的成本大约只有普通价格的十分之一。也就是对重复部分来说,大约能省下 90%。

所以,第一次请求会多付一点成本来写入缓存。之后每个请求都会便宜很多,因为它们是从缓存读取。缓存复用次数越多,省得越多。

流程大概如下:

```text
Request 1  -->  process the stable part  -->  save it    (cache WRITE, ~1.25x cost)
                                               |
                                               v
                                        +-------------+
                                        |    cache    |
                                        +-------------+
                                            ^  ^  ^
Request 2 ----------------------------------+  |  |   (cache READ, ~0.1x cost)
Request 3 -------------------------------------+  |   (cache READ, ~0.1x cost)
Request 4 ----------------------------------------+   (cache READ, ~0.1x cost)
```

这里可以看到,只有第一个请求会做重活并把结果写入缓存。之后每个以相同稳定部分开头的请求,都只是从缓存读取,所以每次成本都会远低于从头重做。

下一个问题是:缓存会永远保留吗?答案是否定的。

缓存有一个 **TTL**,全称是 **存活时间(time to live)**。简单说,TTL 就是缓存过期并被移除之前能存活多久。

常见的默认 TTL 是 5 分钟。也可以选择更长的 TTL,比如 1 小时。实际含义如下:

- 如果一个带有相同前缀的新请求在 TTL 窗口内到达,它就可以从缓存读取。
- 如果 TTL 窗口内没有任何请求到达,缓存就会过期。下一次请求就必须重新做一次 cache write。

所以,当很多请求共享同一个开头,并且在时间上比较接近地到达时,Prompt Caching 的效果最好。

**注意:** 更长的 TTL 可以让缓存保留更久,当请求分布比较分散时会有帮助;但更长 TTL 的 cache write 成本也会稍高一些。因此,我们要根据具体用例选择 TTL。

## 应该把什么放进缓存

现在我们知道,缓存作用在 prompt 开头的稳定部分。自然的问题就是:到底应该把什么放在那里?

答案很简单。把会在很多请求之间保持不变的部分放在前面,把会变化的部分放在最后。

下面这些部分很适合缓存,因为它们通常不会变化:

- **系统指令。** 这些指令描述模型应该如何表现,比如“你是一名礼貌的客服代表。”它们对每个用户都一样。
- **大型文档。** 例如完整的退货政策、产品手册或知识库文章。它们很长,而且会重复出现,所以缓存它们能省很多。
- **工具定义。** 当我们允许模型使用工具时,需要向模型描述每个工具。这些描述通常是固定的。
- **few-shot 示例。** 这些是我们提供给模型的示例问题和答案,用来让模型学会我们想要的风格。“few-shot”的意思很简单,就是给模型几个示例来引导它。这些示例每次都一样。

下面这部分会变化,必须放在最后:

- **用户实际提出的问题或消息。** 每次请求都不同,所以它要放在最末尾,也就是所有可缓存部分之后。

用一个简单图示来看这个顺序:

```text
ORDER OF A WELL-DESIGNED PROMPT

  FIRST  ->  Tool definitions     |
             System instructions  |  stable part: cache this
             Large documents      |
             Few-shot examples    |

  LAST   ->  User's question         changing part: do not cache
```

这个顺序就是关键。稳定块位于前面,可以被缓存。变化的问题位于后面,不会破坏缓存。

到这里,我们就知道到底应该缓存什么,以及应该把它们放在哪里了。

决定 prompt 里放什么、按什么顺序放,本身就是一门学问。我们有一篇详细介绍 [Context Engineering](https://outcomeschool.com/blog/context-engineering) 的文章,专门深入讲这个话题。

## Prompt Caching 的好处

我们快速把好处汇总一下,因为这些正是我们使用这项技术的原因。

- **更低延迟。** 延迟指的是用户拿到回复之前的等待时间。因为模型跳过了重复部分的重新处理,所以可以更快开始回复。
- **更低成本。** 缓存 token 的读取价格要便宜得多,大约只有普通价格的十分之一。当我们一遍又一遍发送同一大块文本时,这种节省会累积成很大的差异。

简单说,Prompt Caching 可以让我们的应用同时更快、更便宜,而且不会改变答案质量。模型仍然看到了完整 prompt,只是避免重复做已经做过的工作。

这就是 Prompt Caching 的妙处。

## 真实世界里的 Prompt Caching

接下来看看 Prompt Caching 在真实系统里用在哪里。

主要 AI 提供商都把 Prompt Caching 做成了内置功能。例如 Claude 背后的 Anthropic、GPT 模型背后的 OpenAI,都支持 Prompt Caching。我们只需要标记 prompt 中稳定的部分,让它可以被缓存,提供商会负责保存和复用。我们也可以检查响应,看看有多少 token 被写入缓存、多少 token 是从缓存读取的,这样就能确认缓存确实在生效。

Prompt Caching 在两类系统里尤其有用。

第一类是 **RAG**。RAG 是 Retrieval-Augmented Generation 的缩写。简单说,它是一种系统:先取回一些相关文档,再把它们和用户问题一起发送给模型。这些取回的文档和固定指令通常很长,而且会在请求之间重复出现。缓存稳定指令,以及任何会重复发送的文本,可以降低成本和延迟。在同一条流水线的更前面,文档 embedding 也可以被缓存;我们有一篇详细介绍 [Embedding Cache 如何工作](https://outcomeschool.com/blog/how-does-an-embedding-cache-work)的文章,解释了它如何避免每次查询都重新计算 embedding。

第二类是 **agent 系统**。[agent](https://outcomeschool.com/blog/ai-agent) 是一种 AI 程序,会一步一步处理任务,通常会调用工具,并通过多个回合完成工作。在 agent 系统里,同一大块指令、工具定义和早前文本,会在每一步都发送一次。步骤可能很多,所以同一个开头会被大量复用。这正是 Prompt Caching 最适合发挥作用的场景,因为缓存前缀会被一遍又一遍读取。

在规模化场景下服务这些重复前缀,是推理引擎的工作。我们有一篇详细介绍 [vLLM](https://outcomeschool.com/blog/how-does-vllm-work) 的文章,逐步解释它如何在请求之间共享相同前缀。另一个推理引擎 [SGLang](https://outcomeschool.com/blog/how-does-sglang-work) 也做同样的事,它使用基数树(radix tree)更精确地匹配共享前缀。

所以,只要我们不断发送同一个很长的 prompt 开头,Prompt Caching 就能带来很大帮助。

如果想深入学习 RAG、向量数据库和 AI Agent,我们有一套完整课程——可以看看 Outcome School 的 [AI and Machine Learning Program](https://outcomeschool.com/program/ai-and-machine-learning)。

这就是 Prompt Caching 的工作方式。我们为 prompt 中固定、重复的开头保存模型内部做过的工作,让这个开头保持完全相同并放在最前面,然后不断复用它,从而获得更快、更便宜的响应。

准备 AI 工程面试可以看这里:[AI Engineering Interview Questions](https://github.com/amitshekhariitbhu/ai-engineering-interview-questions)

这次就到这里。

谢谢

**Amit Shekhar**
[Outcome School](https://outcomeschool.com) 创始人