Files
2026-07-10 17:59:59 +08:00

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,
)