import sys from pathlib import Path from dotenv import load_dotenv load_dotenv() from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from fastapi.responses import RedirectResponse from contextlib import asynccontextmanager from api import router # ============================================================ # 应用生命周期 # ============================================================ @asynccontextmanager async def lifespan(app: FastAPI): """应用启动/关闭时的生命周期管理""" import threading print("=" * 60) print(" 煤矿通风数据智能解读系统 启动中...") print("=" * 60) # === 关键优化:在后台线程预热 Agent,不阻塞 uvicorn 启动 === # 原因:create_deep_agent 需要导入 langchain/langgraph 并编译状态图, # 首次执行耗时可达数分钟,阻塞 uvicorn 等待 lifespan 完成后才接受请求。 # 改为后台预热后,服务可以在几秒内就绪,Agent 在后台慢慢初始化。 # # 首次请求如果 Agent 还没预热完,routes.py 中的 get_xxx_agent() 会触发懒加载, # 第一个请求会稍慢(等待编译完成),后续请求就是热实例直接用了。 agent_ready = threading.Event() def _warmup_agents(): """后台线程:预热 Agent 实例""" try: from agents.vent_agent import get_click_agent, get_dialog_agent print("[启动] 后台预热点选解读 Agent...(不阻塞服务就绪)") get_click_agent() print("[启动] 后台预热对话解读 Agent...(不阻塞服务就绪)") get_dialog_agent() # ── 预热配风计划审查 Agent(消除首次请求的图编译开销)── from agents.review_agent import ( get_form_review_agent, get_data_consistency_agent, get_calc_verification_agent, get_summary_agent, ) print("[启动] 后台预热形式审查 Agent...") get_form_review_agent() print("[启动] 后台预热数据一致性审查 Agent...") get_data_consistency_agent() print("[启动] 后台预热计算核验审查 Agent...") get_calc_verification_agent() print("[启动] 后台预热汇总审查 Agent...") get_summary_agent() print("[启动] Agent 预热完成,服务已完全就绪") except Exception as e: print(f"[警告] Agent 预初始化失败(将在首次请求时懒加载): {e}") finally: agent_ready.set() threading.Thread(target=_warmup_agents, daemon=True, name="agent-warmup").start() print("[启动] 服务已就绪(Agent 后台预热中),监听 http://0.0.0.0:8000") print("[启动] API 文档: http://localhost:8000/docs") print("=" * 60) yield # 关闭时清理 print("[关闭] 服务停止") # ============================================================ # 创建 FastAPI 应用 # ============================================================ app = FastAPI( title="煤矿通风数据智能解读系统", description=""" 基于 DeepAgents 框架的煤矿通风监测数据智能解读服务。 ## 功能 - **点选数据解读**: 对单条巷道监测数据进行深度合规分析 - **对话式数据解读**: 通过自然语言对话查询和分析通风数据 - **聊天历史**: 查询和管理对话历史记录 ## 技术栈 - DeepAgents (LangChain) - Agent 编排 - FastAPI - Web 框架 - SQLite - 聊天历史存储 - SSE - 流式响应 """, version="1.0.0", lifespan=lifespan, ) # CORS 配置(允许前端跨域访问) app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # 注册路由 app.include_router(router) # 静态文件服务(审查报告 .docx 下载) _static_dir = Path(__file__).parent / "static" _static_dir.mkdir(parents=True, exist_ok=True) (_static_dir / "reports").mkdir(exist_ok=True) app.mount("/static", StaticFiles(directory=str(_static_dir)), name="static") # ============================================================ # 根路由 → Chat UI # ============================================================ @app.get("/") async def root(): """根路径重定向到聊天界面""" return RedirectResponse(url="/static/index.html") # ============================================================ # 健康检查 # ============================================================ @app.get("/health") async def health_check(): """健康检查接口""" return { "status": "ok", "service": "煤矿通风数据智能解读系统", "version": "1.0.0", } # ============================================================ # 直接运行入口 # ============================================================ if __name__ == "__main__": import uvicorn uvicorn.run( "main:app", host="0.0.0.0", port=8070, reload=True, log_level="info", )