语音智能体(voice agent)的开发者们,先问自己一个问题:你知道自己第一轮对话(turn 1)的提示词缓存命中率(prompt cache hit rate)是多少吗?

不是整通电话的平均值,而是当来电者说完“你好”后,正安静等待你的智能体回应时,那第一轮的数据。我们曾以为自己的数据还不错——每次通话前都按惯例做预热(pre-warming),直到真正精确测量后才发现,外呼电话的表现竟然不到内呼电话的一半。同样的代码、同样的服务商、同样的提示词模板,差距却如此悬殊。

打开网易新闻 查看精彩图片

这背后到底发生了什么?

缓存机制的基本条件

当你发送提示词时,服务商会将其处理成内部表示(即KV缓存)。前缀缓存(prefix caching)会将其保留几分钟。如果你的下一个请求以完全相同的文本开头,服务商就会跳过重复处理的部分,只处理新增内容。各大服务商现在都这么做,数字也大致相同。

语音智能体来说,这几乎等于白捡的收益:系统提示词、工具和护栏在每通电话的每一轮都相同,且占据了大部分token。成本节省固然不错,但延迟节省同样重要——当有人拿着电话等待时,你能从首token时间(time to first token)中砍掉数百毫秒。

缓存是自动的,但并非无条件。三个条件必须同时满足:

  • 前缀必须完全匹配——不是“基本匹配”,也不是“语义匹配”,而是从第一个token开始逐字节一致。哪怕一个字符不同,匹配就会在此处中断。
  • 长度必须足够——低于最小值(通常是1,024个token),你将什么都得不到缓存,连部分命中都没有,是彻底的零。
  • 必须落在同一台机器上——缓存只存在于一台服务器的内存中。服务商根据提示词开头的哈希值来路由,但在高负载下会分散流量。一旦落到新机器上,无论你的提示词多干净,缓存都是冷的。

第一条规则是悄悄扼杀命中率的元凶——我们恰恰就栽在了这里。

预热只优化了单通电话

语音智能体的标准技巧是预热:在通话接通前,发送一个带有相同系统提示词的临时请求,让服务商缓存它。这样当来电者说“你好”时,第一轮就有东西可复用,后续轮次也能在此基础上叠加。我们也这么做,确实有效。

但看看它实际优化了什么:一通电话。第二轮复用了同一通电话的第一轮。没人讨论另一半——跨通话复用缓存,而我们的数据正是在这里流失的。

我们开始正确追踪缓存命中率:每通电话的缓存token数除以提示词总token数。整体命中率约为40%,而大约三分之一的合格通话完全没有获得缓存,尽管我们的提示词长达数千token。

问题出在跨通话的缓存复用上。预热解决的是单通电话内部的连续性,却无法保证不同通话之间能共享同一台机器的缓存。当外呼电话的流量被分散到不同服务器时,即使提示词完全相同,缓存也形同虚设。

跨通话复用才是真正的战场

找到症结后,我们开始调整策略。核心思路是让所有通话尽可能落在同一台机器上,或者至少让同一批通话共享同一份缓存。这需要重新审视请求的路由逻辑,以及提示词开头的设计——因为服务商正是根据这部分内容来决定将请求发送到哪台服务器。

经过一系列调整,我们的缓存命中率终于有了显著提升。但这个过程让我们意识到:大多数开发者只关注了预热这个“标准答案”,却忽略了跨通话复用这个更隐蔽的优化空间。在语音智能体场景下,每一通电话都是独立的会话,但它们的系统提示词却完全相同——这本身就是巨大的缓存潜力,只是很少有人真正去挖掘它。

如果你也在运行语音智能体,不妨检查一下自己的跨通话缓存命中率。也许你的问题不在预热,而在更深的层面。