ReAct-RAG-Agent
面向金融研报问答、私有知识库检索与多工具分析生成的企业级 ReAct-RAG Agent。
核心目标:让用户用自然语言完成「跨研报检索 → 可信溯源 → 联网补充 → Word / Excel / Markdown 输出 → 多轮会话延续」。
1. 项目定位
金融分析师、投研人员或行业研究团队每天需要阅读大量研报、年报、公告和政策材料。传统流程通常是逐篇打开 PDF、手动搜索关键词、复制表格、再整理成报告,效率低且容易遗漏来源。
本项目实现了一个面向金融研报场景的 ReAct-RAG Agent,能够:
- 在私有研报知识库中检索公司、行业、指标、事件相关内容;
- 对回答中的关键结论标注来源文件和页码,便于追溯和复核;
- 结合联网搜索补充公开信息;
- 调用工具生成 Excel、Word、Markdown 等结构化交付物;
- 通过 Checkpoint 持久化保存会话上下文,支持多轮追问;
- 通过 Streamlit UI 和 FastAPI REST / SSE 双入口接入前端或外部系统;
- 通过 MCP Server 将金融研报 RAG 能力接入支持 MCP 的客户端。
本仓库不包含私有研报数据、向量库、密钥、运行日志和本地数据库。请通过
.env.example配置环境变量,并将自己的 PDF / 数据文件放入本地忽略目录中。
2. 关于这个项目
3. 已验证使用场景
- 跨文档研报问答:从数百份 PDF 中定位涉及特定公司、行业、财务指标或政策事件的段落,并返回来源页码。
- 财务指标精查:
sql.py提供 Text2SQL 路径,可对 SQLite 财务指标库进行自然语言查询,并返回source_file/source_page。 - 联网搜索 + 研究报告生成:先搜索公开事件,再生成带章节结构和来源标注的
.docx报告。 - 同一会话多格式输出:一轮分析后继续追问「整理成 Word」或「生成公司对比 Excel」,Agent 会基于当前上下文调用对应工具。
- 外部系统接入:通过 REST API / SSE 接入 n8n、自定义前端、第三方服务或自动化工作流。
4. 系统架构

flowchart LR
U[User / Frontend] --> S[Streamlit UI]
U --> A[FastAPI REST + SSE]
S --> G[PersistentAgent]
A --> G
G --> LG[LangGraph ReAct Workflow]
LG --> T1[RAG Tool]
LG --> T2[Web Search Tool]
LG --> T3[Excel / Word / Markdown Tools]
T1 --> P[PDF Parser]
P --> R[BM25 + Vector Retriever]
R --> RR[RRF Fusion]
RR --> CE[Cross-Encoder Reranker]
CE --> C[Semantic Cache]
G --> CP[Checkpoint Store]
C --> Redis[(Redis)]
CP --> DB[(SQLite / PostgreSQL / Redis / Memory)]
核心链路
用户请求
→ Streamlit / FastAPI
→ PersistentAgent
→ LangGraph ReAct 循环
→ 工具调用:RAG / Search / Excel / Word / Markdown
→ 反思与结果整理
→ 带来源、工具轨迹、token / cost 信息的响应
5. 核心模块
5.1 Core:Agent 图与状态
5.2 RAG:私有知识库检索
检索流程:
PDF / 文档
→ 版面解析与表格抽取
→ chunking
→ BM25 Top-10 + Vector Top-10
→ RRF 融合到最多 20 个候选
→ Cross-Encoder 精排
→ Top-3 返回给 Agent
5.3 Tools:Agent 工具层
当前默认注册工具以
react_agent/tools/__init__.py为准。sql.py已实现但默认未注册时,不会被 Agent 自动调用。
5.4 API:FastAPI 服务层
FastAPI 与 Streamlit 并存,共享同一套 Agent 实例与持久化存储。
5.5 MCP Server:外部 MCP 客户端接入
本项目新增 stdio 模式 MCP Server,用于将金融研报 RAG 能力接入 Claude Desktop、Cursor、Claude Code、MCP Inspector 等支持 MCP 的客户端。
MCP 启动方式:
cd src
python mcp_rag_server.py
使用 MCP Inspector 测试:
cd src
npx -y @modelcontextprotocol/inspector -- python mcp_rag_server.py
使用 Codex 外接测试
codex mcp add financial-rag --env MCP_EXPOSE_ADMIN_TOOLS=0 -- "E:\anaconda\envs\agent_base\python.exe" "E:\transformer_program\nanoGPT_program\AI_Agent\agent_v0\react-agent-main\src\mcp_rag_server.py"
# 确认是否注册:
/mcp
query: 根据内部数据库,2026 年 1 月,国内领先的芯片设计企业兆易创新和谁正式签署战略合作协议?
MCP 启动入口遵循“薄启动”原则:启动阶段不预热 embedding、reranker、Chroma、Redis 等重资源,避免 stdio 握手阶段阻塞。普通业务查询只需调用 query_financial_reports;首次查询会自动触发 retriever / reranker 单例预热并进行有限等待。诊断或显式预热场景可设置 MCP_EXPOSE_ADMIN_TOOLS=1,再调用 start_rag_singleton_warmup / get_rag_singleton_warmup_status。
6. API 示例
健康检查
curl http://localhost:8000/health
非流式调用
curl -X POST http://localhost:8000/api/v1/chat/invoke \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"message": "总结新能源行业最近的投资主线,并给出来源",
"session_id": "demo-session"
}'
SSE 流式调用
curl -N -X POST http://localhost:8000/api/v1/chat/stream \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"message": "检索半导体行业最近的供需变化,并生成要点",
"session_id": "demo-session"
}'
流式事件类型:
token | tool_call | tool_result | usage | done | error
Prometheus 指标
curl http://localhost:8000/api/v1/metrics
7. 快速启动
7.1 环境准备
推荐 Python 3.10+。
git clone https://github.com/lihaibohhh/ReAct-RAG-Agent.git
cd ReAct-RAG-Agent/src
使用 uv:
uv sync
或使用 pip:
pip install -r requirements.txt
7.2 配置环境变量
cp .env.example .env
根据自己的模型和工具服务填写:
LLM_PROVIDER=deepseek
DEEPSEEK_API_KEY=your_deepseek_api_key
TAVILY_API_KEY=your_tavily_api_key
# 可选:Redis / PostgreSQL / LangSmith 等
REDIS_URL=redis://localhost:6379/0
POSTGRES_URL=postgresql://user:password@localhost:5432/dbname
7.3 启动 Streamlit
cd src
streamlit run tests/test_agent.py
7.4 启动 FastAPI
cd src
uvicorn api.main:app --host 0.0.0.0 --port 8000 --reload
Swagger 文档:
http://localhost:8000/docs
8. 测试与评测
8.1 API 回归测试
pytest tests/api -q
测试设计要点:
- 使用 FakeAgent 替代真实 LLM;
- 使用 fakeredis 替代真实 Redis;
- 覆盖鉴权、限流、错误信封、SSE 断连、Prometheus、会话 CRUD、IDOR 防护;
- CI 中不调用真实模型,不消耗 API 费用。
8.2 RAGAS 评测
python eval/run_eval.py
支持检索评测与端到端评测。已验证指标:
8.3 向量库建库性能
9. 工程亮点与关键取舍
9.1 PDF 解析:从“能读”到“能用于金融研报”
金融研报常见双栏排版、表格密集、页眉页脚干扰。简单 PDF loader 容易造成左右栏交错、表格断裂、页码丢失。本项目改用 PyMuPDF 读取坐标块,按版面重建阅读顺序;表格由 pdfplumber 抽取后转 Markdown 整块保留,避免字符分块器破坏行列结构。
9.2 检索:双路召回 + RRF + reranker
BM25 擅长股票代码、公司名、指标名等精确匹配;向量检索擅长语义近似。两路 Top-K 召回后用 RRF 融合,再交给 Cross-Encoder 精排。召回池从 10 扩到 20 后,减少相关文档在检索阶段被提前丢弃的问题。
9.3 语义缓存:只缓存“可信结果”
早期实现中,低相关结果也会被缓存 1 小时,后续相似 query 命中缓存后会跳过新检索,造成错误固化。本项目让 reranker 返回 top_score,写入缓存前进行门控:
9.4 工具调用协议:把消息序列合法性作为强约束
DeepSeek / LangChain 工具调用中,复杂工具参数可能进入 .invalid_tool_calls,如果路由只看 .tool_calls,就会误判“没有工具调用”,导致悬空 tool_call 被写入 checkpoint,下一轮恢复历史时触发多轮 400 死锁。
本项目统一封装 _ai_tool_call_ids(),同时覆盖 .tool_calls 与 .invalid_tool_calls,并在路由、入口净化、异常兜底三层使用同一检测口径。这个问题的教训是:协议检测必须与实际发送给模型的序列化路径保持一致。
9.5 FastAPI serving:从 demo 接口到可运营服务
这轮服务化改造不仅是“加几个接口”,而是补齐了 LLM 应用上线前常见的工程护栏:
- API versioning;
- request_id 全链路追踪;
- problem+json 统一错误;
- API Key 鉴权;
- 匿名 IP bucket 限流;
- per-user token 预算;
- token 级 SSE;
- 断连取消上游 LLM;
- Prometheus 指标;
- 零真实依赖的回归测试。
9.6 MCP RAG 冷启动处理
MCP 改造中定位到的问题:首次 query_financial_reports 变慢的主要根因不是 BM25、Chroma、Redis、reranker 或 _dual_retrieve() 算法本身,而是 LangSmith/LangChain tracing 在首次 retriever.invoke() 时采集 runtime metadata,触发 git describe --tags --always --dirty 并卡住 40 秒以上。
已落地的处理方式:
mcp_rag_server.py改为 stdio 薄启动入口,启动时不做重资源预热;- MCP 进程启动后强制关闭
LANGCHAIN_TRACING_V2、LANGSMITH_TRACING_V2、LANGCHAIN_TRACING、LANGSMITH_TRACING; - MCP 相关工具拆分到
react_agent/mcp_server/目录,按职责模块化注册; - 预热只加载
_get_retriever()与_get_reranker()两个进程内单例; start_rag_singleton_warmup可手动后台触发单例预热,立即返回;get_rag_singleton_warmup_status用于查询后台单例预热状态;- RAG 查询工具保留语义缓存命中路径,减少重复查询成本。
推荐使用流程:
1. List Tools
2. query_financial_reports
如需管理员提前预热,可手动执行:
1. MCP_EXPOSE_ADMIN_TOOLS=1
2. start_rag_singleton_warmup
3. get_rag_singleton_warmup_status,直到 warmup_status.state=done
4. query_financial_reports
当前已确认的问题边界:完整 RAG 链路预热不是解决首次慢 query 的关键;关闭 tracing 后,预热应降级为“只创建 retriever/reranker 单例”,避免额外执行 _dual_retrieve() 与真实 rerank。
10. 目录结构
react-agent-main/
└── src/
├── api/ # FastAPI 服务层
│ ├── main.py # app 入口、lifespan、路由挂载
│ ├── settings.py # 配置校验
│ ├── errors.py # problem+json 错误信封
│ ├── middleware.py # request_id 日志与 Prometheus 采集
│ ├── security.py # API Key 鉴权
│ ├── ratelimit.py # Redis 限流与 token 预算
│ ├── metrics.py # Prometheus 指标
│ └── routes/
│ ├── chat.py # legacy chat 路由
│ └── v1/
│ ├── chat.py # v1 token 级 SSE / invoke
│ └── sessions.py # 会话历史与删除
├── react_agent/
│ ├── core/ # LangGraph 工作流、节点、路由、状态、checkpointer
│ ├── rag/ # PDF 解析、分块、召回、精排、语义缓存、向量库
│ ├── tools/ # RAG / Search / Excel / Word / Markdown / SQL
│ ├── mcp_server/ # MCP 工具注册与 stdio Server 模块
│ │ ├── app.py # 创建 MCP Server;默认注册 info/rag,admin 模式注册 health/warmup
│ │ ├── info_tools.py # server_info:当前可用工具与能力边界
│ │ ├── health_tools.py # check_knowledge_base,可选 admin 工具
│ │ ├── warmup_manager.py # RAG 单例预热运行时:_get_retriever / _get_reranker
│ │ ├── warmup_tools.py # RAG 单例预热启动 / 状态查询,可选 admin 工具
│ │ ├── rag_tools.py # query_financial_reports
│ │ └── responses.py # mcp_ok / mcp_err 返回结构
│ ├── memory/ # Context 配置
│ └── utils/ # LLM、Redis、token、tool helpers
├── eval/ # RAGAS 评测脚本与数据生成
├── scripts/ # PDF 检查、财务抽取、Redis 检查、历史管理
├── tests/ # Streamlit 入口与 API 回归测试
├── config.yaml # 运行时配置
├── mcp_rag_server.py # MCP stdio 薄启动入口:关闭 tracing / 日志 / create_mcp_server
├── pyproject.toml
├── requirements.txt
├── .env.example
└── .gitignore
11. 当前边界与后续优化
12. 更新日志
2026-07-03:MCP Server warmup 精简与 tracing 关闭
- 将 MCP 工具拆分到
react_agent/mcp_server/,包含app.py、responses.py、info_tools.py、health_tools.py、warmup_manager.py、warmup_tools.py、rag_tools.py; - 改造
mcp_rag_server.py为 stdio 薄启动入口:路径锚定、Windows UTF-8 流修复、.env加载、关闭 tracing、stderr + file 日志,不在握手阶段预热重资源; - 定位首次慢 query 的关键根因为 LangSmith / LangChain tracing 触发 runtime metadata 采集和
git describe长尾; - 删除完整 RAG pipeline warmup,保留
start_rag_singleton_warmup/get_rag_singleton_warmup_status,内部只加载_get_retriever()与_get_reranker()两个进程内单例; - 默认只注册
server_info与query_financial_reports,check_knowledge_base、start_rag_singleton_warmup、get_rag_singleton_warmup_status仅在MCP_EXPOSE_ADMIN_TOOLS=1时暴露; server_info默认只返回普通业务能力,不暴露 hidden admin tools,降低 Claude Code 等 Agent 的信息负担。
2026-06-28:工具调用协议健壮性
- 新增
_ai_tool_call_ids(),统一检测.tool_calls与.invalid_tool_calls; - 修复 invalid tool call 悬空导致的多轮 400 死锁;
- 入口净化、路由、异常兜底统一使用同一检测口径;
- 新增连续 HumanMessage 合并逻辑,减少重试堆积造成的角色交替问题。
2026-06-26:文档生成层
- 新增
docx_tool,支持 Word 研报生成; - 新增
md_tool,支持 Markdown 输出; - 新增
_doc_common.py,复用文档工具公共逻辑; requirements.txt新增python-docx。
2026-06:FastAPI serving 生产化改造
- 新增
/api/v1路由; - 实现 token 级 SSE、断连取消、统一错误、request_id、鉴权、限流、预算、Prometheus;
- 新增 API 回归测试,使用 FakeAgent + fakeredis 避免真实依赖。
13. License
MIT License