单文件拆分(仅搬迁无逻辑修改): - common.py 共享类型/头信息/_outcome/_is_stats_available - form.py form_slice + _get_form - h2h.py h2h_slice + _get_h2h - stats.py stats_slice(复用 form._get_form) - home_away.py home_away_slice + _get_home_away - standings.py standings_slice - aggregate.py build_context context_builder.py 改为纯 re-export 门面,公开签名不变。 同步修复测试 patch 目标(p0_home_away/h2h_perspective/multi_agent_cutoff) 与 regressions 源码断言(读 slices/*.py)。 全量测试 270 通过。
66 lines
2.6 KiB
Python
66 lines
2.6 KiB
Python
"""单 agent 聚合路径: 拼接全部切片(build_context)。
|
|
|
|
共享 session 贯穿所有切片(见 context_builder 模块 docstring 的性能说明)。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from src.db.base import AsyncSessionLocal
|
|
from src.llm.slices.common import MatchContext, header_text, load_match_header
|
|
from src.llm.slices.form import form_slice
|
|
from src.llm.slices.h2h import h2h_slice
|
|
from src.llm.slices.home_away import home_away_slice
|
|
from src.llm.slices.standings import standings_slice
|
|
from src.llm.slices.stats import stats_slice
|
|
|
|
|
|
async def build_context(match_id: int, *, form_last: int = 5, h2h_last: int = 5, backtest: bool = False, cutoff_at=None) -> MatchContext:
|
|
"""单 agent 路径的完整上下文: 拼接全部切片(before=cutoff,防未来信息)。
|
|
|
|
has_stats / has_standings 直接取切片显式声明的 has_data,
|
|
不再靠文案子串匹配(见审查报告 P2-1)。
|
|
|
|
P2-6: backtest=True 时 cutoff = match_date - 1天,确保只用赛前数据。
|
|
cutoff_at: 显式截止时间(优先于 backtest 自动计算)。
|
|
|
|
P1-1: 使用单个共享 session 贯穿所有切片查询,避免连接池耗尽。
|
|
"""
|
|
async with AsyncSessionLocal() as db:
|
|
header = await load_match_header(match_id, db=db)
|
|
# 计算数据截止时间: 显式 > backtest 自动计算 > 默认(比赛时间)
|
|
if cutoff_at is not None:
|
|
cutoff = cutoff_at
|
|
elif backtest and header.match_dt:
|
|
from datetime import timedelta
|
|
cutoff = header.match_dt - timedelta(days=1)
|
|
else:
|
|
cutoff = header.match_dt
|
|
parts = [header_text(header), ""]
|
|
|
|
form_res = await form_slice(header, limit=form_last, before=cutoff, db=db)
|
|
parts.append(form_res.text)
|
|
parts.append("")
|
|
|
|
h2h_res = await h2h_slice(header, limit=h2h_last, before=cutoff, db=db)
|
|
parts.append(h2h_res.text)
|
|
parts.append("")
|
|
|
|
stats_res = await stats_slice(header, before=cutoff, db=db)
|
|
parts.append(stats_res.text)
|
|
parts.append("")
|
|
|
|
home_away_res = await home_away_slice(header, before=cutoff, db=db)
|
|
parts.append(home_away_res.text)
|
|
parts.append("")
|
|
|
|
standings_res = await standings_slice(header, before=cutoff, db=db)
|
|
parts.append(standings_res.text)
|
|
|
|
return MatchContext(
|
|
match_id=match_id,
|
|
text="\n".join(parts),
|
|
has_stats=form_res.has_data or stats_res.has_data,
|
|
has_standings=standings_res.has_data,
|
|
match_dt=header.match_dt,
|
|
cutoff=cutoff,
|
|
)
|