CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
MLOps 入门/课时/MLflow 与血缘
RawBlame
课时目录12 节

MLOps 入门

  1. 01MLOps 是什么
  2. 02数据工程基础
  3. 03版本控制与 DVC
  4. 04训练与实验跟踪
  5. 05MLflow 与血缘
  6. 06编排与调度
  7. 07CI/CD for ML
  8. 08容器化部署
  9. 09云原生 ML
  10. 10监控与可观测
  11. 11可解释 AI
  12. 12综合练习

MLflow 与血缘

Registry、评估门禁与 lineage。

30 分钟

MLflow 与血缘

这一课你将能做到

  1. 启动集中式 MLflow Server(元数据 + artifact 分离),把模型注册进 Model Registry
  2. 用别名(alias)实现模型晋升 challenger → champion,并让服务按别名动态加载
  3. 打通「模型版本 → run → 数据版本/代码版本」的血缘链,做到任何线上模型可回溯

为什么要学

上一课的 Tracking 解决了「实验记下来」,但还有三个生产问题没解决:哪个 run 有资格上线(需要注册与门禁)、线上跑的是哪一版(需要版本指针)、出事后怎么查(需要血缘)。MLflow Model Registry 就是模型界的「发布仓库」:run 是草稿,Model Version 是待审品,alias(champion/challenger)是线上指针,门禁是审核规则。

人话:把「把最新模型文件 scp 到服务器覆盖旧的」这种裸奔操作,升级成「注册 → 评估 → 晋升 → 回滚都动指针」的正规军流程。本站判题超时模型将获得一个真正的生产身份:timeout_classifier@champion。

先建立图像

训练 run (src/train.py)
   │ mlflow.register_model
   ▼
Model Registry: timeout_classifier
├─ Version 5  alias: challenger   ← 新模型先挂挑战者
├─ Version 4  alias: champion     ← 线上正在服务
└─ Version 3  (无 alias,可随时指回)

线上服务启动时读 models:/timeout_classifier@champion
晋升 = 把 champion 从 v4 挪到 v5(一次 API 调用),服务重启即生效
回滚 = 把 champion 指回 v4,秒级完成,不需要重新部署

血缘:Version 5 ──▶ run abc123 ──▶ params/tags ──▶ git_sha + 数据文件哈希

跟着做

步骤 1:启动集中式 MLflow Server

mlflow server \
  --backend-store-uri sqlite:///mlflow.db \
  --artifacts-destination ./mlartifacts \
  --host 127.0.0.1 --port 5000

元数据(实验/run/注册信息)进 SQLite,模型文件进本地目录。生产把两者换成 PostgreSQL + S3/OSS 即可,客户端代码不变。

步骤 2:训练时直连 Server 并注册

给上一课的 src/train.py 增加两处:脚本开头设置远端 URI,run 内注册模型。

# src/train.py 顶部新增
import os
mlflow.set_tracking_uri(os.getenv("MLFLOW_TRACKING_URI", "http://127.0.0.1:5000"))

# main() 里 log_model 之后新增
mlflow.register_model(
    model_uri=f"runs:/{run.info.run_id}/model",
    name="timeout_classifier",
    tags={"git_sha": git_sha()},
)
export MLFLOW_TRACKING_URI=http://127.0.0.1:5000
python src/train.py
# UI 的 Models 页面出现 timeout_classifier 的最新 Version

步骤 3:用别名管理晋升与回滚

新版 MLflow 推荐 alias 替代旧的 stage(staging/production)机制——后者已标记弃用,但面试仍会问到,概念一致。

# src/promote.py
import sys
from mlflow.tracking import MlflowClient

MODEL = "timeout_classifier"
client = MlflowClient()

def promote(version: int):
    v = client.get_model_version(MODEL, str(version))
    assert v.run_id, "必须来自真实 run,拒绝裸文件注册"
    client.set_registered_model_alias(MODEL, "challenger", version)
    print(f"v{version} → challenger")

def gate_and_release(version: int, min_auc: float = 0.80):
    run = client.get_run(client.get_model_version(MODEL, str(version)).run_id)
    auc = run.data.metrics["roc_auc"]
    if auc < min_auc:
        sys.exit(f"门禁不通过:auc={auc:.3f} < {min_auc}")   # 指标门禁
    client.set_registered_model_alias(MODEL, "champion", version)
    client.update_model_version(
        name=MODEL, version=str(version),
        description=f"released, auc={auc:.3f}")            # 留痕
    print(f"v{version} → champion")

if __name__ == "__main__":
    cmd, version = sys.argv[1], int(sys.argv[2])
    if cmd == "stage":
        promote(version)
    elif cmd == "release":
        gate_and_release(version)
    else:
        sys.exit("用法: python src/promote.py stage|release <version>")
python src/promote.py stage 5     # 先挂挑战者
python src/promote.py release 5   # 过指标门禁后晋升冠军

步骤 4:服务端按别名加载

# src/serve.py(替换原来的 joblib.load)
import mlflow

mlflow.set_tracking_uri("http://127.0.0.1:5000")
model = mlflow.pyfunc.load_model("models:/timeout_classifier@champion")
# predict 函数改为:
#   proba = model.predict(X)[0]  → pyfunc 统一入口,换模型类型不改服务代码

champion 指向新版本后重启服务(或热重载),就完成了一次「发布」。回滚同理:把 champion 指回旧 version。

步骤 5:血缘回溯

from mlflow.tracking import MlflowClient
client = MlflowClient()
mv = client.get_model_version_by_alias("timeout_classifier", "champion")
run = client.get_run(mv.run_id)

print("模型版本:", mv.version)
print("代码版本:", run.data.tags.get("git_sha"))
print("数据来源:", run.data.tags.get("data"))
print("参数:", run.data.params)
print("指标:", run.data.metrics)

线上出问题时,这段脚本 30 秒给出答案:线上模型是哪个 run、哪份代码、哪份数据训的。

讲清楚要点

  1. Registry 是状态机,不是文件夹:Version 从注册到发布经过「注册 → 挑战者 → 门禁 → 冠军 → 可回滚」,每个动作都是对指针的原子操作,全程留痕。
  2. alias 与 stage 的关系:stage(Staging/Production/Archived)是旧机制,多套环境时容易和真实环境脱节;alias 是自由标签,champion/challenger/shadow 随你定义,一个 version 可挂多个 alias,语义更干净。
  3. 门禁必须是代码而不是默契:gate_and_release 里的 min_auc 判断就是最简门禁。进阶做法是接 Evidently 评估报告(第 10 课)作为第二道门禁。
  4. 血缘三件套:run 打 git_sha tag、data 数据标识 tag、模型 version 关联 run。DVC 的数据哈希、Git 的提交号、MLflow 的 run_id 三者互相引用,构成完整证据链。
  5. pyfunc 统一推理入口:服务端不关心模型是 sklearn 还是 PyTorch,model.predict(X) 一个签名走天下,切换模型框架不改服务代码。

你可能会懵的地方

  • 新版本 MLflow 找不到 transition_model_stage 了? 该 API 已弃用,改用 set_registered_model_alias。迁移思路:@champion 对应旧 Production,@staging 对应旧 Staging。老教程里的 stage 代码照抄会报错,面试回答时先讲 alias 再补一句 stage 的历史即可。
  • 灰度发布和 Registry 怎么配合? Registry 管版本指针,灰度管流量切分。常见模式:起两个服务实例,一个读 @champion(95% 流量)一个读 @challenger(5% 流量),网关按权重转发;观察无异常后晋升 challenger。
  • 注册模型需要审批流吗? 小团队用「门禁脚本 + PR 审核 promote.py 的改动」即可;平台化团队把 alias 变更接入工单或 GitOps:alias 配置进 Git,CI 审核后调 API,天然带审计日志。
  • run 和 Model Version 生命周期有何区别? run 是一次训练的完整档案,实验期可随意产生与清理;Model Version 是通过注册动作「转正」的产物,只应从有价值的 run 创建,且有指针引用、不可变。清理实验时永远先查有无 version 依赖。
  • 血缘只靠 tag 够吗? 小规模够用。规模化后可升级为 OpenLineage 等标准协议自动采集事件,生成 DAG 式血缘图(数据表 → 作业 → 模型 → 服务)。先用 tag 养成习惯,再谈工具。

错法对照

错法问题正解
新模型直接把 champion 覆盖无门禁、无法回滚先挂 challenger,过门禁再晋升
从本地 joblib 文件手动注册run_id 缺失,血缘断裂必须从 runs:/ URI 注册
version 只换不写描述事后没人知道 v5 改了什么晋升时 update_model_version 写变更摘要
服务端硬编码模型版本号回滚要改代码重新部署服务只认 @champion,回滚动指针
删除旧 version 腾空间血缘链断裂,事故无法归因旧版本归档保留,artifact 用生命周期策略管理

卡点急救

  1. register_model 报 not found:客户端 MLFLOW_TRACKING_URI 与 Server 不一致;mlflow.set_tracking_uri 或环境变量二选一,训练与服务保持同一地址。
  2. load_model 报 alias 不存在:client.search_model_versions 或 UI 确认 version 与 alias 拼写;alias 区分大小写。
  3. Server 重启后实验消失:每次启动 --backend-store-uri 指向不同位置会各建一个库;固定用同一个 SQLite 文件路径(或生产换 PostgreSQL)。

面试常问

  • 模型注册中心解决什么问题? 模型的版本化登记、发布状态管理(晋升/回滚)、门禁集成与血缘追溯。它让「上线哪个模型」从口头约定变成可审计的指针操作,是 CI/CD 与服务之间的枢纽。
  • 描述一次完整的模型发布与回滚流程。 训练 run 注册为 Version → 挂 challenger → 自动门禁(指标 + 数据漂移检查)通过 → champion 指针切换 → 服务滚动重启读新指针 → 监控观察;异常时把 champion 指回上一版本,服务重启即回滚,全程不重新训练、不重新构建镜像。
  • 数据血缘在你项目里如何落地? 三层:数据层 DVC 哈希标识数据集版本;训练层 run 打 git_sha 与数据哈希 tag;发布层 Model Version 关联 run。任何线上模型可沿「version → run → tag」30 秒内定位代码与数据来源,满足审计与事故归因。

自测三问

  1. alias 机制相比 stage 机制好在哪?
  2. 「门禁」至少应包含哪些检查?用代码怎么表达?
  3. 从线上模型出发回溯训练数据,需要哪三层血缘引用?

小结一句话

Model Registry 用「版本 + 别名 + 门禁 + 血缘」把模型发布变成可审计的指针操作,champion/challenger 双指针覆盖发布、灰度与回滚。

延伸

  • MLflow 官方文档:Model Registry——alias、版本管理与部署集成的权威说明。
  • 下一课:编排与调度——用 Prefect/Airflow 把特征、训练、注册串成每天自动跑的流水线。
加载本节练习…
← 上一课训练与实验跟踪下一课 →编排与调度