main.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. """
  2. 研创·智核 - 主应用入口
  3. """
  4. import asyncio
  5. import logging
  6. from contextlib import asynccontextmanager
  7. from fastapi import FastAPI, Request
  8. from fastapi.middleware.cors import CORSMiddleware
  9. from fastapi.middleware.trustedhost import TrustedHostMiddleware
  10. from fastapi.responses import JSONResponse
  11. from fastapi.staticfiles import StaticFiles
  12. import uvicorn
  13. from innocore_ai.core.config import settings
  14. from innocore_ai.core.database import engine, Base
  15. from innocore_ai.core.exceptions import InnoCoreException
  16. from innocore_ai.api.routes import papers, users, tasks, analysis, writing
  17. from innocore_ai.agents.controller import AgentController
  18. # 配置日志
  19. logging.basicConfig(
  20. level=getattr(logging, settings.LOG_LEVEL),
  21. format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
  22. )
  23. logger = logging.getLogger(__name__)
  24. # 全局智能体控制器
  25. agent_controller = None
  26. @asynccontextmanager
  27. async def lifespan(app: FastAPI):
  28. """应用生命周期管理"""
  29. # 启动时执行
  30. logger.info("Starting InnoCore AI application...")
  31. # 创建数据库表
  32. Base.metadata.create_all(bind=engine)
  33. logger.info("Database tables created")
  34. # 初始化智能体控制器
  35. global agent_controller
  36. agent_controller = AgentController()
  37. await agent_controller.initialize()
  38. logger.info("Agent controller initialized")
  39. yield
  40. # 关闭时执行
  41. logger.info("Shutting down InnoCore AI application...")
  42. if agent_controller:
  43. await agent_controller.shutdown()
  44. logger.info("Application shutdown complete")
  45. # 创建FastAPI应用
  46. app = FastAPI(
  47. title="研创·智核 API",
  48. description="基于多智能体架构的智能科研助手平台",
  49. version="1.0.0",
  50. docs_url="/docs" if settings.DEBUG else None,
  51. redoc_url="/redoc" if settings.DEBUG else None,
  52. lifespan=lifespan
  53. )
  54. # 添加中间件
  55. app.add_middleware(
  56. CORSMiddleware,
  57. allow_origins=settings.ALLOWED_HOSTS,
  58. allow_credentials=True,
  59. allow_methods=["*"],
  60. allow_headers=["*"],
  61. )
  62. app.add_middleware(
  63. TrustedHostMiddleware,
  64. allowed_hosts=settings.ALLOWED_HOSTS
  65. )
  66. # 挂载静态文件
  67. try:
  68. app.mount("/static", StaticFiles(directory="innocore_ai/frontend/static"), name="static")
  69. except Exception:
  70. # 如果路径不存在,尝试相对路径
  71. app.mount("/static", StaticFiles(directory="frontend/static"), name="static")
  72. # 注册路由
  73. app.include_router(users.router, prefix="/api/v1/auth", tags=["认证"])
  74. app.include_router(papers.router, prefix="/api/v1/papers", tags=["论文管理"])
  75. app.include_router(tasks.router, prefix="/api/v1/tasks", tags=["任务管理"])
  76. app.include_router(analysis.router, prefix="/api/v1/analysis", tags=["分析报告"])
  77. app.include_router(writing.router, prefix="/api/v1/writing", tags=["学术写作"])
  78. # 前端路由
  79. @app.get("/")
  80. async def read_root():
  81. """前端主页"""
  82. try:
  83. from fastapi.responses import FileResponse
  84. return FileResponse("innocore_ai/frontend/index.html")
  85. except Exception:
  86. return FileResponse("frontend/index.html")
  87. @app.get("/dashboard")
  88. async def dashboard():
  89. """仪表板页面"""
  90. try:
  91. from fastapi.responses import FileResponse
  92. return FileResponse("innocore_ai/frontend/templates/dashboard.html")
  93. except Exception:
  94. return FileResponse("frontend/templates/dashboard.html")
  95. @app.get("/login")
  96. async def login():
  97. """登录页面"""
  98. try:
  99. from fastapi.responses import FileResponse
  100. return FileResponse("innocore_ai/frontend/templates/login.html")
  101. except Exception:
  102. return FileResponse("frontend/templates/login.html")
  103. # 处理前端路由的通配符(用于SPA)
  104. @app.get("/frontend/{path:path}")
  105. async def frontend_files(path: str):
  106. """前端静态文件"""
  107. try:
  108. from fastapi.responses import FileResponse
  109. file_path = f"innocore_ai/frontend/{path}"
  110. return FileResponse(file_path)
  111. except Exception:
  112. file_path = f"frontend/{path}"
  113. return FileResponse(file_path)
  114. @app.get("/health")
  115. async def health_check():
  116. """健康检查"""
  117. return {
  118. "status": "healthy",
  119. "version": "1.0.0",
  120. "service": "InnoCore AI"
  121. }
  122. @app.get("/api/v1/dashboard/stats")
  123. async def get_dashboard_stats(request: Request):
  124. """获取仪表板统计数据"""
  125. # 这里应该从数据库获取真实数据
  126. return {
  127. "total_papers": 156,
  128. "total_tasks": 42,
  129. "total_analyses": 28,
  130. "total_writings": 15,
  131. "recent_activities": [
  132. {"type": "paper_added", "title": "深度学习在医学图像分析中的应用", "time": "2小时前"},
  133. {"type": "task_completed", "title": "文献搜索:机器学习", "time": "4小时前"},
  134. {"type": "analysis_generated", "title": "10篇论文综合分析", "time": "1天前"}
  135. ]
  136. }
  137. # 全局异常处理
  138. @app.exception_handler(InnoCoreException)
  139. async def innocore_exception_handler(request: Request, exc: InnoCoreException):
  140. """处理自定义异常"""
  141. return JSONResponse(
  142. status_code=exc.status_code,
  143. content={
  144. "error": exc.error_code,
  145. "message": exc.message,
  146. "details": exc.details
  147. }
  148. )
  149. @app.exception_handler(Exception)
  150. async def general_exception_handler(request: Request, exc: Exception):
  151. """处理通用异常"""
  152. logger.error(f"Unhandled exception: {exc}", exc_info=True)
  153. return JSONResponse(
  154. status_code=500,
  155. content={
  156. "error": "INTERNAL_SERVER_ERROR",
  157. "message": "服务器内部错误",
  158. "details": str(exc) if settings.DEBUG else None
  159. }
  160. )
  161. # 请求日志中间件
  162. @app.middleware("http")
  163. async def log_requests(request: Request, call_next):
  164. """记录请求日志"""
  165. start_time = asyncio.get_event_loop().time()
  166. # 记录请求
  167. logger.info(f"Request: {request.method} {request.url}")
  168. # 处理请求
  169. response = await call_next(request)
  170. # 计算处理时间
  171. process_time = asyncio.get_event_loop().time() - start_time
  172. # 记录响应
  173. logger.info(f"Response: {response.status_code} - {process_time:.4f}s")
  174. # 添加处理时间到响应头
  175. response.headers["X-Process-Time"] = str(process_time)
  176. return response
  177. def create_app():
  178. """创建应用实例"""
  179. return app
  180. if __name__ == "__main__":
  181. uvicorn.run(
  182. "innocore_ai.main:app",
  183. host=settings.HOST,
  184. port=settings.PORT,
  185. reload=settings.DEBUG,
  186. log_level=settings.LOG_LEVEL.lower()
  187. )