在 Vertex AI Model Registry 中,获取或部署指定模型版本时,关键不是把版本号另塞进一个自定义参数,而是把模型资源写成“基础模型资源名@版本”的形式。版本部分既可以是自动生成的数字版本 ID,也可以是人为维护的版本别名。例如,同一个模型可以用 projects/PROJECT_ID/locations/us-central1/models/MODEL_ID@2 固定指向版本 2,也可以用 projects/PROJECT_ID/locations/us-central1/models/MODEL_ID@production 指向当前生产版本。省略 @... 时,Vertex AI 会选择带有 default 别名的版本。
Model Registry 把一组模型版本组织在同一个模型 ID 下。资源名中 models/ 后面的值是模型 ID,不是版本 ID。上传新版本时,Vertex AI 会为版本分配数字 ID;别名则是模型范围内的可变名称,可从一个版本移动到另一个版本。可以把数字版本 ID 理解为不可变坐标,把 production、candidate 之类的别名理解为可移动指针。
因此,下面三个资源表示不同的选择策略:
projects/my-project/locations/us-central1/models/123456789
projects/my-project/locations/us-central1/models/123456789@3
projects/my-project/locations/us-central1/models/123456789@production
第一行不显式指定版本,服务端会解析 default;第二行永久锁定数字版本 3;第三行跟随 production 别名当前指向的版本。需要完全可复现的训练或审计流程时,应保存数字版本 ID。希望不改流水线参数就能切换生产模型时,可以传稳定别名,但必须把别名迁移当作一次受控发布操作。
别名必须是非纯数字字符串,用于与数字版本 ID 区分。它应以小写字母开头,可包含小写字母、数字和连字符,并以字母或数字结尾。别名在同一模型内只能指向一个版本;把已有别名分配给新版本时,它会从旧版本移走。别名不是资源标签,资源标签用于分类和检索,不能替代版本选择。
高层 Python SDK 的 aiplatform.Model 支持两种等价写法:把 @版本 直接附在 model_name 后,或者把版本 ID、别名单独传给 version 参数。先初始化项目与区域,可以减少资源名拼接错误。
from google.cloud import aiplatform
PROJECT_ID = "my-project"
LOCATION = "us-central1"
MODEL_ID = "123456789"
aiplatform.init(project=PROJECT_ID, location=LOCATION)
# 通过别名选择版本
production_model = aiplatform.Model(
model_name=MODEL_ID,
version="production",
)
# 通过完整资源名和数字版本 ID 选择版本
pinned_model = aiplatform.Model(
model_name=(
f"projects/{PROJECT_ID}/locations/{LOCATION}/models/"
f"{MODEL_ID}@3"
)
)
print(production_model.version_id)
print(production_model.versioned_resource_name)
version_id 可用于确认别名实际解析到哪个不可变版本,versioned_resource_name 则给出带数字版本 ID 的完整资源名。生产任务如果接收别名,建议在任务开始时记录这两个值。这样即使别名稍后被移动,也能知道该次执行究竟使用了哪个版本。
如果既不在名称中写 @版本,也不提供 version,SDK 会获取带 default 别名的版本。这个行为不是“取最新上传版本”的承诺;默认别名可以被移动,因此不要把“未指定版本”误解为按创建时间自动选择最新版本。
需要在部署前做独立验证时,可以调用 Model Service 的 get_model。底层客户端同样接受带 @版本 ID 或 @别名 的名称。Vertex AI 服务是区域性的,客户端端点要与模型区域一致。
from google.api_core.client_options import ClientOptions
from google.cloud import aiplatform_v1
project = "my-project"
location = "us-central1"
model_id = "123456789"
alias = "production"
client = aiplatform_v1.ModelServiceClient(
client_options=ClientOptions(
api_endpoint=f"{location}-aiplatform.googleapis.com"
)
)
name = (
f"projects/{project}/locations/{location}/models/"
f"{model_id}@{alias}"
)
model = client.get_model(name=name)
print(model.name)
print(model.version_id)
print(list(model.version_aliases))
这一步适合放在编译流水线之前的管理脚本中,而不是依赖部署失败后才判断别名是否存在。若返回的 version_id 与发布审批记录不一致,应停止部署;若别名不存在,应修正别名或资源名,而不是去掉版本让任务悄悄回退到默认版本。
Google Cloud Pipeline Components 中,获取已有模型的组件与部署组件之间通常通过模型 artifact 连接。流水线参数必须传项目 ID 字符串,而模型名称必须是合法模型资源。不要把项目数字、项目字符串 ID、模型 ID 和版本 ID 混为一谈,也不要把一个普通 Python SDK 对象直接作为编译期组件输入。
from kfp import dsl
from google_cloud_pipeline_components.v1.endpoint import EndpointCreateOp
from google_cloud_pipeline_components.v1.model import ModelGetOp
from google_cloud_pipeline_components.v1.endpoint import ModelDeployOp
@dsl.pipeline(name="deploy-registered-model")
def pipeline(
project_id: str,
location: str = "us-central1",
model_id: str = "123456789",
model_version: str = "production",
):
versioned_name = dsl.ConcatPlaceholder(
items=[
"projects/", project_id,
"/locations/", location,
"/models/", model_id,
"@", model_version,
]
)
model_task = ModelGetOp(
project=project_id,
location=location,
model_name=versioned_name,
)
endpoint_task = EndpointCreateOp(
project=project_id,
location=location,
display_name="registered-model-endpoint",
)
ModelDeployOp(
model=model_task.outputs["model"],
endpoint=endpoint_task.outputs["endpoint"],
dedicated_resources_machine_type="n1-standard-4",
dedicated_resources_min_replica_count=1,
dedicated_resources_max_replica_count=1,
)
不同版本的 KFP 与 Google Cloud Pipeline Components 对占位符拼接能力和参数类型可能有所差异。如果所用版本不接受在流水线函数中构造该字符串,最稳妥的做法是把完整的 model_resource_name 作为一个流水线参数传入,在提交任务时就传入带 @production 或 @3 的完整名称。这样编译器只处理一个字符串参数,也更容易在运行记录中审计。
@dsl.pipeline(name="deploy-registered-model")
def pipeline(project_id: str, location: str, model_resource_name: str):
model_task = ModelGetOp(
project=project_id,
location=location,
model_name=model_resource_name,
)
# 后续把 model_task.outputs["model"] 交给部署组件
提交时的值应类似:
projects/my-project/locations/us-central1/models/123456789@production
如果组件版本把 model_name 定义为短模型 ID,而不是完整资源名,应以当前已安装组件的签名和生成的组件规范为准。不能仅凭另一个版本的示例猜测。无论组件接受短 ID 还是完整名称,版本选择最终都遵循服务端的 @版本 语义;传入裸模型资源时仍会解析到 default。
不用 KFP 时,可以先创建带版本的 aiplatform.Model,再调用其部署方法。别名适合面向环境的配置,数字版本适合要求严格复现的发布单。
from google.cloud import aiplatform
aiplatform.init(project="my-project", location="us-central1")
model = aiplatform.Model(
model_name="123456789",
version="production",
)
endpoint = model.deploy(
deployed_model_display_name="classifier-production",
machine_type="n1-standard-4",
min_replica_count=1,
max_replica_count=1,
)
print(model.version_id)
print(endpoint.resource_name)
移动别名不会自动把已部署到 Endpoint 的旧版本替换掉。别名是在获取或发起部署时解析的;部署完成后,Endpoint 上已有的 DeployedModel 仍对应当时选中的模型版本。要让线上实例切换到别名的新目标,需要再次执行部署或滚动替换流程,并验证 Endpoint 上的实际版本。
只有一条笼统的 400 信息时,应先检查资源标识,而不是先调整机器规格。第一步确认项目:资源名中的项目必须与模型实际所在项目一致,project 参数通常使用项目 ID;纯数字的项目编号只有在接口明确允许时才使用。第二步确认区域:模型、Endpoint、流水线组件的 location 以及区域 API 端点必须一致。
第三步检查模型 ID 与版本。控制台显示名称不是模型 ID;版本 ID 也不能直接替换 models/MODEL_ID。要指定版本,应保留基础模型 ID并在末尾添加 @VERSION_ID。例如,若模型 ID 是 1800006515679555824、版本 ID 是 2,合法形式是:
projects/my-project/locations/us-central1/models/1800006515679555824@2
第四步检查别名。确认别名确实绑定在该模型的某个版本上,拼写和大小写符合约束,不要把 label 键值当成 alias。第五步检查组件契约:查看当前安装的 Google Cloud Pipeline Components 版本、ModelGetOp 输入定义以及编译后的流水线 JSON,确认运行时收到的字符串没有引号残留、空格、空值或重复的资源名前缀。
第六步隔离权限与输入问题。使用与流水线相同的服务账号,在同一项目和区域调用一次 get_model。若相同的版本化资源名在这里也失败,问题位于名称、区域、版本或权限;若这里成功而组件失败,则比较组件运行时参数和服务账号。获取模型通常至少需要相应的模型读取权限,部署还需要 Endpoint、模型部署以及服务账号使用等相关权限。权限错误常有独立状态码,但组织策略、跨项目身份或组件封装可能让日志不够直观,因此仍应核对实际运行身份。
持续交付流水线可以让环境配置使用 candidate 和 production 等别名,发布系统在审批后移动别名并触发部署。为了可追溯,流水线应在解析别名后记录数字 version_id。离线评估、回归测试和需要完全复现的任务则应直接固定数字版本,避免任务排队期间别名发生移动。
一个稳健流程通常分为四步:先用带别名的资源名获取模型,再读取并记录解析后的数字版本;随后执行模型签名、容器和评估门槛检查;部署时使用已确认的数字版本资源名;最后检查 Endpoint 上的部署结果。这样既保留别名带来的发布便利,也避免别名在长时间运行任务中产生不确定性。
提交任务前,确认资源名含有正确的项目、区域和模型 ID;需要指定版本时,末尾使用 @数字版本 ID 或 @非数字别名;未指定版本时,明确接受 default 的当前指向。再用相同身份调用一次获取模型接口,记录返回的 version_id,并确保 Endpoint 与模型位于兼容区域。部署完成后检查实际 DeployedModel,而不要仅凭别名当前指向判断线上版本。
归根结底,版本别名解决的是“用稳定名称选择可变版本”,而不是自动升级已部署实例。把 @alias 放在正确的模型资源名上、在部署前解析并记录数字版本、在部署后核验 Endpoint,才能同时获得易操作性与可审计性。