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