debt(D2): 统一预测结果类型为 PredictResult,路由去 dict 分支
- PredictResult 扩展可选字段 mode/agent_outputs/agent_weights/prompt_tokens/completion_tokens - MultiPredictResult 变为 PredictResult 别名(保留 R4 守卫标记与 re-export) - baseline 改返回 PredictResult(修复 backtest 对 baseline AttributeError 的潜伏 bug) - 预测路由单一属性映射,删除全部 isinstance(result, dict) 分支 - _persist_baseline 属性化,baseline upsert 语义不变(prompt_version/token/latency 同前) - TDD: 5 新测试 + test_baseline.py 属性化;全量 257 passed
This commit is contained in:
@@ -6,14 +6,13 @@ import hashlib
|
||||
import json
|
||||
import logging
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from src.core.config import settings
|
||||
from src.db.base import AsyncSessionLocal
|
||||
from src.db.models import Match, Prediction
|
||||
from src.db.unit_of_work import get_uow
|
||||
from src.llm.predict import _upsert_prediction
|
||||
from src.llm.predict import PredictResult, _upsert_prediction
|
||||
from src.llm.agents.base import AgentReport, AgentSpec, load_agent_prompt
|
||||
from src.llm.context_builder import (
|
||||
MatchHeader,
|
||||
@@ -81,28 +80,12 @@ AGENT_LABELS_ZH: dict[str, str] = {
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class MultiPredictResult:
|
||||
prediction_id: int
|
||||
provider: str
|
||||
model: str
|
||||
prompt_version: str
|
||||
mode: str
|
||||
pred_home_goals: float | None
|
||||
pred_away_goals: float | None
|
||||
alt_pred_home_goals: int | None
|
||||
alt_pred_away_goals: int | None
|
||||
pred_1x2: str | None
|
||||
subjective_confidence: float | None
|
||||
reasoning: str | None
|
||||
context: str
|
||||
agent_outputs: list[dict]
|
||||
agent_weights: dict | None
|
||||
status: str = "success"
|
||||
latency_ms: int | None = None
|
||||
prompt_tokens: int | None = None
|
||||
completion_tokens: int | None = None
|
||||
raw: dict | None = None
|
||||
# D2(工程债): multi 结果类型与 single 统一 —— 扩展后的 PredictResult 用可选
|
||||
# 字段(agent_outputs/agent_weights/prompt_tokens/completion_tokens/mode)承载
|
||||
# 全部模式,此处仅保留别名。保留 `MultiPredictResult` 名字的原因:
|
||||
# 1. predict_match_multi 签名 `-> MultiPredictResult:` 是 R4 源码守卫的标记;
|
||||
# 2. src/llm/agents/__init__.py 对外 re-export 该名字。
|
||||
MultiPredictResult = PredictResult
|
||||
|
||||
|
||||
async def _agent_provider(agent_id: str, *, tier: str, model_override: str | None = None) -> LLMProvider:
|
||||
|
||||
+25
-20
@@ -12,6 +12,7 @@ from sqlalchemy import case, func, select
|
||||
|
||||
from src.db.base import AsyncSession, AsyncSessionLocal
|
||||
from src.db.models import Match
|
||||
from src.llm.predict import PredictResult
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -52,11 +53,13 @@ async def predict_baseline(
|
||||
*,
|
||||
backtest: bool = False,
|
||||
cutoff_at: datetime | None = None,
|
||||
) -> dict:
|
||||
) -> PredictResult:
|
||||
"""极简基线预测:主场场均进球 vs 客场场均进球。
|
||||
|
||||
返回与 PredictResult 兼容的字典:
|
||||
返回 PredictResult(D2 统一结果类型):
|
||||
provider=model="baseline", 不调用 LLM,latency_ms≈0。
|
||||
prediction_id 为占位 0 —— baseline 不在服务层落库,
|
||||
由路由层 _persist_baseline 落库后取得真实 id。
|
||||
"""
|
||||
async with AsyncSessionLocal() as db:
|
||||
match = await db.get(Match, match_id)
|
||||
@@ -90,24 +93,26 @@ async def predict_baseline(
|
||||
else:
|
||||
pred_1x2 = "X"
|
||||
|
||||
return {
|
||||
"pred_home_goals": float(pred_home),
|
||||
"pred_away_goals": float(pred_away),
|
||||
"alt_pred_home_goals": None,
|
||||
"alt_pred_away_goals": None,
|
||||
"pred_1x2": pred_1x2,
|
||||
"subjective_confidence": 0.5,
|
||||
"prompt_tokens": 0,
|
||||
"completion_tokens": 0,
|
||||
"reasoning": (
|
||||
return PredictResult(
|
||||
prediction_id=0, # 占位:真实 id 由路由层 _persist_baseline 落库后返回
|
||||
provider="baseline",
|
||||
model="baseline",
|
||||
prompt_version="baseline_v1",
|
||||
mode="baseline",
|
||||
pred_home_goals=float(pred_home),
|
||||
pred_away_goals=float(pred_away),
|
||||
alt_pred_home_goals=None,
|
||||
alt_pred_away_goals=None,
|
||||
pred_1x2=pred_1x2,
|
||||
subjective_confidence=0.5,
|
||||
reasoning=(
|
||||
f"基线估计(非投注建议): 主队主场场均进球 {home_avg:.2f} → 预测 {pred_home}; "
|
||||
f"客队客场场均进球 {away_avg:.2f} → 预测 {pred_away}。"
|
||||
),
|
||||
"provider": "baseline",
|
||||
"model": "baseline",
|
||||
"prompt_version": "baseline_v1",
|
||||
"mode": "baseline",
|
||||
"status": "success",
|
||||
"latency_ms": 0,
|
||||
"raw": {"home_avg": round(home_avg, 2), "away_avg": round(away_avg, 2)},
|
||||
}
|
||||
context="", # baseline 不构建 LLM 上下文
|
||||
status="success",
|
||||
latency_ms=0,
|
||||
prompt_tokens=0,
|
||||
completion_tokens=0,
|
||||
raw={"home_avg": round(home_avg, 2), "away_avg": round(away_avg, 2)},
|
||||
)
|
||||
|
||||
+18
-1
@@ -89,6 +89,14 @@ def _prompt_template_hash(version: str) -> str:
|
||||
|
||||
@dataclass
|
||||
class PredictResult:
|
||||
"""三种预测模式(single/multi/baseline)的统一结果类型。
|
||||
|
||||
D2(工程债): 原本 single 返回本类、multi 重复定义 MultiPredictResult、
|
||||
baseline 返回裸 dict,导致路由 isinstance(dict) 双分支 + backtest 对
|
||||
baseline 直接 AttributeError。现以可选字段扩展本类承载全部模式;
|
||||
MultiPredictResult 是本类的别名(见 src/llm/agents/orchestrator.py)。
|
||||
"""
|
||||
|
||||
prediction_id: int
|
||||
provider: str
|
||||
model: str
|
||||
@@ -101,8 +109,15 @@ class PredictResult:
|
||||
subjective_confidence: float | None
|
||||
reasoning: str | None
|
||||
context: str
|
||||
# 模式标识: single(默认) / multi / baseline
|
||||
mode: str = "single"
|
||||
# multi 专属: 各专家报告列表与融合权重;single/baseline 为 None
|
||||
agent_outputs: list[dict] | None = None
|
||||
agent_weights: dict | None = None
|
||||
status: str = "success"
|
||||
latency_ms: int | None = None
|
||||
prompt_tokens: int | None = None
|
||||
completion_tokens: int | None = None
|
||||
raw: dict | None = None
|
||||
|
||||
|
||||
@@ -158,9 +173,11 @@ async def predict_match(
|
||||
use_cache: bool = True,
|
||||
backtest: bool = False,
|
||||
cutoff_at=None,
|
||||
) -> "PredictResult | MultiPredictResult":
|
||||
) -> PredictResult:
|
||||
"""预测入口。mode=multi(默认)走多 agent;mode=single 走单次调用;mode=baseline 走无 LLM 基线。
|
||||
|
||||
三种模式统一返回 PredictResult(D2);multi 的 MultiPredictResult 是其别名。
|
||||
|
||||
Args:
|
||||
mode: multi(默认,5 专家+终裁) / single(单次) / baseline(极简统计基线,不调用 LLM)。
|
||||
use_cache:是否允许返回进程内缓存结果。回测必须传 False——
|
||||
|
||||
Reference in New Issue
Block a user