fix(P0): 修复三处静默失效的阻断缺陷
P0-1 backtest 会话生命周期: - _get_historical_matches 加 selectinload(league/home_team/away_team), 并在 session 内物化为 BacktestCandidate 纯数据快照,避免 session 关闭后访问惰性关系抛 MissingGreenlet - except 收窄并改用 logger.exception 保留堆栈 - 移除未使用的 and_ / League 导入 P0-2 切片函数关系属性 MissingGreenlet: - models.py 为 Match.league/home_team/away_team/stats 声明 lazy=selectin - context_builder 的 _get_form/_get_h2h/_get_home_away 显式 selectinload (修复 form_slice/h2h_slice 恒定失败,被 fail-open 掩盖的问题) - repositories.find_by_teams_and_date 加 selectinload(Match.stats) P0-3 bzzoiro raw 变量泄漏导致血缘错乱: - normalized_matches 改为携带 (nm, raw) 元组,内层循环解包 - source_event_id / source_record_id 现在取到正确 event id - 已有比赛补建 stats 时补齐 source/source_event_id/retrieved_at/available_at - 抽取 _match_key()/_to_date() 统一日期键构造 (P1-6)
This commit is contained in:
+22
-8
@@ -81,11 +81,22 @@ async def predict_match(
|
||||
model: str | None = None,
|
||||
prompt_version: str | None = None,
|
||||
mode: str = "multi",
|
||||
use_cache: bool = True,
|
||||
) -> "PredictResult | MultiPredictResult":
|
||||
"""预测入口。mode=multi(默认)走多 agent;mode=single 走单次调用。"""
|
||||
"""预测入口。mode=multi(默认)走多 agent;mode=single 走单次调用。
|
||||
|
||||
Args:
|
||||
use_cache: 是否允许返回进程内缓存结果。回测必须传 False——
|
||||
缓存命中不会新建 prediction 行,调用方会对同一个 prediction_id
|
||||
反复 settle,把不同比赛的真实比分覆盖到同一条记录上。
|
||||
"""
|
||||
if mode == "single":
|
||||
return await _predict_single(
|
||||
match_id, provider=provider, model=model, prompt_version=prompt_version
|
||||
match_id,
|
||||
provider=provider,
|
||||
model=model,
|
||||
prompt_version=prompt_version,
|
||||
use_cache=use_cache,
|
||||
)
|
||||
from src.llm.agents.orchestrator import predict_match_multi
|
||||
|
||||
@@ -98,6 +109,7 @@ async def _predict_single(
|
||||
provider: LLMProvider | None = None,
|
||||
model: str | None = None,
|
||||
prompt_version: str | None = None,
|
||||
use_cache: bool = True,
|
||||
) -> PredictResult:
|
||||
"""单次调用路径(原有实现)。"""
|
||||
if provider is None:
|
||||
@@ -107,10 +119,11 @@ async def _predict_single(
|
||||
version = prompt_version or "v1"
|
||||
|
||||
# 0. 查缓存(同 match+provider+model+version 5 分钟内直接返)
|
||||
cached = _get_cached(match_id, settings.LLM_PROVIDER, provider.model, version)
|
||||
if cached is not None:
|
||||
logger.debug("predict cache hit match=%s", match_id)
|
||||
return cached
|
||||
if use_cache:
|
||||
cached = _get_cached(match_id, settings.LLM_PROVIDER, provider.model, version)
|
||||
if cached is not None:
|
||||
logger.debug("predict cache hit match=%s", match_id)
|
||||
return cached
|
||||
|
||||
# 1. 拼上下文
|
||||
ctx = await build_context(match_id)
|
||||
@@ -191,6 +204,7 @@ async def _predict_single(
|
||||
raw=resp.raw,
|
||||
)
|
||||
|
||||
# 5. 写入缓存
|
||||
_set_cached(match_id, settings.LLM_PROVIDER, provider.model, version, result)
|
||||
# 5. 写入缓存(仅当允许缓存时)
|
||||
if use_cache:
|
||||
_set_cached(match_id, settings.LLM_PROVIDER, provider.model, version, result)
|
||||
return result
|
||||
|
||||
Reference in New Issue
Block a user