上下文缓存没省钱?先把重复前缀和命中Token对齐

|作者: QUASA 编辑团队|2 分钟阅读| 1
上下文缓存没省钱?先把重复前缀和命中Token对齐

提高千问与 Gemini 隐式上下文缓存的命中率,先确认所用模型支持缓存,再让相关请求共享足够长且顺序一致的开头:固定规则和公共资料,把每轮变化的问题放在后面。尽量让围绕同一份资料的调用相隔较短时间,最后读取响应中的命中 Token。功能默认开启,只表示请求有机会使用缓存;命中量和实际费用仍需核对。

排查时保存实际发出的请求体、模型名称、接口类型和完整用量字段。比较请求要从开头逐项进行,找到最早发生变化的位置;两次输入的总 Token 数相近,并不能说明它们有足够长的公共前缀。以下流程针对自动匹配前缀的隐式缓存,涉及手动创建缓存的配置应按对应模式另行计算。

先分清最低门槛指的是什么

百炼的千问缓存说明指出:对百炼部署、支持隐式缓存的模型,两次请求须有不少于 1024 Token 的相同前缀,才具备写入和命中的技术条件;OpenAI 兼容接口的实际命中量可从 usage.prompt_tokens_details.cached_tokens 读取。达到门槛仍可能因为缓存尚未生成、已被清理或系统调度而未命中。因此,先检查模型和部署范围是否支持,再量从请求开头连续相同的内容,不要拿整段输入的长度代替公共前缀长度。

Gemini API 的缓存说明列出的是模型最低输入量:Gemini 2.5 Flash 和 Gemini 2.5 Pro 为 2048 Token,Gemini 3.5 Flash 为 4096 Token;其 Interactions API 可从 usage.total_cached_tokens 查看命中量。Gemini 2.5 及更新型号默认启用隐式缓存,官方建议把较大且重复的内容放在提示词开头,并在短时间内发送前缀相似的请求。这里的最低输入量与千问所要求的相同前缀长度并非同一种指标,不能直接互换。

门槛排查还要使用实际请求的 Token 统计,而不是按字数或字符数估算。模板里的一段固定资料即使很长,若最终请求在它之前插入了动态内容,可供匹配的开头仍可能很短。不同模型及接口的缓存能力、用量字段也可能不同,迁移调用代码时应连同模型标识和响应结构一起核对。

把稳定内容排在变量之前

前缀匹配从请求开头延伸到首次差异处。适合复用的系统规则、固定参考资料和稳定的输出要求,应尽量先出现;当前问题、临时检索结果和不断变化的会话信息则放在其后。调整顺序仍须保留提示词原有的业务含义,不能为了增加缓存而颠倒有依赖关系的指令。

假设两次请求都根据同一本参考书回答问题。排列为“固定规则→同一份参考书→问题甲或问题乙”时,变化发生在公共资料之后;若排列为“问题甲或问题乙→固定规则→同一份参考书”,请求从问题处就分叉,后面的参考书不能成为两次请求连续相同的开头。这是说明匹配机制的条件示例,实际复用范围仍以服务端返回的命中量为准。

定位差异时,应比较最终发送的数据,而非只看代码中的提示词模板。公共资料前的日期、随机标识、重新排序的检索片段,都会改变开头;即使文字相同,消息角色、内容块排列或附件位置变化,也值得逐项检查。对于多轮对话,稳定的系统指令和既有历史可保持原顺序,把新一轮消息追加在末尾;每轮重写前面的摘要,则会使请求更早分叉。

工具定义、材料顺序和调用间隔

含工具调用的请求还应固定工具定义。建议检查 tools 数组的工具顺序、各工具字段的排列和结构,以及请求序列化后的实际内容;仅比较可见的系统提示词,可能漏掉开头已经发生的变化。若工具集合必须随任务改变,可以把这类请求单独观察,不宜把它们与工具定义稳定的请求混在一起计算命中表现。

重复使用多模态材料时,同样要判断哪部分真正保持不变。反复就同一图像或视频提不同问题,可以让材料出现在变化的问题之前;若材料每次不同而问题文字固定,则把固定文字放在前面更符合前缀匹配的方向。后一种排列只能争取复用相同的文字部分,不能使不同图像或视频变成相同输入。

调用间隔影响隐式缓存能否被再次读到。围绕同一份长资料的一批问题,适合在业务允许的范围内较快发送;间隔很久的零散请求,即使前缀完全一致,也不能预设缓存仍在。首个请求通常只是让系统有机会留下可复用内容,后续请求是否命中要看响应。为追求缓存而额外发起无业务需要的请求,还会增加输入和输出用量,不能直接算作节省。

用响应字段判断命中,再核算费用

用量字段必须与调用接口对应。千问经百炼 OpenAI 兼容接口返回的缓存数包含在输入 Token 中;Gemini Interactions API 使用另一套 usage 字段。若调用的是 Gemini generateContent,Google 的 Token 用量说明将缓存数量列在 response.usage_metadata.cached_content_token_count,同时分别列出输入和输出用量。排障脚本先识别接口,再取相应字段,避免把字段不存在误判成没有命中。

命中数为零时,按模型支持情况、最低门槛、最早变化的位置和请求间隔排查。命中数大于零,说明至少部分输入得到复用;还应计算它占总输入的比例。如果公共资料只占请求的一小段,或者变化内容先于资料出现,缓存功能工作正常也未必能显著降低整次调用的费用。

费用判断要把未命中的输入、命中的输入和输出分别记录,再按实际模型、部署范围及计费方式计算。缓存折扣作用于符合条件的输入部分,输出仍会产生费用;模型、请求次数或输出长度同时变化时,直接比较两张总账单,无法单独归因于提示词顺序的调整。若采用显式缓存,还需计入创建和保存缓存的成本,不能沿用隐式缓存的账法。

用同一组请求定位配置问题

  1. 选定同一模型、部署范围和接口,准备符合该模型门槛的固定资料。保存首个请求的完整请求体和用量响应,在末尾放入一个实际业务问题。
  2. 首个请求完成后,保持前面的规则、资料及工具定义不变,只替换末尾问题。保存第二次请求与响应,并记录两次调用的时间间隔。
  3. 读取第二次请求对应的缓存命中字段。若为零,从请求体第一项开始比较,找出最早变化的位置;若大于零,再与总输入量对照,确认复用了多大一段。
  4. 将有效的排列放回真实调用链,按实际请求间隔和用量核算费用。受控请求可帮助定位前缀与字段问题,真实流量的命中量才反映这种调整能节省多少。

相关阅读:

分享:

订阅我们的新闻通讯

将最新 Web3、AI 和加密货币新闻直接发送到您的邮箱。

0