基于 ReAct 模式的工具调用 Agent 框架,支持多步推理、工具调用和上下文管理。
┌─────────────────────────────────────────────────┐
│ User Task │
└──────────────────────┬──────────────────────────┘
▼
┌─────────────────────────────────────────────────┐
│ Agent Core (ReAct Loop) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌────────────┐ │
│ │ Thought │──│ Action │──│ Observation│ │
│ │ (推理) │ │ (工具调用)│ │ (结果分析) │ │
│ └──────────┘ └──────────┘ └────────────┘ │
│ ▲ │ │
│ └────────────────────────────────┘ │
│ (循环直到完成) │
└──────────────────────┬──────────────────────────┘
▼
┌─────────────────────────────────────────────────┐
│ Tool Registry │
│ │
│ 📁 file_read 📁 file_write 📁 file_list │
│ 🐍 python_exec 🔍 web_search 📊 data_analysis│
│ 📚 knowledge_search (RAG) │
└─────────────────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────┐
│ LLM Client (OpenAI 兼容) │
│ 支持 OpenAI / DeepSeek / Qwen / MiniMax / ... │
└─────────────────────────────────────────────────┘
内置生产级 RAG 检索链路,支持文档导入、混合检索和智能问答。
文档 → 清洗 → 元数据增强 → 自适应分块 → 双路索引
│
查询 → Query Rewrite → 混合检索 → 连坐召回 → Rerank → 上下文
│
BM25 + 向量 → RRF 融合
数据清洗:文档中的噪音(页面元信息、编辑历史、论坛标记等)通过多轮正则规则迭代清除。清洗完成后同时输出两个版本——Markdown 给机器入库,干净版本给人看。
自适应分块:基于文档长度分布驱动分块策略。短文档(< 5000 字)整篇入库保持语义完整性;长文档(> 6000 字)递归切分,chunk_size=6000,overlap=500。每个切片附带文档标题、摘要和关键词前缀,确保检索到任意切片时都能理解整体上下文。
混合检索:向量检索擅长语义理解但长尾关键词召回不足,BM25 擅长精确关键词匹配但不理解语义。通过 RRF(Reciprocal Rank Fusion)融合两路结果,无需手动调权重。
连坐召回:解决摘要块语义相似度太强导致正文切片被截断的问题。任一切片被命中,即强制拉出父文档全部切片,按 chunk_index 排序后重新拼接。在 Milvus 中通过 search + query/expr 标量过滤实现,速度极快。
Rerank 精排:基于 bge-reranker-v2-m3 的 Cross-Encoder 重排。通过 Recall@K 评测数据驱动调参——粗排候选集从 Top-50 优化至 Top-20,重排耗时从 12.6s 降至 2.8s,召回率保持 99%+。
Query Rewrite:多轮对话场景下,用轻量级模型将指代性问题改写为自包含问题,提升检索准确率。
from rag.engine import KnowledgeBase, KnowledgeBaseTool
from rag.pipeline import Document
# 创建知识库
kb = KnowledgeBase()
await kb.ingest([
Document(doc_id="1", title="Nginx 配置", content="..."),
Document(doc_id="2", title="MQTT 说明", content="..."),
])
# 注册为 Agent 工具
registry.add(KnowledgeBaseTool(kb))
# 或直接检索
results = kb.search("Nginx 如何配置过滤规则", top_k=5)- ReAct 推理循环:思考 → 行动 → 观察,迭代直到任务完成
- 插件化工具系统:通过注册机制灵活扩展工具
- RAG 知识库:混合检索 + 连坐召回 + Rerank 精排,支持文档智能问答
- 上下文管理:Token 感知 + 自动摘要压缩,压缩时保留原始任务,避免 Agent 中途"失忆"
- 多 LLM 适配:兼容 OpenAI API 的任何模型提供商
- SSE 真流式:HTTP 接口边执行边推送每一步,不是跑完再一次性补发
- 安全防护:
- 代码沙箱基于 AST 静态分析,拦截危险导入 / 危险调用 / 内省逃逸,
os.popen、from os import system、__import__('os')等绕过手法均被覆盖 - 文件工具强制 工作区隔离,绝对路径与
../越权访问一律拒绝 - 子进程执行 + 超时强杀 + 输出截断 + 步数限制
- 代码沙箱基于 AST 静态分析,拦截危险导入 / 危险调用 / 内省逃逸,
# 安装依赖
pip install -r requirements.txt
# 配置 API Key
export LLM_API_KEY="your-key-here"
export LLM_BASE_URL="https://api.deepseek.com/v1"
export LLM_MODEL="deepseek-chat"
# CLI 单任务模式
python main.py -t "分析 workspace/sales_data.csv 并生成销售报表"
# CLI 交互模式
python main.py
# API 服务模式
uvicorn agent.server:app --host 0.0.0.0 --port 8000
# Docker 部署
docker build -t tool-agent .
docker run -p 8000:8000 -e LLM_API_KEY="your-key" tool-agenttool-agent/
├── agent/ # Agent 核心
│ ├── core.py # ReAct 循环
│ ├── llm.py # LLM 客户端
│ ├── schema.py # 数据模型
│ ├── prompts.py # Prompt 模板
│ ├── config.py # 配置管理
│ ├── factory.py # 装配工厂(CLI 与服务共用一套工具注册)
│ └── server.py # FastAPI 服务(每请求独立 Agent + SSE 流式)
├── rag/ # RAG 知识库
│ ├── pipeline.py # 文档清洗 + 自适应分块 + 元数据增强
│ ├── retriever.py # 混合检索 (BM25 + 向量 → RRF) + 连坐召回
│ ├── reranker.py # Rerank 精排 + Query Rewrite + Recall@K 评测
│ └── engine.py # 知识库引擎 + Agent 工具封装
├── tools/ # 工具系统
│ ├── base.py # 工具基类 + 注册表
│ ├── file_ops.py # 文件操作
│ ├── code_exec.py # Python 代码执行
│ ├── search.py # 网页搜索
│ └── data_analysis.py # 数据分析
├── examples/ # 示例
│ ├── demo_report.py # 报表生成
│ └── demo_research.py # 信息调研
├── tests/ # 测试 (101 cases)
├── conftest.py # pytest 路径配置
├── pytest.ini # pytest 配置(asyncio_mode=auto)
├── config.yaml # 配置文件
├── Dockerfile # 容器化部署
└── main.py # CLI 入口
默认关闭。在 config.yaml 中开启后,Agent 的工具从 6 个变为 7 个
(新增 knowledge_search),启动时自动导入 knowledge_dir 下的文档:
rag:
enabled: true
knowledge_dir: "./knowledge"
short_threshold: 5000 # 短于此长度的文档整篇入库,不切分
chunk_size: 6000
chunk_overlap: 500
rerank_pool_size: 20 # 粗排候选池,Top-50 → Top-20 是实测的性价比拐点
top_k: 5pytest # 全量 101 个用例
pytest -m "not slow"from tools.base import Tool, ToolResult
class MyTool(Tool):
name = "my_tool"
description = "描述你的工具功能"
parameters = {
"type": "object",
"properties": {
"input": {"type": "string", "description": "输入参数"},
},
"required": ["input"],
}
async def execute(self, input: str) -> ToolResult:
# 实现你的逻辑
return ToolResult(success=True, content=f"Processed: {input}")
# 注册到 Agent
registry.add(MyTool())cd tool-agent
python -m pytest tests/ -vMIT