本节摘要:裁判分告诉你"确实坏了",但要等抽样、排程与攒样本——它是滞后指标。漂移信号反过来:不看内容、只看形状,从每次调用的元数据里算出四个代理信号——延迟分布(P95 与首 token 时间)、拒绝率(拒答与被安全策略拦截的占比)、输出长度突变(均值与分布形状)、主题漂移(新话题份额)——它们常常在用户大规模投诉之前先露马脚。本节逐个给出信号的定义、算法与"什么故障的先兆",再给三层阈值法:静态阈值守合规底线、基线带抓缓慢漂移、日环比抓突变;最后是信号组合解读表与一张 ASCII 面板布局。第 3.3 节的动态基线思想(用过去 7~14 天同时段做基线)在本节全面展开成质量侧的版本。
第 4.1 节的探针有两个先天延迟:抽样要凑样本量,裁判要排程跑批。一个周二下午上线的坏 prompt,探针分数可能周四才攒够样本、周五才进周报——而用户周三就开始复述提问了。
漂移信号(drift signal)的思路是:质量劣化几乎总会先改变输出的"形状"——答得更慢、更短、更爱拒答、话题构成变了。形状可以从元数据算,元数据是全量的(第 2.3 节),于是漂移信号天然全覆盖、近实时、零裁判成本。代价是粗:形状变了不一定是质量坏了(也可能只是流量结构变了),所以漂移信号只负责拉响"去看"的第一声,确认要回到探针与 trace 还原。
(文字流程图) 时间轴 ──▶ 故障发生 ──▶ 漂移信号越带(分钟级)──▶ 人工/自动拉探针与 trace 复核 ──▶ 裁判分下跌(天级)──▶ 确认与归因 ──▶ 用户点踩/投诉(天级起)──▶ 最贵的确认方式
信号一:延迟分布。 口径:P50/P95/P99 总耗时 + 首 token 时间(TTFT,第 2.1 节埋的字段)。只看均值会被流量结构骗——长问答占比变多,均值自然涨。先兆:TTFT 恶化常指向供应商容量或排队(第 5.1 节超时类);生成段变慢(总时延涨、TTFT 不动)常指向输出变长或模型侧退化。
信号二:拒绝率。 口径:拒绝数 ÷ 请求数,拒绝包括模型拒答词命中与安全策略拦截,分开口径记。先兆:输入分布变了(用户在问训练时没见过的新话题)、prompt 改动误伤(把正常请求也拦了)、模型快照漂移变保守(第 1.1 节版本飞轮)。
信号三:输出长度突变。 口径:输出 token 的均值与 P95,以及"超短(小于 20 token)占比"和"超长(大于 P99 历史值)占比"两个尾部。双向都要看:突然变短可能是截断与静默失败;突然变长可能是 agent 冗长、循环重试的前兆、或 max_tokens 形同虚设——它同时是成本爆炸的先兆(第 3.1 节账二)。
信号四:主题漂移。 口径:把请求按意图分类(规则或轻量分类器),统计"已知主题占比"与"新主题份额";或用检索命中分布代替——某类问题突然检索零命中暴涨。先兆:产品进入新市场、新闻事件带来新问法(知识库没跟上)、季节性话题。它解释"为什么其他三个信号都动了":很多时候不是系统坏了,是输入世界变了。
| 信号 | 口径 | 越线方向 | 常见先兆(接第 5.1 节故障分类) |
|---|---|---|---|
| 延迟分布 | P95、TTFT | 变慢 | 超时/慢类;上游容量、排队 |
| 拒绝率 | 拒答+拦截,分口径 | 变高 | 坏答案类;输入分布变化 |
| 输出长度 | 均值、尾部占比 | 双向 | 变长→成本爆炸类;变短→坏答案类 |
| 主题漂移 | 新主题份额 | 变高 | 多数信号异动的背景解释项 |
第一层:静态阈值。 人为底线,来自合规或产品定义,如"拦截率超过 30% 必须人工看"(示意)。它抓的是绝对不可接受,不随历史漂移——基线再好,越过底线也要响。
第二层:基线带。 用过去 7~14 天同时段(对齐星期几与小时,社区常用做法)的均值做基线,上下各放带宽(如 ±30%,示意,按信号噪声调):落在带内视为正常波动。它抓缓慢漂移——每天差一点、一个月差一截的温水煮青蛙,静态阈值永远看不见。
第三层:日环比。 今日至今值对比昨日全天同时段值,偏离超过阈值(如 ±40%,示意)即异常。它抓突变——昨天上的新 prompt 今天上午就露馅,不用等 7 天基线重新长出来。
三层的告警级别不同:静态阈值直接进提醒线以上;基线带越界进值班群观察;日环比突变配合"当天有变更"的上下文升级处理(第 3.3 节三线模型的对口应用)。
# drift_panel.py —— 漂移检测:三层阈值法(纯标准库,示意数据) STATIC_FLOOR = {"拦截率": 0.30} # 静态底线(示意) BAND = 0.30 # 基线带宽 ±30%(示意) WOW = 0.40 # 日环比阈值 ±40%(示意) def check(name: str, baseline: float, today: float, yesterday: float, static: float | None = None) -> str: lo, hi = baseline * (1 - BAND), baseline * (1 + BAND) flags = [] if static is not None and today > static: flags.append("越静态底线") if today > hi: flags.append("越上带") elif today < lo: flags.append("跌破下带") if yesterday > 0 and abs(today / yesterday - 1) > WOW: flags.append("日环比突变") state = " ∪ ".join(flags) if flags else "正常" return f"{name:<10s} 基线 {baseline:.3f} | 今日 {today:.3f} | 昨日 {yesterday:.3f} → {state}" if __name__ == "__main__": print(check("P95延迟秒", baseline=3.2, today=4.9, yesterday=3.3)) print(check("拒绝率", baseline=0.05, today=0.12, yesterday=0.05)) print(check("输出token", baseline=420.0, today=180.0, yesterday=390.0)) print(check("新主题份额", baseline=0.04, today=0.19, yesterday=0.05)) print(check("拦截率", baseline=0.08, today=0.34, yesterday=0.09, static=STATIC_FLOOR["拦截率"]))
输出(实测):
P95延迟秒 基线 3.200 | 今日 4.900 | 昨日 3.300 → 越上带 ∪ 日环比突变 拒绝率 基线 0.050 | 今日 0.120 | 昨日 0.050 → 越上带 ∪ 日环比突变 输出token 基线 420.000 | 今日 180.000 | 昨日 390.000 → 跌破下带 ∪ 日环比突变 新主题份额 基线 0.040 | 今日 0.190 | 昨日 0.050 → 越上带 ∪ 日环比突变 拦截率 基线 0.080 | 今日 0.340 | 昨日 0.090 → 越静态底线 ∪ 越上带 ∪ 日环比突变
四行全突变,这不是四个独立故障——更像一件事:输入分布变了或版本变更出问题。这就引出组合解读。
单一信号会骗人,组合才有指向性(右列接第 5 章排障树):
| 组合 | 优先怀疑 | 第一动作 |
|---|---|---|
| 延迟↑ + 长度↑ | 输出变长拖慢生成,可能循环前兆 | 查 TopN 会话 token(第 3.3 节) |
| 延迟↑ + 长度↓ + 拒绝率平 | 上游变慢或排队,输出被截断 | 查 llm.call 段占比与 TTFT |
| 拒绝率↑ + 新主题份额↑ | 输入世界变了,非系统故障 | 补知识库/加意图,暂不回滚 |
| 长度↓ + 超短占比↑ | 截断或静默失败 | 拉超短样本的 trace 还原 |
| 四信号齐动 + 当天有变更 | 版本回归(prompt/模型/检索库) | 直接进变更回滚评估 |
面板布局(一屏五分钟):
┌─ 质量漂移面板(每功能一列,此处示意一个功能)──────────────────┐ │ 信号 │ 基线(7天) │ 今日 │ 状态 │ 趋势(近14天) │ │ P95 延迟 │ 3.2s │ 4.9s │ 越上带 │ ↗ │ │ TTFT │ 1.1s │ 1.2s │ 正常 │ → │ │ 拒绝率 │ 5.0% │ 12.0% │ 越上带 │ ↗ │ │ 输出长度均值 │ 420 │ 180 │ 跌破下带 │ ↘ │ │ 新主题份额 │ 4.0% │ 19.0% │ 越上带 │ ↗ │ │ 探针合格率 │ 91% │ 74% │ 待攒样本 │ ↘ │ └─────────────────────────────────────────────────────────────────┘
最后一行放探针合格率是有意的:代理信号与直接信号同屏,漂移越带时能立刻看到裁判侧是否已确认。缓存命中率也建议放进来(第 3.1 节口径:写入后实际读到的比例)——它同时是成本与质量的交叉信号。
⚠️ 阈值初设一定会误报。约定:新信号上线先"影子运行"两周只记不报,用这两周的数据把带宽调到日均误报不超过一次(社区经验值),再接入告警——否则面板三天就被静音。
三支柱至此合拢:Trace 管发生了什么、成本管花了多少、质量管好不好。下一章把信号变成行动——告警响了以后先看什么、四类故障怎么分、排障树怎么从一条告警走到根因。