将已注册的模型部署为对外可调用的 REST API,是模型服务模块最核心的操作。本文介绍通过控制台部署、通过 MLflow Deployments SDK 部署、获取调用地址与鉴权 Token 的完整流程。
前提条件
已在 Catalog 中注册并发布模型,且模型版本处于可发布状态。详见 模型管理。
当前账号在工作空间内具备模型服务的创建权限。
如使用 SDK 部署:已安装
mlflow 与 DataBuddy 提供的部署插件 wedata3-mlflow-tcdeploy-plugin。方式一:通过控制台部署
操作步骤
1. 进入创建页:在 Catalog 模型详情页单击 部署模型 ;或进入 数据科学 > 模型服务 ,单击 创建服务 。
2. 填写基本配置:输入 服务名称 (创建后不可修改,工作空间内唯一),可选填 服务描述 (不超过 100 字)。
3. 配置服务版本实例:
部署模型、版本 :选择 Catalog 中的模型及其版本。多个版本实例须保持输入、输出参数一致,否则服务调用失败。
资源来源、资源规格 :选择「平台按量计费资源」,并选择单副本的资源规格(GPU 模型选 GPU 规格)。
请求限流 :不限流(最大 500 QPS)、单实例 QPS 或单实例最大并发。
副本数量 :填写目标副本数量(多副本可提升可用性)。
单击 + 新增服务版本实例 可追加版本,用于灰度发布或 A/B 测试。
1. 设置高级配置:
是否生成鉴权 :开启后服务调用需进行签名认证,可在服务调用页面查看签名密钥及签名计算指引。
服务日志投递 :开启后服务日志持久化存储至日志服务(默认存储 15 天),需提前开通日志服务并创建日志集与日志主题。详见 推理监控与日志。
1. 保存并启动:校验必填项后拉起计算资源并加载模型,状态依次进入「未就绪 → 启动中 → 运行中」;也可先保存草稿,稍后在详情页启动。
2. 获取调用地址:服务进入运行中后,进入 服务详情页 复制服务 API 地址,并在 服务调用 页面查看签名密钥与调用示例。
说明:
方式二:通过 MLflow Deployments SDK 部署
SDK 以 DataBuddy 提供的部署插件
wedata3-mlflow-tcdeploy-plugin 形式接入 MLflow 官方的 Deployments API(target 为 tcdeploy)。注意:
该插件仅支持远程部署,不支持
mlflow deployments run-local 本地运行;调用本地运行会抛 NotImplementedError,请改用 client.create_deployment(...)。安装与环境准备
%pip install "wedata3-mlflow-tcdeploy-plugin"
SDK 运行所需的临时密钥与工作空间上下文,由 DataBuddy Notebook 内核或调度运行时自动注入,在平台内运行无需手动配置 。仅当在本地 IDE 调试时,才需自行配置临时密钥、工作空间 ID、地域等环境变量;缺少必需配置时,初始化会抛
ValueError 并提示缺失项。初始化客户端
import mlflow_tcdeploy_plugin; print(mlflow_tcdeploy_plugin.__version__) # 应为 0.1.1from mlflow.deployments import get_deploy_client# 推荐统一通过官方 API 获取客户端,target 固定为 "tcdeploy"client = get_deploy_client("tcdeploy")
模型 URI 规范
create_deployment / update_deployment 的 model_uri 必须使用 MLflow 三段式 Models URI:models:/<catalog_name>.<schema_name>.<model_name>/<version>
协议必须为
models:/,否则抛 ValueError;模型名必须是三段式
Catalog.Schema.Model,缺失任一段抛 ValueError;版本号不可为空;
不支持
runs:/<run_id>/model 形式,请先将模型注册到 Catalog(详见 模型管理)。创建服务
resp = client.create_deployment(name="churn-model-svc", # 服务名称(ServiceName)model_uri="models:/<catalog_name>.<schema_name>.<model_name>/<version>",config={"instance_type": "<instance_spec>", # 必填:实例规格名,用 list_instance_types() 查询"replicas": 2, # 副本数,默认 1"charge_type": "POSTPAID_BY_HOUR", # 计费模式,默认按量计费,可选 PREPAID"scale_mode": "MANUAL", # 弹性模式,默认 MANUAL,可选 AUTO"authorization_enable": True, # 是否开启鉴权 Token,生产建议开启"log_enable": True, # 是否开启日志投递,生产建议开启"service_description": "用户流失预测在线服务",},)service_id = resp["data"]["service_id"] # 形如 ms-xxxxxxservice_group_id = resp["data"]["service_group_id"] # 形如 msg-xxxxxx
注意:
创建服务的几条关键约定:
1.
config 必须包含 instance_type,否则在请求发出前就会被拦下抛 ValueError。可用规格通过 list_instance_types() 查询,或在控制台「创建服务」页面查看。2.
name 是服务名称(ServiceName) ;返回的 service_id(ms-xxxxxx)才是后续 update_deployment / delete_deployment / get_deployment 的入参,service_group_id(msg-xxxxxx)用于 predict。请务必把这两个 ID 落库或写进 Notebook 输出。3.
endpoint 参数语义是服务组 ID(ServiceGroupId) :传入已有服务组可将新服务加入该组实现灰度;首次创建时不传。4. 未在文档中列出的
config 字段会原样下发,拼错的 key 不会报错而是静默失效,建议把配置抽成常量集中维护。常用
config 字段速查:字段 | 说明 |
instance_type(必填) | 实例规格名 |
replicas | 副本数,默认 1 |
charge_type | 计费模式,默认 POSTPAID_BY_HOUR,可选 PREPAID |
scale_mode | 弹性模式,默认 MANUAL,可选 AUTO |
scheduled_action | 定时扩缩容配置 |
service_limit | 服务级限流(QPS / 带宽等) |
authorization_enable | 是否开启鉴权 Token,默认 False |
log_enable | 是否开启日志投递,默认 False |
service_description | 服务业务描述 |
inference_table_push_enable | 是否开启推理表写入 |
catalog_path / schema_path / payload_path | 推理表所在 Catalog / Schema 与 Payload 路径 |
查询实例规格
# 查询可用规格;spec_type 可选 "CPU" / "GPU",不传则全部cpu = client.list_instance_types(spec_type="CPU")print(len(cpu), cpu[:2])print(client.list_instance_types(spec_type="GPU")[:2])print(client.get_instance_type_prices([s["spec_name"] for s in cpu if s["available"]][:2]))
返回项中的
spec_name 即 config["instance_type"] 的取值。等待服务就绪
create_deployment 返回时服务通常仍处于部署中状态,副本拉起、模型加载、健康检查一般需要 1~5 分钟。线上联调或自动化场景必须显式轮询 get_deployment 直到进入终态:import timeTERMINAL = {"RUNNING", "FAILED", "STOPPED"}deadline = time.time() + 600 # 10 分钟超时上限,避免长时间阻塞while True:detail = client.get_deployment(service_id)status = detail["data"].get("status")print("status =", status)if status in TERMINAL:breakif time.time() > deadline:raise TimeoutError(f"service {service_id} not ready, status={status}")time.sleep(15) # 轮询间隔 ≥ 10 秒,避免触发频率限制
发起在线推理
result = client.predict(deployment_name=service_group_id, # 注意:是 service_group_id,不是 service_idinputs={"dataframe_records": [{"f1": 1.0, "f2": 2.0}]},config={"auth_token": "Bearer <token>"}, # 服务开启鉴权时必填)print(result)
注意:
inputs 必须是 JSON 可序列化的对象(dict / list / 基础类型)。numpy.ndarray、pandas.DataFrame、datetime 等需先转换(如 df.to_dict(orient="records")),否则抛 ValueError。endpoint 参数为目标推理实例的 HTTP 相对路径,默认 /predict;只能传相对路径(如 /v1/models/x:predict),传入绝对 URL、协议相对地址、含 @ 或 .. 路径穿越的值都会抛 ValueError。推理服务返回合法 JSON 时得到解析后的
dict / list;返回非 JSON 文本时包装为 {"raw": "<原始文本>"},业务代码应先判断 "raw" in result 再决定如何解析。更新、扩缩容与版本切换
update_deployment 为部分更新(PATCH)语义:只发送本次显式提供的字段,未提供的字段保持服务端原值。name 入参为 service_id。# 1) 调整副本数(普通更新,不重建服务)client.update_deployment(name=service_id, config={"replicas": 4})# 2) 切换到新模型版本(自动滚动重启,无需先下线)client.update_deployment(name=service_id,model_uri="models:/<catalog_name>.<schema_name>.<model_name>/<new_version>",)# 3) 停止 / 恢复 / 触发扩缩容(service_action 特殊语义)client.update_deployment(name=service_id, config={"service_action": "STOP"})client.update_deployment(name=service_id, config={"service_action": "RESUME"})client.update_deployment(name=service_id, config={"service_action": "SCALE"})
注意:
service_action(STOP / RESUME / SCALE)是排他字段:一旦 config 中包含 service_action,本次请求中的其它字段(包括 model_uri、replicas)都会被忽略。切版本、扩缩容与停止、恢复请拆成独立的调用。回滚只需再次 update_deployment(model_uri=旧版本),无需特殊接口。灰度发布:若对版本切换的原子性要求很高,可用同一个
service_group_id 再创建一个新服务(create_deployment(..., endpoint=service_group_id)),验证通过后停止并删除旧服务。流量比例的精细切分在控制台完成,SDK 聚焦于部署生命周期本身。查询与下线服务
# 列举当前工作空间下的服务组;传 endpoint 可按 ServiceGroupId 过滤groups = client.list_deployments()for g in groups:print(g["name"], g.get("service_group_name"), g.get("service_group_status"))# 删除服务(幂等:服务不存在时不会报错)client.delete_deployment(service_id)
说明:
list_deployments 返回项的 name 字段即为 service_group_id(MLflow Deployments 规范要求)。删除为不可逆操作,建议先 update_deployment(name=service_id, config={"service_action": "STOP"}) 冷却,让在途请求自然结束后再删除。错误处理
SDK 不返回错误码字段,所有错误通过 Python 异常传递:
异常类型 | 触发场景 | 处理建议 |
ValueError | 入参 / 环境变量校验失败(缺 instance_type、model_uri 非三段式、inputs 不可序列化、endpoint 非法等) | 按错误信息修正参数或环境变量 |
mlflow.exceptions.MlflowException | 平台接口调用失败, message 形如 <Code>: <Message> | 解析前缀 Code(如 UnauthorizedOperation 权限不足、ResourceNotFound ID 错误、LimitExceeded 配额超限、RequestLimitExceeded 频率超限)后排查 |
NotImplementedError | 调用了本地运行 run_local | 改用 client.create_deployment(...) 远程部署 |
服务管理
进入 数据科学 > 模型服务 可查看服务列表并对服务进行启动、停止、编辑、新增版本、删除等操作。
服务管理分两级页面:单击服务名称进入 服务详情页 (管理版本与流量),再单击版本 ID 进入 版本详情页 (管理实例与运行)。
服务详情页
单击服务名称进入。顶部操作区:权限 、流量分配 、服务调用 、+ 新增版本 、Buddy 。
主区为 服务版本 列表,列含 ID、服务名称、服务版本、状态、流量比、操作(编辑、监控、更多);下方页签为 调用监控 、服务鉴权 。
右侧信息面板:
面板 | 内容 |
基本信息 | 描述、创建人、上次修改时间。 |
高级配置 | 日志服务配置、推理表、服务鉴权的启用状态。可单击 编辑配置 二次开启 / 关闭。 |
版本详情页
在服务详情页单击版本 ID 进入。标题右侧显示版本状态徽标(如「运行中」);顶部操作区:刷新 、停止 、编辑 、删除 、Buddy 。
主区为 实例列表 ,展示各副本实例(实例名称、实例 id、实例状态、创建时间、操作);单击操作列 更多 可对实例 重建 或 进入容器 。下方页签为 监控 、事件 、日志 。
右侧信息面板:
面板 | 内容 |
基本信息 | 描述、服务 ID、状态。 |
接入配置 | 接入模型及版本、副本数量、请求限流。可单击 编辑配置 调整。 |
付费方式 | 计费方式(平台按量计费资源)、算力规格(所选 CPU / GPU 规格)。 |
常用运维操作:
操作 | 说明 |
新增版本 | 单次新增 1 个服务版本,用于灰度或 A/B。 |
编辑配置 | 二次开启 / 关闭日志服务、推理表、鉴权,或调整接入配置。 |
停止 | 释放底层计算资源并停止计费,需要时可重新启动。 |
删除 | 永久删除服务及其所有版本。删除前请确认无业务调用方仍在使用。 |
警告:
删除服务为不可恢复 操作。删除后服务地址立即失效,所有副本释放;如该服务已开启推理表,历史推理数据仍保留在 Catalog 中。
常见问题
Q:服务长时间停留在「未就绪」状态怎么办?
A:进入版本详情页查看 事件 与 日志 页签,常见原因包括:模型服务包拉取失败、资源池容量不足、模型加载报错。可结合日志服务定位具体错误。
Q:如何在不影响线上流量的情况下发布新版本?
A:先在原服务下「新增版本」,初始流量比设为 0%;版本进入运行中后,通过编辑流量比逐步切分(如 90/10 → 50/50 → 0/100),实现灰度发布。