Prompt cache拆分稳定前缀与动态变量的实现方法
来源:17golang原创
时间:2026-09-20 03:05:37 199浏览 收藏
我在做多轮客服调用时,最容易踩的坑不是模型回答慢,而是每次请求都把相同的角色说明、工具定义和动态问题混在一起。看起来只是换了一句用户输入,实际却让可复用的前缀也跟着变化。Prompt cache 的正确拆法很明确:把稳定内容放在前面,把动态变量放在后面,再观察真正的缓存读取量。
官方地址:https://platform.openai.com/docs/guides/prompt-caching
稳定前缀必须从请求开头连续匹配;动态问题不要插入前缀中间。缓存命中并不会替模型生成新答案,只是减少重复处理已经匹配的输入。
- 角色说明、工具定义、固定示例和参考资料适合组成稳定前缀。
- 用户问题、业务字段、时间戳和随机追踪值应集中放在后部。
- 不要只看响应成功;用 cached_tokens、延迟和成本判断拆分是否有效。
先把缓存边界画成稳定前缀和变量区
Prompt caching 比较的是渲染后的输入前缀,不是“语义差不多”就算命中。系统指令、开发者消息、工具定义、对话历史和文本资料只要在断点之前发生变化,后面的那一段就不能继续复用。因此我会先把一次请求拆成两个区域:前缀区负责描述长期不变的工作规则,变量区只承载本次任务。
| 内容 | 建议位置 | 常见处理 |
|---|---|---|
| 角色规则、输出格式、工具 schema | 前缀区 | 版本化后固定顺序,不拼接时间戳 |
| 产品知识、少变的示例和参考资料 | 前缀区 | 按版本整体替换,避免请求间局部漂移 |
| 用户问题、订单号、语言和筛选条件 | 变量区 | 放在前缀之后,每次只替换这一段 |

这里有一个很实用的判断:如果只是用户问题变化,前缀应该仍然完整命中;如果工具列表、参考资料顺序或系统提示中的版本字段变化,不能把未命中简单归咎于模型繁忙。先比较发送给 API 的实际结构,通常比盯着业务代码里的模板字符串更快。
把请求模板固定后再观察命中结果
下面的写法把长期规则放在 developer 消息里,把每次工单放在 user 消息里。示例使用显式模式表达“只希望缓存稳定部分”的意图;如果运行环境只支持隐式缓存,也应保留同样的排列原则。
from openai import OpenAI
client = OpenAI()
# 稳定前缀:角色、格式和工具说明在同一版本内保持不变
stable_rules = """
你是售后分诊助手。
只输出 JSON:priority、reason、next_action。
先判断故障范围,再给出一条可执行的下一步。
""".strip()
# 动态变量:每个请求只替换工单内容,不插入稳定规则中间
ticket = "订单 8472 的 webhook 在支付成功后没有收到回调"
response = client.responses.create(
model="gpt-5.6",
prompt_cache_options={"mode": "explicit"},
input=[
{
"role": "developer",
"content": [{
"type": "input_text",
"text": stable_rules,
# 在稳定前缀末尾设置断点,后面的工单不写入可复用前缀
"prompt_cache_breakpoint": {"mode": "explicit"},
}],
},
{"role": "user", "content": ticket},
],
)
# 记录缓存读取量;未命中时先排查前缀是否被动态字段改变
cached = response.usage.input_tokens_details.cached_tokens
print(f"cached_tokens={cached}")
生产环境里不要把每个用户的随机 ID、当前时间、A/B 实验标志或临时工具描述塞进 developer 消息。它们哪怕只改了一个位置,也可能让后续前缀失去匹配。固定的模型、工具定义和消息顺序也很重要;“同一段文字”但渲染结构不同,仍然不是同一前缀。

命中率下降时按四项清单排查
我通常按“内容、结构、路由、生命周期”四个方向排查,而不是立刻调大缓存参数。
- 内容:比较系统提示、工具 schema、参考资料和版本标记是否真的没变。
- 结构:确认动态 user 内容没有被插入稳定 developer 内容内部,消息顺序也没有漂移。
- 路由:较早模型可用稳定的
prompt_cache_key做一致分组,但它只影响路由,不保证命中。 - 生命周期:结合缓存保留时间、请求间隔和
cached_tokens判断是过期还是前缀变化。
缓存输入仍然会计入速率限制,命中也不代表输出完全相同。最终应把前缀版本、缓存读取量、首 token 延迟和输入成本一起记录,才知道拆分是否真的改善了线上请求。
常见问题
只设置 prompt_cache_key 就能保证命中吗?
不能。它主要帮助相关请求保持一致的路由或分开统计,真正命中仍要求可复用前缀匹配。
动态内容放在 user 消息里就一定安全了吗?
这是更稳妥的默认布局,但模型、工具、历史消息等前置结构仍要保持一致,不能只检查 user 字段。
cached_tokens 为零应该先改哪个地方?
先记录并比较完整渲染前缀,优先查工具定义、版本字段、时间戳和消息顺序,再考虑路由与缓存生命周期。
-
398 收藏
-
298 收藏
-
388 收藏
-
485 收藏
-
493 收藏
-
173 收藏
-
301 收藏
-
398 收藏
-
科技周边 · 人工智能 | 6小时前 | 错误处理 · mcp · 工具调用 · AI工程 · MCP工具错误 isError structuredContent CallToolResult JSON-RPC错误208 收藏
-
359 收藏
-
171 收藏
-
234 收藏
-
380 收藏
-
191 收藏
-
272 收藏
-
251 收藏
-
357 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习