一个让人后背发凉的场景
你的抽取系统跑了三个月,看着一切正常。规则简单粗暴:confidence < 80% 走人审,其他自动通过。吞吐量漂亮,人审成本可控,数据流稳稳的。
季度审计来了。
那些 confidence > 80% 自动通过的样本里,15% 是错的。
也就是说,过去三个月,每一百条"高置信"输出里有十五条带着错误进了下游系统。你的 dashboard 一直在显示绿灯,业务方一直在用这些数据做决策,直到季度审计才暴雷。
最让人难受的不是那 15%------是你的监控视野里根本没有这块区域。它在过去三个月里一直是个黑洞。
这不是 routing 的锅
很多人第一反应是阈值定错了。不是。
Routing 干的事它干了------把低置信样本拦下来送人审、高置信样本放行。它从来没承诺过要"审高置信样本",因为那不是它的工作。它的设计目的就是不去 review 高置信样本 。所以高置信区出多少错,routing 都不会告诉你。这是 routing 系统的结构性盲区------不是 bug,是设计本身。
要解决这个,得在 routing 之外再装一套独立的眼睛。
记住这句话,它是整篇文章唯一要你带走的概念:
Routing 是实时决策,Monitoring 是长期观察。两件事,不能互相替代。
下面三个常见错招,本质上都是用"调决策"在做"加观察"该干的活。
三个看起来合理但走不通的方向
第一种,把阈值从 80% 降到 60%。 直觉是"那高置信也有错,放更多东西去人审"。但仔细看问题------错误出在 80-100% 区间,你把阈值降到 60%,意思是 60-80% 也走人审,而真正出问题的 80-100% 还是自动通过。盲点一个都没消除。代价倒是真实的:生产里 confidence 分布通常向高端集中(大部分样本都在 80% 以上),降阈值会让人审量爆炸,违反 sustainable 要求。
第二种,针对已知问题模式加 heuristic rules。 "见到这种文档格式就拦下来"。听起来务实,实际上只能抓已经见过的旧错误 ------规则是回顾性的,新模式出现时全部失效。规则库会越攒越大,几个月之后变成不可维护的怪兽。更要命的是,规则要么 fire 要么不 fire,binary signal------它没法告诉你"这个月比上个月质量提升了多少"。Monitoring 要的是连续的量化信号,规则给不了。还有一层:很多 semantic error 根本没什么 pattern 可循,模型偶尔把 name 和 employer 字段错位,你规则怎么写都覆盖不到。
第三种,让模型对高置信样本再跑一次做 verification。 看起来很 ML-flavored,实际上有个致命问题叫 self-review bias ------同一个模型第二遍跑相同输入,会重复同一个错误 。它第一次错的原因不是采样运气差,而是它对这类输入的语义理解就是错的。再跑一次还是错的。两次一致并不代表对,只代表它稳定地理解错了。成本翻倍,catch rate 几乎不动。
三招的共同病根都一样:在 routing 这条线 上做文章------调参数、加规则、加步骤------而 monitoring 需要的是另一条独立的观察通道。
正解:分层随机抽样
不改 routing。在 routing 之外 ,每周按 confidence 分层,每层固定比例 抽样送人审。低置信区抽得多,高置信区抽得少,但关键是高置信区也抽。
具体长这样:
| Confidence Tier | Volume | Sample rate | Reviewed |
|---|---|---|---|
| 50-60% | 500 | 20% | 100 |
| 60-70% | 1,000 | 15% | 150 |
| 70-80% | 2,000 | 10% | 200 |
| 80-90% | 4,000 | 5% | 200 |
| 90-100% | 8,000 | 2% | 160 |
注意最后一行。即使 90-100% 的高置信区,也按 2% 抽审 。这就是过去那 15% 隐藏错误能被持续发现的机制。Threshold-based routing 永远不会 review 高置信样本,stratified sampling 会。
总人审量等于 Σ(tier_volume × tier_sample_rate),可预测、可调控、和 routing 互不干扰。
这一招同时解决了四件事
抓得到高置信盲区。 每个 tier 都按比例抽,不存在"放行了就再也看不到"的样本。每周抽样发现,而不是季度审计才发现。
给得出趋势数据。 每个 tier 每周的错误率构成时间序列:
erlang
tier 90-100% error rate:
Week 1: 14%
Week 2: 13.5%
...
Week 8: 8% ← prompt 改动是真的有效
这种时序信号能干三件事:验证你的 prompt 改动 / model 切换 / schema 调整是不是真的有效;检测 model drift (某周突然飙升 = 上游文档分布变了?);给 calibration 重新拟合提供 ground truth------人审标注就是真实标签,可以每月重新画 calibration curve。
统计学合理。 随机抽样无偏,分层保证每个置信区间都有足够样本量做推断,不会发生"高置信区抽到的全是 outlier"这种偏差。
人审预算可控,sustainable 不是空话。
落地到生产大概长这样
骨架很简单,三步:
py
# 1. 每次 extraction 后,trace 落库,带上 confidence_tier 字段
log_trace({
"trace_id": ...,
"extracted": result,
"confidence_score": conf,
"confidence_tier": bucketize(conf), # ← 关键字段
"review_status": "auto_approved",
})
# 2. 每周 cron job 按 tier 抽样
for tier in confidence_tiers:
samples = query_traces(tier=tier, week=current_week)
n = int(len(samples) * SAMPLING_RATES[tier])
enqueue_for_human_review(random.sample(samples, n))
# 3. Reviewer 标注后写回,构成 ground truth
# 每月重新拟合 calibration curve
三件套:trace 记录 + review queue + stratified sampler。任何 production LLM 系统的质量保证体系,骨架都长这样。
最后一句
调 routing 永远治不了 routing 看不见的东西。
要看见高置信区的盲点,得加一双独立的眼睛 ------而那双眼睛叫 stratified random sampling。
Threshold routing 决定数据怎么走 ,stratified sampling 决定你看见了什么。两件事一起跑,你的 LLM 系统才有资格叫 production-ready。