""" AI Chat API Server — 主入口(纯基础设施层) 职责: - 注入运行时依赖(venv site-packages) - 读取 LLM_BACKEND 环境变量,动态加载对应平台模块 - 注册 FastAPI 路由和中间件 平台代码位置(main.py 中不包含任何平台逻辑): - 百炼 DashScope → api/chat_routes.py - 智谱 GLM-4.6V → api/chat_routes_glm.py + utils/glm_adapter.py """ import os import sys from datetime import datetime, timezone from pathlib import Path # ── 注入 venv site-packages(兼容 start.sh 用系统 python3 启动)──────── # 必须在所有第三方 import 前执行 _venv_lib = Path(__file__).parent / ".venv" / "lib" if _venv_lib.exists(): for _sp in sorted(_venv_lib.glob("python*/site-packages"), reverse=True): if _sp.exists() and str(_sp) not in sys.path: sys.path.insert(0, str(_sp)) print(f"[启动] venv 注入:{_sp}") break # ── 第三方导入 ──────────────────────────────────────────────────────── from dotenv import load_dotenv from fastapi import FastAPI, File, Request, UploadFile from fastapi.responses import JSONResponse sys.path.append("/home/mt/project/ai-chat-ui/server") # ── 工具/日志(与平台无关)─────────────────────────────────────────── from utils.helpers import log_response from utils.logger import get_logger logger = get_logger() # ── 加载环境变量 ────────────────────────────────────────────────────── load_dotenv() LLM_BACKEND = os.getenv("LLM_BACKEND", "dashscope").lower().strip() if LLM_BACKEND not in {"dashscope", "glm"}: logger.warning(f"未知的 LLM_BACKEND='{LLM_BACKEND}',回退到 dashscope") LLM_BACKEND = "dashscope" # ── 动态加载平台模块 ────────────────────────────────────────────────── if LLM_BACKEND == "glm": import api.chat_routes_glm as _platform else: import api.chat_routes as _platform _platform.init() # 各平台自行完成初始化(API Key 校验等) # 通用路由处理器(文件上传、会话管理等,与平台无关,统一用百炼路由中的实现) from api.chat_routes import (delete_conversation_handler, get_conversation_handler, get_conversations_handler, save_conversation_handler, serve_upload_handler, stop_generation_handler, upload_file_handler) # ── FastAPI 应用 ────────────────────────────────────────────────────── app = FastAPI( title=f"AI Chat API(LLM_BACKEND={LLM_BACKEND})", version="3.0.0", ) @app.middleware("http") async def logging_middleware(request: Request, call_next): start_time = datetime.now(timezone.utc) client_ip = request.client.host if request.client else "unknown" logger.info(f"→ {request.method} {request.url.path} | IP: {client_ip}") response = await call_next(request) ms = (datetime.now(timezone.utc) - start_time).total_seconds() * 1000 icon = "✅" if response.status_code < 400 else "❌" logger.info( f"{icon} {request.method} {request.url.path} | 状态: {response.status_code} | 耗时: {ms:.0f}ms" ) log_response(response.status_code, ms) response.headers["X-Process-Time"] = f"{ms:.2f}ms" return response # ── 路由注册 ────────────────────────────────────────────────────────── @app.get("/health") async def health_check(): return { "status": "healthy", "backend": LLM_BACKEND, "timestamp": datetime.now(timezone.utc).isoformat(), } @app.post("/api/chat-ui/chat") async def chat_endpoint(request: Request): """聊天接口(自动路由到当前平台)""" return await _platform.chat_handler(await request.json()) @app.get("/api/chat-ui/models") async def get_models(): """模型列表(由当前平台返回)""" result = _platform.models_handler() # 支持同步和异步两种返回 if hasattr(result, "__await__"): return await result return result # ── 通用路由(与平台无关)──────────────────────────────────────────── @app.get("/api/chat-ui/conversations") async def get_conversations(): return await get_conversations_handler() @app.get("/api/chat-ui/conversations/{conversation_id}") async def get_conversation(conversation_id: str): return await get_conversation_handler(conversation_id) @app.post("/api/chat-ui/conversations") async def save_conversation(request: Request): return await save_conversation_handler(await request.json()) @app.delete("/api/chat-ui/conversations/{conversation_id}") async def delete_conversation(conversation_id: str): return await delete_conversation_handler(conversation_id) @app.post("/api/chat-ui/upload") async def upload_file(file: UploadFile = File(...)): return await upload_file_handler(file=file) @app.get("/uploads/{filename}") async def serve_upload(filename: str): return serve_upload_handler(filename) @app.post("/api/chat-ui/stop") async def stop_generation(): return await stop_generation_handler() @app.post("/api/chat-ui/stop/{message_id}") async def stop_generation_by_id(message_id: str): return await stop_generation_handler(message_id) # ── 程序入口 ────────────────────────────────────────────────────────── if __name__ == "__main__": import uvicorn port = int(os.getenv("PORT", 8000)) print("=" * 55) print(f" AI Chat Server v3.0 启动中...") print(f" 后端平台 : {LLM_BACKEND.upper()} [LLM_BACKEND={LLM_BACKEND}]") print(f" 监听端口 : {port}") print(f" 切换平台 : 修改 .env 中 LLM_BACKEND=glm|dashscope,重启") print("=" * 55) uvicorn.run(app, host="0.0.0.0", port=port)