Files
PlantAI-rag-new/backend/app/main.py
T
jerryandClaude Fable 5 1e94de7464 PlantAI-rag-new 首次提交:文献知识工作台
- BFF 薄适配层(FastAPI,8090):QA 代理/SSE 中继/Neo4j 直连/抽取代理/会话持久化
- Vue3 前端:五相位检索流水线、文献来源与证据链、知识图谱、提取任务四 tab
- 四档响应式(桌面/笔记本/平板/手机)、深浅主题
- 81 个 FR 全部实现,测试追溯矩阵 81/81,后端 121 测/前端 156 测
- 真实凭据已脱敏,运行时配置在 backend/.env(不入 git)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 20:47:52 +08:00

92 lines
3.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""main.py —— BFF 应用入口(ARCHITECTURE.md §2/§3)。
- 挂全部 5 个 router(qa/kg/extraction 为 A2/A3 实现,import 路径不变)。
- CORS:允许 http://localhost:5180 与 http://127.0.0.1:5180(Vite dev)。
- lifespan:init_db(幂等迁移);关闭回收 httpx 客户端与 Neo4j 连接。
- 全局 RequestValidationError → VALIDATION 信封(API.md §1,2026-08-25 PM 集成)。
- 生产形态(M6):frontend/dist 存在时静态托管(ARCHITECTURE.md §3)。
"""
from __future__ import annotations
import logging
from contextlib import asynccontextmanager
from pathlib import Path
from fastapi import FastAPI, Request
from fastapi.exceptions import RequestValidationError
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from .config import get_settings
from .db import close_db, init_db
from .routers import extraction, health, kg, qa, sessions
from .upstream import close_client
logging.basicConfig(level=logging.INFO)
_ALLOWED_ORIGINS = [
"http://localhost:5180",
"http://127.0.0.1:5180",
]
def create_app() -> FastAPI:
settings = get_settings()
app = FastAPI(title=settings.app_name, version=settings.version)
app.add_middleware(
CORSMiddleware,
allow_origins=_ALLOWED_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(health.router)
app.include_router(sessions.router)
app.include_router(qa.router)
app.include_router(kg.router)
app.include_router(extraction.router)
@app.exception_handler(RequestValidationError)
async def _validation_handler(_: Request, exc: RequestValidationError) -> JSONResponse:
# API.md §1 已裁决:参数校验错误收敛为统一 VALIDATION 信封(422)
return JSONResponse(
status_code=422,
content={
"ok": False,
"error": {"code": "VALIDATION", "message": "请求参数不合法", "degraded": False},
},
)
@asynccontextmanager
async def _lifespan(_app: FastAPI):
await init_db()
try:
yield
finally:
await close_client()
try:
from .services.neo4j import close_neo4j # A3 提供;缺失则跳过
await close_neo4j()
except ImportError:
pass
await close_db()
app.router.lifespan_context = _lifespan
# 生产形态:静态托管 frontend/dist(存在时挂载;本地开发期可无)。
# 2026-08-25 PM 修复:dist 路径必须基于项目根解析(BFF 工作目录是 backend/,
# 相对路径会解析成 backend/frontend/dist);sync.sh 排除 dist,需单独同步。
project_root = Path(__file__).resolve().parent.parent.parent
dist = project_root / settings.frontend_dist_dir if not Path(settings.frontend_dist_dir).is_absolute() else Path(settings.frontend_dist_dir)
if dist.is_dir():
app.mount("/", StaticFiles(directory=str(dist), html=True), name="frontend")
return app
app = create_app()