feat: Sprint 2 - 概率语义 + 轻量快照 + 数据库约束

P0-05: confidence → subjective_confidence 改名(15 文件)
       LLM 主观置信度与概率分离
P0-02: predictions 增加 cutoff_at + input_hash(轻量快照)
       MatchContext 暴露 match_dt
       单/多 Agent 路径均记录快照元数据
P2-05: 数据库 CHECK 约束
       - pred_home_goals >= 0
       - pred_away_goals >= 0
       - subjective_confidence 0~1
       - pred_1x2 IN (1,X,2)
       - mode IN (single,multi)
P2-06: limit 分页约束(ge=1, le=200)
P2-01: 新增 /health/ready 就绪检查
This commit is contained in:
shangfangjian
2026-09-15 00:14:24 +08:00
parent f3160e3062
commit cb36dc3ef9
14 changed files with 70 additions and 41 deletions
+2 -2
View File
@@ -46,7 +46,7 @@ async def backtest(req: BacktestRequest):
"scored": summary.scored,
"accuracy_1x2": summary.accuracy_1x2,
"avg_score_rmse": summary.avg_score_rmse,
"avg_confidence": summary.avg_confidence,
"avg_subjective_confidence": summary.avg_confidence,
"calibration": summary.calibration,
},
"results": [
@@ -61,7 +61,7 @@ async def backtest(req: BacktestRequest):
"pred_home": r.pred_home,
"pred_away": r.pred_away,
"pred_1x2": r.pred_1x2,
"confidence": r.confidence,
"subjective_confidence": r.subjective_confidence,
"correct_1x2": r.correct_1x2,
}
for r in summary.results
+5 -5
View File
@@ -1,7 +1,7 @@
"""预测路由。"""
from __future__ import annotations
from fastapi import APIRouter, Depends, HTTPException
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import select
from sqlalchemy.orm import selectinload
@@ -38,7 +38,7 @@ async def predict(req: PredictRequest, db: AsyncSession = Depends(get_db)):
pred_home_goals=result.pred_home_goals,
pred_away_goals=result.pred_away_goals,
pred_1x2=result.pred_1x2,
confidence=result.confidence,
subjective_confidence=result.subjective_confidence,
reasoning=result.reasoning,
agent_outputs=getattr(result, "agent_outputs", None),
agent_weights=getattr(result, "agent_weights", None),
@@ -50,7 +50,7 @@ async def predict(req: PredictRequest, db: AsyncSession = Depends(get_db)):
@router.get("/predictions", response_model=list[PredictionOut])
async def list_predictions(
match_id: int | None = None,
limit: int = 50,
limit: int = Query(50, ge=1, le=200),
db: AsyncSession = Depends(get_db_read),
):
stmt = select(Prediction).options(selectinload(Prediction.match))
@@ -69,7 +69,7 @@ async def list_predictions(
pred_home_goals=p.pred_home_goals,
pred_away_goals=p.pred_away_goals,
pred_1x2=p.pred_1x2,
confidence=p.confidence,
subjective_confidence=p.subjective_confidence,
reasoning=p.reasoning,
agent_outputs=p.agent_outputs,
created_at=p.created_at,
@@ -96,7 +96,7 @@ async def get_prediction(prediction_id: int, db: AsyncSession = Depends(get_db_r
pred_home_goals=p.pred_home_goals,
pred_away_goals=p.pred_away_goals,
pred_1x2=p.pred_1x2,
confidence=p.confidence,
subjective_confidence=p.subjective_confidence,
reasoning=p.reasoning,
agent_outputs=p.agent_outputs,
created_at=p.created_at,