上下文检索是一种通过解决一个根本问题来提高 RAG 流程准确性的技术:当您将文档拆分成块时,每个块都会失去与更广泛文档上下文的联系。

其基本思路很简单。在对源文档进行分块后,您要求 Claude 在将每个块存储到检索器数据库之前为其添加上下文。这一预处理步骤有助于将每个块"定位"在更大的文档中。
工作原理
对于每个文本块,您将该块和原始源文档一起发送给 Claude,并附上如下提示:
Write a short and succinct snippet of text to situate this chunk within the
overall source document for the purposes of improving search retrieval of the chunk.
Here is the original source document:
<document>
{source_text}
</document>
Here is the chunk we want to situate within the whole document:
<chunk>
{text_chunk}
</chunk>
Answer only with the succinct context and nothing else.Claude 可能会生成这样的上下文:"本节摘自一份关于跨学科团队的更大报告。其中提到了 INC-2023-04-011,该编号也在网络安全分析部分被提及。"

然后,您将生成的上下文与原始块文本结合,创建一个"上下文化的块",并将其存储到您的向量索引和 BM25 索引中。
处理大型文档
如果您的源文档太大,无法放入单个提示中,您可以提供一组精简的上下文,而不是整个文档。

对于您要进行上下文化处理的任何给定块,请包含:
- 文档开头的几个块(通常包含摘要或概要)
- 紧邻目标块之前的块(提供局部上下文)
这种方法为 Claude 提供了足够的信息来生成有意义的上下文,而不会让整个文档使提示内容过载。
实现示例
以下是上下文检索函数的基本实现:
def add_context(text_chunk, source_text):
prompt = f"""
Write a short and succinct snippet of text to situate this chunk within the
overall source document for the purposes of improving search retrieval of the chunk.
Here is the original source document:
<document>
{source_text}
</document>
Here is the chunk we want to situate within the whole document:
<chunk>
{text_chunk}
</chunk>
Answer only with the succinct context and nothing else.
"""
messages = []
add_user_message(messages, prompt)
result = chat(messages)
return result["text"] + "\n" + text_chunk在处理文档块时,您需要遍历每个块并生成上下文化版本:
# 为每个分块添加上下文,然后添加到检索器中
for i, chunk in enumerate(chunks):
# 根据起始分块和前面的分块构建上下文
context_parts = []
context_parts.extend(chunks[:min(num_start_chunks, len(chunks))])
start_idx = max(0, i - num_prev_chunks)
context_parts.extend(chunks[start_idx:i])
context = "\n".join(context_parts)
contextualized_chunk = add_context(chunk, context)
retriever.add_document({"content": contextualized_chunk})预期结果
生成的上下文提供了有关文档结构和关系的宝贵信息。例如,Claude 可能会将某个块描述为"《年度跨学科研究综述》的第 2 节,详细介绍了软件工程团队为解决 Phoenix 项目稳定性问题所做的努力。该节紧接在方法论部分之后,财务分析部分之前,是一份涵盖组织内十个研究领域的综合报告的一部分。"
这些额外的上下文有助于检索系统更好地理解每个块不仅包含什么内容,还能理解它如何融入更大的文档结构并与其他部分相关联。对于简单的文档,您可能不会看到显著的改进,但随着文档变得更加复杂,各部分之间存在错综复杂的交叉引用和依赖关系时,上下文检索的价值会越来越大。