跳至主要内容

Anthropic 的上下文检索:实现指南

了解 Anthropic 的上下文检索如何提升检索系统的准确性,并按步骤实现它。
· 8分钟 阅读

使用 AI 探索

检索增强生成(RAG)可帮助 AI 模型整合来自外部来源的额外知识。然而,这些系统常常丢失关键信息上下文,从而导致结果不够准确。

Anthropic 提出了上下文检索——一种简单而有效的改进信息检索的方法。为每个片段保留合适的上下文可将检索错误最多减少 67%,从而显著提升下游任务的表现。

在本文中,我将解释什么是上下文检索,以及如何在您的应用中使用它。

什么是上下文检索?

尽管传统的 RAG 系统行之有效,但它们有一个主要缺陷:通常会将文档拆分为较小的片段以便检索,但这可能会移除重要的上下文。

例如,一个片段可能会写道“Its more than 3.85 million inhabitants make it the European Union's most populous city”,却未指明所指的城市或国家。缺乏上下文会导致结果不完整或不相关,尤其在需要具体细节时更为明显。

standard RAG diagram

来源:Introducing Contextual Retrieval

上下文检索通过在嵌入前为每个片段生成并添加简短且特定于上下文的说明来解决此问题。在上述示例中,该片段将被转换如下:

contextualized_chunk = """Berlin is the capital and largest city of Germany, known for being the EU's most populous city within its limits.
Its more than 3.85 million inhabitants make it the European Union's most populous city, as measured by population within city limits.
"""

contextual retrieval RAG diagram

来源:Introducing Contextual Retrieval

总体而言,Anthropic 在包含代码库、科学论文和小说等不同领域的内部测试显示,配合上下文嵌入模型与 Contextual BM25 使用时,上下文检索可将检索错误减少 49%。

contextual retrieval performance

来源:Introducing Contextual Retrieval

上下文检索的实现

下面我将逐步说明如何实现上下文检索。我们将使用以下示例文档作为演示:

# Input text for the knowledge base
input_text = """Berlin is the capital and largest city of Germany, both by area and by population.
Its more than 3.85 million inhabitants make it the European Union's most populous city, as measured by population within city limits.
The city is also one of the states of Germany and is the third smallest state in the country in terms of area.
Paris is the capital and most populous city of France.
It is situated along the Seine River in the north-central part of the country.
The city has a population of over 2.1 million residents within its administrative limits, making it one of Europe's major population centers."""

步骤 1:将文档拆分为片段

第一步是把示例文档拆分成更小、相互独立的片段。在此示例中,我们将其划分为单句。

# Splitting the input text into smaller chunks
test_chunks = [
    'Berlin is the capital and largest city of Germany, both by area and by population.',
    "\\n\\nIts more than 3.85 million inhabitants make it the European Union's most populous city, as measured by population within city limits.",
    '\\n\\nThe city is also one of the states of Germany and is the third smallest state in the country in terms of area.',
    '\\n\\n# Paris is the capital and most populous city of France.',
    '\\n\\n# It is situated along the Seine River in the north-central part of the country.',
    "\\n\\n# The city has a population of over 2.1 million residents within its administrative limits, making it one of Europe's major population centers."
]

步骤 2:定义提示模板

接下来,我们将设置模型用于为每个片段生成上下文的提示。Anthropic 提供了一个很实用的模板。该提示接收两个输入:整个文档,以及我们希望定位的特定文本片段。

from langchain.prompts import ChatPromptTemplate, PromptTemplate, HumanMessagePromptTemplate

# Define the prompt for generating contextual information
anthropic_contextual_retrieval_system_prompt = """<document>
{WHOLE_DOCUMENT}
</document>
Here is the chunk we want to situate within the whole document
<chunk>
{CHUNK_CONTENT}
</chunk>
Please give a short succinct context to situate this chunk within the overall document for the purposes of improving search retrieval of the chunk. Answer only with the succinct context and nothing else."""

# Create a PromptTemplate for WHOLE_DOCUMENT and CHUNK_CONTENT
anthropic_prompt_template = PromptTemplate(
    input_variables=['WHOLE_DOCUMENT', 'CHUNK_CONTENT'],
    template=anthropic_contextual_retrieval_system_prompt
)

# Wrap the prompt in a HumanMessagePromptTemplate
human_message_prompt = HumanMessagePromptTemplate(prompt=anthropic_prompt_template)
# Create the final ChatPromptTemplate
anthropic_contextual_retrieval_final_prompt = ChatPromptTemplate(
    input_variables=['WHOLE_DOCUMENT', 'CHUNK_CONTENT'],
    messages=[human_message_prompt]
)

步骤 3:初始化您偏好的语言模型

在这里,您可以选择任意 LLM 为每个片段生成上下文。在我们的示例中,将使用 OpenAI 的GPT-4o 模型。

import os
from langchain_openai import ChatOpenAI

# Load environment variables
os.environ["OPENAI_API_KEY"] = "YOUR_OPENAI_API_KEY"

# Initialize the model instance
llm_model_instance = ChatOpenAI(
    model="gpt-4o",
)

步骤 4:将各部分连接起来

我们将把提示模板与语言模型连接,创建一个可处理前面生成片段的 LLM 链。

from langchain.output_parsers import StrOutputParser

# Chain the prompt with the model instance
contextual_chunk_creation = anthropic_contextual_retrieval_final_prompt | llm_model_instance | StrOutputParser()

步骤 5:处理每个片段

现在我们将遍历各个片段,为每个片段生成上下文信息,并使用 contextual_chunk_creation 这条 LLM 链输出结果。

# Process each chunk and generate contextual information
for test_chunk in test_chunks:
    res = contextual_chunk_creation.invoke({
        "WHOLE_DOCUMENT": input_text,
        "CHUNK_CONTENT": test_chunk
    })
    print(res)
    print('-----')
The document compares Berlin and Paris, highlighting Berlin as Germany's capital and largest city by area and population, and noting its significance within the European Union.
-----
Berlin is the capital and largest city of Germany, known for being the EU's most populous city within its limits.
-----
Berlin is the capital and largest city of Germany, both by area and by population.
-----
Paris, the capital of France, is a major population center in Europe with over 2.1 million residents.
-----
Paris is the capital and most populous city of France.
-----
Paris is the capital and most populous city of France, with a population of over 2.1 million residents within its administrative limits.
-----

通过重排序进一步提升

尽管上下文检索已能提升检索准确性,您还可以借助重排序将其进一步优化。该过滤技术确保只有最相关的片段会被发送给模型,从而提升响应质量并降低成本与处理时间。

重排序通过为第一步检索到的片段打分,仅保留最优者。在我们的测试中,重排序将检索错误率从 5.7% 降至 1.9%,相较传统方法准确率提升 67%。

contextual retrieval with reranking performance

来源:Introducing Contextual Retrieval

其他注意事项

Anthropic 的研究发现,并非所有场景都需要上下文检索的复杂度。对于少于 200,000 个 token(约 500 页)的较小知识库,更好的做法可能是将整个知识库直接放入模型的提示中,完全跳过检索系统。

他们还建议善用提示缓存,这是为 Claude 引入的一项功能。通过在 API 调用之间缓存常用提示,开发者可将成本降低最多 90%,并将响应时间加速两倍以上。此提示缓存手册提供了分步实现指南。

结语

Anthropic 的上下文检索是一种简单而有效的检索系统改进方法。结合上下文嵌入、BM25 与重排序,可显著提升此类系统的准确性。

如需进一步了解不同的检索技术,我推荐以下博客:

  1. 使用 LangGraph 实现 Corrective RAG(CRAG)
  2. RAG 的递归检索:基于 LlamaIndex 的实现
Ryan Ong

作者

Ryan Ong

Ryan 是一名首席数据科学家,专注于使用大型语言模型构建 AI 应用。他是伦敦帝国理工学院自然语言处理与知识图谱方向的博士候选人,并在该校获得了计算机科学硕士学位。除数据科学之外,他还撰写每周的 Substack 时事通讯 The Limitless Playbook,分享来自全球顶尖思想家的一个可操作理念,并不时撰写关于核心 AI 概念的文章。

主题