mle-workflow

star 1

生产级 ML 工程全流程——数据契约、可复现训练、模型评估、部署、监控、回滚。适用于需要超越 notebook 一次性脚本的 ML 系统。

letsgetai By letsgetai schedule Updated 6/4/2026

name: mle-workflow description: 生产级 ML 工程全流程——数据契约、可复现训练、模型评估、部署、监控、回滚。适用于需要超越 notebook 一次性脚本的 ML 系统。 origin: ECC

ML 工程工作流

把模型工作变成生产级 ML 系统:明确的数据契约、可重复训练、可度量的质量门禁、可部署的产物、运行时监控。

什么时候用

  • 规划或审核生产级 ML 功能:模型刷新、排序系统、推荐、分类、embedding、预测流水线
  • 把 notebook 代码转化为可复用的训练、评估、批量推理或在线推理流水线
  • 设计模型晋级标准、离线/在线评估、实验追踪、回滚路径
  • 排查数据漂移、标签泄露、特征过期、产物不匹配、训练-服务不一致等问题
  • 添加模型监控、灰度发布、影子流量、部署后质量检查

范围校准

只使用当前系统需要的部分。这个 skill 适用于排序、搜索、推荐、分类、预测、embedding、LLM 工作流、异常检测、批量分析,但不应强制套一个架构到所有场景。

  • 不要假设每个模型都有监督标签、在线服务、特征存储、PyTorch、GPU、人工审核、A/B 测试或实时反馈
  • 当一个数据契约 + 基线 + 评估脚本 + 回滚说明就够时,不要上加重量级 MLOps 工具
  • 当项目缺少标签、延迟结果、切片定义、生产流量或监控负责人时,明确写出假设
  • 示例只是脚手架,替换成项目实际的指标、服务方式、数据存储和发布机制

相关 Skill

  • python-patterns / python-testing — Python 实现和 pytest 覆盖
  • pytorch-patterns — 深度学习模型、数据加载器、设备处理、训练循环
  • eval-harness / ai-regression-testing — 晋级门禁和回归检查
  • database-migrations / postgres-patterns / clickhouse-io — 数据存储和分析
  • deployment-patterns / docker-patterns / security-review — 服务、密钥、容器和生产加固

复用软件工程基础

不要把 MLE 当作和软件工程完全独立的事。大多数 SWE 工作流直接适用于 ML 系统,只是失败模式更严格:

SWE 能力 MLE 用途
产品能力定义 / 架构决策记录 把模型工作变成明确的产品契约,记录不可逆的数据、模型和发布决策
仓库扫描 / 代码入门 在引入并行 ML 栈之前,找到已有的训练、特征、服务、评估和监控路径
计划 / 功能开发 把模型改动范围化为:数据、评估、服务、回滚四个阶段
TDD / Python 测试 在实现之前测试特征变换、数据拆分、指标计算、产物加载和推理 schema
代码审核 / MLE 审核 审核代码质量 + ML 特有的泄露、可复现性、晋级和监控风险
构建修复 / PR 测试分析 诊断失败的 CI、不稳定的评估、缺失的 fixture、环境相关的模型或依赖失败
质量门禁 / 测试覆盖 为变换、指标、推理契约、晋级门禁和回滚行为要求自动化证据
评估框架 / 验证循环 把离线指标、切片检查、延迟预算和回滚演练变成可重复的门禁
AI 回归测试 把每个生产 bug 保存为回归用例:缺失特征、过期标签、坏产物、schema 漂移、服务不匹配
API 设计 / 后端模式 设计预测 API、批量任务、幂等重训练端点和响应格式
数据库迁移 / Postgres / ClickHouse 版本化标签、特征快照、预测日志、实验指标和漂移分析
部署模式 / Docker 打包可复现的训练和服务镜像,含健康检查、资源限制和回滚
灰度观察 / 仪表盘 让发布健康度可见:模型版本、切片、漂移、延迟、成本和延迟标签
安全审核 / 安全扫描 检查模型产物、notebook、prompt、数据集和日志中的密钥、PII、不安全反序列化和供应链风险
端到端测试 / 浏览器 QA 测试使用预测结果的关键产品流程,包括可解释性和降级 UI 状态
基准测试 / 性能优化 测量吞吐量、p95 延迟、内存、GPU 利用率和每次预测/重训练的成本
成本感知 LLM 流水线 按质量、延迟和预算路由 LLM/embedding 工作负载,而非默认用最贵的模型

迭代契约(Iteration Compact)

在动模型代码之前,把工作压缩成一份可审核的文档。应该短到能放进 PR 描述,精确到另一个工程师能质疑其中的权衡。

目标:
谁关心:
决策负责人:
模型改变了哪个用户/系统行为:
成功指标:
护栏指标:
错误预算:
不可接受的错误:
可接受的错误:
假设:
约束:
标签和数据快照:
基线:
候选信号:
阈值/配置方案:
评估切片:
已知风险:
下一个实验:
回滚/降级方案:

这个契约是 MLE 版的强力设计文档。防止团队去优化一个没人信任的指标、添加不解决真实错误模式的特征、或者在没有回滚方案的情况下发布复杂改动。

决策思维

任务模糊、影响大、或指标密集时用这个循环:

  1. 从决策出发,不从模型出发 — 明确哪个下游行为会被改变
  2. 明确谁关心、为什么 — 不同利益方对误报、漏报、延迟、计算成本、不透明性、错过机会的代价不同
  3. 把模糊转化为假设 — 什么信号能区分结果?什么证据能推翻假设?什么简单基线应该很难被超越?
  4. 先查先例或类似问题,再从头发明
  5. 用 (概率, 置信度) x (成本, 严重性, 重要性, 影响) 来评分方案
  6. 考虑对抗行为、激励、选择性披露、分布漂移和反馈循环
  7. 偏好最简单的、能减少最重要错误的改动 — 简单不是偷懒,是在保持迭代速度的同时减少失误
  8. 记录决策、证据、反面论点和下一个可逆步骤

指标与错误经济学

从失败成本出发选指标,不要凭习惯:

  • 混淆矩阵先行 — 让团队讨论具体的误报和漏报,而不是抽象的"准确率"
  • 误报代价大 → 倾向精确率(precision)
  • 漏报代价大 → 倾向召回率(recall)
  • 精确率/召回率真正平衡时 → 用 F1(且能解释清楚)
  • 排序质量比单一阈值重要时 → 用 AUC 或排序指标
  • 延迟、吞吐量、内存、成本作为一等指标 — 它们决定了可行的模型复杂度
  • 和基线以及当前生产模型对比,再庆祝离线提升
  • 真实反馈信号有延迟、偏差和覆盖缺口 — 不要不加分析地当作 ground truth

每个指标选择都应说明:它让哪种错误变便宜了、让哪种错误变更可能了、谁来承担这个成本。

数据与特征假设

特征应来自区分理论

  • 文本、分类字段、数值历史、图关系、时间近度、频率和聚合都是候选信号族,不是自动特征
  • 对每个信号族,说明它为什么应该能区分结果,以及它可能如何泄露未来信息
  • 对噪声标签,考虑裁定、标签置信度、软目标或置信度加权
  • 对类别不平衡,比较加权损失、重采样、阈值移动和校准决策规则
  • 对缺失值,决定缺失本身是否有信息量、是否可以插补、还是应该拒绝预测
  • 对异常值,决定是裁剪、分桶、调查还是作为稀有但重要的信号保留
  • 对相关特征,检查它们是冗余的、不稳定的、还是不可用未来状态的代理

不要在错误分析表明基线失败原因之前,就加模型复杂度。

错误分析循环

每次基线、训练、阈值变更或配置变更后:

  1. 把错误分为:误报、漏报、拒绝预测、低置信度案例、系统故障
  2. 按共性聚类:语言、实体类型、来源、时间、地域、设备、稀疏度、时间近度、特征新鲜度、标签来源、模型版本
  3. 区分模型错误 vs 数据 bug、标签歧义、产品歧义、监控缺口、服务不匹配
  4. 把每个主要错误簇追溯到四种应对之一:更好的标签、更好的特征、更好的阈值/配置、更好的产品降级
  5. 把每个重要错误保存为回归测试、评估切片、仪表盘面板或运维手册条目
  6. 把下一次迭代写成可证伪的实验,而不是模糊的"改进模型"

最强的 MLE 循环不是 训练→指标→发布,而是 错误→聚类→假设→实验→证据→更简单的系统。

观察台账

在代码、PR、实验报告或运维手册旁保留一份精简的决策和证据记录:

迭代:
改动:
为什么重要:
指标变化:
切片变化:
误报:
漏报:
意外错误:
决策:
接受的权衡:
记录的经验:
添加的回归:
产生的债务:
下一轮迭代:

用台账让模型工作累积化。目标是每次迭代让下一个决策更容易,而不只是产出另一个产物。

核心工作流

1. 定义预测契约

写模型代码之前,先确定产品级契约:

  • 预测目标和决策负责人
  • 输入实体、输出 schema、置信度/校准字段、允许的延迟
  • 批量、在线、流式或混合服务模式
  • 模型/特征存储/依赖不可用时的降级行为
  • 高影响决策的人工审核或覆盖路径
  • 输入、预测和标签的隐私、保留和审计要求

不接受"改进模型"作为需求 — 绑定到一个可观察的产品行为和可度量的验收门禁。

2. 锁定数据契约

每个 ML 任务需要明确的数据契约:

  • 实体粒度和主键
  • 标签定义、标签时间戳、标签可用延迟
  • 特征时间戳、新鲜度 SLA、时间点 join 规则
  • 训练、验证、测试、回测的拆分策略
  • 必需列、允许的 null、范围、类别和单位
  • 不得进入训练产物或日志的 PII 或敏感字段
  • 数据集版本或快照 ID(可复现性)

防泄露优先 — 如果特征在预测时不可用,或使用了未来信息才能 join,移除它或仅用于分析。

3. 构建可复现的流水线

训练代码应该能被另一个工程师跑通,不依赖隐藏的 notebook 状态:

  • 用类型化配置文件或 dataclass 管理所有超参数和路径
  • 固定包和模型依赖版本
  • 设置随机种子,记录任何非确定性 GPU 行为
  • 记录数据集版本、代码 SHA、配置哈希、指标和产物 URI
  • 预处理逻辑和模型产物一起保存,不要单独留在 notebook 里
  • 训练、评估和推理的变换共享同一份代码
  • 每步幂等,重试不会破坏产物或指标

优先用不可变值和纯变换函数。特征生成期间不要 mutate 共享 DataFrame 或全局配置。

import hashlib
from dataclasses import dataclass
from pathlib import Path


@dataclass(frozen=True)
class TrainingConfig:
    dataset_uri: str
    model_dir: Path
    seed: int
    learning_rate: float
    batch_size: int


def artifact_name(config: TrainingConfig, code_sha: str) -> str:
    config_key = f"{config.dataset_uri}:{config.seed}:{config.learning_rate}:{config.batch_size}"
    config_hash = hashlib.sha256(config_key.encode("utf-8")).hexdigest()[:12]
    return f"{code_sha[:12]}-{config_hash}"

4. 晋级前评估

晋级标准应在训练结束前就声明:

  • 基线模型和当前生产模型的对比
  • 主指标与产品行为对齐
  • 护栏指标:延迟、校准、公平性切片、成本、错误集中度
  • 重要群体的切片指标(地域、设备、语言、数据来源)
  • 指标噪声大时的置信区间或重复运行方差
  • 高影响模型的失败样例需人工审核
  • 明确的"不发布"阈值
PROMOTION_GATES = {
    "auc": ("min", 0.82),
    "calibration_error": ("max", 0.04),
    "p95_latency_ms": ("max", 80),
}


def assert_promotion_ready(metrics: dict[str, float]) -> None:
    missing = sorted(name for name in PROMOTION_GATES if name not in metrics)
    if missing:
        raise ValueError(f"模型晋级指标缺少必要门禁: {missing}")

    failures = {
        name: value
        for name, (direction, threshold) in PROMOTION_GATES.items()
        for value in [metrics[name]]
        if (direction == "min" and value < threshold)
        or (direction == "max" and value > threshold)
    }
    if failures:
        raise ValueError(f"模型未通过晋级门禁: {failures}")

离线指标是门禁,不是保证。当模型改变了产品行为时,在全量发布前规划影子评估、灰度发布或 A/B 测试。

5. 打包服务

ML 产物只有在服务契约可测试时才算生产就绪:

  • 模型产物包含版本、训练数据引用、配置和预处理
  • 输入 schema 拒绝无效、过期或超范围的特征
  • 输出 schema 包含模型版本和置信度/解释字段(如适用)
  • 服务路径有超时、批处理、资源限制和降级行为
  • CPU/GPU 需求明确且已测试
  • 预测日志不含 PII,包含足够的标识符用于调试和标签 join
  • 集成测试覆盖:缺失特征、过期特征、错误类型、空批次、降级路径

绝不允许训练端特征代码和服务端特征代码分叉,除非有测试证明等价。

6. 运维模型

模型监控需要系统信号和质量信号并重:

  • 可用性、错误率、超时率、队列深度、p50/p95/p99 延迟
  • 特征 null 率、范围漂移、类别漂移、新鲜度漂移
  • 预测分布漂移和置信度分布漂移
  • 标签到达健康和延迟质量指标
  • 业务 KPI 护栏和回滚触发条件
  • 灰度和回滚的分版本仪表盘

每次部署都应有回滚方案,明确:上一个产物、配置、数据依赖和流量切换机制。

审核清单

  • 预测契约明确且可测试
  • 数据契约定义了实体粒度、标签时间、特征时间和快照/版本
  • 泄露风险已对照预测时可用性检查
  • 训练可从代码、配置、数据版本和种子复现
  • 指标与基线和当前生产模型对比
  • 高风险群体的切片指标和护栏已包含
  • 晋级门禁已自动化,失败时拒绝晋级
  • 训练和服务的变换共享同一份代码或已做等价测试
  • 模型产物携带版本、配置、数据集引用和预处理
  • 服务路径验证输入,有超时、降级和回滚行为
  • 监控覆盖系统健康、特征漂移、预测漂移和延迟标签
  • 敏感数据不进入产物、日志、prompt 和示例

反模式(要避免的坑)

  • 需要 notebook 状态才能复现模型
  • 随机拆分把未来数据泄露到验证集或测试集
  • 特征 join 忽略了事件时间和标签可用性
  • 离线指标提升了,但重要切片退步了
  • 阈值在测试集上反复调优
  • 训练预处理被手动复制到服务代码
  • 预测日志缺少模型版本
  • 监控只检查服务是否在线,不看数据或预测质量
  • 回滚需要重新训练,而不是切换到已知可用的产物

输出期望

使用此 skill 时,返回具体产物:数据契约、晋级门禁、流水线步骤、测试计划、部署计划或审核发现。明确标出阻碍生产就绪的未知项,而不是用假设填充。

Install via CLI
npx skills add https://github.com/letsgetai/agent-skills --skill mle-workflow
Repository Details
star Stars 1
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator