65 lines
2.5 KiB
Python
65 lines
2.5 KiB
Python
"""评估路由。"""
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
|
|
from src.api.deps import require_admin
|
|
from src.api.schemas import EvalSummaryOut, SettleRequest
|
|
from src.db.base import AsyncSession, get_db, get_db_read
|
|
from src.llm.eval import get_eval_summary, settle_prediction
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter(prefix="/api/v1", tags=["eval"])
|
|
|
|
|
|
@router.post("/eval/settle", dependencies=[Depends(require_admin)])
|
|
async def settle(req: SettleRequest, db: AsyncSession = Depends(get_db)):
|
|
"""回填实际结果。
|
|
|
|
status 为 degraded/failed 的预测无法结算(返回 400);
|
|
记录不存在返回 404。
|
|
"""
|
|
try:
|
|
pred = await settle_prediction(req.prediction_id, req.home_goals, req.away_goals)
|
|
return {"id": pred.id, "settled": pred.settled}
|
|
except ValueError as e:
|
|
msg = str(e)
|
|
# degraded/failed 拒绝:明确的 400,而非与"未找到"混为一谈
|
|
if "无法结算" in msg:
|
|
logger.warning("settle rejected: %s", msg)
|
|
raise HTTPException(400, msg)
|
|
logger.warning("settle failed: %s", msg)
|
|
raise HTTPException(404, "预测记录不存在")
|
|
except Exception as e:
|
|
logger.exception("settle error")
|
|
raise HTTPException(500, "回填失败,请查看服务器日志")
|
|
|
|
|
|
@router.get("/eval/summary", response_model=EvalSummaryOut, dependencies=[Depends(require_admin)])
|
|
async def eval_summary(
|
|
limit: int = Query(1000, ge=1, le=10000, description="最大评估条数"),
|
|
provider: str | None = Query(None, description="按提供商筛选"),
|
|
model: str | None = Query(None, description="按模型筛选"),
|
|
prompt_version: str | None = Query(None, description="按 prompt 版本筛选"),
|
|
mode: str | None = Query(None, description="按模式筛选(single/multi)"),
|
|
league_code: str | None = Query(None, description="按联赛代码筛选(如 E0/SP1)"),
|
|
db: AsyncSession = Depends(get_db_read),
|
|
):
|
|
"""提供商/模型准确率对比。
|
|
|
|
P3-4: 默认评估最近 1000 条,可通过 limit 调整。
|
|
支持按 provider / model / prompt_version / mode / league_code 筛选。
|
|
只统计 status=success 且预测比分齐全的已结算预测,degraded 不计入。
|
|
"""
|
|
return await get_eval_summary(
|
|
limit=limit,
|
|
provider=provider,
|
|
model=model,
|
|
prompt_version=prompt_version,
|
|
mode=mode,
|
|
league_code=league_code,
|
|
)
|