Compare commits

...

3 Commits

Author SHA1 Message Date
sinohqb
5a81c570c0 style: fix ruff whitespace warnings
All checks were successful
CI / test (push) Successful in 3m16s
2026-08-24 01:53:35 +08:00
sinohqb
09ff2ed123 refactor(intelligent-eval): reduce nesting complexity in supplement_decision_logs
Extract helper functions _supplement_executing and _supplement_completed
to flatten the nested conditional logic. This improves readability and
makes the code easier to test and maintain.

Addresses code review finding: supplement_decision_logs nested complexity
2026-08-24 01:53:15 +08:00
sinohqb
da7dd434dd perf(intelligent-eval): 修复 N+1 查询和参数名混淆
- expire_stale_running_sessions: 使用单次 JOIN 查询替代 N+1 查询
  将每个会话单独查询最后消息时间改为一次性获取所有 running 会话及其最后消息时间

- submit_report/evals_needing_analyst_nudge: 消除 session/sessions 参数名混淆
  将局部变量 sessions 重命名为 eval_sessions,避免与数据库会话参数 session 混淆

这些改进提升了查询性能并增强了代码可读性。
2026-08-24 01:52:05 +08:00
2 changed files with 120 additions and 81 deletions

View File

@ -130,6 +130,92 @@ def list_decision_logs(eval_id: str, session: Session) -> list[dict]:
return [_log_to_dict(log) for log in logs] return [_log_to_dict(log) for log in logs]
def _supplement_executing(
ev: IntelligentEvalDB,
sessions: list,
completed: int,
estimated: int,
types: set[str],
session: Session,
) -> int:
"""Supplement decision logs for EXECUTING evals."""
added = 0
if "execute_session" not in types and completed < estimated:
_append_row(
ev.id,
"execute_session",
"平台兜底:时段欠账需执行会话",
"platform",
{"platform_supplemented": True, "completed": completed, "estimated": estimated},
session,
)
added += 1
elif "start_analysis" not in types and sessions and completed >= estimated:
_append_row(
ev.id,
"start_analysis",
"平台兜底:所有会话已完成开始分析",
"platform",
{"platform_supplemented": True, "completed": completed, "estimated": estimated},
session,
)
added += 1
return added
def _supplement_completed(
ev: IntelligentEvalDB,
sessions: list,
completed: int,
estimated: int,
plan: dict,
types: set[str],
session: Session,
) -> int:
"""Supplement decision logs for COMPLETED evals (historical backfill)."""
added = 0
if "execute_session" not in types:
slots = plan.get("time_distribution") or []
if slots:
for slot in slots:
_append_row(
ev.id,
"execute_session",
f"平台兜底:时段{slot.get('time_slot', '')}执行会话(历史回填)",
"platform",
{
"platform_supplemented": True,
"time_slot": slot.get("time_slot"),
"sessions": slot.get("sessions"),
"completed": completed,
"estimated": estimated,
},
session,
)
added += 1
else:
_append_row(
ev.id,
"execute_session",
"平台兜底:执行会话(历史回填)",
"platform",
{"platform_supplemented": True, "completed": completed, "estimated": estimated},
session,
)
added += 1
if "start_analysis" not in types and sessions:
_append_row(
ev.id,
"start_analysis",
"平台兜底:所有会话已完成开始分析(历史回填)",
"platform",
{"platform_supplemented": True, "completed": completed, "estimated": estimated},
session,
)
added += 1
return added
def supplement_decision_logs(session: Session) -> int: def supplement_decision_logs(session: Session) -> int:
"""Platform audit backfill for decision logs. """Platform audit backfill for decision logs.
@ -162,7 +248,9 @@ def supplement_decision_logs(session: Session) -> int:
for ev in evals: for ev in evals:
plan = ev.get_plan() if ev.plan else {} plan = ev.get_plan() if ev.plan else {}
estimated = plan.get("estimated_sessions", 0) estimated = plan.get("estimated_sessions", 0)
sessions = session.exec(select(IntelligentEvalSessionDB).where(IntelligentEvalSessionDB.eval_id == ev.id)).all() sessions = session.exec(
select(IntelligentEvalSessionDB).where(IntelligentEvalSessionDB.eval_id == ev.id)
).all()
completed = sum(1 for s in sessions if s.status == "completed") completed = sum(1 for s in sessions if s.status == "completed")
types = { types = {
x.decision_type x.decision_type
@ -170,66 +258,10 @@ def supplement_decision_logs(session: Session) -> int:
select(IntelligentEvalDecisionLogDB).where(IntelligentEvalDecisionLogDB.eval_id == ev.id) select(IntelligentEvalDecisionLogDB).where(IntelligentEvalDecisionLogDB.eval_id == ev.id)
).all() ).all()
} }
if ev.status == IntelligentEvalStatus.EXECUTING.value: if ev.status == IntelligentEvalStatus.EXECUTING.value:
if "execute_session" not in types and completed < estimated: added += _supplement_executing(ev, sessions, completed, estimated, types, session)
_append_row(
ev.id,
"execute_session",
"平台兜底:时段欠账需执行会话",
"platform",
{"platform_supplemented": True, "completed": completed, "estimated": estimated},
session,
)
added += 1
elif "start_analysis" not in types and sessions and completed >= estimated:
_append_row(
ev.id,
"start_analysis",
"平台兜底:所有会话已完成开始分析",
"platform",
{"platform_supplemented": True, "completed": completed, "estimated": estimated},
session,
)
added += 1
elif ev.status == IntelligentEvalStatus.COMPLETED.value: elif ev.status == IntelligentEvalStatus.COMPLETED.value:
# 历史回填completed 评估决策日志全缺失时,按时段补 execute_session added += _supplement_completed(ev, sessions, completed, estimated, plan, types, session)
if "execute_session" not in types:
slots = plan.get("time_distribution") or []
if slots:
for slot in slots:
_append_row(
ev.id,
"execute_session",
f"平台兜底:时段{slot.get('time_slot', '')}执行会话(历史回填)",
"platform",
{
"platform_supplemented": True,
"time_slot": slot.get("time_slot"),
"sessions": slot.get("sessions"),
"completed": completed,
"estimated": estimated,
},
session,
)
added += 1
else:
_append_row(
ev.id,
"execute_session",
"平台兜底:执行会话(历史回填)",
"platform",
{"platform_supplemented": True, "completed": completed, "estimated": estimated},
session,
)
added += 1
if "start_analysis" not in types and sessions:
_append_row(
ev.id,
"start_analysis",
"平台兜底:所有会话已完成开始分析(历史回填)",
"platform",
{"platform_supplemented": True, "completed": completed, "estimated": estimated},
session,
)
added += 1
return added return added

View File

@ -226,8 +226,8 @@ def submit_report(session: Session, eval_id: str, report: dict[str, Any]) -> Int
不完整证据不再阻塞报告提交 不完整证据不再阻塞报告提交
""" """
repo = IntelligentEvalRepository(session) repo = IntelligentEvalRepository(session)
sessions = IntelligentEvalSessionRepository(session).list_by_eval(eval_id) eval_sessions = IntelligentEvalSessionRepository(session).list_by_eval(eval_id)
if any(s.status == IntelligentEvalSessionStatus.RUNNING for s in sessions): if any(s.status == IntelligentEvalSessionStatus.RUNNING for s in eval_sessions):
raise IntelligentEvalTransitionError("存在进行中的会话,不能提交报告") raise IntelligentEvalTransitionError("存在进行中的会话,不能提交报告")
# ADR-0011submit 边界把 scores 归一到 {overall, dimensions} 单一规范结构 # ADR-0011submit 边界把 scores 归一到 {overall, dimensions} 单一规范结构
if report.get("scores"): if report.get("scores"):
@ -432,29 +432,36 @@ def expire_stale_running_sessions(session: Session) -> int:
now = utc_now() now = utc_now()
# SQLite 读出为 naive datetime阈值须同为 naive 才能在 Python 侧比较 # SQLite 读出为 naive datetime阈值须同为 naive 才能在 Python 侧比较
threshold = now.replace(tzinfo=None) - timedelta(minutes=SESSION_IDLE_EXPIRE_MINUTES) threshold = now.replace(tzinfo=None) - timedelta(minutes=SESSION_IDLE_EXPIRE_MINUTES)
rows = session.exec(
select(IntelligentEvalSessionDB).where(IntelligentEvalSessionDB.status == "running") # 单次查询获取所有 running 会话及其最后消息时间(避免 N+1 查询)
).all() stmt = (
select(
IntelligentEvalSessionDB,
func.max(IntelligentEvalMessageDB.created_at).label("last_message_at"),
)
.outerjoin(
IntelligentEvalMessageDB,
IntelligentEvalMessageDB.session_id == IntelligentEvalSessionDB.id,
)
.where(IntelligentEvalSessionDB.status == "running")
.group_by(IntelligentEvalSessionDB.id)
)
rows = session.exec(stmt).all()
expired = 0 expired = 0
for row in rows: for session_row, last_message_at in rows:
last_message_at = session.exec( last_activity = last_message_at or session_row.created_at
select(func.max(IntelligentEvalMessageDB.created_at)).where(
IntelligentEvalMessageDB.session_id == row.id
)
).one()
last_activity = last_message_at or row.created_at
if last_activity is None or last_activity >= threshold: if last_activity is None or last_activity >= threshold:
continue continue
row.status = IntelligentEvalSessionStatus.EXPIRED.value session_row.status = IntelligentEvalSessionStatus.EXPIRED.value
row.closed_at = now session_row.closed_at = now
expired += 1 expired += 1
append_decision_log( append_decision_log(
row.eval_id, session_row.eval_id,
"session_expired", "session_expired",
f"平台兜底:会话 {SESSION_IDLE_EXPIRE_MINUTES} 分钟无新轮次,置为过期(不完整证据)", f"平台兜底:会话 {SESSION_IDLE_EXPIRE_MINUTES} 分钟无新轮次,置为过期(不完整证据)",
"platform", "platform",
{"platform_supplemented": True, "session_id": row.id, "turn_count": row.turn_count}, {"platform_supplemented": True, "session_id": session_row.id, "turn_count": session_row.turn_count},
session, session,
) )
@ -674,16 +681,16 @@ def evals_needing_analyst_nudge(session: Session) -> list[str]:
needing: list[str] = [] needing: list[str] = []
for row in executing: for row in executing:
sessions = session.exec( eval_sessions = session.exec(
select(IntelligentEvalSessionDB).where(IntelligentEvalSessionDB.eval_id == row.id) select(IntelligentEvalSessionDB).where(IntelligentEvalSessionDB.eval_id == row.id)
).all() ).all()
if not sessions or any(s.status not in _TERMINAL_SESSION_STATUSES for s in sessions): if not eval_sessions or any(s.status not in _TERMINAL_SESSION_STATUSES for s in eval_sessions):
continue continue
# 冒烟教训:窗口未结束且会话数未达计划时,未来时段到期后还要建会话, # 冒烟教训:窗口未结束且会话数未达计划时,未来时段到期后还要建会话,
# 此时催促 analyst 会让报告提前收敛(漏掉后续时段的证据) # 此时催促 analyst 会让报告提前收敛(漏掉后续时段的证据)
if _window_has_pending_future_slots(row, sessions, now): if _window_has_pending_future_slots(row, eval_sessions, now):
continue continue
closed_moments = [s.closed_at for s in sessions if s.closed_at is not None] closed_moments = [s.closed_at for s in eval_sessions if s.closed_at is not None]
if not closed_moments: if not closed_moments:
continue continue
last_closed = max(closed_moments) last_closed = max(closed_moments)