采用自定义编排器 + 3个独立 DeepAgent的架构(而非 deepagents 的 subagent 模式),原因是用户要求"固定3个子智能体、按固定流程并行检查",自定义编排器保证确定性并行执行,而 deepagents 的 subagent 由 LLM 决定何时调用,不够确定。
POST /api/vent/review/pdf
│
▼
stream_review() 编排器
│
1. PDF文本提取 (PyPDF2 → PaddleOCR)
2. 创建3个 DeepAgent 实例
3. asyncio 并行执行
4. 流式 yield SSE 进度事件
5. 汇总合并结果
┌───────┬───────┬───────┐
▼ ▼ ▼
Agent1 Agent2 Agent3
表单审查 数据一致性 计算核验
requirements.txt — 新增依赖pypdf>=5.0
paddleocr>=2.9
paddlepaddle>=3.0
tools/pdf_tools.py — 新建 PDF 提取工具extract_pdf_text(file_path): PyPDF2 提取 → 失败则 PaddleOCRsave_upload_file(upload_file): 保存上传文件到临时目录tools/calc_tools.py — 新建本地需风量计算工具按《煤矿安全规程》和 AQ 1056 标准,实现各用风地点类型的计算工具:
| 工具函数 | 用途 |
|---|---|
calc_face_air_volume_by_gas(q_gas, k_gas) |
采煤面-按瓦斯涌出量 Q=100×q×K |
calc_face_air_volume_by_workers(n) |
采煤面-按人数 Q=4×N |
calc_face_air_volume_by_wind_speed(v, s) |
采煤面-按风速 Q=60×S×v |
calc_face_air_volume_max(...) |
采煤面-取最大值 |
calc_tunnel_air_volume_by_gas(q_gas, k_gas) |
掘进面-按瓦斯 Q=100×q×K |
calc_tunnel_air_volume_by_explosives(a) |
掘进面-按炸药 Q=25×A |
calc_tunnel_air_volume_by_workers(n) |
掘进面-按人数 Q=4×N |
calc_tunnel_air_volume_by_wind_speed(v, s) |
掘进面-按风速 Q=60×S×v |
calc_chamber_air_volume(...) |
硐室-机电设备配风 |
calc_other_air_volume_by_wind_speed(v, s) |
其他巷道-按风速 |
calc_effective_area(max_control, min_control, avg_height) |
有效断面积计算 |
每个工具返回列式:{formula, steps, result} 结构化数据,供 LLM 对比。
agents/review_agent.py — 新建审查 Agent 工厂基于现有 vent_agent.py 的模式,复用 _get_model() 和 FilesystemBackend:
create_form_review_agent() → 子智能体1:基本形式审查
skills/vent-plan-review-formwrite_todoscreate_data_consistency_agent() → 子智能体2:数据一致性审查
skills/vent-plan-review-datawrite_todos + (MCP 工具预留接口)create_calc_verification_agent() → 子智能体3:计算核验
skills/vent-plan-review-calcwrite_todos + 所有 calc_tools 函数create_summary_agent() → 汇总 Agent
stream_review(file, message, session_id) → 核心编排器异步生成器
asyncio.gather 并行执行 → yield SSE 事件 → 汇总skills/vent-plan-review-form/SKILL.md — 新建形式审查技能,包含:
skills/vent-plan-review-data/SKILL.md — 新建数据一致性审查技能,包含:
skills/vent-plan-review-calc/SKILL.md — 新建计算核验技能,包含:
api/routes.py — 修改新增端点:
@router.post("/api/vent/review/pdf")
async def api_review(
file: UploadFile = File(),
session_id: str | None = Form(default=None),
message: str | None = Form(default=None)
):
return StreamingResponse(
stream_review(file, message, session_id),
media_type="text/event-stream",
headers={
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"X-Accel-Buffering": "no"
}
)
| type | 描述 | 关键字段 |
|---|---|---|
progress |
进度描述(LLM 翻译后的文字) | message, agent? |
agent_start |
子智能体开始审查 | agent (form-review/data-check/calc-verify) |
agent_done |
子智能体审查完成 | agent, content (摘要) |
agent_error |
子智能体审查出错 | agent, message |
token |
汇总报告的 token 流 | content |
done |
审查结束 | session_id |
error |
整体错误 | message |
asyncio.Queue 收集各 Agent 的进度事件,编排器从队列读取并 yield SSEvent_agent.py 的 _get_model() 函数,确保模型配置一致FilesystemBackend(virtual_mode=True) 模式,skills 路径为 skills/vent-plan-review-*tools/pdf_tools.py — PDF 提取tools/calc_tools.py — 计算工具skills/vent-plan-review-form/SKILL.md — 表单审查技能skills/vent-plan-review-data/SKILL.md — 数据一致性技能skills/vent-plan-review-calc/SKILL.md — 计算核验技能agents/review_agent.py — Agent 工厂 + 编排器api/routes.py — 新增端点requirements.txt — 更新依赖