RAG召回准确率从75到90 我做对了这三件事

0 评论 141 浏览 0 收藏 10 分钟

当AI客服频繁答非所问时,问题往往不在大模型本身,而是RAG召回机制的短板。本文揭秘如何通过分层索引、混合检索和差异化策略三重优化,将召回准确率从75%提升至90%,并分享从Embedding模型选择到文档分块的血泪教训,为AI产品落地提供实战解决方案。

「AI 怎么又答非所问了?」

这是我们客服 AI 上线后收到最多的投诉。

用户问「怎么退票」,AI 回答的是「如何改签」。用户问「价格是多少」,AI 回答的是「如何支付」。

问题出在哪?不是大模型不行,是 RAG 召回不准。

今天聊聊我们是怎么把 RAG 召回准确率从 75% 提升到 90% 的。

01

先搞清楚 RAG 召回为什么不准。

RAG 检索增强生成的核心逻辑很简单,用户问题到向量检索到召回相关文档到大模型生成回答。

准确率不高问题可能出在三个环节。

第一个环节是向量化质量差。如果文档的向量化做得不好,相似度计算就不准。常见问题包括 Embedding 模型选得不对、文档分块方式不合理、没有做预处理去噪和归一化。

第二个环节是检索策略单一。很多人用 RAG 就是简单地「向量相似度 Top K」。但这种方式有个问题,向量相似不等于语义相关。「退票」和「改签」在向量空间里可能很近,但它们是完全不同的业务场景。

第三个环节是知识库质量差。垃圾进垃圾出。如果知识库里的内容混乱、过时、冗余,再好的检索策略也没用。

02

我们做的第一个优化是分层索引。

原来的做法是用户问题到全库向量检索到 Top 10 到送给大模型。

问题是知识库有几万条文档,用户问「退票」可能召回一堆「改签」「投诉」「价格」相关的内容,因为它们在向量空间里都挺近的。

优化后的做法是用户问题先做意图分类,判断属于哪个大类,再在对应类目下做检索,最后返回 Top 5 送给大模型。

我们把知识库分成了几个大类,产品介绍、操作流程包括订票退票改签、规则政策包括价格优惠限制、常见问题。

用户问题先做意图分类判断属于哪个大类,再在对应类目下做检索。

效果是召回准确率从 75% 提升到 82%。

具体怎么做意图分类呢。我们用了一个简单的方法,关键词加语义双重判断。

先用关键词规则做快速分类,如果问题里有「退」或「取消」就分到操作流程退票,如果有「价」或「多少钱」就分到规则政策价格。

关键词匹配不上的再用大模型做语义分类。

这样既保证了速度因为关键词匹配很快,又保证了覆盖率因为语义分类兜底。

03

第二个优化是混合检索。

纯向量检索有个问题。向量检索擅长语义匹配,但对精确匹配不太行。

比如用户问「北京到上海的票价」,向量检索可能召回「上海到杭州的票价」,因为语义很接近。但用户明明指定了「北京到上海」,你给他「上海到杭州」肯定不对。

混合检索的做法是这样的。先做向量检索召回 Top 20,再做关键词检索召回 Top 20,然后取两者的交集和并集根据得分加权排序,最终返回 Top 5。

关键词检索怎么做?我们用了 BM25 算法,这是一个经典的关键词检索算法。简单说就是用户问题里的关键词在文档里出现得越多、越集中,得分越高。

效果是召回准确率从 82% 提升到 87%。

04

第三个优化是差异化策略。

我们发现不同类型的知识适合不同的检索策略。

第一类是结构化数据。比如「不同城市的票价」。这种数据是结构化的,应该用精确匹配而不是向量检索。我们的做法是把票价数据存成结构化表格,用户问票价时先解析出「出发地」「目的地」,直接查表不走向量检索。

第二类是时效性数据。比如「今天的限行政策」「当前的促销活动」。这种数据变化快,放在知识库里容易过时。我们的做法是不存知识库直接调 API 实时查询,知识库只存「如何查询」的指引,返回时标注「数据来源 XX 系统,更新时间 XX」。

第三类是长尾 FAQ。比如「如何开发票」「忘记密码怎么办」。这种问题量大覆盖长尾,适合用向量检索加语义重排。我们的做法是每个问题单独成段方便召回,向量检索召回 Top 10,用大模型对召回结果做语义重排选出最相关的 3 个。

第四类是核心方法论。比如「内容创作方法论」「运营 SOP」。这种知识非常重要被频繁引用必须 100% 准确。我们的做法是单独整理设为最高召回优先级,意图匹配到后直接返回不走向量检索,人工定期 Review 确保内容准确。

应用差异化策略后,整体准确率从 87% 提升到 90%。

更重要的是不同类型问题的准确率都更稳定了。票价查询从 72% 提升到 95%,政策查询从 68% 提升到 88%,操作流程从 80% 提升到 92%,长尾 FAQ 从 78% 提升到 86%。

05

除了上面三件大事还有一些细节优化也很重要。

第一个是文档分块策略。原来我们按固定长度分块比如 500 字一块,效果不好。后来改成按语义分块,检测段落边界、保持标题和正文的关联、每个分块都带上标题作为上下文。分块质量提升后召回准确率提升了约 3%。

第二个是 Query 改写。用户的问题有时候很口语化很模糊。比如「那个怎么弄」,「那个」是什么?「弄」是什么操作?我们加了一个 Query 改写环节,用大模型改写补充缺失的上下文,把口语化表达转成规范表达,拆解复合问题。

第三个是负反馈学习。上线后我们会收集用户的负反馈,用户点了「没有帮助」,用户重复问同一个问题,用户直接转人工。这些负反馈会进入一个 Bad Case 库,我们每周 Review 分析召回错误的原因、补充缺失的知识、优化检索策略。持续迭代比一次性优化更重要。

06

分享几个血泪教训。

第一个教训是别迷信 Embedding 模型。很多人觉得换一个更好的 Embedding 模型准确率就能大幅提升。我们试过了,从 OpenAI 的 ada 换成 text-embedding-3-large 准确率只提升了 2%。Embedding 模型只是基础,检索策略和知识库质量更重要。

第二个教训是分块不是越小越好。一开始我们想分块越小召回越精准。结果发现不对。分块太小会丢失上下文,用户问「怎么退票」召回了一个只包含「点击确认」的分块,完全不知道是在说什么。后来我们找到了平衡点,每个分块包含完整的一个知识点通常是 200 到 500 字。

第三个教训是召回数量不是越多越好。直觉上召回 Top 20 应该比 Top 5 好因为覆盖更全。但实际测试发现召回太多反而会「稀释」相关内容,大模型被无关信息干扰生成质量下降。我们最终的设置是召回 Top 5,每个分块 300 字左右,总共 1500 字左右的上下文。

07

RAG 看起来简单做好很难。

核心不是技术多先进,而是对业务的理解有多深。

你要知道用户会问什么样的问题。你要知道不同类型的知识应该怎么处理。你要知道什么时候用向量检索什么时候用精确匹配。

这些都需要对业务的深入理解,不是调几个参数就能搞定的。

如果你也在做 RAG,希望这篇文章对你有帮助。

没有银弹,只有持续迭代。

本文由 @鸣老师 原创发布于人人都是产品经理。未经作者许可,禁止转载

题图来自Unsplash,基于CC0协议

更多精彩内容,请关注人人都是产品经理微信公众号或下载App
评论
评论请登录
  1. 目前还没评论,等你发挥!