| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- """
- 研创·智核 - 主应用入口
- """
- import asyncio
- import logging
- from contextlib import asynccontextmanager
- from fastapi import FastAPI, Request
- from fastapi.middleware.cors import CORSMiddleware
- from fastapi.middleware.trustedhost import TrustedHostMiddleware
- from fastapi.responses import JSONResponse
- from fastapi.staticfiles import StaticFiles
- import uvicorn
- from innocore_ai.core.config import settings
- from innocore_ai.core.database import engine, Base
- from innocore_ai.core.exceptions import InnoCoreException
- from innocore_ai.api.routes import papers, users, tasks, analysis, writing
- from innocore_ai.agents.controller import AgentController
- # 配置日志
- logging.basicConfig(
- level=getattr(logging, settings.LOG_LEVEL),
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
- )
- logger = logging.getLogger(__name__)
- # 全局智能体控制器
- agent_controller = None
- @asynccontextmanager
- async def lifespan(app: FastAPI):
- """应用生命周期管理"""
- # 启动时执行
- logger.info("Starting InnoCore AI application...")
-
- # 创建数据库表
- Base.metadata.create_all(bind=engine)
- logger.info("Database tables created")
-
- # 初始化智能体控制器
- global agent_controller
- agent_controller = AgentController()
- await agent_controller.initialize()
- logger.info("Agent controller initialized")
-
- yield
-
- # 关闭时执行
- logger.info("Shutting down InnoCore AI application...")
- if agent_controller:
- await agent_controller.shutdown()
- logger.info("Application shutdown complete")
- # 创建FastAPI应用
- app = FastAPI(
- title="研创·智核 API",
- description="基于多智能体架构的智能科研助手平台",
- version="1.0.0",
- docs_url="/docs" if settings.DEBUG else None,
- redoc_url="/redoc" if settings.DEBUG else None,
- lifespan=lifespan
- )
- # 添加中间件
- app.add_middleware(
- CORSMiddleware,
- allow_origins=settings.ALLOWED_HOSTS,
- allow_credentials=True,
- allow_methods=["*"],
- allow_headers=["*"],
- )
- app.add_middleware(
- TrustedHostMiddleware,
- allowed_hosts=settings.ALLOWED_HOSTS
- )
- # 挂载静态文件
- try:
- app.mount("/static", StaticFiles(directory="innocore_ai/frontend/static"), name="static")
- except Exception:
- # 如果路径不存在,尝试相对路径
- app.mount("/static", StaticFiles(directory="frontend/static"), name="static")
- # 注册路由
- app.include_router(users.router, prefix="/api/v1/auth", tags=["认证"])
- app.include_router(papers.router, prefix="/api/v1/papers", tags=["论文管理"])
- app.include_router(tasks.router, prefix="/api/v1/tasks", tags=["任务管理"])
- app.include_router(analysis.router, prefix="/api/v1/analysis", tags=["分析报告"])
- app.include_router(writing.router, prefix="/api/v1/writing", tags=["学术写作"])
- # 前端路由
- @app.get("/")
- async def read_root():
- """前端主页"""
- try:
- from fastapi.responses import FileResponse
- return FileResponse("innocore_ai/frontend/index.html")
- except Exception:
- return FileResponse("frontend/index.html")
- @app.get("/dashboard")
- async def dashboard():
- """仪表板页面"""
- try:
- from fastapi.responses import FileResponse
- return FileResponse("innocore_ai/frontend/templates/dashboard.html")
- except Exception:
- return FileResponse("frontend/templates/dashboard.html")
- @app.get("/login")
- async def login():
- """登录页面"""
- try:
- from fastapi.responses import FileResponse
- return FileResponse("innocore_ai/frontend/templates/login.html")
- except Exception:
- return FileResponse("frontend/templates/login.html")
- # 处理前端路由的通配符(用于SPA)
- @app.get("/frontend/{path:path}")
- async def frontend_files(path: str):
- """前端静态文件"""
- try:
- from fastapi.responses import FileResponse
- file_path = f"innocore_ai/frontend/{path}"
- return FileResponse(file_path)
- except Exception:
- file_path = f"frontend/{path}"
- return FileResponse(file_path)
- @app.get("/health")
- async def health_check():
- """健康检查"""
- return {
- "status": "healthy",
- "version": "1.0.0",
- "service": "InnoCore AI"
- }
- @app.get("/api/v1/dashboard/stats")
- async def get_dashboard_stats(request: Request):
- """获取仪表板统计数据"""
- # 这里应该从数据库获取真实数据
- return {
- "total_papers": 156,
- "total_tasks": 42,
- "total_analyses": 28,
- "total_writings": 15,
- "recent_activities": [
- {"type": "paper_added", "title": "深度学习在医学图像分析中的应用", "time": "2小时前"},
- {"type": "task_completed", "title": "文献搜索:机器学习", "time": "4小时前"},
- {"type": "analysis_generated", "title": "10篇论文综合分析", "time": "1天前"}
- ]
- }
- # 全局异常处理
- @app.exception_handler(InnoCoreException)
- async def innocore_exception_handler(request: Request, exc: InnoCoreException):
- """处理自定义异常"""
- return JSONResponse(
- status_code=exc.status_code,
- content={
- "error": exc.error_code,
- "message": exc.message,
- "details": exc.details
- }
- )
- @app.exception_handler(Exception)
- async def general_exception_handler(request: Request, exc: Exception):
- """处理通用异常"""
- logger.error(f"Unhandled exception: {exc}", exc_info=True)
- return JSONResponse(
- status_code=500,
- content={
- "error": "INTERNAL_SERVER_ERROR",
- "message": "服务器内部错误",
- "details": str(exc) if settings.DEBUG else None
- }
- )
- # 请求日志中间件
- @app.middleware("http")
- async def log_requests(request: Request, call_next):
- """记录请求日志"""
- start_time = asyncio.get_event_loop().time()
-
- # 记录请求
- logger.info(f"Request: {request.method} {request.url}")
-
- # 处理请求
- response = await call_next(request)
-
- # 计算处理时间
- process_time = asyncio.get_event_loop().time() - start_time
-
- # 记录响应
- logger.info(f"Response: {response.status_code} - {process_time:.4f}s")
-
- # 添加处理时间到响应头
- response.headers["X-Process-Time"] = str(process_time)
-
- return response
- def create_app():
- """创建应用实例"""
- return app
- if __name__ == "__main__":
- uvicorn.run(
- "innocore_ai.main:app",
- host=settings.HOST,
- port=settings.PORT,
- reload=settings.DEBUG,
- log_level=settings.LOG_LEVEL.lower()
- )
|