面试官让你解释模型应该如何平稳上线,你的回答里有没有先检查“够不够稳”再谈“有没有变好”?很多候选人一上来就展示线上指标提升,却绕过了 MLOps 里真正要命的顺序——模型发布不是“候选指标更高就发上线”,而是一串有严格优先级的门控判断。

一个候选模型可能在线下或某个线上指标上比基线更好,同时让整个服务链路变得更糟。因此在面试中,更值得被记住的回答不是列出看板上的数字,而是展示一份有先后次序的决策链条。那份链条的第一条规则往往比最后一条更能看出候选人的实践判断力——即使还没到讨论金丝雀发布那一步。

打开网易新闻 查看精彩图片

下面这个无外部依赖的 JavaScript 示例,接收基线切片和候选切片的聚合指标,返回决策结果和第一个决定性原因。生产环境里这些输入当然来自受监控的、带时间窗的指标,而不是写死的对象。

import assert from "node:assert/strict";const errorRate = ({ errors, samples }) => errors / samples;function decideRollout(baseline, candidate, policy) {const { minSamples, maxErrorRateDelta, maxP95Increase, minQualityLift } = policy;if (Math.min(baseline.samples, candidate.samples) < minSamples) {return "HOLD: collect more traffic";if (errorRate(candidate) - errorRate(baseline) > maxErrorRateDelta) {return "ROLLBACK: error rate regressed";const p95Increase = (candidate.p95 - baseline.p95) / baseline.p95;if (p95Increase > maxP95Increase) {return "ROLLBACK: latency regressed";if (candidate.quality - baseline.quality < minQualityLift) {return "HOLD: quality lift is not proven";return "PROMOTE: guardrails passed";

策略对象里把每个阈值都明晃晃地写了出来,目的就是让审核者——或是那位坐在对面的面试官——能够逐条挑战你的设定:

const policy = {minSamples: 500,maxErrorRateDelta: 0.002, // 0.2 个百分点maxP95Increase: 0.10, // 10%minQualityLift: 0.01, // 一个质量点

基线的数据是 2000 样本、20 个错误、P95 延迟 180、质量分数 0.80。接下来四个断言正好覆盖了从“放行”到“挡下”的完整决策树,也顺便验证了顺序本身就是策略的一部分。

第一个候选模型在 1000 个样本里仅产生 8 个错误,P95 降到 170,质量提到 0.82。它同时满足样本量、错误率、延迟和质量提升四个条件,输出 PROMOTE。

第二个候选质量更高(0.83),但在 1000 个样本中出现了 18 个错误。它的错误率差值超过了 0.2 个百分点的阈值,直接被 ROLLBACK。注意,即使它的质量提升更明显,仍然会在第一步检查样本量后、就因错误率退化而被驳回——它根本没机会走完后续的延迟和质量判断。

第三个候选指标极其漂亮:120 个样本、仅 1 个错误、P95 170、质量 0.90。然而决策函数一上来就发现双方样本均未达到 500,立即返回 HOLD。更好的质量在证据不足时并不构成提前放行的理由。

第四个候选在相同样本量下错误率和延迟都合格,唯独质量只从 0.80 提到 0.805,未达到 1 个质量点的最小提升要求,于是被 HOLD。哪怕其他防护门都已通过,质量提升不足就是不足。

四个用例全部通过断言:

assert.match(decideRollout(baseline, { samples: 1000, errors: 8, p95: 170, quality: 0.82 }, policy),/PROMOTE/assert.match(decideRollout(baseline, { samples: 1000, errors: 18, p95: 170, quality: 0.83 }, policy),/ROLLBACK: error/assert.match(decideRollout(baseline, { samples: 120, errors: 1, p95: 170, quality: 0.90 }, policy),/HOLD: collect/assert.match(decideRollout(baseline, { samples: 1000, errors: 8, p95: 170, quality: 0.805 }, policy),/HOLD: quality/

重要的不是算数本身,而是决策的优先级。样本量不够的候选哪怕质量更优,也得先被 hold 住而不是直接上线。质量提升明显但错误率恶化的候选被直接回滚,连被 hold 的机会都没有——正是这种先后次序让整个发布策略具备可审计性。面试时把顺序理清,比记住了几个数字阈值要管用得多。你说的每个门控条件其实都在告诉对方:你知道什么时候该拒绝,什么时候才配谈提升。