
你有没有向你的RAG系统问过一个具体问题,却得到一个令人沮丧的模糊答案?你并不孤单。以下是一个巧妙的改进方法如何改变游戏规则。
想象一下:你为公司的文档建立了一个流畅的RAG(Retrieval Augmented Generation)系统。你问它:“2023年第二季度的收入增长是多少?”它自信地回答:“收入比上一季度增长了3%。”很好,但是……哪家公司?哪个季度?你的系统只是给了你一块拼图,却没有告诉你拼图盒子在哪里。
如果你使用过RAG系统,你可能已经遇到过这个难题。好消息是?Anthropic最近推出了一种看似简单的解决方案,称为“contextual retrieval”,它显示出显著的效果——与现有技术结合时,检索失败率降低了高达49%。

让我们深入探讨这个方法的特别之处,以及为什么你可能想在下一个项目中实现它。
如果对您有帮助请点赞、转发、关注,感谢感谢~~
上下文问题:当好的chunk变得不好时
在了解解决方案之前,我们先来理解为什么标准的RAG系统在上下文方面会遇到困难。在一个典型的RAG流程中,你可能会这样做:
1.将文档分成chunk(通常每个几百个token)2.为每个chunk生成embeddings3.将这些embeddings存储在vector database中4.当查询到来时,找到语义上最相似的chunk5.将这些chunk输入LLM以生成答案
这在许多用例中效果很好。询问“machine learning最佳实践”,你很可能会得到关于ML技术的相关chunk。但问题来了。

想象你的文档包含多个公司的季度报告。当你将文档分成chunk时,那个关键的“收入增长3%”被剥离了标识其为“Acme公司2023年第二季度表现”的上下文。你的embedding model看到“收入增长”并认为“这与财务相关!”但不知道是哪家公司或哪个时间段。
临时解决方法:keyword search来救场?
许多开发者尝试通过在semantic search之外添加keyword search(例如BM25)来修补这个问题。这在你寻找特定术语(如错误代码)时很有帮助。搜索“Error TS-99”,keyword search会准确命中,而纯semantic search可能会返回一般的故障排除指南。
但即使是这种双重方法也有局限性。如果你的文档多次提到“收入增长3%”但对应不同上下文,keyword search单独无法知道你需要哪个实例。你仍然缺少关键的上下文信息。
引入Contextual Retrieval:教chunk记住它们来自哪里
这正是Anthropic方法的巧妙之处。他们没有试图修复检索机制,而是增强了chunk本身。核心思想非常简单:在存储chunk之前,为其添加相关的上下文信息。
让我们来看看收入的例子:
原始chunk:“收入比上一季度增长了3%”
带上下文的chunk:“这个chunk来自Acme公司2023年第二季度表现的备案。收入比上一季度增长了3%”
现在,你的embedding model和keyword search都有了完整的图景。当有人搜索“Acme 2023年第二季度收入”时,两种搜索机制都能自信地识别出这是相关的chunk。
实现:让LLM承担重任
你可能会想:“好主意,但我不会手动为数千个chunk添加上下文。”这正是实现的趣味所在。Anthropic建议使用LLM(他们推荐高效的Claude Haiku模型)来自动生成这些上下文。

过程如下:
1.正常地将文档分成chunk2.对于每个chunk,将完整文档和该特定chunk发送给LLM3.使用一个提示,指示LLM生成一个简洁的上下文语句4.将此上下文添加到原始chunk之前5.使用这些增强的chunk生成embeddings并更新BM25索引
这里的prompt engineering至关重要。你实际上是在要求LLM扮演侦探:“给定这个完整文档和这个特定chunk,编写一个简短的上下文,帮助别人理解这个chunk在整体中的位置。”
数据:它真的有效吗?
Anthropic的基准测试令人印象深刻。仅使用contextual embeddings,他们看到检索失败率降低了35%(从5.7%降至3.7%,基于top-20检索)。当他们将contextual embeddings与contextual BM25结合时,改进幅度跃升至49%的失败率减少。

更有趣的是,当他们在所有这些之上添加一个re-ranker时,平均检索错误率从5.7%下降到仅1.9%。这是一个巨大的改进,仅通过一个预处理步骤和一些巧妙的prompt engineering实现。
权衡:没有免费的午餐
在你急于实现之前,我们来谈谈成本。添加上下文意味着:
•更大的chunk:每个chunk增加50-100个token,这会稍微减少你能在LLM上下文窗口中适应的chunk数量•处理成本:你需要在索引期间为每个chunk运行一次LLM调用•存储开销:你的vector database和搜索索引会变得更大

Anthropic估计一次性处理成本约为每百万token 1.02美元。这听起来可能不多,但如果你处理数百万文档,成本会累积。好消息是,像prompt caching这样的功能可以将成本降低高达90%,特别是在处理类似文档时。
何时使用Contextual Retrieval(以及何时跳过)
以下是一个实用的决策树:
使用contextual retrieval的场景:
•你的文档包含多个实体、时间段或上下文•你需要针对特定、定向查询的高准确性•你的knowledge base太大,无法使用长上下文LLM(超过200K token)•检索错误的成本很高(例如法律文件、财务报告)
考虑替代方案的场景:
•你的knowledge base较小(少于200K token或1MB,例如使用Gemini)•你的文档已经高度结构化,上下文清晰•你处理的是一致的、chunk本身就自包含的内容

来自实践的实施建议
根据Anthropic的实验和他们分享的代码,以下是一些实用建议:
•定制你的上下文提示:财务文档的提示需要与技术文档不同的上下文。试验并迭代。•明智选择embedding model:在他们的测试中,Google的Gemini Text-004表现最佳,Voyage embeddings也显示出很强的结果。•不要吝啬re-ranker:contextual retrieval加上re-ranking的组合显示出最佳结果。考虑使用像Cohere的re-ranking API这样的服务。•检索更多,然后过滤:Anthropic发现最初检索20个chunk,然后使用re-ranker选择最佳的chunk很成功。•用你的实际数据测试:提供的基准测试基于特定数据集。你的结果可能因文档类型和查询模式而异。

大局观:RAG并未消亡
随着LLM拥有越来越大的上下文窗口,你可能想知道RAG是否正在过时。Anthropic的工作表明并非如此。即使有200K+ token的上下文窗口,RAG对于大型knowledge base仍然更具成本效益和可扩展性。Contextual retrieval让RAG变得更好,而不是过时。
这样想:长上下文LLM就像拥有对当前看到的一切的摄影记忆。RAG就像一个组织良好的图书馆,配备一个聪明的图书管理员。Contextual retrieval只是为那个图书管理员提供了一个更好的卡片目录。

总结:小改变,大影响
Contextual retrieval不是一个革命性的新架构或复杂的神经网络创新。它是一个巧妙的预处理步骤,承认一个简单的事实:上下文很重要。通过确保每个chunk都带有自己的上下文,我们不是在对抗embedding model或keyword search的局限性——我们是在与它们合作。
对于构建RAG系统的开发者来说,这种技术提供了一种相对简单的方法来显著提高检索准确性。是的,有成本和权衡,但对于准确性至关重要的应用来说,投资可能是值得的。
下次你的RAG系统返回一个令人沮丧的模糊答案时,记住:它可能只是需要帮助记住它把钥匙放哪儿了。Contextual retrieval确保每个chunk都带有一张回家的地图。
如果对您有帮助请点赞、转发、关注,感谢感谢~~
(文:PyTorch研习社)