为RAG构建语义缓存

为RAG构建语义缓存

💡 原文英文,约4300词,阅读约需16分钟。
📝

内容提要

本文介绍为RAG流水线构建语义缓存:用Qdrant存储历史问题向量,命中则跳过知识库检索和LLM调用,节省时间与成本。相似度阈值需按用例校准,建议用金标集划分训练、验证、测试集调优。高阈值只能覆盖近似重复问题,可用Jev分类器处理灰色地带。缓存需设置过期时间,并在源文档变更时失效。

🔎

延伸解读

语义缓存适合什么场景

文章指出,语义缓存对问答类系统尤其有效,因为事实型查询重复度高,命中后能跳过知识库检索和LLM调用,节省时间和成本。但如果是需要多样化回复的文本生成任务,缓存会返回旧答案,可能限制变化,因此是否使用缓存取决于具体用例。

相似度阈值为何不能照搬

阈值决定什么算“足够接近”,它依赖嵌入模型和你的问题分布,所以不能直接复用其他系统的设置。文章建议用金标集划分训练、验证、测试集来校准,并提醒:若在n个应未命中的问题上零错误,95%置信下错误率仅能声称低于约3/n,例如15个问题对应20%,要声称1%则需约300个。

高阈值的局限与灰色地带

高阈值只能覆盖近似重复问题。文章举例:一个改写问题相似度仅0.68,而一个仅差一词但答案相反的问题相似度高达0.97,单一阈值无法同时正确处理。为此可引入Jev分类器在灰色地带二次判断,但需权衡成本:Jev调用约是RAG调用的三分之一成本、十分之一时间,只有灰色地带命中收益大于开销时才划算。

缓存过期与失效维护

缓存答案可能因时间或源文档变更而失效。文章建议设置过期时间(如7天),查询时跳过已过期条目,并定期删除以释放空间;当知识库文档更新时,先更新文档,再删除所有基于旧文档构建的缓存答案,使后续问题重新走RAG获取最新回答。

❓

Q&A

语义缓存和传统缓存有什么区别?

传统缓存基于精确匹配,而语义缓存搜索键的含义而非精确匹配。例如“What is the capital of Brazil?”和“Can you tell me the capital of Brazil?”语义等价,语义缓存能识别出来。当大量用户重复相同问题时,系统可从缓存中取回已生成的答案,而不必重新执行整个流程。

语义缓存命中后能节省什么?

缓存命中会跳过主要的知识库检索和LLM调用,从而节省时间和成本。命中时仍要支付问题嵌入的费用,但只是很小的一部分;如果加上可选的Jev检查,还会增加其成本。

如何为语义缓存确定相似度阈值?

需要为你的数据准备一个金标集:把传入问题标注为缓存是否应回答。可按查询日志构建,或让LLM生成问题。把金标集按缓存问题划分为训练、验证、测试三部分,确保同一问题的改写不会落在不同部分。在训练集上对每个候选阈值统计正确命中和错误命中,决定可接受多少错误命中;在验证集上检查,若出现错误命中则重新在训练+验证集上选择;最后在测试集上测量一次,之后不再更改。不要复用其他设置的阈值,它取决于嵌入模型和你的问题。

高阈值下语义缓存能覆盖哪些问题?

在零错误命中的高阈值下,缓存只能处理精确重复和部分轻度改写。释义类问题可能得分很低,而仅一词之差但含义完全相反的问题可能得分很高,单一阈值无法同时处理这两类情况。

Jev分类器在语义缓存中起什么作用?

Jev是TypeSafe的模型,用概率而非生成文本回答问题。保留“确定”阈值,在其下方增加灰色地带,把两个问题交给Jev,询问“缓存的答案能否完整正确地回答新问题”,返回“是”的概率。若概率达到分类器阈值则提供缓存答案,否则走RAG。灰色地带下界取所有应命中问题对其自身缓存问题得分的最低值向下取整;分类器阈值用与余弦阈值相同的扫描在灰色地带问题上选取,取零错误命中区间的中间值。Jev通过OpenRouter调用,模型版本固定为typesafe/jev-1.13-20260917。

缓存答案什么时候需要失效?

当缓存答案变旧或背后的文档发生变化时需要失效。查找时已跳过超过expires_at的答案,可定期删除以释放空间。文档变更时,先更新知识库中的文档,再删除所有由旧版本构建的缓存答案,这样下一个相关问题会缓存未命中并从RAG获得新答案。

🏷️

标签

➡️

继续阅读