我运行了一个多代理系统:十个代理分析同一份输入。相同的文档、相同的市场数据、其他一切都相同。唯一的区别是角色设定——每个代理被要求以不同视角审视这些材料。

十个代理,共享一份上下文。这本该是提示缓存的理想场景:昂贵上下文只发送一次,付一次全价,其余九次读取只需支付一小部分费用。

然而事实是:我使用的五个模型中,有三个缓存命中率为零,另外两个也低于百分之七。

我盯着账单研究了很久,一直以为是自己哪里配置错了,结果真正的问题出在结构上。我相信我不是唯一犯这个错的人。

提示缓存的匹配机制到底是什么?托管推理服务商缓存的是“前缀”。提供商从第一个token开始对你的请求做哈希,寻找已经计算过的最长连续片段。如果你的请求开头与最近某个请求的前3000个token相同,那么这3000个token就是缓存读取,通常比全新计算便宜约五倍。一旦token流出现分歧,后续部分就不再缓存,之后也不会重新同步。

关键在于“前缀”这个词——我之前恰恰没有仔细想过它的含义。

我的调用代码长得和所有示例一样:

messages = [{"role": "system", "content": agent_persona}, {"role": "user", "content": shared_context}]

persona很短,只有几百个token,描述这个特定代理应该怎么推理。而共享上下文很大,是几千个token的源材料。

按提供商的处理方式,把这个消息数组当作扁平的token流来看:流中的第一个东西就是persona。每个代理的persona都不同。所以从前缀开始,在大约第一个token处就分道扬镳了。位于其后的几千个相同上下文,永远无法进入缓存。

这个错误是结构性的。如果你也在多代理场景中把所有persona放在共享内容前面,你的缓存命中率也可能和我一样是零。修正方法很简单:让共享上下文成为请求的前缀,把persona放到它后面,或者用其他方式让相同内容对齐到开头。