""" FastAPI 应用主模块 创建和配置 FastAPI 应用,包括路由、中间件等。 启动(在 backend 目录下、已激活虚拟环境时,推荐短命令):: uvicorn main:app --host 0.0.0.0 --port 7861 开发热重载:: uvicorn main:app --reload --host 0.0.0.0 --port 7861 也可使用 ``uvicorn core.main:app``(与 ``main:app`` 等价)。 默认 host/port 来自配置项 api_host / api_port(可通过环境变量覆盖)。 """ from pathlib import Path from dotenv import load_dotenv load_dotenv(Path(__file__).resolve().parent.parent / ".env") import os from contextlib import asynccontextmanager from logger.logging import setup_logger, get_logger setup_logger() from utils.helpers import set_httpx_config set_httpx_config() from fastapi import FastAPI, __version__ from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from starlette.responses import RedirectResponse from api.chat_router import chat_router from api.chat_title import chat_title_router from api.chat_file import chat_file_router from api.auth import auth_router from api.kb_router import kb_router from api.kb_file_router import kb_file_router from api.kb_processing_router import kb_processing_router from api.knowledge_graph_router import knowledge_graph_router from api.user_setting import user_setting_router from admin import admin_router from core.config import settings from core.database import close_db_pool from core.exception_handlers import register_exception_handlers logger = get_logger(__name__) # 设置 Hugging Face tokenizers 的并行性 if "TOKENIZERS_PARALLELISM" not in os.environ: os.environ["TOKENIZERS_PARALLELISM"] = "false" def create_app() -> FastAPI: """ 创建 FastAPI 应用实例 Returns: 配置好的 FastAPI 应用实例 """ @asynccontextmanager async def lifespan(app: FastAPI): """应用生命周期管理""" logger.info("应用启动中...") # 启动时:预热数据库连接池 try: from core.database import get_db_pool logger.info("预热数据库连接池...") pool = await get_db_pool() # 健康检查 async with pool.acquire() as conn: result = await conn.fetchval("SELECT 1") logger.info(f"数据库健康检查通过: {result}") logger.info("数据库连接池预热完成") except Exception as e: logger.error(f"数据库连接池初始化失败: {e}") logger.error("请检查数据库配置和网络连接") # 不抛出异常,让应用继续启动,但记录错误 yield # 关闭时:断开数据库连接 try: await close_db_pool() logger.info("数据库连接已关闭") except Exception as e: logger.error(f"关闭数据库连接时出错: {e}") app = FastAPI( title=settings.app_name, version=__version__, description=settings.app_description, docs_url="/docs", redoc_url="/redoc", lifespan=lifespan, ) # 添加 CORS 中间件,允许跨域请求 # 这在开发环境中很有用,允许前端应用访问 API app.add_middleware( CORSMiddleware, allow_origins=["*"], # 允许所有来源(生产环境应该限制) allow_credentials=True, allow_methods=["*"], # 允许所有 HTTP 方法 allow_headers=["*"], # 允许所有请求头 ) # 根路径重定向到 API 文档 @app.get("/", summary="API 文档", include_in_schema=False) async def root(): """ 根路径,重定向到 Swagger 文档 """ return RedirectResponse(url="/docs") # 注册路由 # 认证路由 app.include_router(auth_router) # 企业后台管理 app.include_router(admin_router) # 聊天路由 app.include_router(chat_router) # 聊天标题路由 app.include_router(chat_title_router) # 聊天文件路由 app.include_router(chat_file_router) # 知识库路由 app.include_router(kb_router) app.include_router(kb_file_router) app.include_router(kb_processing_router) # 用户设置路由 app.include_router(user_setting_router) app.include_router(knowledge_graph_router) # 注册全局异常处理器 register_exception_handlers(app) # 静态文件服务(backend/core/main.py -> backend/static) static_path = Path(__file__).resolve().parent.parent / "static" if static_path.exists(): app.mount("/static", StaticFiles(directory=str(static_path)), name="static") logger.info(f"静态文件目录已挂载: {static_path}") logger.info(f"FastAPI 应用已创建: {settings.app_name}") return app # 供 uvicorn 使用:后端目录下优先 uvicorn main:app;或 uvicorn core.main:app app = create_app()