关于 agent-platform-tuning
面向使用 Agent Platform 微调开放模型和 Gemini 模型的流程技能,涵盖环境准备、数据集处理、作业配置与部署,并在各阶段设置检查和确认步骤。
主要功能
- 01环境与 IAM 检查
- 02数据集校验与上传指引
- 03模型和位置选择
- 04微调作业配置与监控
- 05部署流程指引
适用场景
- 01为模型微调准备项目
- 02校验并上传微调数据集
- 03运行和监控微调作业
- 04部署微调后的模型
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ google/ skills --skill agent-platform-tuning安装后在 Claude Code 中输入/agent-platform-tuning确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/data_prep.mdhf_datasets.mdmodels.mdrequirements.txttuning_guide.mdscripts/calculate_cost.pycancel_tuning_job.pylist_models.pymonitor_tuning_job.pyprepare_dataset.pytune_open_model.py详细介绍
Agent Platform 模型调优
概述
此技能提供使用 Agent Platform 的调优服务微调大模型(包括开放模型和 Gemini 模型)的流程知识,涵盖从环境设置和数据准备到作业配置、监控和部署的整个生命周期。
工作流决策树
-
项目和区域验证检查:用户是否提供了 Google Cloud 项目和区域?
- 否 → 立即停止工具执行。不要运行验证
命令(
gcloud services list、gcloud projects get-iam-policy),不要创建资源,也不要开始准备数据集。提示用户指定或确认项目和区域(例如:“能否请您指定要使用的 Google Cloud 项目和区域?”)。- 如果用户只询问如何检查或验证环境是否就绪(API、IAM、服务代理),则只询问项目和区域。不要询问模型类别。
- 如果用户请求调优工作流,同时未说明要调优开放模型还是 Gemini 模型,你可以一并询问这两个问题。
- 是 → 继续。
- 否 → 立即停止工具执行。不要运行验证
命令(
-
模型类别识别:用户是否明确说明要调优开放模型还是 Gemini 模型?
- 否 →
- 环境验证查询的例外情况: 如果用户只是在询问环境、API、IAM 权限或服务代理是否已准备好进行微调,请勿询问模型类别。获知项目和 区域后,验证环境并确认其已准备就绪。
- 否则,停止执行工具。询问用户要微调 Open Model 还是 Gemini Model。一般设置和前置条件查询(例如“需要进行哪些环境设置?”): 如果用户询问开始微调所需的环境设置、前置条件、API 或权限,且尚未 选择模型类别:
- 说明设置要求(API、IAM 权限/服务代理和 Python SDK)。
- 关于 Cloud Storage:说明数据集和工件需要使用现有的 Cloud Storage
存储桶(例如,
gs://<existing-bucket>)。重要: 不要指示用户 创建存储桶,不要在设置说明中输出gcloud storage buckets create命令,也不要假设存在一个实际上不存在的存储桶(用户可能没有创建 存储桶的权限,并且会提供自己的现有存储桶)。 - 必须在回复结尾明确询问用户要微调 Open Model 还是 Gemini Model。 未询问用户选择模型类别前,绝不能提供设置说明。 (注意:如果用户要求主动检查或验证某个项目,但未提供项目 ID 或区域, 请先询问项目和区域,不要运行工具调用。)
- 如果用户说明了具体的微调目的,应推荐三个模型:一个 Open Model、一个
Gemini Model,以及一个通常推荐的选项。简要列出每个模型的优缺点
(例如,Gemini 模型可能更贵等)。重要: 此步骤必须读取
references/models.md,并且只能推荐该目录中明确列出的模型。绝不能推荐 目录中未列出或不受支持的模型,例如google/gemma-2-9b-it、gemma-2或Mistral。只能推荐受支持的模型,例如 Gemma 3 (google/gemma3@gemma-3-12b-it)、Qwen 3 (qwen/qwen3@qwen3-8b) 或 Llama 3.1 (meta/[email protected])。对于 Gemini 模型,只能推荐gemini-2.5-flash(适用于一般用途、编码或聊天,推荐使用)或gemini-2.5-pro。绝不能推荐gemini-1.5-flash-002、gemini-1.5-pro-002或gemini-1.5-flash,这些模型已弃用,且微调服务 不支持。如果用户指定的模型不在目录中,请遵循该目录中的回退规则。确认 模型类别之前,不要继续进行模型配置。 - 是 → 继续。
- 否 →
-
环境检查:环境(身份验证、API、IAM、虚拟环境)是否已初始化?
- 否 → 转到阶段 0:环境与 IAM 设置。
- 是 → 继续。
-
数据集状态:数据集是否已准备为 JSONL 格式,其结构是否符合微调要求, 并且是否已上传到 Google Cloud Storage?
- **否** → 转到[阶段 1:数据集准备与上传](#phase-1)。 - **是** → 继续。 -
列选择确认:是否已向用户展示各列并确认映射关系?
- 否 → 停止。继续之前,必须如阶段 1.0 所述展示样例并获得用户对 列映射的确认。
- 是 → 继续。
-
配置:用户是否已提供目标模型和超参数,或明确同意了你的推荐?
- 否 → 转到 阶段 2:模型配置与推荐。
- 是 → 继续。
-
作业状态:是否已提交微调作业?
- **否** → 转到 [阶段 3:微调作业执行](#phase-3-tuning-job-execution)。 - **是** → 继续。 -
作业完成情况:微调作业是否已完成?
- **否** → 转到 [阶段 4:监控](#phase-4-monitoring)。 - **是** → 继续。 -
部署:是否已部署微调后的模型(如有需要)?
- **否** → 转到 [阶段 5:模型部署](#phase-5-model-deployment)。 - **是** → 任务完成。
阶段 0:环境与 IAM 设置 {#phase-0}
继续之前,请确保基础环境已就绪。
0.1 身份验证与项目上下文
- 检查是否已安装
gcloudCLI。如果尚未安装,请先征求用户许可再进行安装。如果已安装,请更新:
gcloud components update --quiet > /dev/null 2>&1
- 验证
gcloud auth list。如果尚未通过身份验证,请运行gcloud auth login。 - 项目与区域确认:检查用户是否在提示词中指定了 GCP
项目和区域。如果用户的提示词遗漏了项目或区域(例如,在环境验证或设置请求中),你必须立即停止工具执行,不得运行任何 bash 或 gcloud 命令(不要调用
gcloud config get project或gcloud services list)。请用户提供项目 ID/编号和区域。 - 用户提供或确认项目和区域后,验证
gcloud已通过身份验证,并执行只读检查以验证环境。报告环境就绪情况时,摘要必须明确说明以下三类内容的状态:- 必需的 API:明确报告
aiplatform.googleapis.com(Agent Platform)和storage.googleapis.com(Cloud Storage)均已启用。 - 用户/调用方 IAM 权限:明确确认用户身份或默认计算服务帐号具有
roles/aiplatform.user和roles/storage.admin(或roles/storage.objectAdmin)。 - 服务 Agent 与角色:明确报告 Agent Platform
服务 Agent
(
[email protected])具有roles/aiplatform.serviceAgent,且微调服务 Agent(service-PROJECT_NUMBER@gcp-sa-vertex-moss-ft.iam.gserviceaccount.com或gcp-sa-vertex-tune)具有roles/aiplatform.tuningServiceAgent。 始终明确说明已验证的项目和区域(例如,project: <PROJECT_NUMBER>, region: us-central1),并明确确认环境已完成配置,可以开始微调。
- 必需的 API:明确报告
0.2 位置
位置处理取决于你在工作流决策树中确定的模型类别。这两个类别支持的位置不同,切勿将一个类别的位置用于另一个类别。
- 开放模型共用一组固定位置,建议选择
global。 - Gemini 模型因模型而异,必须查询确认。目前不接受
global。
如果用户指定的位置对其模型和类别无效,请停止。回复错误,指出所请求的位置不受支持,并列出有效位置;不要询问数据集,不要继续任何其他设置步骤,也不要悄悄改用其他位置重试。
开放模型(推荐:global)
推荐使用 global,并向用户确认。 将它作为唯一推荐选项提出,而不是先让用户选择区域;也不要引导用户改用特定区域。
开放模型微调仅支持以下位置:
global(推荐选项)us-central1europe-west4us-west1us-east5asia-southeast1
global 端点会自动选择有可用容量的受支持区域,因此最有可能成功安排任务。预先固定区域会将任务限制在该区域的容量内,因此开放模型微调推荐使用 global。
- 用户指定了位置 → 原样使用,只要该位置是
global或上述列表中的区域即可。不要劝用户改选其他位置。 - 用户询问支持哪些位置 → 回答这个问题。分享上述列表,并说明推荐使用
global及其原因。绝不要隐瞒。 - 用户没有指定位置 → 提出使用
global,并在继续操作前请用户确认。说明global会让服务选择有可用容量的区域。不要默默假定使用global。
提出单一选项的目的是避免让用户必须先做出区域选择,才能继续其他操作——此前正是这种顺序阻碍了用户。这并不意味着要隐瞒列表:用户询问时应列出;拒绝不受支持的位置时也应列出。
仅在以下情况回退到明确指定的区域,并告知用户原因:
-
CMEK。 使用客户管理的加密密钥时,
global会返回FAILED_PRECONDITION错误。受 CMEK 保护的任务必须指定存放密钥的区域。 -
数据驻留。 如果用户要求任务必须留在特定司法管辖区内,请遵循其指定的区域。目前,
global会在us-central1或europe-west4中运行任务。
如果 global 任务已被接受,但随后因模型不支持全局端点微调而失败,并返回 FAILED_PRECONDITION 错误,则表示该模型尚未接入全局端点。模型本身仍可微调:在上述列表中指定一个明确的区域重新提交(us-central1 是最稳妥的选择),并告知用户切换的原因。
使用 global 任务
- API 主机仍为
aiplatform.googleapis.com。不存在global-aiplatform.googleapis.com主机。 - 服务会在运行时将
global解析为实际区域。子资源(微调后的模型、检查点、TensorBoard)返回的资源名称中会包含该实际区域,而不是global。在用于监控或部署之前,请从返回的资源名称中读取位置;绝不要假定它仍是global。 - 配额在各区域之间共享,因此固定区域并不会增加配额。
Gemini 模型(按模型查询)
目前,Gemini 调优不接受 global——服务会在创建作业时拒绝该值,并返回 FAILED_PRECONDITION 错误,因此不要在此处推荐它。
Gemini 没有统一的区域允许列表。 支持的调优区域因模型和模型版本而异:有些 Gemini 模型仅限两个区域,而另一些则支持更多区域。不要重复使用上面的开放模型列表,也不要假设一个 Gemini 模型适用的区域也适用于其他 Gemini 模型。
提交前,请在监督微调文档中查找所选模型,并阅读其**“模型调优支持的端点”**一行: 监督调优
- 用户询问支持哪些区域 → 查询该具体模型,并告知用户文档中的说明。不要凭记忆回答,也不要参考开放模型列表,更不要针对其他 Gemini 模型作答。
- 模型对应的行列出了具体区域 → 用户指定的区域必须是其中之一。如果不是,请停止操作,并报告该模型支持的区域。
- 模型对应的行不存在,或文档表述不清楚 → 询问用户要使用哪个区域,不要猜测。
继续操作前,请向用户确认区域。请注意,有些 Gemini 模型还会限制 CMEK,并且仅在 us 和 eu 多区域端点上提供调优后的模型,因此在作出承诺前,请查看同一张表中的这些限制。
0.3 启用 API
确保已启用 aiplatform.googleapis.com 和 storage.googleapis.com。
gcloud services enable aiplatform.googleapis.com storage.googleapis.com \
--project=YOUR_PROJECT
0.4 IAM 权限
确认以下身份具有所需角色。
- Agent Platform 服务代理:
[email protected] - 托管式 OSS 微调服务代理:
service-PROJECT_NUMBER@gcp-sa-vertex-moss-ft.iam.gserviceaccount.com - 用户身份:运行命令的账号。
0.5 Python 依赖项
此技能中的脚本会导入 vertexai(来自 google-cloud-aiplatform)、google-genai、google-cloud-storage 和 datasets。
重要的 Agent 指示: 不要创建虚拟环境,也不要在检查前安装任何内容。虚拟环境是空的,会隐藏环境已有的软件包,导致重复安装,耗时数分钟。
请先探测,仅在探测失败时安装:
python3 -c "import vertexai, google.genai, google.cloud.storage, datasets" \
|| pip install -r references/requirements.txt
然后使用普通的 python3 scripts/... 运行所有脚本——不要添加激活前缀。
references/requirements.txt 中固定的版本适用于环境尚未提供这些 SDK 的情况。不要在可正常使用的环境中应用这些版本:它们会降级其他工具可能共用的软件包。
阶段 1:数据集准备与上传 {#phase-1}
1.0 数据集发现与确认
-
验证用户提供的数据集: 如果用户在提示词中指定了数据集文件名 或路径,请验证其是否存在于工作区中 (例如,通过执行脚本或检查是否存在拼写错误)。
- 如果在任何位置都找不到该文件,你必须告知用户 数据集文件不存在或无法访问。你必须 提示用户提供有效的数据集路径。或者,如果 搜索期间在工作区中找到候选数据集文件,你必须向用户 列出候选文件并请其选择一个。报告文件缺失或列出候选文件后, 必须立即停止执行工具,并等待用户回复。 不要询问是否允许进行 90/10 验证集划分,也不要 在收到用户选择的有效数据集文件之前尝试上传数据集。
- 如果已找到并验证该文件,请继续执行下方的步骤 1.1「格式化与 验证」。
-
自动发现:从用户存储桶中查找: 如果用户没有数据集, 且 Hugging Face 参考资料中没有合适的替代数据集,请提出搜索用户 GCS 存储桶以查找潜在训练数据。优先搜索扩展名为
.jsonl、.json、.csv和.parquet等的文件。如果找到此类 文件,请读取每个文件的前几行或记录,以判断其中是否包含适合微调的文本数据 (例如,提示词/补全内容对),这些数据是否可以修改为符合 数据准备指南,且是否与用户请求的微调任务相关。 请勿在事先征求同意前进行搜索。 -
自动发现:根据任务从 Hugging Face 查找: 如果用户有具体任务 (例如数学推理、编码、指令遵循),或想使用 Hugging Face 数据集但 未指定具体数据集,请参考 Huggingface 数据集参考,并推荐匹配的数据集 (例如,用于数学推理的
open-r1/OpenR1-Math-220k或AI-MO/NuminaMath-TIR;openai/gsm8k也广泛使用)。对于每个推荐的 数据集,请提供一些相关信息和合理的数据划分选项,并请用户选择一个。 不要输出泛泛的指示,让用户自行准备并上传数据——应主动引导用户完成交互式数据集发现、 预览和准备流程。重要
关键:征求确认并选择列。 选定 数据集后,通过
run_command执行 Python,使用load_dataset(..., streaming=True)检查数据集。在完成以下步骤并获得用户确认之前, 不得开始准备或上传数据集:1. 确认数据集和划分: 向用户展示 数据集和可用划分,并请用户确认要使用哪一个。2. 选择列(Hugging Face 或自定义数据集): 你 必须:- 列出所选数据集划分中的所有可用列。- 展示数据集中的几个样本,帮助用户 了解内容并选择列。- 建议哪些列应映射到prompt(或用户消息)和completion(或助手回复);如适用,提供几个合理选项。- 请用户确认 列映射,或指定要使用哪些列。
1.1 格式化与验证
- 转换:如果数据采用 CSV、JSON 或 Parquet 格式,请使用
scripts/prepare_dataset.py进行转换。 - 确认验证集划分:每当生成或准备单个数据集且未明确提供验证集时(包括生成示例聊天/指令数据集或准备训练数据集),都必须通过
run_command使用 Python 生成或处理数据,并且必须询问用户是否同意将训练数据集按 90/10 划分,以形成验证集(使用--validation_split 0.1或 Python 脚本)。如果用户同意,则进行划分;如果用户拒绝,则仅使用训练数据集,不使用验证集。不要提供 80/20 划分选项;调优服务会拒绝此划分,原因见 数据准备指南。 在询问用户是否同意按 90/10 划分验证集之前,不要上传数据集或提交调优任务! - 验证:如果数据已经采用 JSONL 格式,请在上传前进行验证。仅有
.jsonl扩展名并不足以证明格式有效。必须确认内容架构符合调优要求(例如,system/user/model 角色正确)。
python3 scripts/prepare_dataset.py \
--input my_data.jsonl \
--format <messages|messages_gemini> \
--validate_only
(开放模型使用 --format messages,Gemini 模型使用 --format messages_gemini。) - 如需了解必需的架构,请参阅数据准备指南。
1.2 上传
将格式化后的 .jsonl 文件上传到 GCS,并使用唯一目录(例如带日期时间戳的目录),以避免覆盖不同运行的输出。如果用户指定了存储桶(例如 gs://mybucket),请严格按照用户提供的名称使用该存储桶,绝不添加项目 ID 前缀或修改存储桶名称。
ARTIFACTS="gs://YOUR_BUCKET/tuning_agent_job_<datetime>/dataset.jsonl"
gcloud storage cp dataset.jsonl "$ARTIFACTS"
第 2 阶段:模型配置与推荐 {#phase-2}
帮助用户选择最佳模型和参数。提交任务前务必征求用户确认。
- 如果用户的提示词中未指定具体模型,请根据模型目录计算推荐结果。
- 征求确认:向用户展示推荐的模型,并在配置超参数前征求其确认。
2.1 配置
开放模型
验证当前模型 ID
提交任务前,运行 scripts/list_models.py,并且仅从其 models 输出中选择 --base_model。不要编造 ID 或版本号。
python3 scripts/list_models.py --project YOUR_PROJECT --filter gemini
输出:{"models": [...], "total_count": N, "truncated": bool}。
- 对于 Gemini,请去掉
google/和@default(例如google/gemini-2.5-flash@default→gemini-2.5-flash);对于开放模型,请原样传入publisher/family@version。 - 跳过以
-embedding、-tts、-image、-computer-use或-native-audio结尾的 Gemini 变体;这些模型无法调优。 - 如果
truncated为true,请使用更严格的--filter(例如gemini-2.5)重新运行,然后再判断目标版本是否不可用。 - 如果
models为空,请停止并询问用户。
2.2 计算费用(仅限开放模型)
警告
关键:始终使用
run_command和scripts/calculate_cost.py请勿调用estimate_costADK 工具来进行模型调优。estimate_cost工具仅支持特定端点的服务定价,用于调优请求时会因Unsupported request type而失败。你必须调用run_command工具来执行 Python 代码或scripts/calculate_cost.py(或/workspace/skills/agent-platform-tuning/scripts/calculate_cost.py)来计算费用。每当选择模型或用户切换模型(例如从 Llama 切换到 Gemma)时,你都必须调用run_command计算或重新计算费用,然后才能显示试运行确认提示。请务必在试运行确认提示中报告计算出的金额(例如,Estimated tuning cost: $X.XX)。
-
我们根据数据集和 模型目录 中选定的模型,计算预计调优费用:
python3 scripts/calculate_cost.py \ --input my_data.jsonl \ --model MODEL_NAME \ --tuning_mode TUNING_MODE \ --epochs epochs--model可使用显示名称(Qwen 3 8B)或传递给--base_model的同一资源名称(qwen/qwen3@qwen3-8b),因此可以直接复用步骤 2.1 中选定的值。
说明
处理数据集缺失错误:如果
scripts/calculate_cost.py因找不到数据集文件(例如my_data.jsonl或dummy_data.jsonl)而失败,你必须告知用户该数据集文件不存在或无法访问。你必须提示用户提供有效的数据集路径,并立即停止工具执行,等待用户回复。请勿重试或循环执行,请勿编造具体费用,也请勿在收到用户提供的有效数据集之前提示用户批准提交作业。
- **请求确认:**向用户展示推荐的超参数配置和预计费用(使用上文计算出的具体金额),并在继续提交作业前征求用户批准。请务必说明预计费用仅为估算值,可能与实际账单费用不同。
第 3 阶段:调优作业执行 {#phase-3-tuning-job-execution}
关键预检(GCS 验证):在提出确认提示或提交任何调优作业之前,你必须验证指定的训练数据集 GCS URI(例如 gs://dummy_bucket/dataset.jsonl 或 gs://YOUR_BUCKET/...)确实存在且可访问。运行 gcloud storage ls $DATASET_URI(或 gsutil ls)。
- 如果验证失败(例如出现
BucketNotFound、404、AccessDenied,或表明存储桶是虚构的/不存在),你必须告知用户该 GCS 存储桶或数据集不存在或无法访问。你必须提示用户提供有效的数据集 GCS URI,并立即停止工具执行,等待用户回复。在收到用户提供的有效数据集 URI 之前,请勿提出确认提示,也请勿执行任何调优脚本。 - 如果验证成功,请继续提出下方的确认提示。
Gemini 模型
使用 Python SDK(google.genai 或 vertexai.tuning.sft)提交 Gemini 监督式微调作业:
from google import genai
from google.genai import types
client = genai.Client(enterprise=True, project=PROJECT, location=LOCATION)
tuning_job = client.tunings.tune(
base_model=BASE_MODEL, # e.g. "gemini-2.5-flash"
training_dataset=types.TuningDataset(gcs_uri=TRAIN_DATASET_URI),
config=types.CreateTuningJobConfig(
epoch_count=EPOCHS, # e.g. 3
learning_rate_multiplier=LEARNING_RATE_MULTIPLIER, # e.g. 1.0
validation_dataset=(
types.TuningValidationDataset(gcs_uri=VAL_DATASET_URI)
if VAL_DATASET_URI
else None
),
),
)
print("Tuning Job Resource Name:", tuning_job.name)
也可以使用 vertexai.tuning.sft:
import vertexai
from vertexai.tuning import sft
vertexai.init(project=PROJECT, location=LOCATION)
job = sft.train(
source_model=BASE_MODEL,
train_dataset=TRAIN_DATASET_URI,
validation_dataset=VAL_DATASET_URI,
epochs=EPOCHS,
learning_rate_multiplier=LEARNING_RATE_MULTIPLIER,
)
print("Tuning Job Resource Name:", job.resource_name)
通过 python3 执行 Python 脚本(内联执行或写入
/tmp/submit_gemini_tuning.py)。报告返回的操作名称或可跟踪的资源标识符,不要等待终端状态。
对于开放模型
使用 scripts/tune_open_model.py 或 Python SDK 提交开放模型调优任务。通过可用模型文档识别模型 ID,参见
文档。
--base_model 接受发布方模型资源名称
({publisher}/{model_id}@{version_id}),而不是目录中显示的名称。有关格式、已验证示例,以及如何查询未知名称,请参阅 references/models.md 中的“模型资源名称格式”。
使用 scripts/tune_open_model.py:
python3 scripts/tune_open_model.py \
--project YOUR_PROJECT \
--location global \
--base_model BASE_MODEL_ID \
--train_dataset gs://YOUR_BUCKET/tuning_agent_job_<datetime>/dataset.jsonl \
--output_uri gs://YOUR_BUCKET/tuning_agent_job_<datetime>/output \
--epochs EPOCHS \
--learning_rate LR \
--tuning_mode MODE
(如果当前工作目录中没有 scripts/tune_open_model.py,请直接使用 python3 -c "..." 运行 Python SDK 代码片段,或使用 client.tunings.tune 将其写入 /tmp/submit_open_tuning.py。)
此脚本仅适用于开放模型;如果省略 --location,则会回退到 global。务必显式传入用户在第 0.2 节确认的位置,以便该位置显示在提交审批的命令字符串中。
警告
开放模型必须提供
--output_uri。 Python SDK 将其声明为output_uri: Optional[str] = None,但如果开放模型任务未提供该参数,调优后端会拒绝任务,并返回INVALID_ARGUMENT: The output_uri field is required for this model.。此处 SDK 的“可选”签名有误,务必提供 GCS 目标位置。
由于此标志是必需的,因此提交前必须确定调优后的模型要写入的位置。**绝不能凭空编造存储桶名称、根据项目编号推导名称,或在未询问的情况下运行 gcloud storage buckets create。**创建存储桶属于变更操作,受下文 Tier M 确认政策约束。
- 用户指定了存储桶或 URI → 按用户指定的内容原样使用,并按照第 1.2 节追加唯一的任务专属目录。
**重要:**绝不能更改、添加前缀或在用户指定的存储桶名称前添加项目编号或其他内容!即使
gcloud storage buckets list显示已有一个带项目编号前缀的存储桶(例如,用户要求gs://mybucket,但已有gs://PROJECT-mybucket),也必须原样使用用户指定的存储桶名称gs://mybucket。绝不能悄悄替换为现有存储桶。 - 第 1.2 节上传数据集时已使用存储桶 → 提议将其用于输出,并请用户确认。
- 以上情况都不符合,或用户表示没有存储桶 → 检查项目中的现有存储桶(
gcloud storage buckets list --project=PROJECT),或提出创建专用存储桶。提议创建存储桶时,须在名称中加入唯一后缀或时间戳(例如,gs://PROJECT-tuning-$(date +%s)或gs://PROJECT-tuning-artifacts-<timestamp>,位于 LOCATION 中),以避免与先前创建的存储桶发生 HTTP 409 冲突。在配置试运行预览中提出目标存储桶,并在继续前征求用户确认。
重要
**必须进行交互式确认(Tier M):**提交任务前,必须向用户展示拟执行的命令字符串,其中包含所有字面值标志,并提供“Yes”和“No”选项供用户确认。
重要:向用户展示此确认提示时,必须直接输出纯文本回复,并立即停止工具执行。同一轮中不得调用任何命令执行或交互式工具,因为意外的工具调用可能会被模拟环境自动回复,导致无限循环。立即等待用户回复。
阶段 4:监控 {#phase-4-monitoring}
通过脚本输出中提供的 Cloud Console 链接监控作业。
--location 为必填项,且必须与提交时使用的位置相同:在 global 提交的开放模型作业,要使用 --location global 进行轮询,即使实际运行是在后台的某个真实区域。
此外,询问用户是否希望你在后台为其监控作业状态。如果用户同意,则将 scripts/monitor_tuning_job.py 作为后台任务执行,定期轮询作业状态并通知用户查看状态。如果用户拒绝,则完全由用户自行查看状态。
阶段 5:模型部署 {#phase-5-model-deployment}
调优作业的状态变为 SUCCEEDED 后,使用基础模型的服务容器将调优后的检查点注册到 Model Registry,然后将注册的模型部署到新的端点。
部署需要使用真实区域,global 在此处无效。如果作业在 global 上运行,请从调优模型的资源名称(projects/.../locations/<REGION>/models/...)中读取区域并在该区域部署;不要猜测。
如果部署步骤因配额问题被拒绝,请逐字报告 API 的错误信息。
#!/bin/bash
# Deploy a tuned checkpoint by registering it in Model Registry with the base
# model's serving container, then deploying to a new endpoint. All four gcloud
# calls hit aiplatform.googleapis.com.
set -euo pipefail
PROJECT_ID="YOUR_PROJECT"
LOCATION_ID="YOUR_LOCATION" # e.g. us-central1; NOT global.
BASE_MODEL="<PUBLISHER>/<FAMILY>@<VERSION-ID>" # the base model you tuned; e.g. google/gemma3@gemma-3-4b-it
ARTIFACTS="gs://YOUR_BUCKET/tuning_agent_job_<datetime>/output/postprocess/node-0/checkpoints/final"
DISPLAY_NAME="my-tuned-model"
# Explicit IDs, so no step can pick up an older model or endpoint that shares
# the display name.
RUN_ID="tuned-$(date +%Y%m%d-%H%M%S)"
# 1. List the base model's verified deployment configs and pick the row that
# fits the user-approved cost/perf. CONFIG_INDEX is its 0-based table row.
gcloud ai model-garden models list-deployment-config \
--model="$BASE_MODEL" \
--project="$PROJECT_ID"
CONFIG_INDEX="<pick from step 1>"
# Turn that row into gcloud flags files. The table shows only the image, but
# the container also needs the row's args, env, ports and routes; its
# --model/--model-path arg points at the base weights and is repointed at
# $ARTIFACTS.
gcloud ai model-garden models list-deployment-config \
--model="$BASE_MODEL" \
--project="$PROJECT_ID" \
--format=json | python3 -c '
import json, sys
idx, artifacts = int(sys.argv[1]), sys.argv[2]
cfg = json.load(sys.stdin)[idx]
spec = dict(cfg["containerSpec"])
args, repointed = [], 0
for a in spec.pop("args", []):
flag = a.split("=", 1)[0]
if flag in ("--model", "--model-path"):
a, repointed = flag + "=" + artifacts, repointed + 1
args.append(a)
if repointed != 1:
sys.exit("expected exactly one --model/--model-path arg, found %d" % repointed)
upload = {"--container-image-uri": spec.pop("imageUri"), "--container-args": args}
if "command" in spec:
upload["--container-command"] = spec.pop("command")
if "env" in spec:
upload["--container-env-vars"] = {e["name"]: e["value"] for e in spec.pop("env")}
if "ports" in spec:
upload["--container-ports"] = [str(p["containerPort"]) for p in spec.pop("ports")]
for key, flag in (("predictRoute", "--container-predict-route"),
("healthRoute", "--container-health-route"),
("sharedMemorySizeMb", "--container-shared-memory-size-mb")):
if key in spec:
upload[flag] = str(spec.pop(key))
if "deploymentTimeout" in spec: # e.g. "7200s"
upload["--container-deployment-timeout-seconds"] = str(
int(float(spec.pop("deploymentTimeout").rstrip("s"))))
if spec:
sys.exit("unhandled containerSpec fields: %s" % sorted(spec))
m = cfg["dedicatedResources"]["machineSpec"]
deploy = {"--machine-type": m["machineType"]}
if "acceleratorType" in m:
deploy["--accelerator"] = {
"type": m["acceleratorType"].lower().replace("_", "-"),
"count": str(m.get("acceleratorCount", 1))}
json.dump(upload, open("/tmp/upload_flags.yaml", "w"), indent=1)
json.dump(deploy, open("/tmp/deploy_flags.yaml", "w"), indent=1)
' "$CONFIG_INDEX" "$ARTIFACTS"
cat /tmp/upload_flags.yaml /tmp/deploy_flags.yaml
# 2. Register the tuned checkpoint in Model Registry with the base model's
# serving container. Blocks until the upload finishes.
gcloud ai models upload \
--project="$PROJECT_ID" \
--region="$LOCATION_ID" \
--model-id="$RUN_ID" \
--display-name="$DISPLAY_NAME" \
--artifact-uri="$ARTIFACTS" \
--flags-file=/tmp/upload_flags.yaml
# 3. Create a dedicated endpoint.
gcloud ai endpoints create \
--project="$PROJECT_ID" \
--region="$LOCATION_ID" \
--endpoint-id="$RUN_ID" \
--display-name="$DISPLAY_NAME"
# 4. Deploy the registered model to the endpoint.
gcloud ai endpoints deploy-model "$RUN_ID" \
--project="$PROJECT_ID" \
--region="$LOCATION_ID" \
--model="$RUN_ID" \
--display-name="$DISPLAY_NAME" \
--flags-file=/tmp/deploy_flags.yaml
set -e 会在第一个步骤失败时停止整个流程。第 4 步会一直阻塞,直到模型开始提供服务,这可能需要 20 分钟或更久;其进度输出会显示操作名称 projects/<PROJECT>/locations/<REGION>/operations/<OP_ID>。在另一个 shell 中检查状态时,将完整名称传给 gcloud ai operations describe <OPERATION_NAME>:只有当 gcloud 已设置项目时,单独使用 <OP_ID> 才有效。
重要
需要交互式确认(Tier M): 继续部署之前,你必须在确认提示中向用户展示三条写入命令(第 2 至 4 步),填入所有字面值,并附上生成的标志文件(容器映像、参数、机器类型、加速器配置),同时提供“Yes”和“No”选项。
关键: 向用户显示此确认提示时,必须直接以纯文本回复的形式输出,并立即停止工具执行。同一轮中不得调用任何命令执行工具或交互式工具,因为意外的工具调用可能会被模拟框架自动回复并导致无限循环。立即等待用户回复。
有关特定开放模型的硬件建议,请参阅 Models Catalog。