登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  人工智能

MLflow 模型别名怎样把新版本切换到 champion 并支持回滚

来源:17golang原创

时间:2026-11-07 23:19:13 296浏览 收藏

如果推理代码里直接写死 models:/sales-model/2,每次发布新模型都要改配置、发版并承担回滚成本。更稳妥的做法是给当前线上版本绑定一个固定的别名,例如 champion,服务端始终读取 models:/sales-model@champion。切换时把别名指向新版本,回滚时再把同一个别名指回旧版本,推理代码本身不需要改变。

官方地址:https://mlflow.org/docs/latest/ml/model-registry/workflow/

下面的示例假设注册模型名为 sales-model,当前版本为 2,待上线版本为 3。示例只展示 API 关系和操作写法,版本号应替换为你在 Model Registry 中实际存在的版本。

为什么 alias 能替代固定版本号

模型版本号适合记录不可变的模型产物,champion 则适合表示团队当前选择的部署指针。MLflow 文档把 model version alias 定义为可由用户命名、并且可以在注册后重新指向其他版本的标识;因此调用方可以固定使用 alias,而不必把具体版本号写进服务代码。

写法含义切换成本
models:/sales-model/2明确读取版本 2切换需要修改调用配置
models:/sales-model@champion读取 champion 当前指向的版本只修改注册中心里的 alias
Model Registry 中注册模型、版本 v1、版本 v2、champion alias、模型 URI 与推理服务的静态关系说明图
图1:静态关系说明图,展示注册模型、模型版本、champion alias 和推理调用之间的关系;这不是 MLflow 页面截图或运行证据。

切换前先记录当前版本

回滚能否快速完成,关键不在于重新训练模型,而在于切换前是否保存了当前 alias 指向的版本。可以先读取 champion 的模型版本,再把候选版本和发布批次写入你的变更记录。不要只记录“切到版本 3”,还要记录切换前的版本 2、注册模型名、registry URI 和操作时间。

from mlflow import MlflowClient

client = MlflowClient()
model_name = "sales-model"
alias_name = "champion"

# 先读取当前 alias,保留回滚目标;没有 alias 时会抛出异常,需要单独初始化。
current = client.get_model_version_by_alias(model_name, alias_name)
current_version = str(current.version)

# 读取候选版本,确认它已经注册,再进入发布变更记录。
candidate_version = "3"
candidate = client.get_model_version(model_name, candidate_version)
print({
    "model_name": model_name,
    "old_version": current_version,
    "candidate_version": str(candidate.version),
    "alias": alias_name,
})

这里的读取动作只负责取得注册中心元数据。候选版本是否满足业务指标、输入输出签名是否兼容,应由你的发布门禁负责;不要把“能够被 alias 指向”误认为“已经通过业务验收”。

把新版本指向 champion

切换 alias 使用 MlflowClient.set_registered_model_alias。它接收注册模型名、别名和目标版本号。下面的函数把旧版本作为返回值,便于调用方把它写入变更记录或后续回滚命令。

from mlflow import MlflowClient

def promote_to_champion(model_name: str, new_version: str) -> dict[str, str]:
    client = MlflowClient()
    alias_name = "champion"

    # 切换前读取旧指针,回滚时仍然使用这个版本号。
    old_info = client.get_model_version_by_alias(model_name, alias_name)
    old_version = str(old_info.version)

    # alias 是可移动指针;目标版本必须是该注册模型中的已存在版本。
    client.set_registered_model_alias(model_name, alias_name, str(new_version))

    # 再读取一次 alias,确认注册中心记录已经指向目标版本。
    new_info = client.get_model_version_by_alias(model_name, alias_name)
    return {
        "model_name": model_name,
        "alias": alias_name,
        "old_version": old_version,
        "new_version": str(new_info.version),
    }

change = promote_to_champion("sales-model", "3")
print(change)

如果目标版本不存在,或客户端连接的 registry 与你查看的环境不是同一个,调用会失败。生产流程中应把返回的旧版本、新版本、发布人和变更单号保存下来,避免只依赖操作者的记忆。

推理端固定读取 champion

服务代码只需要使用 alias URI。MLflow 官方示例同时展示了 get_model_version_by_alias 和 models:/模型名@别名 两种读取方式;推理端更适合直接使用后者,让注册中心负责解析当前指针。

import mlflow.pyfunc

model_name = "sales-model"
alias_name = "champion"

# 使用 alias URI,避免把具体版本号耦合到推理代码。
model_uri = f"models:/{model_name}@{alias_name}"
model = mlflow.pyfunc.load_model(model_uri)

# data 应该符合注册模型记录的输入签名;这里不伪造业务数据。
prediction = model.predict(data)
return prediction

如果使用的是带有专用 flavor 的模型,也可以调用对应的 mlflow..load_model。关键点是 URI 的尾部使用 @champion,而不是把某次发布的数字版本写死。

出现问题时怎样回滚

回滚不需要删除版本,也不需要重新注册旧模型。只要旧版本仍保留在同一个注册模型中,就把 champion 重新指向切换前保存的版本号。回滚动作与发布动作使用同一个 API,差别只有目标版本不同。

from mlflow import MlflowClient

def rollback_champion(model_name: str, rollback_version: str) -> dict[str, str]:
    client = MlflowClient()
    alias_name = "champion"

    # 回滚前读取当前版本,保留这次反向变更的审计信息。
    before = client.get_model_version_by_alias(model_name, alias_name)

    # 将 alias 指回切换前保存的稳定版本,不删除任何模型版本。
    client.set_registered_model_alias(model_name, alias_name, str(rollback_version))

    # 读取最终指针,供变更记录和服务重载检查使用。
    after = client.get_model_version_by_alias(model_name, alias_name)
    return {
        "model_name": model_name,
        "alias": alias_name,
        "before_version": str(before.version),
        "after_version": str(after.version),
    }

rollback = rollback_champion("sales-model", "2")
print(rollback)
MlflowClient、set_registered_model_alias、champion、候选版本、当前版本、模型 URI、推理工作负载与回滚记录的静态关系说明图
图2:静态调用关系说明图,展示别名控制、版本记录和推理工作负载的关系;这不是 MLflow 运行截图。

回滚后,使用 alias URI 的新加载动作会解析到旧版本。若服务进程在启动时把模型加载到内存,是否需要重启或重新加载由你的服务实现决定;alias 更新本身不会替你刷新已经驻留内存的对象。

切换不生效时按三层排查

  1. 先看 registry 是否一致:确认切换脚本与推理服务使用相同的 MLflow tracking/registry 配置。不同环境的同名注册模型可能拥有完全不同的版本。
  2. 再看 alias 的实际指向:用 get_model_version_by_alias(model_name, "champion") 读取当前版本;不要只看发布脚本是否返回成功。
  3. 最后看加载时机:如果服务只在启动时调用 load_model,注册中心的指针变化不会自动替换已经加载的 Python 对象,需要由服务提供重载、滚动发布或重新启动机制。
  4. 检查版本与权限:目标版本必须属于该注册模型,调用身份还需要具备修改 alias 的权限;不要通过删除旧版本来“强制回滚”。

一份可执行的切换清单

  • 切换前读取并保存当前 champion 指向的版本号。
  • 确认候选版本已注册,并确认它的输入输出契约与服务兼容。
  • 用 set_registered_model_alias 将 champion 指向候选版本。
  • 让服务继续使用 models:/模型名@champion,不要在代码中改数字版本。
  • 把旧版本、新版本、registry URI 和变更记录一起保存。
  • 出现异常时,用同一 API 把 alias 指回旧版本,再按服务的加载策略刷新内存模型。

相关问题

champion alias 和模型版本号应该同时写进推理 URI 吗?

通常不需要。固定版本号用于复现和审计,线上服务若要支持无代码切换,应使用 alias URI;需要复现某次结果时再显式加载数字版本。

回滚时要删除新模型版本吗?

不需要。回滚只是移动 alias 指针,保留新版本更利于复盘、再次发布或比较指标。

修改 alias 后服务一定会立刻切换吗?

不一定。如果服务已经把模型对象加载到内存,必须配合重新加载或滚动发布;alias 的变化不会自动改变现有 Python 对象。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>