缓存方案里最容易被忽略的一条线,是“这个请求可能出现过”与“我有权返回这个答案”之间的距离。布隆过滤器只适合做前一种判断。把命中当成答案命中,省下的模型调用可能换来错误响应,甚至把别人的答案返回给当前用户。
10 月 13 日 GitHub 介绍了用于密钥检测的小型分类器管线。我的关注点不是把它公布的降本比例照搬到客服系统,而是一个更朴素的选型原则:任务边界窄、评价信号明确时,专用组件可能比每次调用通用大模型更合适。GitHub 原文
Bloom 命中之后还缺什么
Redis 文档将布隆过滤器定义为概率型集合成员测试结构。它不保存业务答案,也不能替代精确键查询。工程上应把“可能存在”的结果送去查真实缓存;缓存不存在、失效或权限不匹配,就继续计算。Redis 文档
如果请求含订单号、用户身份或政策版本,精确键还必须包含这些影响答案的条件。只用一句自然语言做全局键,会让“我的订单发了吗”在不同用户之间碰撞。路由节省率要在隔离和答案正确的前提下测量。
用一个故意容易碰撞的小例子复现错误
下例用一位的过滤器,让所有输入都表现为“可能见过”,从而稳定触发假阳性。它不是可上线的 Bloom 实现,而是演示为什么后面不能省掉精确查询。全部逻辑只用 Python 标准库。
def maybe_seen(_key): return True # one-bit saturated filter: deliberate false positives cache = {("a", "policy-v1", "refund"): "7 days"} computed = [] def answer(tenant, version, question): key = (tenant, version, question) if maybe_seen(key) and key in cache: return cache[key] computed.append(key) return "compute" assert answer("a", "policy-v1", "refund") == "7 days" assert answer("b", "policy-v1", "refund") == "compute" assert len(computed) == 1 print("false-positive path recomputed safely")第二个断言很关键:过滤器说“可能见过”时,系统仍然计算了新答案。测试没有模拟向量召回、Redis服务或大模型,也没有测量吞吐和Token价格。
分流比例应该怎样算
我会分别统计精确命中、规则直接处理、小模型完成和大模型完成四类结果,并把失败后重试也计入成本。假设100个教学请求里40个精确命中、40个由低成本路径完成,20个走旗舰模型,只能说这组样本把80%的旗舰调用分流了;不能把80%全部归功于布隆过滤器。
| 误区 | 代价 | 修正方式 |
|---|---|---|
| Bloom阳性直接返回 | 缓存不存在时返回空值/旧值 | 精确查询兜底 |
| 跨租户共用键 | 回答越权 | 在可信上下文构建键 |
| 只报命中率 | 看不见错误答案 | 同时记录错误命中率 |
| 忽略重试 | 低估真实账单 | 按完成一次任务计费 |
布隆过滤器的价值是少做不必要的查询,不是让系统相信一个概率判断。产品上线前,我更想看到“误命中后仍正确”的测试,而不是一张没有样本定义的80%降本海报。