自己搭企业内部中转站,怎么让请求更容易命中缓存

自己搭企业内部中转站,怎么让请求更容易命中缓存

前言

公司自建中转站之后,账单并没有降下来。我一开始以为是模型选贵了,拉 usage 一看,cache_read_input_tokens 几乎是 0。

缓存不是「开了就有」。它按前缀精确匹配,中转站每转发一次就顺手改一点,前缀就变了,缓存永远打不中。钱照付,延迟也没省。

这篇讲三件事:缓存到底按什么命中、中转站哪些动作会破坏它、以及怎么设计才能把命中率提上来。


一、先分清三种缓存

「缓存」这个词在中转站里经常被混着用,其实是三件不同的事:

  • 上游 prompt cache:模型厂商提供的缓存,命中的输入 token 打折,省的是真金白银;
  • 中转站自己的 response cache:同样的请求直接返回上次的结果,省的是整次调用;
  • 应用层 cache:工具结果、检索结果、用户会话,和模型无关。

这篇文章主要讲第一种。它是成本大头,也最容易被中转站破坏。


二、缓存按什么命中

不管哪家厂商,核心规则都差不多:从请求的第一个 token 开始,逐 token 匹配,连续一致的部分才算命中。

几个关键点:

  • 缓存的是前缀,不是整段请求。前缀里任何一个字符变了,从变化点往后全部失效。
  • 有最小 token 门槛。前缀太短,厂商根本不给你缓存,具体数值看模型文档。
  • 有 TTL。Anthropic 默认几分钟,可以延长;OpenAI 是自动前缀缓存,也有一段时间的保留窗口。会话闲置太久,缓存就没了。
  • 断点位置决定命中范围。Anthropic 用 cache_control 显式打断点,最多几个;OpenAI 是自动的,按前缀块递增。

所以「命中率低」通常不是厂商的问题,是请求本身每次都长得不一样。


三、中转站最容易破坏缓存的七个动作

第一,在 system prompt 最前面注入动态信息。

text 复制代码
当前时间:2026-11-02 21:37:12
请求 ID:req_8f2a...
用户:张三

这些内容每次都不一样,放在最前面,等于把整段前缀废掉。

坏的做法:

text 复制代码
system: 你是专业助手。当前时间 2026-11-02 21:37:12,请求 ID req_8f2a,用户张三。

好的做法:

text 复制代码
system: 你是专业助手。
metadata: {"time": "2026-11-02 21:37:12", "request_id": "req_8f2a", "user": "张三"}

时间、用户、trace id 这些中转站需要,模型不一定需要。真要给模型,就放在消息末尾或者单独一条 user 消息里,不要放 system 开头。

第二,每次重新拼 messages。

有的中转站会做「消息裁剪」「补 system」「合并连续消息」,本意是省 token,实际把前缀改了。裁剪本身没问题,但要从尾部裁,不要动前面的稳定部分。

第三,工具列表顺序不稳定。

工具定义通常放在请求前部,顺序一变,前缀就变。用 HashMap、Set 遍历生成 tools,每次顺序可能不同,缓存必然打不中。生成前按名字排序,固定下来。

第四,把检索结果放在最前面。

RAG 场景很常见:系统提示、检索到的文档、用户问题。如果每次检索结果都插在 system 后面,前缀每次都不一样。稳定的放前面,检索结果放后面,或者单独放一条消息。

第五,轮询或最少连接路由。

同一个会话的请求被轮到不同渠道、不同区域、不同账号,缓存大概率不共享。尤其是多区域部署,缓存是跟着区域走的。

第六,模型别名映射到不同版本。

对外叫 claude-opus,背后今天映射到 A 版本、明天映射到 B 版本,或者同名多渠道随机切,缓存都会断。要做故障切换可以,但同一会话尽量粘住同一个上游。

第七,中转站自己加「优化」提示词。

有些网关会统一注入一段「你是专业助手」之类的系统提示,或者做 prompt 改写。只要这段内容每次不同,或者位置在稳定前缀里,缓存就废了。要注入就注入固定内容,并且接受它成为前缀的一部分。


四、缓存友好的中转站怎么设计

能透传就透传。 中转站的第一原则是少改。请求体原样转发,别做「聪明」的重写。确实要改,也改尾部,不动前缀。

稳定前缀。 把不变的东西按顺序放前面:tools、system、few-shot 示例;把动态内容放后面:用户输入、检索结果、时间、会话状态。断点打在稳定前缀的末尾。

保留 cache_control。 客户端标的断点要原样透传,别在中转站里丢掉或者重排。支持多断点的厂商,断点数量也有限制,别超。

会话粘性路由。 用 session id 或 conversation id 做哈希,同一个会话固定走同一个渠道、同一个 key、同一个区域。渠道挂了再切,切过去接受一次 miss。

java 复制代码
public Channel pick(String sessionId, List<Channel> channels) {
    int idx = Math.floorMod(sessionId.hashCode(), channels.size());
    return channels.get(idx);
}

渠道扩容时,普通取模会让大量会话重新分布,缓存成片失效。渠道数量会变的话,用一致性哈希,只迁移一小部分会话。

缓存感知的负载均衡。 如果必须做多渠道路由,优先选「这个会话最近用过、缓存还热」的渠道,而不是简单轮询或最少连接。可用性优先,缓存其次。

模型映射要稳定。 对外别名背后的真实模型、区域、版本,在一个会话周期内不要变。要升级就整体切,别让同一个会话一半走旧版一半走新版。

工具 schema 固定。 工具名、描述、参数顺序都固定。描述里不要放时间戳、请求 ID、动态数据。工具版本升级时,接受一次缓存失效,但别每次请求都变。

动态信息放 header 或 metadata。 租户、用户、trace id、权限范围,这些中转站需要,但模型不一定需要。需要就放请求末尾,不需要就别塞进 prompt。


五、中转站自己的 response cache 怎么做

prompt cache 省的是输入 token,response cache 省的是整次调用。两件事不冲突,可以一起做。

response cache 的 key 至少要包含:模型、完整的 messages、tools、temperature、max_tokens、租户。少一个,就可能把 A 租户的答案返回给 B 租户。

几条边界:

  • 个性化数据不要缓存。 用户画像、权限过滤后的数据、订单详情,缓存了就是越权风险。
  • temperature 大于 0 的请求慎用。 同样的输入本来就不保证同样的输出,缓存等于把随机性去掉,业务能不能接受要评估。
  • 语义缓存只用在低风险场景。 FAQ、产品说明、公开文档可以;涉及金额、权限、实时状态的不行。阈值要保守,宁可多打一次模型。
  • TTL 要短。 尤其是业务数据,宁可失效快一点,也不要返回过期结果。
  • 流式响应也能缓存。 先把完整结果缓存下来,再从缓存里按流式返回,首 token 延迟反而更低。

六、怎么度量

先看厂商返回的 usage 字段:

  • Anthropic:cache_creation_input_tokens、cache_read_input_tokens;
  • OpenAI:prompt_tokens_details.cached_tokens。

命中率可以简单算成:

text 复制代码
cache_read / (cache_read + cache_creation + 未缓存的 input)

然后按渠道、模型、租户、会话类型拆开看。整体命中率 60%,可能是少数几个高频场景撑起来的,长尾场景全是 0。

再做一次 A/B:同一批请求,一组走当前中转站,一组走直连或不做改写的透传,对比成本和延迟。差距就是中转站改写带来的损耗。


七、一份检查清单

  1. system prompt 开头有没有时间、请求 ID、用户名;
  2. tools 顺序是否固定,描述里有没有动态内容;
  3. 检索结果、用户上下文是不是放在前缀里;
  4. cache_control 有没有被中转站丢掉或重排;
  5. 同一会话是否粘在同一个渠道、key、区域;
  6. 模型别名背后的真实版本是否稳定;
  7. 中转站有没有偷偷注入或改写 prompt;
  8. response cache 的 key 是否包含租户和权限;
  9. TTL 是否符合业务的数据新鲜度要求;
  10. 有没有按渠道、模型、租户看命中率。

这十条里,前四条造成的浪费最大。很多时候不用改架构,只是把动态内容从前面挪到后面,命中率就能从个位数回到一半以上。


参考资料

相关推荐
特立独行的猫A18 分钟前
Ionic + 仓颉语言的 cj-tauri 开发框架实战:开发精美移动端 APP
java·后端·python
张然Adolf23 分钟前
人工智能电力系统应用新手实战指南
人工智能
高洁0132 分钟前
数据同化与动态状态估计:让孪生持续贴合现实
人工智能·python·深度学习·transformer·迁移学习
feasibility.33 分钟前
一物降一物?AI逆向没有终局:REA拆App,BLA设套,LASIK清场
人工智能·爬虫·github·逆向·skill·rea
SomeOtherTime1 小时前
Rust集合(AI回答)
开发语言·后端·rust
IT古董1 小时前
AI 资讯日报 | 2026年10月25日:Kimi K3.1 Pro开源逼近前沿,OpenAI改离线训练,Claude合并Cowork,神经网络黑箱获新解,具身智能竞技场落幕
人工智能·神经网络·开源
小虎AI生活1 小时前
WorkBuddy + Loomy 实操教程:装开源技能反推任意图片提示词(附完整流程与提示词包)
人工智能·超级个体·一人公司·青玥ai
我不会起名字3221 小时前
req.Seqs[len-1]:空切片防御缺口与 RPC 二次校验
后端·mongodb·go·即时通讯·im·故障排查
Rattenking1 小时前
OpenCV 轨迹栏操作和键盘响应操作
人工智能·opencv·计算机外设