feat(sense): T-G3 标签+校准(labeler 四规则推导 + split-conformal + last-good)
- labeler.py:derive_true_tier 纯函数(规则0 人工优先 / plan_multi->T3 / 失败->下一档(T3保持) / 成功->executed / 空结果跳过)+ derive_true_tiers 批量回填 + 180d 留存清理 - calibrate.py:compute_thresholds(τ1/τ3 分组扫描——并列分数整组判定, 精度 >= 1-α 的最大覆盖阈值;<min_labels -> ok=False 沿用 last-good); save_thresholds 工件落盘+登记;load_active 回退链 active->同kind扫描->last-good->保守值 - store:all_observations/list_artifacts 支撑方法 - 测试 +9(四规则/批量清理/覆盖达标/标签不足/工件往返与回退),全量 395 passed
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
"""夜间 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
|
||||
Reference in New Issue
Block a user