fix:批量修复了一些问题

This commit is contained in:
shangfangjian
2026-09-19 22:51:35 +08:00
parent 835d7217d0
commit 8e6ad5394e
44 changed files with 4921 additions and 395 deletions
+43 -9
View File
@@ -25,6 +25,10 @@ async def settle_prediction(prediction_id: int, home_goals: int, away_goals: int
pred.actual_home_goals = home_goals
pred.actual_away_goals = away_goals
pred.settled = True
logger.info(
"结算完成 prediction_id=%s match=%s actual=%s:%s mode=%s",
prediction_id, pred.match_id, home_goals, away_goals, pred.mode or "single",
)
return pred
@@ -109,8 +113,14 @@ async def get_eval_summary(
rows = list((await session.execute(stmt)).scalars().all())
from collections import defaultdict
buckets: dict[tuple[str, str], dict] = defaultdict(lambda: {
buckets: dict[tuple[str, str, str], dict] = defaultdict(lambda: {
"total": 0, "correct_1x2": 0, "score_errors": [], "conf_sum": 0.0, "conf_count": 0,
# 置信度校准分桶(仅 settled 且 pred 完整者计入)
"conf_buckets": {
"low(0-0.5)": {"total": 0, "correct": 0},
"medium(0.5-0.7)": {"total": 0, "correct": 0},
"high(0.7-1)": {"total": 0, "correct": 0},
},
})
evaluated = 0
skipped_incomplete = 0
@@ -118,35 +128,59 @@ async def get_eval_summary(
if (p.pred_home_goals is None or p.pred_away_goals is None or p.pred_1x2 is None):
skipped_incomplete += 1
continue
key = (p.provider, p.model)
key = (p.provider, p.model, p.prompt_version or "")
b = buckets[key]
b["total"] += 1
evaluated += 1
if p.actual_home_goals is None or p.actual_away_goals is None:
continue
actual = _actual_1x2(p.actual_home_goals, p.actual_away_goals)
if p.pred_1x2 == actual:
b["correct_1x2"] += 1
if p.pred_home_goals is not None and p.pred_away_goals is not None:
correct = False
if p.actual_home_goals is not None and p.actual_away_goals is not None:
actual = _actual_1x2(p.actual_home_goals, p.actual_away_goals)
if p.pred_1x2 == actual:
b["correct_1x2"] += 1
correct = True
if (
p.pred_home_goals is not None and p.pred_away_goals is not None
and p.actual_home_goals is not None and p.actual_away_goals is not None
):
err = ((p.pred_home_goals - p.actual_home_goals) ** 2 +
(p.pred_away_goals - p.actual_away_goals) ** 2) ** 0.5
b["score_errors"].append(err)
if p.subjective_confidence is not None:
b["conf_sum"] += p.subjective_confidence
b["conf_count"] += 1
# 仅当有实际结果可用于校准时,才落入置信度分桶
if p.actual_home_goals is not None and p.actual_away_goals is not None:
conf = p.subjective_confidence
if conf < 0.5:
bucket = "low(0-0.5)"
elif conf < 0.7:
bucket = "medium(0.5-0.7)"
else:
bucket = "high(0.7-1)"
b["conf_buckets"][bucket]["total"] += 1
if correct:
b["conf_buckets"][bucket]["correct"] += 1
summary = []
for (prov, model), b in sorted(buckets.items()):
for (prov, model, ver), b in sorted(buckets.items()):
acc = (b["correct_1x2"] / b["total"] * 100) if b["total"] else 0
avg_err = (sum(b["score_errors"]) / len(b["score_errors"])) if b["score_errors"] else None
avg_conf = (b["conf_sum"] / b["conf_count"]) if b["conf_count"] else None
# 校准分桶 → 命中率
calibration = {}
for name, cb in b["conf_buckets"].items():
hit_rate = round(cb["correct"] / cb["total"] * 100, 1) if cb["total"] else None
calibration[name] = {"total": cb["total"], "hit_rate": hit_rate}
summary.append({
"provider": prov,
"model": model,
"prompt_version": ver or None,
"total": b["total"],
"accuracy_1x2": round(acc, 1),
"avg_score_rmse": round(avg_err, 2) if avg_err is not None else None,
"avg_subjective_confidence": round(avg_conf, 2) if avg_conf is not None else None,
"calibration": calibration,
})
return {
"summary": summary,