法律文档检索中的上下文断裂问题
在法律文档检索场景中,用户常常需要从海量的法规、判例和合同中精确定位某一条款。例如,一位律师询问“根据知识产权的定义,哪些对象可以享有专有权利?”时,系统需要从《中华人民共和国民法典》中检索出相关条款。然而,传统的 RAG(检索增强生成)系统在预处理阶段将文档切分为小块后,单个文本块往往缺乏必要的上下文,导致检索失败或回答不完整。
Anthropic 在 2024 年 9 月发布的博客中提出了上下文检索(Contextual Retrieval)方法,通过为每个文本块生成包含文档上下文的嵌入,显著提升了检索相关性。据其官方数据,该方法可将检索失败率降低 49%,结合重排序可降低 67%。本文将围绕法律文档检索场景,分析上下文检索的核心机制、实现步骤、成本与延迟,并对比传统分块嵌入的优劣。
传统 RAG 的预处理流程与失效原因
传统 RAG 的预处理流程通常包括三个步骤:首先将文档分解为较小的文本块(通常不超过几百个 token);然后使用嵌入模型将每个文本块转换为向量;最后将向量存储到向量数据库中。在运行时,系统将用户查询转换为向量,在数据库中检索语义相似的文本块,并将最相关的文本块加入提示词中,供生成模型使用。
这种流程的失效点在于文本切块破坏了上下文。以《中华人民共和国民法典》为例,固定长度切块可能将第一百二十三条的知识产权定义拆分成两个文本块,第二个文本块包含“(五)商业秘密”等客体,但缺少条款标题。当用户询问知识产权客体时,第二个文本块因缺乏“知识产权”关键词而难以被召回,导致回答遗漏部分客体。
类似地,在金融文档中,一个文本块可能写着“该公司收入较上一季度增长了 3%”,但若不指明公司名称和时间段,检索系统无法准确匹配“ACME Corp 在 2023 年第二季度的收入增长”这类查询。Anthropic 在博客中明确指出,传统 RAG 在编码信息时移除了上下文,导致系统无法从知识库中检索到相关信息。
上下文检索的核心机制:为文本块添加上下文
上下文检索的核心理念是在嵌入之前,为每个文本块前置一段简短的、针对该块的解释性上下文。具体做法是:将整个文档和待处理的文本块一起输入给一个长上下文大模型(如 Claude),并提示模型生成一段 50~100 个 token 的上下文描述,说明该文本块在文档中的位置、涉及的主题或关键实体。
Anthropic 提供的提示词模板大致如下(伪代码):
<document>
{{WHOLE_DOCUMENT}}
</document>
这是我们希望置于整个文档上下文中的块:
<chunk>
{{CHUNK_CONTENT}}
</chunk>
请提供一个简短的上下文,以便将该块置于整个文档中,从而改进搜索检索。仅回答简短的上下文,不要回答其他任何内容。
生成的上下文被添加到原始文本块之前,形成“上下文化的文本块”,然后用于生成嵌入和 BM25 索引。例如,对于“该公司收入较上一季度增长了 3%”这一文本块,生成的上下文可能是“此块来自 ACME Corp 2023 年第二季度业绩的 SEC 文件;上一季度的收入为 3.14 亿美元。”这样,嵌入向量和 BM25 索引都包含了关键实体和时间信息。
上下文嵌入与上下文 BM25 的协同
上下文检索包含两个子技术:上下文嵌入(Contextual Embeddings)和上下文 BM25(Contextual BM25)。上下文嵌入是指将添加上下文后的文本块输入嵌入模型,生成语义向量;上下文 BM25 则是基于添加上下文后的文本块构建词法索引。
BM25 是一种基于词法匹配的排序函数,擅长精确匹配唯一标识符或技术术语。例如,查询“错误代码 TS-999”时,嵌入模型可能找到关于错误代码的通用内容,但 BM25 能精确匹配字符串。在上下文中添加了公司名称、条款编号等关键词后,BM25 的匹配能力大幅提升。
Anthropic 的实验表明,单独使用上下文嵌入可将检索失败率降低 35%,结合上下文 BM25 后可降低 49%,再加入重排序可降低 67%。这表明两种技术是互补的:嵌入捕捉语义相似性,BM25 捕捉精确词法匹配,而上下文补充了缺失的实体和结构信息。
法律文档场景中的具体实现步骤
以法律文档检索为例,实现上下文检索需要以下步骤:
- 文档解析:将 PDF 等格式的法律文档解析为文本,保留段落、表格等结构。
- 文本切块:按固定长度或语义边界切分为小块,但需注意保留条款完整性。
- 上下文生成:对每个文本块,调用长上下文模型生成上下文描述。这一步需要将整个文档和文本块一起输入,因此文档需要一次性加载到模型上下文中。
- 嵌入与索引:将上下文化的文本块分别输入嵌入模型和 BM25 索引构建器,生成向量和词法索引。
- 检索融合:在运行时,同时使用嵌入和 BM25 检索,通过倒数排名融合(RRF)等方法合并结果,去重后取前 K 个文本块。
- 重排序:可选步骤,使用重排序模型(如 Cohere Reranker)对候选文本块重新打分,选择最相关的 20 个。
以下流程图展示了这一流程:
flowchart TD
A[原始法律文档] --> B[文档解析]
B --> C[文本切块]
C --> D[为每个块生成上下文]
D --> E[上下文嵌入]
D --> F[上下文BM25索引]
E --> G[向量数据库]
F --> H[BM25索引]
G --> I[检索融合]
H --> I
I --> J[重排序]
J --> K[最终结果]
在步骤 3 中,生成上下文需要将整个文档输入模型,因此文档长度直接影响预处理成本。Anthropic 建议使用提示缓存来降低重复处理的开销,因为文档只需加载到缓存一次,后续的文本块可以复用缓存。
预处理成本与延迟分析
上下文检索的主要成本在于为每个文本块生成上下文,这需要调用大模型。Anthropic 在博客中给出了一个成本估算:使用提示缓存后,生成上下文的一次性成本约为每百万文档 token 1.02 美元。这个成本是预处理阶段的固定开销,不随查询次数增加。
延迟方面,预处理阶段的时间会增加,但运行时检索的延迟与传统的嵌入检索相差不大,因为上下文化的文本块已经离线生成。重排序步骤会增加少量延迟,但通常控制在可接受范围内。
对于知识库小于 200,000 token(约 500 页)的场景,Anthropic 建议直接使用长提示,配合提示缓存,可以降低延迟 2 倍以上,成本降低 90%。但对于更大的知识库,上下文检索是更可扩展的方案。
与替代方案的比较
除了上下文检索,还有其他方法尝试解决文本切块带来的上下文丢失问题,例如 RAPTOR(递归抽象处理)。RAPTOR 通过对文本块进行聚类并生成总结,构建树状结构,检索时从高层节点向下查找。这种方法能聚合相关内容,但构建树状结构的计算量大,在大规模文档场景下效率较低。
下表对比了传统 RAG、RAPTOR 和上下文检索在多个维度的差异:
| 方案 | 检索质量 | 预处理成本 | 运行时延迟 | 实现复杂度 | 适用场景 |
|---|---|---|---|---|---|
| 传统 RAG | 低(上下文丢失) | 低(仅嵌入) | 低 | 低 | 小型知识库、对精度要求不高的场景 |
| RAPTOR | 中(聚合摘要) | 高(聚类和总结) | 中(树状检索) | 高 | 需要全局理解的场景,但文档规模有限 |
| 上下文检索 | 高(补充上下文) | 中(模型调用) | 低(离线预处理) | 中 | 大型知识库、对精度要求高的场景,如法律检索 |
从表中可以看出,上下文检索在检索质量和成本之间取得了较好的平衡。虽然预处理成本高于传统 RAG,但远低于 RAPTOR,且运行时延迟较低。
失败模式与注意事项
上下文检索并非万能,存在一些失败模式和限制。首先,生成的上下文依赖于大模型的准确性,如果模型对文档的理解有误,可能会引入错误的上下文,反而降低检索质量。其次,对于非常长的文档,生成上下文时可能受限于模型的上下文窗口,需要分段处理,可能影响上下文的完整性。
此外,上下文检索对文档的结构解析要求较高。在法律文档中,条款、章节等结构信息对检索至关重要,如果解析阶段未能正确提取这些结构,上下文生成的效果会大打折扣。庖丁科技的研究也指出,文档解析和文本切块是影响 RAG 效果的关键瓶颈,单纯升级嵌入模型的收益有限。
在工程实现中,还需要注意以下几点:
- 上下文长度控制:生成的上下文应控制在 50~100 token,过长的上下文会增加存储和计算开销,且可能引入噪声。
- 缓存策略:对于频繁更新的文档,需要及时更新上下文和索引,否则会导致检索结果过时。
- 评估指标:应使用检索召回率、命中率等指标评估上下文检索的效果,而不仅仅是最终问答的准确率。
结论与展望
上下文检索通过为每个文本块补充文档级上下文,有效缓解了传统 RAG 中文本切块导致的语义缺失和歧义问题。在法律文档检索场景中,这种方法能显著提升检索相关性,减少遗漏关键条款的情况。其代价是预处理阶段需要调用大模型生成上下文,但通过提示缓存可以控制成本。
然而,上下文检索仍然依赖于文档解析的质量和生成模型的准确性。未来,随着嵌入模型和重排序模型的进步,以及文档解析技术的改进,上下文检索有望在更多领域发挥价值。对于开发者而言,在构建 RAG 系统时,应综合考虑知识库规模、成本预算和检索精度要求,选择合适的方案。