M15 · 评测分数回注 trace 与工具 RT 告警#
简历 Bullet Point: 补齐可观测性两处缺口——Rubric 评测分数回注 Langfuse trace(三条 score + 失败维度 comment,支持按低分筛 bad case trace),工具 RT 告警(P95 滑动时间窗 + 三态状态机防抖 + hard_ms 兜底低 QPS),refdocs 示例代码四处真错全部更正
开场钩子#
评测跑完有分数,Langfuse 有 trace,但两套数据割裂——看到一条低分不知道对应哪条 trace,看到一条 trace 不知道它的评测分是多少。做不到”按低分筛 bad case trace”这个最基本的调试 SOP。
更隐蔽的问题:run_agent 的 trace_id 最初用 ContextVar 传给下游。但 run_agent 跑在 asyncio.create_task 里——子 task 的 ContextVar.set 不回传父上下文。结果 trace_id 在 run_rubric.py 主进程里永远是 None,分数挂不到 trace 上。
一、模块运作流程#
1.1 分数回注 trace#
run_agent() → 返回 {final_text, trace_id, ...}
│ ↑ 显式返回值,不用 ContextVar
▼
run_rubric.py → judge 打分 → record_rubric_scores(trace_id, scores)
│
├─ rubric_total(归一 0-1,UI 按它筛低分)
├─ rubric_pass(BOOLEAN)
├─ rubric_p2_avg
└─ comment:失败维度 + judge 判词(不是无信息量的计数)
│
▼
finally: flush_traces() ← 短命进程不 flush,score 随进程蒸发plaintext评测报告新增 trace_id 字段;evolution/ 全链路串起”证据 trace”。
1.2 工具 RT 告警#
refdocs 示例代码四处真错(全部更正):
window_minutes是死字段(deque(maxlen)按条数截断)→ 改滑动时间窗min_samples=10配 P99 = “max 值告警” → 改min_samples=20+ P95check_alerts()没有调用者(抄下来即死代码)→lifespan起后台轮询- 没配 webhook 直接
return(告警凭空消失)→ 落logger.error
三态状态机:breached / cleared / 滞回带静默。两态会发出自相矛盾告警(P95=760ms > 阈值 800ms 但报 breached)。
只有 status=ok 进 RT 窗口:熔断 OPEN 时快速失败 ~0ms,计入会在故障最重时报”已恢复”。
hard_ms 绝对阈值兜底:低 QPS 工具 P95 无统计意义,用绝对阈值兜。
告警消息带最慢调用的 trace 链接(把 SOP 四步压成一次点击)。
1.3 告警规则#
三条:工具 RT P95 / 断路器非 CLOSED / 安全事件增量。一致性测试:规则的 tool 名必须真在 FULL_TOOL_SET 里(名字对不上 = 死规则)。
二、踩坑实录#
坑 1:trace_id 用 ContextVar 传,子 task set 不回传父#
run_agent跑在 create_task 里,ContextVar.set 不回传。改成返回值显式带 trace_id。
坑 2:短命进程不 flush#
run_rubric.py是短命脚本。Langfuse SDK 的 score 在后台队列里,进程退出前不 flush 就蒸发。加finally: flush_traces()。
坑 3:scores_v3.get_many_v3() 不返回 comment#
- Langfuse 列表接口不返回 comment 字段。需要用
api.trace.get()单条读取。
三、面试问答#
Q1: 为什么不直接用 Langfuse Dataset/Experiment?#
“score 挂 trace” 是更轻的方案——不需要创建 Dataset 和 Run,直接把分数打到已有 trace 上。按 rubric_total 降序排就能找到所有 bad case trace。
Q2: 三态状态机为什么比两态好?#
两态(breached/cleared)在边界抖动时会频繁翻转:P95=800ms → breached → P95=799ms → cleared → P95=801ms → breached。三态加滞回带——breached 后必须降到 threshold × 0.8 才 cleared,消除毛刺。
四、诚实边界#
| 维度 | 做了 | 没做 |
|---|---|---|
| 分数回注 | 三条 score + comment | Langfuse Dataset/Experiment |
| 告警 | P95 + hard_ms + 三态 | 告警分级与静默窗口 |
| 告警状态 | 进程内存 | 多 worker Redis 共享 |
| 分位数 | 低频工具 hard_ms 兜底 | 自适应阈值 |