🚀 一个具有自主规划、动态检索、自我反思能力的智能 RAG 系统
Agentic-RAG 是一个基于 LangGraph 实现的智能检索增强生成(Agentic Retrieval-Augmented Generation)系统。与传统 RAG 系统相比,它具备:
- 🔍 问题澄清能力:智能判断用户问题是否清晰、完整
- 🎯 动态规划能力:协调者负责任务规划,动态调整检索策略
- 🔧 多工具协同:支持向量检索、网络搜索、数据库查询等多种工具
- 🗜️ 上下文压缩:Token 超限时自动压缩对话历史
- 🤔 自我反思能力:评估答案质量,决定是否重新生成或补充检索
- 📊 评估体系:集成 Ragas 评估框架,支持多维度质量评估
┌─────────────────────────────────────────────────────────────────┐
│ Agentic RAG 核心流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 用户问题 → 🔍 Clarify → 🎯 Coordinator → 🔧 Tool Calling │
│ ↓ │
│ ✍️ Generator → 🤔 Self Reflect │
│ ↓ │
│ ✅ 答案 / 🔄 迭代 │
│ │
└─────────────────────────────────────────────────────────────────┘
- 稠密向量检索:基于语义相似度匹配
- 稀疏向量检索:基于 BM25 关键词匹配
- RRF 融合:结合两种检索方式的优势
- 二次重排序:使用大模型提升相关性
- 为每个文档块生成上下文窗口
- 扩展左右相邻内容,提升召回率
- 智能停止:遇到表格/图片时停止扩展
- 支持 PDF、Word 等多种格式
- 自动提取表格和图片
- 使用 LLM 生成多模态内容描述
flowchart TD
subgraph 用户层["👤 用户层"]
Q[用户提问]
end
subgraph Agentic层["🤖 Agentic RAG 层"]
CLARIFY[🔍 Clarify Node<br/>问题澄清]
COORD[🎯 Coordinator Node<br/>协调者节点]
TOOL[🔧 Tool Calling Node<br/>工具决策]
TOKEN[📊 Token Check Node<br/>Token检查]
COMPRESS[🗜️ Compressor Node<br/>上下文压缩]
GEN[✍️ Generator Node<br/>答案生成]
REFLECT[🤔 Self Reflect Node<br/>自我反思]
end
subgraph 工具层["🔧 工具层"]
VECTOR[📊 向量检索工具]
WEB[🌐 网络搜索工具]
DB[🗄️ 数据库查询工具]
end
subgraph 向量层["🔢 向量处理层"]
LOAD[📄 文档加载]
SPLIT[✂️ 文档分块]
EMBED[🔢 向量化]
RETRIEVE[🔍 混合检索]
RERANK[🏆 重排序]
end
subgraph 存储层["💾 存储层"]
MILVUS[(Milvus<br/>向量数据库)]
OSS[(阿里云 OSS<br/>对象存储)]
end
Q --> CLARIFY
CLARIFY --> COORD
COORD --> TOOL
TOOL --> VECTOR
TOOL --> WEB
VECTOR --> RETRIEVE
RETRIEVE --> RERANK
RERANK --> GEN
GEN --> REFLECT
REFLECT -.->|需要补充| COORD
LOAD --> SPLIT
SPLIT --> EMBED
EMBED --> MILVUS
MILVUS --> RETRIEVE
style Agentic层 fill:#e3f2fd,stroke:#0288d1
style 工具层 fill:#fff3e0,stroke:#ef6c00
style 向量层 fill:#e8f5e9,stroke:#2e7d32
style 存储层 fill:#fce4ec,stroke:#ad1457
flowchart LR
START([👤]) --> CLARIFY
CLARIFY -->|清晰| COORD
CLARIFY -->|不清晰| END1([⚠️])
COORD -->|需要工具| TOOL
COORD -->|不需要工具| GEN
TOOL --> VECTOR
VECTOR --> TOKEN
TOKEN -->|压缩| COMPRESS
TOKEN -->|不压缩| COORD
COMPRESS --> COORD
GEN --> REFLECT
REFLECT -->|合格| END2([✅])
REFLECT -->|重新生成| GEN
REFLECT -->|补充检索| COORD
- Python 3.12+
- Milvus 2.4+(向量数据库)
- 阿里云 OSS(对象存储)
- VLLM 或 DashScope(模型服务)
# 1. 克隆项目
git clone https://github.com/your-repo/agentic-rag.git
cd agentic-rag
# 2. 安装依赖
pip install uv
uv sync
# 3. 配置环境变量
cp .env.example .env
# 编辑 .env 文件,填入必要的 API Key 和配置
# 4. 初始化 Milvus
python -m init.init_milvus
# 5. 上传文档
python -m init.batch_upload --path document/your_document.pdf
# 6. 运行问答
python main.pyimport asyncio
from rag.graph.rag_graph import build_rag_graph
async def test_rag():
graph = build_rag_graph()
result = await graph.ainvoke({
"original_question": "传音控股2024年的营收是多少?",
"prompt_info": "",
"conversation_summary": "",
"messages": [],
})
print(result['answer'])
asyncio.run(test_rag())agentic-rag/
├── main.py # 主程序入口
├── config.yaml # 全局配置文件
│
├── rag/ # Agentic RAG 核心模块
│ ├── graph/
│ │ ├── rag_graph.py # LangGraph 工作流编排
│ │ ├── prompt.py # Prompt 模板
│ │ └── schemas.py # 结构化输出 Schema
│ └── tools/
│ ├── vector_tools.py # 向量检索工具
│ └── web_tools.py # 网络搜索工具
│
├── vector/ # 向量处理模块
│ ├── core/
│ │ ├── loaders.py # 文档加载器
│ │ ├── splitters.py # 文档分块策略
│ │ ├── embeddings.py # 向量化处理
│ │ └── retrieve.py # 混合检索
│ └── graph/
│ ├── vector_search_graph.py # 检索工作流
│ └── save_graph.py # 文档上传工作流
│
├── shared/ # 共享模块
│ ├── config/ # 配置管理
│ │ ├── config.py # YAML 配置加载
│ │ ├── model_config.py # 模型配置
│ │ └── *_choice.py # 模型选择工厂
│ ├── client/ # 客户端
│ │ ├── milvus_client.py # Milvus 连接
│ │ └── aliyun_oss_client.py # OSS 连接
│ └── utils/
│ └── unstructured_util.py # 文档解析工具
│
├── rag_eval/ # 评估模块
│ ├── rag_evals.py # RAG 评估
│ └── evals/datasets/ # 测试数据集
│
├── init/ # 初始化脚本
│ ├── init_milvus.py # Milvus 初始化
│ ├── batch_upload.py # 批量文档上传
│ └── test_rag.py # 测试脚本
│
└── document/ # 文档存储目录
# ============ 文档处理配置 ============
rag:
object_store:
policy: "oss" # 对象存储:oss
endpoint: "oss-cn-beijing.aliyuncs.com"
bucket_name: "agentic-core"
split:
policy: 4 # 分块策略:4=句子窗口
chunk_size: 200 # 分块大小
overlap: 0 # 分块重叠
window_size: 3 # 句子窗口大小
# ============ 检索配置 ============
retrieve:
top_k: 100 # 检索返回数量
rerank:
enable: true # 启用重排序
top_n: 20 # 重排序返回数量
# ============ 向量数据库配置 ============
vector_store:
policy: "milvus"
uri: "http://localhost:19530"
db_name: "agentic_rag"
collection_name: "doc_collection"
# ============ AI 模型配置 ============
ai:
embedding: # Embedding 模型
- name: "qwen3_vl_embeddings"
policy: "openai"
model: ${VLLM_QWEN_EMBEDDING_MODEL}
dimension: 2048
rerank: # 重排序模型
- name: "qwen3_vl_rerank"
policy: "dashscope"
model: "qwen3-vl-rerank"
chat: # Chat 模型
- name: "qwen3.5_plus"
policy: "openai"
model: "qwen3.5-flash"
temperature: 0.2
max_tokens: 8192# .env 文件
# 阿里云 AI
ALIYUN_AI_API_KEY=your_api_key
ALIYUN_AI_BASE_URL=https://dashscope.aliyuncs.com/api/v1
# VLLM(Embedding 服务)
VLLM_API_KEY=your_vllm_key
VLLM_BASE_URL=http://localhost:8000/v1
VLLM_QWEN_EMBEDDING_MODEL=Qwen/Qwen3-Embedding-2048
# 阿里云 OSS
ALIYUN_OSS_ACCESSKEY_ID=your_access_key
ALIYUN_OSS_ACCESSKEY_SECRET=your_secret_keyfrom vector.graph import build_save_graph
import asyncio
async def upload_document():
graph = build_save_graph()
result = await graph.ainvoke({
"file_path": "document/report.pdf"
})
print(f"上传成功: {len(result['doc_list'])} 个文档块")
asyncio.run(upload_document())python -m init.batch_upload --path document/ --pattern "*.pdf"import asyncio
from rag.graph.rag_graph import build_rag_graph
async def query():
graph = build_rag_graph()
result = await graph.ainvoke({
"original_question": "传音控股2024年的营收增长情况如何?",
"prompt_info": "",
"conversation_summary": "",
"messages": [],
})
print(result['answer'])
asyncio.run(query())# 通过 question_expr 过滤特定文件
result = await graph.ainvoke({
"original_question": "研发投入情况?",
"question_expr": "file_name like '%传音%' and pub_year == '2024'",
...
})from rag_eval import evaluate_rag
# 评估 RAG 系统
results = evaluate_rag(
dataset="rag_eval/evals/datasets/new_test_dataset.csv",
metrics=["faithfulness", "answer_relevancy", "context_relevance"]
)测试集基于传音控股、艾力斯、广联达三份上市公司研究报告设计,共 20 道题目:
| 类型 | 数量 | 占比 | 说明 |
|---|---|---|---|
| single_doc | 6 | 30% | 单文档事实型问题 |
| multi_doc | 5 | 25% | 多文档综合型问题 |
| semantic_ambiguous | 5 | 25% | 语义模糊型问题 |
| irrelevant | 4 | 20% | 无关型问题(防幻觉) |
| 指标 | 说明 | 目标值 |
|---|---|---|
| Faithfulness | 生成内容与检索内容的忠诚度 | > 0.9 |
| Answer Relevancy | 答案与问题的相关性 | > 0.85 |
| Context Precision | 上下文精确度 | > 0.8 |
| Context Recall | 上下文召回率 | > 0.85 |
# 运行评估
python -m rag_eval.rag_evals
# 查看结果
# 结果保存在 rag_eval/experiments/ 目录- 在
rag/tools/目录下创建新工具文件:
# rag/tools/mysql_tools.py
from langchain.tools import tool
@tool
def mysql_query_tool(query: str) -> str:
"""执行 MySQL 查询"""
# 实现查询逻辑
return result- 在
rag/graph/rag_graph.py中注册工具:
from rag.tools import mysql_tools
tool_list = [
vector_search_tool,
web_search_tool,
mysql_query_tool, # 新增
]在 rag/graph/prompt.py 中添加新的 Prompt 模板:
def get_custom_prompt() -> str:
return """
## 角色
你是一个...
"""在 vector/core/splitters.py 中扩展分块器:
def semantic_chunk_splitter(documents: List[Document]) -> List[Document]:
"""基于语义的智能分块"""
# 实现语义分块逻辑
pass| 节点 | 职责 | 循环上限 |
|---|---|---|
| Clarify | 问题澄清 | 1次 |
| Coordinator | 问题重写 + 工具决策 | 5次 |
| Tool Calling | 工具选择 | 3次 |
| Token Check | Token 计算 | - |
| Compressor | 上下文压缩 | - |
| Generator | 答案生成 | 2次 |
| Self Reflect | 质量评估 | - |
文档加载 → 元素清洗 → 分块处理 → 向量化 → Milvus 入库
↓
表格/图片处理 → LLM 描述
↓
句子窗口生成 → 扩展上下文
查询 → Embedding → 稠密检索 ─┐
↓ │
查询 → BM25 → 稀疏检索 ─────┼─→ RRF 融合 → 重排序 → 结果
│
← ← ← ← ← ← ← ← ← ← ← ← ← ┘
A: 检查以下几点:
- 确认文档已成功上传到 Milvus
- 检查
question_expr过滤条件是否过于严格 - 尝试使用更通用的查询词
A: 系统会自动触发上下文压缩。如果仍然超限:
- 降低
chunk_size重新上传文档 - 减少
window_size缩小上下文窗口
| 策略 | 适用场景 |
|---|---|
| 固定大小 | 通用场景,简单高效 |
| 递归字符 | 需要更细致的分块 |
| 语义分块 | 需要保持语义完整性 |
| 句子窗口 | 推荐,兼顾上下文和精确性 |
A: 从以下几个方面入手:
- 调整
top_k和rerank.top_n - 优化 Embedding 模型
- 使用更好的重排序模型
- 调整
window_size扩展更多上下文
| 指标 | 数值 | 说明 |
|---|---|---|
| 文档处理速度 | 50+ docs/s | 向量化并发处理 |
| 检索延迟 | < 500ms | P99 |
| 端到端问答延迟 | < 3s | 含重排序 |
| Token 压缩效率 | 70%+ | 平均压缩比 |
| 组件 | 技术选型 | 版本 |
|---|---|---|
| LLM 框架 | LangChain + LangGraph | 1.2+ / 1.0+ |
| 向量数据库 | Milvus | 2.4+ |
| 对象存储 | 阿里云 OSS | - |
| Embedding | 通义 Embedding | Qwen3-Embedding |
| 重排序 | 通义 Rerank | qwen3-vl-rerank |
| Chat 模型 | 通义千问 | qwen3.5-flash |
| 文档解析 | Unstructured | - |
| 评估框架 | Ragas | 0.4+ |
| 日志美化 | Rich | 14+ |
欢迎提交 Issue 和 Pull Request!
- Fork 本仓库
- 创建特性分支 (
git checkout -b feature/AmazingFeature) - 提交更改 (
git commit -m 'Add some AmazingFeature') - 推送到分支 (
git push origin feature/AmazingFeature) - 创建 Pull Request
本项目采用 MIT 许可证 - 详见 LICENSE 文件
- LangChain - LLM 应用框架
- Milvus - 向量数据库
- Unstructured - 文档解析
- Ragas - RAG 评估框架
⭐ 如果这个项目对你有帮助,请给个 Star!