Contextual Retrieval 系统 — 教学版实现


文档摘要

源文件:chapter3/contextual-retrieval/README.md Contextual Retrieval 系统 — 教学版实现 Anthropic Contextual Retrieval 技术的教学版实现,演示如何在索引前为文本块补上上下文,从而显著提升 RAG 系统的检索准确率。 🌟 核心洞见 问题:传统 RAG 系统在切分文档时会丢失上下文。一个写着"公司营收增长 3%"的块,如果不知道是哪家公司、哪个时段,就失去了意义。 解决方案:Contextual Retrieval 在嵌入与索引之前,为每个文本块前置一段针对该块的说明性上下文,从而保留语义。 📊 核心实验:离线量化召回提升(实验 3-11) 上面的 Key Insight 是本项目要验证的核心主张。

源文件:chapter3/contextual-retrieval/README.md

Contextual Retrieval 系统 — 教学版实现

Anthropic Contextual Retrieval 技术的教学版实现,演示如何在索引前为文本块补上上下文,从而显著提升 RAG 系统的检索准确率。

🌟 核心洞见

问题:传统 RAG 系统在切分文档时会丢失上下文。一个写着"公司营收增长 3%"的块,如果不知道是哪家公司、哪个时段,就失去了意义。

解决方案:Contextual Retrieval 在嵌入与索引之前,为每个文本块前置一段针对该块的说明性上下文,从而保留语义。

📊 核心实验:离线量化召回提升(实验 3-11)

上面的 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 直接做并排检索对比。

📚 教学特性

本实现包含详尽的日志与对比能力,帮助你理解:

  1. 上下文生成如何工作:观察 LLM 为每个块生成上下文的过程
  2. 双重索引策略:看 BM25 与嵌入如何都从上下文中受益
  3. 对比模式:用 use_contextual=False 运行,与标准分块对比
  4. 性能指标:跟踪检索准确率的提升
  5. 成本分析:理解 token 用量与成本

🏗️ 架构

┌─────────────────────────────────────────┐ │ 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 │ └─────────────────────────────────────────┘

🚀 快速开始

1. 安装

pip install -r requirements.txt

2. 配置环境

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.

3. 启动检索流水线

# In a separate terminal, start the retrieval pipeline server cd ../retrieval-pipeline python main.py # Server will run on http://localhost:4242

4. 索引文档

# 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

5. 运行查询

# 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

上下文生成过程

系统为每个块生成上下文的流程如下:

  1. 把完整文档(或周围上下文)提供给 LLM
  2. 展示要被上下文化的具体块
  3. 请求简短的上下文(2–3 句话)来为该块定位

示例 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...

📚 参考文献

🤝 参与贡献

这是一个教学版实现。欢迎在以下方面贡献:

  • 更多分块策略
  • 其他上下文生成 prompt
  • 性能优化
  • 评估指标
  • 可视化工具

📝 许可证

用于学习目的的教学项目。

🙏 致谢

基于 Anthropic 工程团队通过上下文增强提升 RAG 检索准确率的研究。

OpenRouter 通用回退 / Universal OpenRouter fallback

本实验现已为其对话 LLM 支持通用 OpenRouter 回退

  • 若主提供方 key(如 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.8kimi-*moonshotai/kimi-k2.6,已含 / 的 id 保持原样,其他提供方原生 id(如 doubao-*)回退为 openai/gpt-5.6-luna。设置 OPENROUTER_MODEL 可强制指定 OpenRouter 模型 id。
  • 否则会给出清晰错误,列出可接受的 key。

.env 中加入 OPENROUTER_API_KEY=... 即可启用(见 env.example)。


作者与出处
原作者: bojieli
来源:bojieli
许可证:Apache-2.0
整理: 灏天文库整理
由灏天文库结构化整理,提供目录导航、全文检索与在线阅读,便于系统化学习
发布者: 作者: bojieli 转发
评论区 (0)
U