- 按生产 7900 容器黄金清单迁移(compile.manifest 449 条目,0 缺失) - 入口双态:api.app(生产同源 3 路由)/ api.main(裁剪 11 路由族 91 路径) - 修复:advanced/__init__ 空文件(包标记误覆盖,已从主项目恢复) - 修复:api/rag_routes.py 跨环境 site-packages 注入改 LEGACY_GF_SITE_PACKAGES 门控 - 修复:scripts/utils 缺失(动态加载 reasoning_engine) - 影子验证:kg/stats 数据连通(6.2s,与 7900 同源 normalized 后端) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
72 lines
1.9 KiB
Python
Executable File
72 lines
1.9 KiB
Python
Executable File
"""Case-specific deterministic QA routes.
|
|
|
|
These endpoints expose validated reproduction-case packages before they are
|
|
merged into the general RAG chat route. They do not call an LLM.
|
|
"""
|
|
|
|
from functools import lru_cache
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
from fastapi import APIRouter, HTTPException
|
|
from pydantic import BaseModel, Field
|
|
|
|
from src.rag.unified.case_qa import CasePackageQAEngine
|
|
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
|
FT_SPL_CASE_PACKAGE = PROJECT_ROOT / "data" / "ft_spl_reproduction_case_package.json"
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
class CaseQARequest(BaseModel):
|
|
query: str = Field(..., min_length=1)
|
|
|
|
|
|
class CaseQAResponse(BaseModel):
|
|
query: str
|
|
intent: str
|
|
answer: str
|
|
citations: list[str]
|
|
facts: dict[str, Any]
|
|
|
|
|
|
class CaseStatusResponse(BaseModel):
|
|
case_id: str
|
|
package_path: str
|
|
package_exists: bool
|
|
supported: bool
|
|
|
|
|
|
@lru_cache(maxsize=1)
|
|
def get_ft_spl_engine() -> CasePackageQAEngine:
|
|
if not FT_SPL_CASE_PACKAGE.exists():
|
|
raise FileNotFoundError(str(FT_SPL_CASE_PACKAGE))
|
|
return CasePackageQAEngine(FT_SPL_CASE_PACKAGE)
|
|
|
|
|
|
@router.get("/ft-spl/status", response_model=CaseStatusResponse)
|
|
async def ft_spl_case_status():
|
|
return CaseStatusResponse(
|
|
case_id="ft_spl_reproduction_job_1777615271527",
|
|
package_path=str(FT_SPL_CASE_PACKAGE),
|
|
package_exists=FT_SPL_CASE_PACKAGE.exists(),
|
|
supported=FT_SPL_CASE_PACKAGE.exists(),
|
|
)
|
|
|
|
|
|
@router.post("/ft-spl/qa", response_model=CaseQAResponse)
|
|
async def ft_spl_case_qa(request: CaseQARequest):
|
|
try:
|
|
response = get_ft_spl_engine().answer(request.query)
|
|
except FileNotFoundError as exc:
|
|
raise HTTPException(status_code=503, detail=f"Case package missing: {exc}") from exc
|
|
return CaseQAResponse(
|
|
query=response.query,
|
|
intent=response.intent,
|
|
answer=response.answer,
|
|
citations=response.citations,
|
|
facts=response.facts,
|
|
)
|