深度指南详解如何逐步改进 RAG 系统性能,包括评估、调试和优化策略,对 AI 应用开发者实用性很高。
本文介绍了如何改进检索增强生成(RAG)系统。文章基于我与 Hamel 的一次交流,并在我之前撰写的其他 RAG 文章基础上进一步展开。如需全面了解 RAG 的基础知识,请参阅我的 RAG 概念指南。
在《RAG 不只是 Embedding》中,我讨论了为什么 RAG 不仅仅是向量 Embedding。这有助于你更深入地理解 RAG。我还写过《如何构建一个糟糕的 RAG 系统》,通过展示不应该做什么,帮助你掌握良好的实践方法。
如果你想了解 RAG 系统能够复杂到什么程度,可以阅读《RAG 复杂度分级》。这篇文章将 RAG 拆分成更小的组成部分,使其更容易理解。如果你想快速了解改进 RAG 系统的技巧,请阅读《RAG 中唾手可得的优化》。
我还在《对 RAG 未来的预测》中写过自己对 RAG 未来发展的看法。该文探讨了未来如何使用 RAG 创建报告。
这些文章相互配合,共同构成了一份完整的 RAG 系统改进指南。它们为希望优化系统的开发者和公司提供了实用建议。如需了解更多改进策略,可以阅读我总结的六条 RAG 改进技巧以及对 RAG 反模式的分析。如果你对 AI 工程这个更宽泛的主题感兴趣,可能也会喜欢我在 AI Engineer Summit 上的演讲。在这次演讲中,我解释了 Pydantic 等工具如何帮助进行提示词工程,而这对构建 RAG 系统很有帮助。
通过这些文章,我试图为你提供一幅完整的 RAG 系统图景,涵盖从基本理念到高级应用和未来预测的所有内容。这应该能帮助你理解这个快速变化的领域,并在其中取得良好成果。
读完本文后,你将理解我为合作公司逐步改进 RAG 应用的方法。我们将研究以下重要领域:
生成人工合成的问题和答案,以快速测试系统的运行效果
结合使用全文搜索和向量搜索,以获得最佳结果
建立合适的机制,针对你希望研究的问题获取用户反馈
通过聚类找出存在问题的问题集合,并按主题和能力进行分类
构建有针对性的系统来提升能力
随着获得更多真实世界的数据,持续进行检查和测试
这份分步操作手册展示了如何循序渐进地提升 RAG 应用的性能和实用性。下面让我们深入探讨如何系统化地改进 RAG 系统。
我认为,在改进系统时,最大的错误是大多数人把太多时间花在实际的内容合成上,却没有真正弄清楚数据是否被正确检索。为了避免这个问题:
为数据库中的每个文本分块创建合成问题
使用这些问题测试检索系统
计算精确率和召回率,建立基线
根据基线分数找出需要改进的方面
我们应该通过合成数据确认,系统对合成数据的召回率和精确率应达到约 97%。一开始,合成数据可以非常简单。
我们可以说:对于每个文本分块,我希望系统以合成方式生成一组可由该文本分块回答的问题。对于这些问题,我们能否检索出相应的文本分块?你可能认为答案肯定始终是可以。但在实践中,我发现,在针对文章进行测试时,全文搜索和 Embedding 的表现基本相同,只不过全文搜索的速度大约快 10 倍。这种方法是我更广泛的 RAG 飞轮策略的一部分。
然而,当我在从代码仓库中检索 issue 的场景下进行相同实验时,全文搜索的召回率约为 55%,而 Embedding 搜索的召回率约为 65%。了解这些问题在基线上的挑战程度非常重要,因为这能帮助你判断需要进行哪些实验才能获得更好的表现。这将为你提供一个用于后续工作的基线,并帮助你找出需要改进的方面。如需详细了解评估指标,请参阅我的指南《你只需要这 6 项 RAG 评估》。
提取相关元数据并使其可供搜索,例如日期范围、文件名和所有权,以改善搜索结果。
从文档中提取相关元数据
将元数据纳入搜索索引
使用查询理解,从用户查询中提取元数据
使用相关元数据扩展搜索查询,以改善结果
例如,如果有人问:“最新的 x、y 和 z 是什么?”全文搜索永远无法得到答案,语义搜索也永远无法得到答案。
你需要执行查询理解,以提取日期范围。这需要进行一些提示词工程。有关企业级实现,请参阅我的 RAG 企业流程指南。这里的关键在于元数据,同时也要意识到:有些问题之所以始终无法得到回答,是因为全文搜索和语义搜索永远无法捕获这些过滤条件。
在实践中,它的工作方式是这样的:如果你提出“该领域最近有哪些进展?”这一问题,搜索查询现在会被扩展为更多术语。查询中还会包含一个日期范围,语言模型会推理对于这项研究而言,“最近”具体意味着什么;此外,它还会判断应该只搜索特定来源。如果不这样做,你可能无法获得可信来源,也可能无法确定“最近”到底意味着什么。
你需要进行一定的查询理解,以提取日期范围并将元数据纳入搜索。
同时使用全文搜索和向量搜索(Embedding)来检索相关文档。理想情况下,你应该使用单一数据库系统,以避免同步问题。
同时实现全文搜索和向量搜索
针对你的具体使用场景测试每种方法的性能
考虑使用单一数据库系统存储这两类数据
评估速度与召回率之间的权衡,以确定哪种方案适合你的应用
根据我的经验,全文搜索可能更快,但向量搜索可以提供更高的召回率。
最后真正变得非常复杂的是:如果你只有一个知识库,那么这种复杂度或许还可以接受,因为你可以为每一种搜索方式进行更多配置。
但我的一位客户处理的是建筑数据,他们必须为每个项目创建单独的索引。结果,他们很快就面对着一个不断膨胀的不同数据源集合,这些数据源随时可能出现同步或失同步的情况。比如数据库发生中断,数据没有进入数据库,却进入了另一个系统。于是当检索出 Embedding 时,相应的文本却缺失了。
这种复杂的配置会带来巨大的麻烦。例如,有些工具能够在单个对象中同时处理这三类操作。因此,即使拥有大量分区数据源,你也可以针对同一个数据对象执行全文搜索、Embedding 搜索和 SQL 查询。这种方式非常有用,尤其是在考虑前面那类需要查找最新内容的示例时。此时,你只需执行全文搜索查询,然后按日期排序并添加一个 between 子句。
把两种方式都测试一下,看看哪一种最适合你的使用场景。
实现清晰的用户反馈系统,例如赞成或反对按钮,以收集关于系统表现的数据,并找出需要改进的方面。
在应用中加入用户反馈机制
确保这些机制的文案清楚描述了你正在衡量的内容
提出“我们是否正确回答了问题?”这样的具体问题,而不是“我们表现得怎么样?”这类笼统问题
使用反馈数据找出需要改进的方面,并确定修复工作的优先级
我发现,尽早建立这些反馈机制非常重要。同时,还要确保这些反馈机制的文案明确描述你真正关心的问题。
有时,即使答案是正确的,我们仍会收到反对反馈,仅仅因为用户不喜欢它的语气。又或者答案是正确的,但延迟过高,或者需要经过太多跳才能获得答案。
这意味着,我们无法仅凭赞成和反对反馈来生成评估数据集,其中存在太多混杂变量。我们不得不把文案改成:“我们是否正确回答了问题?是或否。”我们需要认识到,语气和延迟最终都会得到改善,但当时我们需要依靠用户反馈来构建评估数据集。
请确保这些反馈机制的文案明确描述你真正关心的问题。这将帮助你隔离用户遇到的具体问题。
分析用户查询和反馈,以识别主题聚类、能力以及用户不满意的方面。这将帮助你确定改进工作的优先级。
为什么应该这样做?让我用一个例子来说明。我曾与一家提供技术文档搜索系统的公司合作过。通过对用户查询进行聚类分析,我们发现了两个主要问题:
主题聚类:大部分用户查询与最近更新的特定产品功能有关。然而,我们的系统没有检索到该功能的最新文档,导致用户感到困惑和沮丧。
主题聚类:大部分用户查询与最近更新的特定产品功能有关。然而,我们的系统没有检索到该功能的最新文档,导致用户感到困惑和沮丧。
能力缺陷:另一个查询聚类显示,用户经常询问故障排查步骤和错误代码解释。虽然我们的系统能够检索相关文档,但在提供这些问题的直接、可操作答案方面表现不足。
能力缺陷:另一个查询聚类显示,用户经常询问故障排查步骤和错误代码解释。虽然我们的系统能够检索相关文档,但在提供这些问题的直接、可操作答案方面表现不足。
基于这些洞察,我们优先更新了产品功能文档,并实现了一项功能来提取分步说明和错误代码解释。这些有针对性的改进提高了用户满意度,并减少了支持请求。
寻找以下类型的模式:
主题聚类:用户是否比其他主题更多地询问特定主题?这可能表明需要在这些领域增加更多内容,或改进现有内容的检索。我在关于 RAG 分解、主题和能力的文章中进一步探讨了这个概念。
主题聚类:用户是否比其他主题更多地询问特定主题?这可能表明需要在这些领域增加更多内容,或改进现有内容的检索。我在关于 RAG 分解、主题和能力的文章中进一步探讨了这个概念。
能力:您的系统是否有某些类型的问题根本无法回答?这可能表明需要新的功能或能力,例如直接答案提取、多文档摘要或特定领域的推理。
能力:您的系统是否有某些类型的问题根本无法回答?这可能表明需要新的功能或能力,例如直接答案提取、多文档摘要或特定领域的推理。
通过持续分析主题聚类和能力缺陷,您可以识别高影响力的改进领域,并更有效地分配资源。这种数据驱动的优先级排序方法确保您始终在处理影响用户的最关键问题。
一旦建立了这套体系,有了这些主题和聚类,您就可以与领域专家沟通几周,明确确定这些类别是什么。随后,您可以构建系统,在数据传入时对其进行标记。
就像打开 ChatGPT 开始对话时,它会在角落自动生成标题一样。现在您可以对每个问题都这样做。作为这项能力的一部分,您可以添加分类,比如主题是什么、能力是什么。能力可能包括所有权和职责、获取表格、获取图像、仅获取文档、不进行综合、比较和对比、截止日期等等。有关选择正确的工具和能力的更多信息,请参阅我关于工具选择权衡的文章。
然后您可以将这些信息放入 Amplitude 或 Sentry 这样的工具中。这将为您提供人们提出的查询类型的实时流,帮助您理解如何优先化这些能力和主题。
持续监测您系统的性能,并运行实验来测试改进。
设置监测和日志记录,以跟踪系统随时间的性能
定期审查数据以识别趋势和问题
设计并运行实验来测试潜在改进
衡量变化对精确度、召回率和其他相关指标的影响
实施显示出显著改进的变化
这可能包括调整搜索参数、添加元数据或尝试不同的嵌入模型。衡量对精确度和召回率的影响,以确定这些变化是否值得。
现在,一旦您有了这些问题、合成数据集和一堆带有评分的用户数据,系统改进 RAG 的真正工作才真正开始。
系统将围绕这些问题运行许多主题建模聚类,根据点赞和点踩评分对这些模型进行建模,以找出哪些聚类表现不佳。它将随后确定每个聚类的用户不满意的计数和概率。
系统将定期执行此操作,确定对于什么数量的问题和用户满意度水平,它应该专注于改进这些特定用例。
可能发生的情况是,您集成了一个新组织,突然之间这些分布就会改变,因为他们的用例不同。那时您可以说:"我们集成了这些新客户端,他们非常关心截止日期。我们知道我们决定不服务截止日期,但现在我们知道这是一个优先事项,因为它从占问题的 2% 增加到了 80%。"随后您可以确定围绕这一点可以进行什么样的教育或改进。
最后,根据您的特定用例和用户需求,为系统延迟和搜索性能之间的权衡做出知情决定。
了解您的应用程序的延迟和性能需求
衡量不同配置对延迟和性能的影响
根据对用户最重要的因素做出权衡
考虑不同用例的不同需求(例如医学诊断与通用搜索)
在这里,拥有用于测试的合成问题可以有效地回答这个问题。因为我们会用和不用这个父文档检索器运行查询,我们会获得有和没有该功能的召回率以及该功能的延迟改进。
现在我们就能够说,好的。召回率翻倍。延迟增加了 20%,那么对话就可以进行。或者,这值得投资吗?但如果延迟翻倍,召回率只增加 1%,那又取决于,好吧。
如果这是医学诊断,也许我确实关心那 1% 被包括在内,因为风险很高。但如果是文档页面,也许增加的延迟会降低流失率。
如果您能将召回率提高 1%,但结果太复杂,那也不值得在将来部署。
例如,如果您在构建医学诊断工具,稍微增加延迟可能值得换取更好的召回率。但如果您在构建通用搜索工具,更快的结果可能更重要。
这是基于与一位客户的 30 分钟对话写的,所以我知道我跳过了许多细节和实现细节。留下评论,让我知道,我们可以深入了解具体情况。
这是基于 30 分钟的对话,所以我肯定在跳过实现细节。真正的突破发生在您停止随意改进、开始衡量什么真正能产生影响的时候:
免费 6 周 RAG 电子邮件课程 完整课程分解 RAG 常见问题