登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  人工智能

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前缀区版本化后固定顺序,不拼接时间戳
产品知识、少变的示例和参考资料前缀区按版本整体替换,避免请求间局部漂移
用户问题、订单号、语言和筛选条件变量区放在前缀之后,每次只替换这一段
Prompt caching 稳定前缀与动态变量分区结构说明图
图1:Prompt cache 前缀结构说明图,展示稳定规则、工具定义和动态问题的边界;这是静态说明图,不是运行截图。

这里有一个很实用的判断:如果只是用户问题变化,前缀应该仍然完整命中;如果工具列表、参考资料顺序或系统提示中的版本字段变化,不能把未命中简单归咎于模型繁忙。先比较发送给 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 消息。它们哪怕只改了一个位置,也可能让后续前缀失去匹配。固定的模型、工具定义和消息顺序也很重要;“同一段文字”但渲染结构不同,仍然不是同一前缀。

Prompt cache 命中观测与动态请求分流的结构说明图
图2:缓存命中观测结构图,展示稳定前缀复用、动态请求处理和 cached_tokens 记录之间的关系;这是静态说明图,不是运行截图。

命中率下降时按四项清单排查

我通常按“内容、结构、路由、生命周期”四个方向排查,而不是立刻调大缓存参数。

  • 内容:比较系统提示、工具 schema、参考资料和版本标记是否真的没变。
  • 结构:确认动态 user 内容没有被插入稳定 developer 内容内部,消息顺序也没有漂移。
  • 路由:较早模型可用稳定的 prompt_cache_key 做一致分组,但它只影响路由,不保证命中。
  • 生命周期:结合缓存保留时间、请求间隔和 cached_tokens 判断是过期还是前缀变化。

缓存输入仍然会计入速率限制,命中也不代表输出完全相同。最终应把前缀版本、缓存读取量、首 token 延迟和输入成本一起记录,才知道拆分是否真的改善了线上请求。

常见问题

只设置 prompt_cache_key 就能保证命中吗?

不能。它主要帮助相关请求保持一致的路由或分开统计,真正命中仍要求可复用前缀匹配。

动态内容放在 user 消息里就一定安全了吗?

这是更稳妥的默认布局,但模型、工具、历史消息等前置结构仍要保持一致,不能只检查 user 字段。

cached_tokens 为零应该先改哪个地方?

先记录并比较完整渲染前缀,优先查工具定义、版本字段、时间戳和消息顺序,再考虑路由与缓存生命周期。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>