167 lines
4.9 KiB
Python
167 lines
4.9 KiB
Python
"""
|
||
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()
|