浅谈RAG前的语义缓存层(3) —— 语义相似不是业务等价
在上一节里,我们介绍了现在的语义缓存层是怎么做的。它的逻辑很简单:
- 把用户的问题转成向量
- 在向量数据库里匹配最接近的问题
- 最相似的问题相似度是否 >=0.9 ?
- 如果是,就直接返回这个问题的答案
- 否则走完整个RAG流程
博主的配置如下:
| 项 | 配置 | 备注 | 成本 |
|---|---|---|---|
| 向量数据库 | milvus-lite | 本地部署 | 免费 |
| 向量化模型 | text-embedding-3-small | api调用 | 0.02$ / M tokens |
因为对手上QA的质量非常有信心,我的阈值设得很大胆,直接调到了0.85。
如果缓存命中,不需要调用大语言模型,不需要文档检索,也不需要AI对着又臭又长的召回文档思考半分钟总结出答案。整个过程3秒钟搞定,api调用成本低到我想一直点击发送按钮烧钱。
重新评测
然而拉回去评测的结果并不是很好,我把加了缓存层之后的模型重新放回我的评测集里面跑,出现的一些问题甚至想让我马上把刚刚写的代码都删掉。
1. 高度相似的问题有可能并不等价
我的知识库里有这样一个QA:
一个模组大概会对应多少个采集点?
很不巧的是评测集里有一条很接近的真实提问:
六个模组一共对应多少个采集点?
这两条问题的相似度高达0.87,评测集的问题直接命中我的缓存层,然后我的智能体在3秒钟之内返回了一个完全错误的答案。
博主之前也是搞过NLP的,这个问题非常非常似曾相识。向量的相似性在识别语义上的相近性上表现非常不错,但是对于细微的变化并不敏感,举例来说:
- 一套系统 vs 六套系统
- 生产环境 vs 测试环境
- 单节点部署 vs 集群部署
这些差异会彻底改变问题含义,但是这些用词的改变可能无法造成语义向量的大幅改动。
我的业务场景显然需要确保逻辑上准确无误,但是相似向量匹配这种做法可能还不够好。
2. 最权威的知识无法被模型利用
和腾讯元器不同的是,在我的业务场景中,QA并不是从文档里生成的,而是由真正设计和维护这个系统的开发人员对用户的真实回答。很多答案非常简洁扼要,并且高度浓缩,只通过文档很难推导出来。
我现在的设计对于这些最权威的知识是怎么运用的呢?
- 如果缓存命中,就直接返回;
- 如果缓存没命中,就直接忽略所有QA知识,直接去找文档;
换而言之,下游的RAG流程完全失去了这一部分知识。我在很多的问题里都观察到了这点,添加了缓存层之后,deepseek由于看不到这些答案,回答反而比之前把QA一股脑丢到markdown里更差。大模型完整阅读设计文档和代码片段,深度思考了半分钟(有时候甚至会想一分钟以上),然后给出一堆很长、看起来很对、验证起来非常费劲的回答。相比之下,没有加入缓存层的回答虽然也很长,但是deepseek会把QA的信息放在前面,这些知识非常扼要,用户可以立即验证。
这个案例给出了一个很重要的启示:
QA不仅仅是缓存的答案,也是宝贵的知识来源
如果在其他流程里忽略掉QA的作用,后续的流程就失去了一块价值非常高的知识。
3. “想都不想”就答错比“深思熟虑”再答错糟糕得多
我花了很大功夫敲出来问题,然后看到模型在4秒钟答错我的问题的时候,心里想的是:
这个系统压根就没有认真理解我的问题,而是一通瞎蒙
我认为应该不会有用户认为“缓存命中率很高”。很有意思的是,如果模型花费了很多时间,但是依然答错,这个时候我会认真考虑这个问题对于AI来说是不是太难了;相反,如果它在很短的时间内就给了我一个错的离谱的答案,我会认为这个人工智障只是在瞎蒙。
这在用户体验上是非常致命的缺点。如果有一个新用户遇到了这种情况,毫无疑问他对于整个系统的态度将会瞬间从好奇转变到失望。在这种需要严谨回答业务问题的场景,一旦失去用户信任,响应延迟缩短多少都毫无意义。
总结
本节中我们总结了把模型拉回去评测之后的一系列结果,指出了简单的“语义缓存”存在的几个问题:
- 语义相似不等于业务等价;
- QA是高价值的知识来源,即使缓存未命中,也要想办法利用QA;
- 快速答错会严重损害用户体验;
到这里,语义缓存层就不仅仅是一个“缓存层”了。它是非常重要的知识来源,不能简单地当作传统缓存来处理。换而言之,我的这个“缓存层”应该贯穿整个知识检索链路,发挥更重要的作用。
为了解决以上的问题,我改进了原来的流程,设计了一套新架构,我们会在下一节中详细讨论。
浙公网安备 33010602011771号