references/models.md during this step and only recommend models
explicitly listed in that catalog. Do not recommend unsupported models
like Mistral. If the user names a model that is not in the catalog,
follow the fallback rule in that catalog. Do not proceed with model
configuration until the category is confirmed.- **No** → Go to [Phase 1: Dataset Preparation & Upload](#phase-1).
- **Yes** → Proceed.
- **No** → Go to
[Phase 3: Tuning Job Execution](#phase-3-tuning-job-execution).
- **Yes** → Proceed.
- **No** → Go to [Phase 4: Monitoring](#phase-4-monitoring).
- **Yes** → Proceed.
- **No** → Go to [Phase 5: Model Deployment](#phase-5-model-deployment).
- **Yes** → Task Complete.
gcloud CLI is installed. If it is not installed, prompt the user
for permission to install it before proceeding. If it is installed, update
it:gcloud components update --quiet > /dev/null 2>&1
gcloud auth list. If not authenticated, run gcloud auth login.project is known. Use gcloud config get project to retrieve the
current project.global is the
recommended choice.global is not
accepted for them today.global)global and confirm it with the user. Propose it as a single
recommended choice rather than making the user pick a region first, and do not
steer them toward a specific region instead.global (the recommended choice)us-central1europe-west4us-west1us-east5asia-southeast1global endpoint automatically selects a supported region that has
available capacity, so it is the most likely to be scheduled successfully.
Pinning a region up front restricts the job to that one region's capacity, which
is why global is the recommended location for open model tuning.global or
one of the regions listed above. Do not talk them out of it.global is recommended and why. Never
withhold it.global and ask them to
confirm it before you proceed. Say that global lets the service pick a
region with available capacity. Do NOT silently assume global.global with a
FAILED_PRECONDITION error. A CMEK-protected job must name the region that
holds the key.global currently runs the job in either
us-central1 or europe-west4.global job is accepted but then fails with a FAILED_PRECONDITION error
saying the model does not support global endpoint tuning, that model is not
onboarded to the global endpoint yet. The model itself is still tunable:
resubmit once in an explicit region from the list above (us-central1 is the
safest choice) and tell the user why you switched.global jobaiplatform.googleapis.com. There is no
global-aiplatform.googleapis.com host.global to a real region at run time. Sub-resources
(the tuned model, checkpoints, TensorBoard) come back with that real
region in their resource names, not global. Read the location out of the
returned resource name before using it for monitoring or deployment; never
assume it is still global.global is not accepted for Gemini tuning today — the service rejects it at
job creation with a FAILED_PRECONDITION error, so do not propose it here.us and eu multi-region
endpoints, so check the same table for those limits before promising them.aiplatform.googleapis.com and storage.googleapis.com are enabled.gcloud services enable aiplatform.googleapis.com storage.googleapis.com \
--project=YOUR_PROJECT
service-PROJECT_NUMBER@gcp-sa-aiplatform.iam.gserviceaccount.comservice-PROJECT_NUMBER@gcp-sa-vertex-moss-ft.iam.gserviceaccount.comvertexai (from google-cloud-aiplatform),
google-genai, google-cloud-storage, and datasets.python3 -c "import vertexai, google.genai, google.cloud.storage, datasets" \
|| pip install -r references/requirements.txt
python3 scripts/... — no activation prefix.references/requirements.txt pins are a fallback for an environment that
does not already provide these SDKs. Do not apply them on top of a working
environment: they would downgrade packages other tools may share..jsonl, .json, .csv, and
.parquet. If such files are found, read the first few lines/records of
each to determine if they contain text-based data suitable for tuning (e.g.,
prompt/completion pairs) that can be modified to follow
Data Preparation Guide [blocked] and is related to the
tuning task requested. DO NOT search without prompting first.prompt (or user > message) and completion (or assistant response),
offering a few > reasonable options if applicable. > - Ask the user to
confirm the column mapping or specify which > columns to use.scripts/prepare_dataset.py to convert.--validation_split 0.1). If they agree, proceed with the split. If they
decline, just use the training dataset without a validation dataset. Do
NOT offer an 80/20 split; the tuning service rejects it, for the reason
given in
Data Preparation Guide [blocked]..jsonl extension is not enough. You must verify that the
content schema is valid for tuning (e.g. correct system/user/model roles).python3 scripts/prepare_dataset.py \
--input my_data.jsonl \
--format <messages|messages_gemini> \
--validate_only
--format messages for open models and --format messages_gemini for
Gemini models.) - Refer to Data Preparation Guide [blocked]
for required schemas..jsonl files to GCS using a unique directory (e.g., with a
datetime timestamp) to avoid overwriting outputs from different runs.ARTIFACTS="gs://YOUR_BUCKET/tuning_agent_job_<datetime>/dataset.jsonl"
gcloud storage cp dataset.jsonl "$ARTIFACTS"
tuning_mode, epochs, learning_rate, and adapter_size based
on the Tuning Guide [blocked] and model-specific
baselines in the Models Catalog [blocked].scripts/list_models.py and pick --base_model
only from its models output. Do not invent IDs or version numbers.python3 scripts/list_models.py --project YOUR_PROJECT --filter gemini
{"models": [...], "total_count": N, "truncated": bool}.google/ and @default (e.g.
google/gemini-2.5-flash@default → gemini-2.5-flash); for open models,
pass publisher/family@version as-is.-embedding, -tts, -image,
-computer-use, or -native-audio; they are not tunable.truncated is true, re-run with a tighter --filter (e.g.
gemini-2.5) before deciding the target version is unavailable.models is empty, stop and ask the user.python3 scripts/calculate_cost.py \
--input my_data.jsonl \
--model MODEL_NAME \
--tuning_mode TUNING_MODE \
--epochs epochs
--model takes either the display name (Qwen 3 8B) or the same resource
name you pass to --base_model (qwen/qwen3@qwen3-8b), so the value chosen
in Step 2.1 can be reused as-is.[!NOTE] Handling Missing Dataset Errors: Ifscripts/calculate_cost.pyfails because the dataset file (e.g.my_data.jsonlordummy_data.jsonl) cannot be found, you MUST inform the user that the dataset file does not exist or cannot be accessed. You MUST prompt the user to provide a valid dataset path, and stop tool execution immediately to wait for their response. Do NOT retry or loop, do NOT invent a specific cost number, and do NOT prompt for job submission approval before receiving a valid dataset from the user.
gcloud storage ls $DATASET_URI (or gsutil ls).BucketNotFound, 404, AccessDenied,
or indicating a dummy/missing bucket), you MUST inform the user that the
GCS bucket or dataset does not exist or cannot be accessed. You MUST
prompt the user to provide a valid GCS URI for the dataset, and stop tool
execution immediately to wait for their response. Do NOT propose a
confirmation prompt and do NOT execute any tuning scripts before
receiving a valid dataset URI from the user.scripts/tune_gemini_model.py exists.scripts/tune_gemini_model.py exists: Submit the Gemini model tuning
job using this script.python3 scripts/tune_gemini_model.py
scripts/tune_gemini_model.py does not exist: Instruct the user to
manually configure and submit the tuning job via the Google Cloud Console UI
or using the Agent Platform SDK for Python.scripts/tune_open_model.py. Identify
the model id using available models documentation
at
documentation.--base_model takes a publisher model resource name
({publisher}/{model_id}@{version_id}), not the display name shown in the
catalog. See "Model Resource Name Format" in references/models.md for the
format, verified examples, and how to look up a name you do not have.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
--location falls back to global if
omitted. Always pass the location the user confirmed in section 0.2 explicitly,
so it is visible in the command string you present for approval.[!WARNING]--output_uriis required for open models. The Python SDK declares it asoutput_uri: Optional[str] = None, but the tuning backend rejects open model jobs that omit it withINVALID_ARGUMENT: The output_uri field is required for this model.Treat the SDK's "optional" signature as wrong here and always pass a GCS destination.
gcloud storage buckets create unprompted. Creating a
bucket is a mutating action and is subject to the Tier M confirmation policy
below.[!IMPORTANT] Interactive Confirmation Required (Tier M): Before proceeding with job submission, you MUST present the proposed command string showing all literal flags in a confirmation prompt to the user with 'Yes' and 'No' options.
CRITICAL: When presenting this confirmation prompt to the user, you MUST output it as a direct plain text response and stop tool execution immediately. Do NOT call any command execution or interactive tools in the same turn, as unexpected tool calls may be auto-replied by the simulation harness and cause an infinite loop. Yield immediately for the user's reply.
--location is required and must be the same location you submitted with: an
open model job submitted on global is polled with --location global, even
though the work runs in a real region behind the scenes.scripts/monitor_tuning_job.py as a
background task to periodically poll the job status and notify the user to show
the status. If the user declines, leave it completely to the user to check on
the status.SUCCEEDED, deploy the model.--region=global is not valid here. If the
job ran on global, read the region out of the tuned model's resource name
(projects/.../locations/<REGION>/models/...) and deploy there; do not guess.ARTIFACTS="gs://YOUR_BUCKET/tuning_agent_job_<datetime>/output/postprocess/node-0/checkpoints/final"
gcloud ai model-garden models deploy \
--project=YOUR_PROJECT \
--region=YOUR_LOCATION \
--model="$ARTIFACTS" \
--machine-type=MACHINE_TYPE \
--accelerator-type=ACCELERATOR_TYPE \
--accelerator-count=COUNT
[!IMPORTANT] Interactive Confirmation Required (Tier M): Before proceeding with deployment, you MUST present the proposed command string showing all literal flags in a confirmation prompt to the user with 'Yes' and 'No' options.
CRITICAL: When presenting this confirmation prompt to the user, you MUST output it as a direct plain text response and stop tool execution immediately. Do NOT call any command execution or interactive tools in the same turn, as unexpected tool calls may be auto-replied by the simulation harness and cause an infinite loop. Yield immediately for the user's reply.
scripts/prepare_dataset.py: Data conversion & validation.scripts/tune_open_model.py: Open model tuning job submission.Start with one job and grow from there.