"""夜间 true_tier 推导(T-G3,§4 四条规则,确定性)+ 留存清理。 规则(对每条 true_tier 为空的观察,按序判定): 0. human_override 非空 -> 以人工为准(规则 4,优先级最高)。 1. features.plan_multi(consumer=pipeline 发出 brief 的多步信号)-> true=T3。 2. outcome∈{escalated,failed,user_retry,timeout} -> true = executed 的下一档 (T1→T2→T3,T3 保持 T3)。 3. outcome∈{ok,verified} -> true = executed(T1 成功即 T1;T2/T3 同理)。 4. 其余(outcome 为空等)-> 跳过,等下一轮。 """ from __future__ import annotations import json import time from typing import Any, Dict, Optional NEXT_TIER = {"T1": "T2", "T2": "T3", "T3": "T3"} SUCCESS = ("ok", "verified") FAILURE = ("escalated", "failed", "user_retry", "timeout") def _features(row: Dict[str, Any]) -> Dict[str, Any]: try: obj = json.loads(row.get("features") or "{}") return obj if isinstance(obj, dict) else {} except json.JSONDecodeError: return {} def derive_true_tier(row: Dict[str, Any]) -> Optional[str]: """单行推导(纯函数,测试友好)。返回 None = 暂不判定。""" if row.get("human_override"): return str(row["human_override"]) outcome = row.get("outcome") or "" executed = row.get("executed_tier") or "T2" feats = _features(row) if feats.get("plan_multi"): return "T3" # 规则 1(pipeline brief 信号) if outcome in FAILURE: # 规则 2 return NEXT_TIER.get(executed, "T3") if outcome in SUCCESS: # 规则 3 return executed return None # 规则 4:等待结果 def derive_true_tiers(store, now: Optional[float] = None, retention_days: int = 180) -> int: """批量推导(§7 签名):返回回填条数;顺带 180d 留存清理。""" now = time.time() if now is None else now rows = store.all_observations() count = 0 for row in rows: if row.get("true_tier"): continue true_tier = derive_true_tier(row) if true_tier: store.set_true_tier(row["request_id"], true_tier) count += 1 store.purge_older_than(now - retention_days * 86400) return count