源文件:chapter3/contextual-retrieval/README.md Contextual Retrieval 系统 — 教学版实现 Anthropic Contextual Retrieval 技术的教学版实现,演示如何在索引前为文本块补上上下文,从而显著提升 RAG 系统的检索准确率。 🌟 核心洞见 问题:传统 RAG 系统在切分文档时会丢失上下文。一个写着"公司营收增长 3%"的块,如果不知道是哪家公司、哪个时段,就失去了意义。 解决方案:Contextual Retrieval 在嵌入与索引之前,为每个文本块前置一段针对该块的说明性上下文,从而保留语义。 📊 核心实验:离线量化召回提升(实验 3-11) 上面的 Key Insight 是本项目要验证的核心主张。
源文件:chapter3/contextual-retrieval/README.md
Anthropic Contextual Retrieval 技术的教学版实现,演示如何在索引前为文本块补上上下文,从而显著提升 RAG 系统的检索准确率。
问题:传统 RAG 系统在切分文档时会丢失上下文。一个写着"公司营收增长 3%"的块,如果不知道是哪家公司、哪个时段,就失去了意义。
解决方案:Contextual Retrieval 在嵌入与索引之前,为每个文本块前置一段针对该块的说明性上下文,从而保留语义。
上面的 Key Insight 是本项目要验证的核心主张。compare_retrieval.py 用一组
可控的对比实验完全离线地量化它:把同一批文本块分别以两种方式建 BM25 索引——
无上下文(只索引原始文本)与有上下文(索引 LLM 生成的前缀 + 原始文本)——
再在评测集 evaluation/retrieval_eval.json(15 条查询 + 人工标注 gold 文本块)
上比较 recall@k(命中率)。无需任何 API 或检索服务(BM25 + jieba 分词)。
# 跑完整对比表(默认语料 document_store.json,默认评测集) python compare_retrieval.py # 查看每条查询的命中排名明细 python compare_retrieval.py --per-query # 临时单条查询:并排看无上下文 / 有上下文的 Top-K 结果 python compare_retrieval.py --query "国家主席有哪些职权?" --top-k 5 # 只看无上下文基线 / 另存机器可读结果 python compare_retrieval.py --mode plain python compare_retrieval.py --output result.json # 中文 --help python compare_retrieval.py --help
真实运行输出(22 个《宪法》《检察官法》文本块,15 条查询,jieba 分词):
检索召回对比:无上下文分块 vs. 上下文感知检索(BM25) ==================================================================== 方法 recall@1 recall@3 recall@5 ---------------------------------------------------- 无上下文 (plain) 60.0% 86.7% 93.3% 有上下文 (ctx) 86.7% 86.7% 93.3% ---------------------------------------------------- 提升 (Δpp) +26.7pp +0.0pp +0.0pp ---------------------------------------------------- 失败率下降 67% 0% 0%
结论与书中一致:为文本块补上上下文前缀显著提升 top-1 召回(60% → 86.7%,
失败率 1−recall@1 下降 67%),前缀为 BM25 注入了"身份标签"式的可匹配关键词。
这一提升在 recall@1 上最明显;--query 模式可直观看到前缀如何把"正确所属章节"
的文本块重新排到前面。
--method embedding/--method hybrid(上下文向量嵌入 + RRF 融合)需要
调用 embedding API,无法离线运行;脚本会给出提示并回退到 BM25 离线结果。
稠密检索 + 重排序的完整实现见contextual_tools.py。
同一对比逻辑也内建在 ContextualChunker.compare_retrieval_methods() 中(书中compare_retrieval_methods 功能),可对任意一组 ContextualChunk 直接做并排检索对比。
本实现包含详尽的日志与对比能力,帮助你理解:
use_contextual=False 运行,与标准分块对比┌─────────────────────────────────────────┐ │ Document Input │ └────────────────┬────────────────────────┘ │ ▼ ┌─────────────────────────────────────────┐ │ Basic Chunking │ │ (Respects paragraph boundaries) │ └────────────────┬────────────────────────┘ │ ▼ ┌─────────────────────────────────────────┐ │ Context Generation (Optional) │ │ Using LLM API │ │ (Enabled with use_contextual=True) │ └────────────────┬────────────────────────┘ │ ▼ ┌─────────────────────────────────────────┐ │ Enhanced Chunks │ │ • Contextual: Context + Original Text │ │ • Standard: Original Text Only │ └────────────────┬────────────────────────┘ │ ▼ ┌─────────────────────────────────────────┐ │ Retrieval Pipeline Indexing │ │ • Sparse Index (BM25) │ │ • Dense Index (Embeddings) │ └────────────────┬────────────────────────┘ │ ▼ ┌─────────────────────────────────────────┐ │ Hybrid Search with Reranking │ │ Combines BM25 + Embedding scores │ │ Cross-encoder reranking for accuracy │ └─────────────────────────────────────────┘
pip install -r requirements.txt
cp env.example .env # Edit .env and add your API keys: # - MOONSHOT_API_KEY for Kimi # - ARK_API_KEY for Doubao # - OPENAI_API_KEY for OpenAI # - etc.
# In a separate terminal, start the retrieval pipeline server cd ../retrieval-pipeline python main.py # Server will run on http://localhost:4242
# Index Chinese law documents with contextual enhancement python index_local_laws_contextual.py # Or index without contextual enhancement for comparison python index_local_laws_contextual.py --no-contextual
# Interactive mode with contextual retrieval python main.py # Query with specific mode python main.py --query "宪法第一条是什么" --mode agentic # Compare agentic vs non-agentic modes python main.py --query "宪法第一条是什么" --mode compare
系统为每个块生成上下文的流程如下:
示例 prompt 模板:
<document> [Full document or surrounding context] </document> Here is the chunk we want to situate: <chunk> [Specific chunk text] </chunk> Please give a short, succinct context to situate this chunk within the overall document...
这是一个教学版实现。欢迎在以下方面贡献:
用于学习目的的教学项目。
基于 Anthropic 工程团队通过上下文增强提升 RAG 检索准确率的研究。
本实验现已为其对话 LLM 支持通用 OpenRouter 回退。
MOONSHOT_API_KEY / KIMI_API_KEY / OPENAI_API_KEY / DOUBAO_API_KEY …)存在,行为不变。OPENROUTER_API_KEY,对话 LLM 会自动经 OpenRouter 路由(https://openrouter.ai/api/v1)。模型名会自动映射:gpt-*/o1-* → openai/…,claude-* → anthropic/claude-opus-4.8,kimi-* → moonshotai/kimi-k2.6,已含 / 的 id 保持原样,其他提供方原生 id(如 doubao-*)回退为 openai/gpt-5.6-luna。设置 OPENROUTER_MODEL 可强制指定 OpenRouter 模型 id。在 .env 中加入 OPENROUTER_API_KEY=... 即可启用(见 env.example)。