Files
liqiang b119135836
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
2026-08-20 13:12:50 +00:00

252 lines
9.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Contextual Retrieval System / 上下文感知检索系统
> Companion material for *AI Agents in Depth*, Chapter 3 — **Experiment 3-10**: Anthropic-style contextual prefixes before indexing; offline BM25 recall@k compare.
> 配套《深入理解 AI Agent》第 3 章 **实验 3-10**:索引前为分块生成上下文前缀;离线 BM25 recall@k 对比。
← [Chapter 3 index / 返回第 3 章目录](../README.md)
---
## English
### Canonical live campaign
`python campaign.py` regenerates every prefix live from the full source
document plus its target chunk, then compares the same 15 labeled queries over
plain/contextual BM25, dense Qwen3 embeddings, and RRF hybrid indexes. It records
recall@1/3/5, MRR, model revision, index-time usage/cost assumptions, source
hashes, and raw ARK receipts in `validation/runs/<run-id>/`; the canonical
pointer is `validation/latest.json`. `compare_retrieval.py` remains the small
offline demonstration and is not accepted as the canonical live result.
### Overview
Educational implementation of Anthropics Contextual Retrieval: prepend chunk-specific context before embedding/indexing to fix the “orphaned chunk” problem.
### Key insight
**Problem:** Traditional RAG loses context when chunking. “The companys revenue grew by 3%” is meaningless without which company / which period.
**Solution:** Generate short explanatory context per chunk and prepend it before indexing so BM25 and embeddings keep identity signals.
### Core offline experiment (Experiment 3-10)
`compare_retrieval.py` quantifies the claim **fully offline**: same chunks indexed two ways—plain (raw text only) vs contextual (LLM-generated prefix + text)—then compares `recall@k` on `evaluation/retrieval_eval.json` (15 queries + human gold chunks). **No API or retrieval service** (BM25 + jieba).
```bash
python compare_retrieval.py
python compare_retrieval.py --per-query
python compare_retrieval.py --query "国家主席有哪些职权?" --top-k 5
python compare_retrieval.py --mode plain
python compare_retrieval.py --output result.json
python compare_retrieval.py --help # Chinese help
```
Real run (22 Constitution / Prosecutor Law chunks, 15 queries, 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%
```
Conclusion (matches the book): context prefixes lift top-1 recall (60% → 86.7%; failure rate 1recall@1 down 67%). Gain is strongest at recall@1; `--query` shows how the prefix re-ranks the correct section first.
> `--method embedding` / `--method hybrid` need embedding APIs (not offline); the script falls back to BM25 offline results. Full dense + rerank lives in `contextual_tools.py`.
> Same logic is also in `ContextualChunker.compare_retrieval_methods()`.
### Educational features
1. Watch LLM context generation per chunk
2. Dual indexing (BM25 + embeddings) benefits from context
3. Compare with `use_contextual=False`
4. Metrics and token/cost awareness
### Architecture
```
Document → Basic Chunking → Context Generation (optional LLM)
→ Enhanced chunks (context+text vs text only)
→ Retrieval pipeline (sparse BM25 + dense embeddings)
→ Hybrid search + reranking
```
### Quick start
```bash
# From the repository root: use the shared Chapter 3 environment
uv sync --locked --python 3.12 --extra ch3
# Activate it before changing directories:
# macOS/Linux:
source .venv/bin/activate
# Windows PowerShell: .venv\Scripts\Activate.ps1
# Windows cmd: .venv\Scripts\activate.bat
# pip fallback when uv is not installed:
# python -m pip install -e ".[ch3]"
cd chapter3/contextual-retrieval
# Single-project compatibility path, still supported during migration:
# python -m pip install -r requirements.txt
cp env.example .env
# MOONSHOT_API_KEY / ARK_API_KEY / OPENAI_API_KEY / etc.
# Separate terminal for full e2e with pipeline:
cd ../retrieval-pipeline
python main.py
# http://localhost:4242
# Back in this project directory (or a second terminal):
cd ../contextual-retrieval
# Index with contextual enhancement
python index_local_laws_contextual.py
python index_local_laws_contextual.py --no-contextual
# Queries
python main.py
python main.py --query "宪法第一条是什么" --mode agentic
python main.py --query "宪法第一条是什么" --mode compare
```
### Context generation process
1. Provide full document (or surrounding context) to the LLM
2. Show the specific chunk
3. Ask for 23 sentence situating context
Template sketch:
```
<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...
```
### References / license
- [Anthropic Contextual Retrieval](https://www.anthropic.com/engineering/contextual-retrieval)
- Educational project for learning purposes. Acknowledgments: Anthropic engineering research.
---
## 中文
### 概述
Anthropic 上下文感知检索的教学实现:在嵌入/建索引前为每个分块附加专属上下文,缓解「孤儿分块」问题。
### 核心洞察
**问题:** 传统 RAG 分块后丢失语境。「公司收入增长 3%」不知是哪家公司、哪个时期。
**方案:** 为每块生成简短解释性上下文并前置,使 BM25 与向量都能保留身份信号。
### 核心实验:离线量化召回提升(实验 3-10)
`compare_retrieval.py` **完全离线**量化:同一批文本块分别以无上下文 / 有上下文前缀两种方式建 BM25 索引,在 `evaluation/retrieval_eval.json`15 查询 + 人工 gold 块)上比较 `recall@k`。**无需 API 或检索服务**BM25 + jieba)。
```bash
python compare_retrieval.py
python compare_retrieval.py --per-query
python compare_retrieval.py --query "国家主席有哪些职权?" --top-k 5
python compare_retrieval.py --mode plain
python compare_retrieval.py --output result.json
python compare_retrieval.py --help
```
真实输出(22 个《宪法》《检察官法》文本块,15 查询):
```
检索召回对比:无上下文分块 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%,失败率下降 67%)。`--method embedding` / `hybrid` 需 embedding API,脚本会提示并回退 BM25 离线结果。完整稠密+重排见 `contextual_tools.py`
### 教学特性
观察上下文生成、双索引策略、`use_contextual=False` 对照、指标与成本。
### 架构
文档 → 基础分块 → 可选 LLM 上下文生成 → 增强块 → 检索流水线(稀疏+稠密)→ 混合检索+重排。
### 快速开始
```bash
# 在仓库根目录使用统一的第 3 章环境
uv sync --locked --python 3.12 --extra ch3
# 切换目录前先激活环境:
# macOS/Linux
source .venv/bin/activate
# Windows PowerShell.venv\Scripts\Activate.ps1
# Windows cmd.venv\Scripts\activate.bat
# 未安装 uv 时可用 pip 兜底:
# python -m pip install -e ".[ch3]"
cd chapter3/contextual-retrieval
# 迁移期间仍支持单项目兼容路径:
# python -m pip install -r requirements.txt
cp env.example .env
# 另开一个终端运行完整检索流水线:
cd ../retrieval-pipeline
python main.py
# http://localhost:4242
# 回到本项目目录(或新开一个终端):
cd ../contextual-retrieval
python index_local_laws_contextual.py
python index_local_laws_contextual.py --no-contextual
python main.py
python main.py --query "宪法第一条是什么" --mode agentic
python main.py --query "宪法第一条是什么" --mode compare
```
### 上下文生成流程
向 LLM 提供全文(或周边)+ 目标块,请求 2–3 句定位上下文。提示模板见 English 节。
### 参考与许可
[Anthropic 博客](https://www.anthropic.com/engineering/contextual-retrieval) · 教学项目。
---
## Notes / 说明
### OpenRouter 通用回退 / Universal OpenRouter fallback
Chat LLM falls back to OpenRouter when primary keys are missing and `OPENROUTER_API_KEY` is set. See `env.example`. Related: [`../contextual-retrieval-for-user-memory/`](../contextual-retrieval-for-user-memory/) (Exp. 3-11).