「同样的五十个表情包,每小时都在审核队列里出现;同样的'重置密码'请求,每天从一千个聊天窗口涌进来。」一位工程师这样描述他遇到的困境——每次调用都付费,每次返回的都是一小时前相同的答案。
这不是提示词缓存(prompt caching)能解决的问题。提示词缓存只削减输入成本,模型仍在运行,输出 tokens 照样计费。响应缓存才是那个更便宜的替代方案:把整个请求哈希,命中时直接从 Redis 返回存储结果,零 tokens、零模型延迟。
代价是苛刻的——请求必须完全一致。这个限制排除了大量大语言模型工作负载,但剩下的那些,正是本文要讨论的场景。
命中条件:什么样的请求能被缓存
响应缓存只在两种条件同时满足时生效。输入分布必须重尾——你能画出分布图并指出那个肥大的头部;输出对于给定输入必须是确定性的。
内容审核分类器是典型场景。五十个 trending 表情包每小时重复出现,模型每次给出相同的违规判定。客服意图识别同理,"密码重置"的语义向量高度集中。CI 评估套件每次有人修改配置文件,都重跑同一批提示词集合。
这些场景的共同特征:高频重复输入、期望输出稳定不变。如果无法指着输入分布图说"这里有一大块重复",缓存不会省钱。
反例同样明确。多轮对话的上下文窗口持续变化,用户查询长尾分散,创意写作要求每次输出不同——这些场景缓存命中率趋近于零,不值得部署。
哈希构建:决定生死的字段选择
缓存键的构造是系统中最关键的函数。每个纳入的字段都是承诺:共享这些值的请求将产生相同响应。每个排除的字段都是赌注:它不影响输出。
必须包含的字段:模型名称、完整提示词、工具集定义、采样参数。模型版本迭代会改变行为,提示词的任何字符差异都可能导致不同输出,工具集的可用函数列表直接影响模型决策,temperature 和 seed 决定随机性。
必须排除的字段:用户标识、会话标识、时间戳、请求元数据。把这些放进键,命中率直接归零——每个用户的每次请求都变成唯一键。
确定性规则同样严格:仅当 temperature=0 时缓存,理想情况下固定 seed。在 temperature=0.7 时缓存,会永久存储众多有效答案中的一个。用户两次看到相同的"创意"回复,创意感瞬间消失。
Redis 实现:双 TTL 与防击穿
技术选型很直接:Redis 做存储,SHA-256 做哈希,SETNX 防缓存击穿。
缓存击穿场景真实存在:十个并行工作线程同时未命中同一键,全部调用模型。SETNX 确保只有一个获胜者执行模型调用,其余等待结果。
两个 TTL 需要分别调优。结果存活 24 小时,锁存活 30 秒——仅覆盖最坏情况下的模型调用时长。根据实际工作负载调整这两个数值。
键构造函数使用稳定 JSON,键名排序,包含所有影响响应的字段。这是整个系统的承重结构。
成本边界:什么时候该用,什么时候不该
响应缓存不是银弹。它的价值高度依赖输入分布形态——重尾分布的肥大头部越大,节省越显著。80/20 法则在这里 literal 成立:20% 的输入可能贡献 80% 的调用量。
但部署成本不容忽视。Redis 集群、哈希计算开销、缓存一致性维护,这些在小型工作负载上可能超过模型调用节省。只有当调用量跨越某个阈值,响应缓存才从成本中心转为利润中心。
更隐蔽的风险是语义漂移。模型提供商静默更新权重,相同提示词的输出缓慢变化。缓存机制对此无感知,持续返回旧版本答案。需要监控机制检测输出分布偏移,或设置保守的 TTL 强制刷新。
另一个陷阱是工具执行副作用。如果模型调用触发外部 API(发送邮件、创建工单),缓存会跳过这些副作用,导致业务逻辑断裂。纯文本生成场景才安全。
工程权衡:确定性承诺与用户体验
temperature=0 的要求看似技术细节,实则是产品决策。它强制所有缓存命中返回完全相同的内容,牺牲了模型固有的输出多样性。
对于内容审核,这是特性而非缺陷——一致性正是监管要求。对于客服场景,用户可能察觉机械重复,需要权衡成本节省与体验损失。
种子固定进一步收紧约束。即使 temperature=0,不同 seed 仍可能产生不同输出(取决于模型实现)。完整确定性需要同时锁定两者。
这种严格性指向一个深层事实:响应缓存本质上是把概率模型当确定性函数使用。它只在特定业务场景下成立,那些场景的共同点是"正确答案"的客观存在性——违规与否、意图分类、测试断言通过与否。
创意生成、开放式问答、个性化推荐——这些依赖模型内在随机性的场景,被天然排除在响应缓存的适用范围之外。这不是技术限制,是产品定义的分野。
输入分布的可视化能力因此成为前置条件。在部署前,你需要能够绘制历史请求的直方图,识别出那个可缓存的头部。没有数据支撑,缓存策略就是盲飞。
哈希字段的取舍同样需要数据验证。排除某个字段前,需要抽样证明该字段的变异确实不影响输出。这种验证在快速迭代的业务中难以持续,导致缓存键逐渐膨胀,命中率衰减。
Redis 的运维复杂度常被低估。缓存失效策略、内存压力下的逐出、跨可用区延迟——这些在大规模部署中成为主要工程负担。云托管服务简化部分问题,但成本结构改变决策算术。
SETNX 的锁竞争是另一个隐藏成本点。高并发未命中场景下,等待线程的轮询间隔和超时设置需要精细调优。过短导致重复调用,过长拖尾延迟。
代码实现中的细节同样关键。JSON 键名排序确保哈希稳定,浮点数的序列化精度影响键匹配,Unicode 规范化避免编码陷阱。这些边缘情况在生产环境中逐个暴露。
监控体系需要覆盖缓存层本身。命中率、未命中原因分类(新键 vs 键变异)、Redis 延迟百分位、锁等待时长——这些指标比模型调用成本更直接反映系统健康。
与提示词缓存的对比值得展开。提示词缓存适合长前缀共享场景,如 RAG 系统中相同的文档块前缀接不同查询。响应缓存适合短请求高重复场景。两者可以叠加,但收益计算需要避免重复计数。
模型提供商的定价结构影响策略选择。输入输出价格比例、缓存折扣力度、批量调用优惠——这些商业条款改变自建缓存的经济性。需要持续重新评估。
长期看,响应缓存可能是过渡性技术。模型推理成本持续下降,专用硬件普及,边缘部署降低延迟——这些趋势压缩缓存的价值空间。但在当前成本结构下,对于符合特征的工作负载,它仍是立竿见影的优化手段。
识别适合缓存的场景,比实现缓存本身更有价值。这要求工程师深入理解业务输入分布,而非套用通用架构模式。数据驱动的缓存决策,是成本优化的核心能力。
最终,响应缓存是一个关于约束的故事:严格的确定性要求、苛刻的输入一致性、有限的适用场景。在这些约束内,它提供近乎免费的重复查询服务。突破约束,系统失效。这种清晰的边界,反而让它成为可依赖的工具。
热门跟贴