Agentic RAG 系统


文档摘要

源文件:chapter3/agentic-rag/README.md Agentic RAG 系统 一个教学版的 Agentic 检索增强生成(RAG)系统实现,采用 ReAct 模式,支持多种 LLM 提供方与知识库后端。 🌟 特性 带 ReAct 模式的 Agentic RAG:使用推理与工具调用来迭代式搜索与检索信息 非 Agentic RAG 模式:简单的检索 + LLM 响应,便于对比 多 LLM 提供方支持: Kimi/Moonshot 豆包 SiliconFlow OpenAI OpenRouter Groq Together AI DeepSeek 灵活的知识库: 离线 BM25(内置,零依赖离线运行):在内置 语料上做进程内 BM25 检索——无需服务、无需 API

源文件:chapter3/agentic-rag/README.md

Agentic RAG 系统

一个教学版的 Agentic 检索增强生成(RAG)系统实现,采用 ReAct 模式,支持多种 LLM 提供方与知识库后端。

🌟 特性

  • 带 ReAct 模式的 Agentic RAG:使用推理与工具调用来迭代式搜索与检索信息
  • 非 Agentic RAG 模式:简单的检索 + LLM 响应,便于对比
  • 多 LLM 提供方支持
    • Kimi/Moonshot
    • 豆包
    • SiliconFlow
    • OpenAI
    • OpenRouter
    • Groq
    • Together AI
    • DeepSeek
  • 灵活的知识库
    • 离线 BM25(内置,零依赖离线运行):在内置 laws/ 语料上做进程内 BM25 检索——无需服务、无需 API Key
    • 本地检索流水线(需要 ../retrieval-pipeline)
    • Dify 知识库 API
  • 文档分块:可配置的分块策略,尊重段落边界
  • 评估框架:基于中文法律数据集的完整评估
  • 对话历史:支持后续提问
  • 详细日志:详尽日志帮助你理解 Agent 的推理过程

📦 安装

pip install -r requirements.txt

⚙️ 配置

.env 文件中设置环境变量:

# LLM API Keys (set the one you're using) MOONSHOT_API_KEY=your_kimi_api_key ARK_API_KEY=your_doubao_api_key SILICONFLOW_API_KEY=your_siliconflow_api_key OPENAI_API_KEY=your_openai_api_key OPENROUTER_API_KEY=your_openrouter_api_key GROQ_API_KEY=your_groq_api_key TOGETHER_API_KEY=your_together_api_key DEEPSEEK_API_KEY=your_deepseek_api_key # Knowledge Base Configuration (optional, defaults to local) KB_TYPE=local # Options: "offline" (内置离线 BM25,无需服务/API), "local", "dify" DIFY_API_KEY=your_dify_api_key # if using Dify DIFY_DATASET_ID=your_dataset_id # optional # LLM Configuration (optional) LLM_PROVIDER=kimi # default provider LLM_MODEL=kimi-k3 # optional, uses provider defaults

🚀 用法

0. 零依赖离线对比实验(推荐先跑,无需 API / 无需外部服务)

本实验的核心论点是:面对复杂问题,让 Agent 自主分解、多轮迭代检索,其证据召回显著优于单次检索
compare_offline.py 用内置的离线 BM25 检索器(offline_retriever.py,直接读取 laws/ 语料)
在小型中文司法问答集上量化这一差距,完全离线、无需任何 API Key

python compare_offline.py # 可选参数:--corpus laws --top-k 5 --dataset evaluation/offline_qa.json --output result.json

真实输出(本机实测,21372 个法条分块 / 288 篇文档):

问题 难度 单次检索 分解检索 检索次数 ------------------------------------------------------------------------------ 故意伤害致人重伤的,如何处… easy 100% 100% 1 → 1 正当防卫是怎么规定的? easy 100% 100% 1 → 1 醉酒驾驶机动车如何处罚? easy 100% 100% 1 → 1 故意杀人罪判几年? hard 0% 100% 1 → 1 盗窃罪的立案标准是什么? hard 0% 100% 1 → 1 诈骗罪的量刑标准是什么? hard 0% 100% 1 → 1 醉酒过失致人重伤且有盗窃前… hard 33% 100% 1 → 3 ------------------------------------------------------------------------------ 聚合指标(平均证据召回率): 全部 48% 100% 1.0 → 1.3 简单题 100% 100% 1.0 → 1.0 复杂题 8% 100% 1.0 → 1.5

解读(与书中实验 3-9 一致):简单问题两种范式相差无几(均 100%),一次直接检索就够;
复杂/措辞欠佳的问题上差距显著(8% → 100%),单次检索因关键词不精确而漏检关键法条,
分解式多轮检索则能逐一补齐证据。该指标为纯检索层的『证据召回率』,是回答质量的上界
——检索不到证据,生成阶段无从谈起。金标准法条均已确认存在于 laws/ 语料中。

说明:离线模式用数据集中预先标注的 subqueries 表示『Agent 分解后发起的检索』,
以隔离出检索策略本身的贡献;在真实系统中,这些子查询由 LLM 在 ReAct 循环中动态生成。
需要 LLM 生成、端到端评测答案质量时,请使用 evaluation/evaluate.py(需配置 API Key)。

也可以让完整 Agent 直接跑在离线知识库上(检索离线,仅答案生成需要 API Key):

python main.py --kb-type offline --query "醉酒过失致人重伤且有盗窃前科如何量刑" python main.py --kb-type offline --query "故意杀人罪判几年" --mode compare

1. 启动检索流水线

首先,启动检索流水线服务(本地知识库需要):

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

2. 索引文档

选项 A:索引内置的中文法律文档

# Index the included Chinese law documents python index_local_laws.py # With specific categories python index_local_laws.py --categories 宪法 民法典 # With document limit python index_local_laws.py --max-docs 10

选项 B:索引自定义文档

# Index a single file python main.py --index path/to/document.txt # Index a directory python main.py --index path/to/documents/ # Custom chunk size python main.py --index documents/ --chunk-size 2048

3. 运行 Agentic RAG 系统

交互模式(默认)

# Start in agentic mode (default) python main.py # Start in non-agentic mode python main.py --mode non-agentic # Enable verbose logging (default is enabled) python main.py --verbose # Disable verbose logging python main.py --no-verbose

在交互模式下:

  • 输入你的问题并回车
  • 输入 'quit' 或 'exit' 停止
  • 输入 'clear' 清空对话历史
  • 输入 'mode' 在 agentic / non-agentic 模式之间切换

单次查询

# Agentic mode python main.py --query "宪法第一条是什么?" --mode agentic # Non-agentic mode python main.py --query "盗窃罪的立案标准是什么?" --mode non-agentic # Compare both modes python main.py --query "故意杀人罪判几年?" --mode compare

批量处理

# Create a file with queries (one per line) echo "故意杀人罪判几年? 盗窃罪的立案标准是什么? 醉酒驾驶如何处罚?" > queries.txt # Run batch python main.py --batch queries.txt --output results.json # Batch with specific mode python main.py --batch queries.txt --mode non-agentic

切换不同提供方

python main.py --provider openai --model gpt-5.6-luna python main.py --provider doubao --model doubao-seed-1-6-thinking-250715 python main.py --provider siliconflow --query "你好"

4. 运行评估

# Build evaluation dataset cd evaluation python dataset_builder.py # Run evaluation python evaluate.py # With specific configuration python evaluate.py --provider kimi --kb-type local --output custom_results

📁 项目结构

agentic-rag/ ├── config.py # Configuration classes ├── agent.py # Main AgenticRAG implementation ├── tools.py # Knowledge base tools (含 offline BM25 后端) ├── offline_retriever.py # 内置离线 BM25 检索器(读取 laws/,无需服务/API) ├── compare_offline.py # 离线对比实验:分解检索 vs 单次检索(证据召回率表) ├── chunking.py # Document chunking and indexing ├── main.py # Main entry point ├── index_local_laws.py # Index Chinese law documents ├── quickstart.py # Quick demo script ├── test_simple.py # Simple test script ├── requirements.txt # Dependencies ├── README.md # This file ├── document_store.json # Local document storage ├── laws/ # Chinese law documents │ ├── 1-宪法/ │ ├── 2-宪法相关法/ │ ├── 3-民法典/ │ ├── 3-民法商法/ │ ├── 4-行政法/ │ ├── 5-经济法/ │ ├── 6-社会法/ │ ├── 7-刑法/ │ └── 8-诉讼与非诉讼程序法/ └── evaluation/ ├── dataset_builder.py # Build evaluation dataset ├── offline_qa.json # 离线对比数据集(问题 + 金标准法条 + Agent 分解子查询) └── evaluate.py # Evaluation framework (端到端答案质量,需 API)

🧠 工作原理

Agentic RAG 模式

Agent 采用 ReAct(Reasoning + Acting)模式:

  1. 推理:分析回答问题需要哪些信息
  2. 工具调用:用 knowledge_base_search 工具查找相关文本块
  3. 迭代搜索:可用更精炼的查询进行多次搜索
  4. 文档检索:可用 get_document 获取完整文档以补充上下文
  5. 答案综合:结合检索到的信息并附上引用
  6. 对话记忆:为后续提问保持上下文

示例流程:

User: 宪法第一条是什么? Agent: [Thinks] Need to find information about Article 1 of the Constitution [Tool] knowledge_base_search("宪法第一条") [Result] Found relevant chunks about constitutional articles [Answer] Based on the retrieved information, Article 1 states...

非 Agentic RAG 模式

简单的检索增强生成:

  1. 直接搜索:用用户原始查询搜索一次
  2. 上下文注入:把 top-K 结果放入 prompt
  3. 单次响应:LLM 基于提供的上下文作答
  4. 不迭代:一次成型,不做精炼

📊 配置选项

Top-K 结果

控制检索多少条结果:

# In config.py or via environment local_top_k = 3 # Number of results to retrieve

详细模式

查看 Agent 的详细推理:

# Enable verbose (default) python main.py --verbose # Disable for cleaner output python main.py --no-verbose

LLM Temperature

控制响应随机性:

# In config.py temperature = 0.7 # 0.0 = deterministic, 1.0 = more creative

🎯 评估结果

检索层(离线、可复现、真实实测):见上文第 0 节
的证据召回率表——分解式多轮检索把复杂题的召回率从 8% 提升到 100%,而简单题两种范式打平(均 100%)。

生成层(端到端答案质量,需 LLM API)evaluation/evaluate.py 在此基础上真正调用 LLM 生成答案,
统计关键词/分析点召回、引用覆盖率、响应时间等指标。以下为该框架产出的指标与典型模式:

指标

  • 成功率:答案是否包含关键法律概念
  • 响应时间:生成响应的耗时
  • 检索质量:检索到的文本块的相关性
  • 引用覆盖率:来源归属是否到位

预期模式

Agentic RAG 通常表现出:

  • ✅ 对复杂多维度问题覆盖更好
  • ✅ 通过显式工具调用获得更准确的引用
  • ✅ 能根据初步结果精炼搜索
  • ⚠️ 响应更慢(多次 LLM 调用)

非 Agentic RAG 通常表现出:

  • ✅ 响应更快(单次检索)
  • ✅ 在简单直接的问题上表现良好
  • ⚠️ 查询措辞不佳时可能漏掉相关信息
  • ⚠️ 处理模糊查询的能力有限

🔧 故障排查

检索流水线无响应

# Check if the service is running curl http://localhost:4242/health # If not, start it: cd ../retrieval-pipeline python main.py

无搜索结果

  1. 确保已索引文档:
python index_local_laws.py
  1. 检查文档存储:
ls -la document_store.json
  1. 核实检索流水线中有文档:
curl http://localhost:4242/stats

API Key 问题

# Check if environment variable is set echo $MOONSHOT_API_KEY # Or use .env file cat .env | grep API_KEY

索引错误

  • 索引前确保检索流水线已运行
  • 检查文件编码(应为 UTF-8)
  • 核实到 localhost:4242 的连通性

🤝 参与贡献

可增强的方向:

  • 更多评估指标
  • 更精细的分块策略
  • 更好的重排序算法
  • 更多知识库后端(RAPTOR、GraphRAG)
  • 多语言支持
  • 查询扩展技术
  • 混合检索策略

📄 许可证

这是一个用于学习目的的教学项目。

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