<!-- title: 长提示词在裸奔：原生缓存砍掉九成 -->
<!-- domain: cost-hacks -->

# 长提示词在裸奔：原生缓存砍掉九成

如果你在用 Claude / GPT-4o 做带长系统提示、few-shot 示例或 RAG 上下文的应用，**你每一笔请求里 80% 的输入 token 都在原价重算**——而三大厂商早就内置了"原生缓存"，把这部分重复前缀按 **1 折到 5 折** 计费，绝大多数团队却从没改过提示词结构去吃它。这一篇只讲一件事：怎么让"不变的提示词"只付一次钱，并顺手用观测工具确认你真的吃到了缓存。预计可砍掉输入账单的 70%–90%，且**不改模型、不降智、不写额外服务**。

---

## 一、被忽视的事实：你的请求 80% 在重复付费

先做个小实验。打开你的线上请求日志，把每一次 prompt 拆成两段：

- **前缀（不变部分）**：系统提示、工具定义、few-shot 示例、检索回来的大段文档、角色设定。
- **后缀（变化部分）**：用户这一句话、当前时间戳、session_id。

对绝大多数对话类、Agent 类、RAG 类应用，前缀能占到总输入 token 的 **70%–95%**，而后缀只有几百 token。问题在于：你每次都把那段 5 万 token 的前缀**按原价**发给厂商，厂商每次也都**从头算一遍 attention**。

这就好比你每天进同一家公司，保安每天重新核验你的护照。厂商其实早就给了你一张工牌——**原生 prompt 缓存**——但很多人压根不知道它存在，或者以为它就是"语义缓存"。这是两个完全不同的东西。

---

## 二、原生缓存 vs 语义缓存：根本不是一回事

这点是国内技术圈最容易混淆的，必须先讲清楚，否则后面全是坑。

| 维度 | 原生缓存（Native Prompt Caching） | 语义缓存（Semantic Cache） |
|------|----------------------------------|----------------------------|
| 谁来做 | **厂商在 API 内部做**（Anthropic / OpenAI / Google） | 你自己搭外部缓存层（如 GPTCache、Redis+embedding） |
| 匹配方式 | **精确前缀**匹配，逐 token 对齐 | **向量相似度**匹配，意思接近就命中 |
| 准确性 | 100% 精确，无幻觉风险 | 可能命中"形似神不似"的旧答案，有错答风险 |
| 折扣 | Claude 读 **1 折**、OpenAI 读 **5 折** | 命中后接近免费（不调用模型） |
| 适用场景 | 前缀重复、内容可对齐 | 用户问法多样的 FAQ 场景 |

一句话：**原生缓存是厂商白给的确定性折扣，语义缓存是你自己造的概率性捷径。** 本文只讲前者——因为它是确定、安全、零额外基础设施的，而恰恰是被忽略得最狠的那一个。

---

## 三、Claude 原生缓存：读取只要一折

Anthropic 的 prompt caching 是目前三家力度最大的。机制和价格：

- **写入（cache write）**：缓存前缀按 **1.25× 基础输入价**计费（多收 25%，作为一次性存储成本）。
- **读取（cache hit）**：命中前缀按 **0.1× 基础输入价**计费——**直接 9 折 off，只剩一折**。
- **TTL**：默认 **5 分钟**，每次命中会刷新；还有一档 **1 小时**的扩展 TTL，适合请求不那么密集但有规律复访的场景（写入费略高）。
- **最小缓存长度**：Sonnet/Haiku 一般 **1024 token** 起，Opus 2048 token 起。
- **开启方式**：在请求体的 content block 上加 `cache_control` 断点标记，无需别的改动。

代码大概长这样（把系统提示和文档标记成可缓存，把用户问题放最后）：

```python
client.messages.create(
    model="claude-sonnet-4-6",
    system=[{
        "type": "text",
        "text": SYSTEM_PROMPT,           # 不变：角色、规则
        "cache_control": {"type": "ephemeral"}   # ← 标记缓存
    }],
    messages=[
        {"role": "user", "content": [
            {"type": "text", "text": BIG_RAG_CONTEXT,
             "cache_control": {"type": "ephemeral"}},  # 不变：检索文档
            {"type": "text", "text": user_question}    # 变化：放最后
        ]}
    ]
)
```

**算笔账**。以 Claude Sonnet（输入约 $3/M token）为例，假设你的前缀是 50K token：

- **不开缓存**：每次请求 50K × $3/M = **$0.15**。100 次请求 = **$15.00**。
- **开缓存**：首次写入 50K × $3.75/M = $0.1875；后续 99 次命中 50K × $0.30/M = $0.015/次。100 次合计 = $0.1875 + 99×$0.015 = **约 $1.67**。

**砍掉约 89%。** 唯一前提：这 100 次请求要落在同一个 5 分钟（或 1 小时）TTL 窗口内。对客服、Agent 多轮、文档问答这类场景，命中率轻轻松松。

---

## 四、OpenAI：自动缓存，零代码改动直接五折

OpenAI 的做法更"傻瓜"，也正因为太傻瓜，很多人根本没意识到自己已经在用它——只是没拿到最优命中率。

- **完全自动**：**不需要任何代码改动**，OpenAI 自动识别重复前缀并缓存。
- **折扣**：命中的输入 token 按 **50%（5 折）**计费。
- **前缀对齐**：按 token 逐个比对，**只要前缀和某次近期请求完全一致就命中**；一旦某个位置 token 不同，从那个位置往后全部失效、按原价算。
- **空闲寿命**：通常 **5–10 分钟**无请求即过期。
- **最小长度**：通常 **1024 token** 起。

怎么确认你吃到了缓存？看响应里的 `usage.prompt_tokens_details.cached_tokens`：

```python
resp = client.chat.completions.create(model="gpt-4o", messages=[...])
cached = resp.usage.prompt_tokens_details.cached_tokens
total_in = resp.usage.prompt_tokens
print(f"缓存命中率: {cached/total_in:.0%}")
```

**算笔账**。GPT-4o 输入约 $2.50/M，前缀 50K：

- **不开缓存**：每次 $0.125，100 次 = **$12.50**。
- **开缓存**：没有写入溢价（自动），命中部分按 $1.25/M 计。100 次约 **$6.38**。

砍掉约 49%——力度不如 Claude，但**零改造成本**，属于"躺着就有的钱"。

关键认知：**OpenAI 的缓存一直在自动跑，但你的命中率可能很低**，因为你的提示词结构不对（见下一节）。很多人以为"我反正自动有缓存"，结果观测一看命中率只有 5%——等于白瞎。

---

## 五、最关键的一招：把"会变的内容"挪到末尾

这是全文最值钱的一段。原生缓存是**前缀对齐**的——它从 prompt 的**第一个 token** 开始往后匹配，**一旦遇到第一个不同的 token，缓存就从那里断掉**，后面全部按原价。

这意味着你的提示词**结构**直接决定生死：

```mermaid
flowchart TD
    A[每次请求 prompt] --> B{前缀与缓存逐 token 对齐?}
    B -->|未命中: 写入| C[Claude 1.25x 写入<br/>OpenAI 原价自动写]
    B -->|命中: 读取| D[Claude 0.1x / OpenAI 0.5x 折扣]
    C --> E[窗口内下次复用]
    D --> E
    E --> F{你把'变量'放哪了?}
    F -->|静态在前, 动态在后| G[缓存完整复用<br/>砍 49%–89%]
    F -->|中间插入时间戳/用户名| H[缓存断裂<br/>断点之后全量重算]
    F -->|最前面放当天日期| I[整段缓存作废<br/>等于没开]
    H --> A
    I --> A
```

三条铁律，背下来：

1. **静态内容放最前面**：系统提示、工具定义、few-shot 示例、检索文档——这些不变的东西全部堆到 prompt 开头，并标记 `cache_control`。
2. **动态内容放最后面**：用户本轮问题、当前时间、session_id、动态变量——全部塞到 prompt **末尾**。
3. **绝不在中间插变量**。反例（很多人踩的坑）：

```
[系统提示]
今天是 2026-06-19 14:32:11        ← 致命！每次都变
[工具定义]
[检索文档]
[用户问题]
```

只要"今天"那一行变了，**从那一行往后所有内容缓存全部失效**——工具定义、检索文档全白缓存。把它挪到 prompt 最末尾，或者干脆放进单独的 user message 尾部，命中率立刻从个位数飙升到 80%+。

> 同理，日志里常见的 `{user_id}`、`{request_id}`、随机 nonce 也别放前面。**凡是会变的，一律往后挪。**

---

## 六、Gemini 显式缓存：超大上下文专用

Google Gemini 走的是**显式缓存**路线（Context Caching）：你得先创建一个 `CachedContent` 对象（绑定一大段内容），然后后续请求引用它。

- 适合**上下文特别大**（几十万 token 的代码库、整本书、长视频）且要**反复查询**的场景。
- 计费是"**存储费（按小时）+ 命中后降低的处理费**"，所以它要算清楚：你的查询频率够不够摊掉存储成本。
- 查询密集、上下文巨大时，比逐次重算便宜得多；查询稀疏反而可能亏。

对绝大多数中小应用，Claude 的 ephemeral 缓存或 OpenAI 的自动缓存已经够用，Gemini 显式缓存留给"超大文档 + 高频问答"这类重场景。

---

## 七、别瞎开：先观测，确认你到底吃没吃到缓存

缓存这东西有个陷阱：你以为开了，其实没命中。**务必接一个观测工具看真实命中率**，否则省下的钱全凭想象。

- **Helicone**（helicone.ai）：开源 LLM 可观测平台，做成代理层挡在你和厂商之间，**按请求记录成本、延迟、token、以及缓存命中数**。开箱即用看到 cache hit rate、哪些请求没命中、为什么没命中。可自托管，也有托管版。
- **Langfuse**（langfuse.com）：开源 LLM 工程平台，侧重 trace + 成本分析，能沿调用链看到每一步花了多少、缓存吃了几成。同样可自托管。

接入后先看两个指标：

1. **Cache hit rate（缓存命中率）**：健康的应用应 > 70%。低于 30% 说明你的提示词结构有问题（多半是变量放前面了）。
2. **Cost per request 的下降曲线**：开缓存前后对比单次请求成本，应该肉眼可见地掉。

一个真实可复现的诊断动作：**在 Helicone 里筛"未命中"的请求，diff 它们的前缀**，几乎一定能找到那个偷偷插在前面的时间戳或变量。改掉它，命中率和省钱效果立刻翻倍。

---

## 八、按预算给你的方案

| 你的场景 | 推荐动作 | 预期省钱 |
|---------|---------|---------|
| 用 Claude + 长系统提示/Agent | 加 `cache_control`，静态前、动态后 | 输入砍 **~89%** |
| 用 GPT-4o，懒得改代码 | 仅做"变量挪末尾"的结构调整 | 输入砍 **~49%**，零代码 |
| 超大文档（几十万 token）高频问答 | Gemini 显式缓存，算清存储摊销 | 重场景砍 **70%+** |
| 不知道有没有命中 | 先接 Helicone/Langfuse 观测 | 先诊断再优化 |

组合拳威力最大：**Claude 原生缓存（砍九成输入）+ 变量后置（保证命中）+ Helicone（监控命中率）**。三者都是确定性的，不靠概率、不降模型质量、不需要额外推理服务。

---

## 信息差总结

| 你以为的 | 别人早知道的（信息差） |
|---------|---------------------|
| 每次请求都要为整段提示词原价付费 | 不变前缀可被厂商缓存，Claude 只收 1 折、OpenAI 5 折 |
| "缓存"就是语义缓存那套，容易答错 | 原生缓存是精确前缀匹配，零幻觉风险，厂商白给 |
| 我的 OpenAI 应用反正自动有缓存 | 自动≠命中，变量放错位置命中率可能只有 5% |
| 提示词顺序无所谓，能跑就行 | 中间插一个时间戳，整段缓存作废，等于没开 |
| 省钱得搭复杂中间件 | 一个 `cache_control` 字段 + 一行观测即可 |

---

## 行动指南（今晚就能做）

1. **挑一个高频接口**（客服、Agent、文档问答任一），把它的系统提示 + 检索文档提取出来，确认是否 ≥1024 token 且跨请求不变。
2. **加缓存标记**：Claude 在 content block 上加 `cache_control: {type:"ephemeral"}`；OpenAI 自动开启，但**务必**把变量挪到 prompt 末尾。
3. **接观测**：Helicone 或 Langfuse 套一层代理，盯 cache hit rate。
4. **改前缀结构**：删掉/后置所有前置的日期、用户 ID、随机数。
5. **看账单**：上线 24 小时后对比单次请求成本，预期降 50%–90%。

整个过程不动模型、不动业务逻辑，纯结构调整 + 一个字段，ROI 极高。

---

## 参考来源

- Anthropic Prompt Caching 官方文档：https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching
- OpenAI Prompt Caching 指南：https://platform.openai.com/docs/guides/prompt-caching
- Google Gemini Context Caching：https://ai.google.dev/gemini-api/docs/caching
- Helicone 可观测平台：https://www.helicone.ai
- Langfuse 开源 LLM 工程平台：https://langfuse.com
- Anthropic 定价页：https://www.anthropic.com/pricing

---
> 本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵**爱卫生**（微信ID: gprshome201101）维护。
> 聚焦5G/6G核心网、3GPP标准、AI工具实战。知识星球「51学通信」提供深度技术答疑和行业洞察。

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
