4 步 · 4 段可复制提示词 · 约 11 分钟读完
站内精选
核心结论

批处理脚本每天问同样的问题,账单却看不出哪次是重复的——因为多一个空格、换个标点、带个任务 ID,缓存就全部落空。做法是四步:先用三种口径量出重复率、再把缓存键分三层逐层放行、语义层只给抽取类任务用、最后加 TTL 与命中抽检。实测月 6,000 次调用命中率从 21% 提到 39%,账单降 34%。

一个批处理脚本每天跑,同样的问题反复问模型。账单上看不出哪次是重复的——因为每次请求长得都不一样:多一个空格、换个标点、前面带个随机任务 ID,缓存就全部落空。加了缓存但命中率只有个位数,多数人的第一反应是「缓存没用」,其实是键没设计对。

一句话结论

缓存的关键不是加个字典,是先定义「什么算同一个问题」。三层递进:原文精确匹配(最安全、命中率最低)、规范化后匹配(去掉不影响语义的差异)、语义匹配(最激进、有误命中风险)。实测一个月 6,000 次调用的批处理,原文匹配命中率 21%,加规范化后提到 39%,账单降 34%;语义层试着加过,误命中一次就撤回到白名单模式。

这篇解决什么问题

三种情况最常见。一是只按原文命中:写完发现命中率 5%,于是认定「我们的问题都不重复」,实际是同一问题有十几种写法。二是缓存键里混了噪声:请求里带任务 ID、时间戳、会话 token,这些每次都变,键就永远不相等——代码看起来完全正确,命中率恒为 0。三是语义缓存误命中:「A 产品的退款政策」和「B 产品的退款政策」相似度 0.94,被当成同一条,B 产品的用户拿到 A 的答案,这种错很难被日志发现。

根子是把缓存当成「省 token 的手段」,而它其实是「判断两次请求是否等价」的问题。等价关系定得越松,省得越多、错得越隐蔽。所以顺序必须是:先量重复率,再定等价规则,最后才谈省了多少钱。

开始前要准备什么

  • 至少一周的请求日志:完整提示词、模型、输入输出 token、时间。没有日志只能靠猜重复率。
  • 任务的确定性分级:哪些「同一问题应得同一答案」(抽取、分类、翻译),哪些「每次都该不一样」(头脑风暴、文案创作)。后者不进语义缓存。
  • 成本结构:输入与输出 token 的占比。输入占大头时缓存收益高。
  • 一条底线:每次命中都要记下「命中的是哪个原始请求」,否则误命中查不出来。

具体怎么做

第一步:先量重复率,别急着写缓存

量法是把一周日志里的提示词抽出来,做三种口径的去重统计——原文完全相同、去空白与标点后相同、人工判定的语义相同,三个数字的差距就是缓存天花板。实测 6,000 次调用里原文相同 1,260 次(21%),规范化后 2,340 次(39%),抽 200 条判语义重复 47%。

这三个数的差距决定做到哪一层:规范化能多拿 18 个百分点,语义只能再多 8 个,却要担误命中风险。

这是我一周的 API 请求日志(每条含完整提示词、模型、输入输出 token)。请做重复率分析,不要给缓存方案。

三件事:
1. 原文完全相同的请求有多少组、涉及多少次调用、占总调用次数的百分比;
2. 去掉首尾空白、合并连续空格、统一全半角标点后相同的,有多少组、多少次、占比;
3. 从日志里随机抽 50 条,找出「语义上是同一个问题」的组,报告组数和占比。抽样要有说明(按什么规则抽的,避免只抽到同一批任务的)。

另外回答:重复集中在哪几类任务上?请按任务类型分组给出重复率,我要知道缓存该优先加在哪条链路上。
不要建议技术选型,也不要估算省钱金额。

第二步:缓存键分三层,逐层放行

第一层用原文的哈希,零风险但命中少。第二层做无害规范化:去首尾空白、合并连续空格、全角转半角、去掉行尾标点差异、把同义的系统前缀抽出来单独存。第三层才是语义,且必须加白名单。

第三层之前要做一次噪声排查:剥掉每次都会变的部分(任务 ID、时间戳、trace_id、随机种子)。实测第一版把这些算进哈希,命中率恒为 0 且毫无异常——只能靠打印几次实际的键发现。

这是我的缓存键生成函数和 20 条真实请求样本。请帮我做两件事:

一、找出请求里「每次都会变、但与问题语义无关」的片段(任务 ID、时间戳、随机串、trace 头等),逐条列出它在样本里的出现形式;
二、给一份规范化规则清单,每条规则要写清:改什么、为什么它不影响语义、有没有反例(举一个「改了会出错」的情况)。

要求:
– 规则按风险从低到高排列,我要能一条一条往上加;
– 对每条规则,说明它大概能提升多少命中(可以按样本估算,标明是估算);
– 如果某条规则存在明显反例(比如大小写在某些任务里有意义),直接标「慎用」并说明条件。

第三步:语义层只给「抽取类」任务用,且要白名单

语义缓存的风险不对称:错一次的代价远大于对十次省的钱。所以只开在「同一问题答案唯一」的任务上——抽取字段、分类打标、格式转换、字段翻译;创作类与需要上下文的对话一律不开。

再加一道:命中时不直接返回,而是返回「疑似命中」让人确认,或只对相似度阈值的上沿自动返回。实测阈值设到 0.92 仍误命中一次(两个不同产品的同名政策),改成白名单加阈值双条件后没再出现。

我要给语义缓存设边界。这是我目前的 6 条任务链路(附任务说明和示例输入输出)。

请对每条链路回答:
1. 同一问题是否应该得到唯一答案?(是 / 否 / 视参数而定)
2. 如果误命中,最坏后果是什么?请具体到业务动作(不是「影响体验」这种话);
3. 建议:进语义缓存 / 只进精确缓存 / 不进缓存。

另外给我:
– 一个「语义命中但不应直接返回」的判断条件,要能写成代码里的 if;
– 三个最容易误命中的问题对(从我的示例里找,或者构造相似的),说明它们为什么相似但不等价。

第四步:加 TTL 和命中率报表,否则等于没加

缓存必须能失效,两类:时间失效(TTL:政策类 7 天、术语类 30 天)与版本失效(模板或模型一改,整批前缀作废)。少了后者,改了提示词结果没变,你会以为是模型的问题。

报表只盯三个数:命中率、按链路的命中分布、命中样本抽检结果。第三个最容易被省掉,却是发现误命中的唯一可靠办法。

给这个缓存加观测。三样东西:

一、报表字段设计:每次请求落一行,包含 请求哈希 / 规范化后哈希 / 语义命中标记 / 命中来源(哪个原始请求)/ 是否人工复核 / 复核结论。说明每个字段用来回答什么问题。
二、抽检机制:每天抽多少条命中样本、按什么规则抽(不能只抽同一链路)、发现误命中后的处理动作(撤单条 / 降阈值 / 关某链路)。
三、失效触发条件:列出必须让整批缓存作废的事件(提示词模板变更、模型版本变更、知识库更新等),并说明怎么自动检测到这些事件。

不要写监控平台选型,写规则和字段就够。

实测记录

素材是一个月 6,000 次调用的内容批处理,5 条链路(字段抽取、分类打标、摘要、术语翻译、文案生成)。量重复率 40 分钟,抽 50 条语义判重 35 分钟,结论 21% / 39% / 47%。

第二步设计缓存键 50 分钟。第一版直接把整个请求体做哈希,跑一天命中率 0——原因是请求体里带了任务 ID。剥掉噪声后命中率跳到 21%,加上空白与标点规范化到 34%,再把系统前缀单独抽出来做前缀缓存,到 39%。

第三步语义层花了 90 分钟,包括一次真的误命中:「A 产品退款政策」命中「B 产品退款政策」,相似度 0.94,用户拿到错误条款。这一条是抽检时发现的,日志里看不出异常。之后改成白名单(只允许字段抽取与分类打标进语义缓存)加阈值 0.95 双条件,跑了两周没再误命中。

第四步加 TTL 与报表 45 分钟。TTL 按链路分:政策类 7 天、术语类 30 天、抽取类 90 天。第四周看报表:整体命中率 39%,其中字段抽取 62%、分类打标 51%、摘要 33%、术语翻译 44%、文案生成 8%(本来就该低,创作类每次都要不一样)。账单下降 34%,比命中率 39% 低 5 个点,因为命中的多是短请求,长请求重复少。

全程约 4 小时 20 分钟,一半时间花在定规则和抽检上。收益大小取决于重复率,不是取决于缓存写得多好——规范化重复率低于 15%,这套东西不值得做。

最容易错的 3 个地方

第一,缓存键里混了每次都会变的字段。这是最隐蔽的错:代码完全正确,只是永远不命中。打印连续五次的键值对比,一眼看出哪一段在变,别靠读代码找。

第二,全局开语义缓存。语义匹配的收益上限只有 8 个百分点(47% 减 39%),但误命中的代价是一次错误交付,所以它只能开在「同一问题唯一答案」的链路上,且要配抽检。

第三,没有版本失效。改了提示词模板或换了模型版本,缓存里还是旧结果,你会以为改动没生效,可能反过来去改本来正确的提示词。事件触发的整批失效比 TTL 更重要。

可复用的东西

三口径测重复:原文相同、规范化后相同、语义相同。三个数的差距决定该做到哪一层。

三层缓存键:原文哈希(零风险)→ 无害规范化(去空白、全半角、去尾标点)→ 语义白名单(只限抽取与分类)。

噪声剥离清单:任务 ID、时间戳、trace 头、随机种子、会话 token。这些进键即命中率归零。

语义层双条件:任务白名单 + 相似度阈值上沿(实测 0.95),两个都满足才自动返回。

观测三数:命中率、按链路命中分布、命中样本抽检结论。第三个是发现误命中的唯一办法。

收益判断线:规范化重复率低于 15%,不值得做缓存。

常见问题解答

为什么加了缓存命中率还是接近零

八成是缓存键里混了每次都会变的字段:任务 ID、时间戳、trace 头、随机种子、会话 token。这类 bug 代码逻辑完全正确,只是键永远不相等,而且没有任何报错。这次第一版把整个请求体做哈希,跑一天命中率 0,剥掉任务 ID 后立刻跳到 21%。判断方法很简单:打印连续五次的键值对比,一眼看出哪一段在变,别靠读代码找。

语义缓存到底该不该开

要算收益与风险。这次三种口径测出来原文重复 21%、规范化后 39%、语义 47%,也就是说语义层最多再多 8 个百分点,但误命中的代价是一次错误交付。实测就误命中过一次:「A 产品退款政策」命中「B 产品退款政策」,相似度 0.94,这种错在日志里看不出来,是抽检才发现的。结论是只对「同一问题应有唯一答案」的链路开(字段抽取、分类打标),创作类一律不开。

什么样的请求不该进缓存

每次都应该不一样的。这次 5 条链路里文案生成命中率只有 8%,这是对的,不是缓存失效——创作类任务本来就该每次不同。另外还要防一类:需要结合上下文和会话历史的对话,它的正确性依赖前文,单独拿一轮问题去匹配会得到看似合理但错的答案。

缓存做好了怎么知道没出错

靠三个数:命中率、按链路的命中分布、命中样本抽检结论。第三个最重要也最容易被省掉——日志里误命中看起来和正常命中一模一样,只有人工抽 20 条看一眼才能发现。另外必须做版本失效:提示词模板改了、模型版本换了,整批缓存要作废,否则你会以为改动没生效,反过来去改本来正确的提示词。

小程序阅读免费
微信扫码进入小程序,按岗位找 AI 实操步骤
微信扫码进小程序
按岗位找 AI 实操步骤 · 提示词可收藏

发表回复

后才能评论