mcpField
A
agent-platform-tuning

agent-platform-tuning

github.com/googleクラウド・DevOps21.6k8.8k 回インストール今日更新
リポジトリ

agent-platform-tuning について

Agent PlatformでオープンモデルとGeminiモデルをファインチューニングするための手順スキルです。環境準備からデータセット処理、ジョブ設定、監視、デプロイまでを段階的な確認事項とともに扱います。

主な機能

  1. 01環境とIAMの確認
  2. 02データセット検証とアップロードの案内
  3. 03モデルとロケーションの選択
  4. 04チューニングジョブの設定と監視
  5. 05デプロイ手順の案内

活用シーン

  1. 01モデルチューニング用のプロジェクト準備
  2. 02チューニングデータセットの検証とアップロード
  3. 03チューニングジョブの実行と監視
  4. 04チューニング済みモデルのデプロイ

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/google/skills --skill agent-platform-tuning

インストール後、Claude Code で/agent-platform-tuningを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
data_prep.md
hf_datasets.md
models.md
requirements.txt
tuning_guide.md
scripts/
calculate_cost.py
cancel_tuning_job.py
list_models.py
monitor_tuning_job.py
prepare_dataset.py
tune_open_model.py

詳細

エージェントプラットフォームのモデルチューニング

概要

このスキルでは、Agent Platform のチューニングサービスを使用して、大規模言語モデル(オープンモデルと Gemini モデルの両方)をファインチューニングするための手順に関する知識を提供します。環境設定やデータ準備から、ジョブの構成、モニタリング、デプロイまで、ライフサイクル全体を網羅しています。

ワークフローの判断ツリー

  1. プロジェクトとリージョンの確認:ユーザーは Google Cloud のプロジェクトとリージョンを指定していますか?

    • いいえ → ツールの実行を直ちに停止してください。確認コマンド(gcloud services list、gcloud projects get-iam-policy)を実行せず、リソースを作成せず、データセットの準備も開始しないでください。プロジェクトとリージョンを指定するか確認するよう、ユーザーに求めてください(例:「使用する Google Cloud プロジェクトとリージョンを指定していただけますか?」)。
      • ユーザーの問い合わせが環境の準備状況(API、IAM、サービスエージェント)の確認だけを目的としている場合は、プロジェクトとリージョンのみを尋ねてください。モデルのカテゴリは尋ねないでください。
      • ユーザーがチューニングのワークフローを希望していて、オープンモデルと Gemini モデルのどちらをチューニングするかも指定していない場合は、両方をまとめて尋ねてもかまいません。
    • はい → 続行します。
  2. モデルカテゴリの特定:ユーザーは、オープンモデルと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 を 1 つ、Gemini Model を 1 つ、一般的に推奨されるモデルを 1 つ、計 3 つのモデルを推奨してください。それぞれの長所と短所を簡潔に示します(例: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 は絶対に推奨しないでください。ユーザーがカタログにないモデルを指定した場合は、そのカタログに記載されたフォールバックルールに従ってください。カテゴリが確認されるまで、モデルの設定に進まないでください。
    • はい → 続行します。
  3. 環境の確認:環境(認証、API、IAM、Venv)は初期化されていますか?

  4. データセットの状態:データセットは JSONL 形式で準備できており、その構造はチューニングに有効で、Google Cloud Storage にアップロードされていますか?

    -   **いいえ** → [フェーズ 1:データセットの準備とアップロード](#phase-1)に進みます。
    -   **はい** → 続行します。
    
  5. 列選択の確認:列をユーザーに提示し、対応付けを確認しましたか?

    • いいえ → 停止します。先に進む前に、フェーズ 1.0 の説明に従ってサンプルを示し、列の対応付けについてユーザーの確認を得る必要があります。
    • はい → 続行します。
  6. 設定:ユーザーは対象モデルとハイパーパラメーターを提示しましたか。それとも、提示した推奨内容に明示的に同意しましたか?

  7. ジョブのステータス:チューニングジョブは送信済みですか?

    -   **いいえ** → 次へ進みます
        [フェーズ 3:チューニングジョブの実行](#phase-3-tuning-job-execution)。
    -   **はい** → 続行します。
    
  8. ジョブの完了:チューニングジョブは完了していますか?

    -   **いいえ** → 次へ進みます [フェーズ 4:モニタリング](#phase-4-monitoring)。
    -   **はい** → 続行します。
    
  9. デプロイ:チューニング済みモデルはデプロイされていますか(必要な場合)?

    -   **いいえ** → 次へ進みます [フェーズ 5:モデルのデプロイ](#phase-5-model-deployment)。
    -   **はい** → タスク完了です。
    

フェーズ 0:環境と IAM の設定 {#phase-0}

先に進む前に、基本的な環境が整っていることを確認します。

0.1 認証とプロジェクトのコンテキスト
  • gcloud CLI がインストールされているか確認します。インストールされていない場合は、先に進む前にインストールの許可をユーザーに求めます。インストールされている場合は、更新します:
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 が認証済みであることを確認し、環境を検証する読み取り専用のチェックを実行します。環境の準備状況を報告する際は、次の 3 つのカテゴリすべてのステータスを要約に明記しなければなりません。
    1. 必須 API:aiplatform.googleapis.com(Agent Platform)と storage.googleapis.com(Cloud Storage)の両方が有効であることを明記します。
    2. ユーザー/呼び出し元の IAM 権限:ユーザー ID またはデフォルトのコンピューティング サービス アカウントに、roles/aiplatform.user と roles/storage.admin(または roles/storage.objectAdmin)が付与されていることを明記します。
    3. サービスエージェントとロール:Agent Platform サービスエージェント([email protected])に roles/aiplatform.serviceAgent が付与され、チューニング サービスエージェント(service-PROJECT_NUMBER@gcp-sa-vertex-moss-ft.iam.gserviceaccount.com または gcp-sa-vertex-tune)に roles/aiplatform.tuningServiceAgent が付与されていることを明記します。確認済みのプロジェクトとリージョン(例:project: <PROJECT_NUMBER>, region: us-central1)を必ず明記し、環境が完全に設定され、チューニングを実行できる状態であることも明記します。
0.2 ロケーション

ロケーションの扱いは、ワークフローの判断ツリーで確定したモデルのカテゴリに依存します。2 つのカテゴリではサポートされるロケーションが異なるため、一方のカテゴリのロケーションを他方に適用してはいけません。

  • オープンモデルで共通の固定ロケーションセットを使用します。global が推奨されます。
  • Gemini モデルではモデルごとに異なるため、対応するロケーションを調べる必要があります。現時点では global は受け付けられません。

ユーザーが指定したロケーションが、そのモデルとカテゴリで有効でない場合は、停止します。要求されたロケーションがサポート対象外であることを示すエラーを返し、有効なロケーションを一覧表示します。データセットを求めたり、ほかの設定手順に進んだり、別のロケーションで黙って再試行したりしてはいけません。

オープンモデル(推奨:global)

globalを推奨し、ユーザーに確認してください。 ユーザーに最初にリージョンを選ばせるのではなく、推奨する選択肢として単独で提案してください。また、特定のリージョンを選ぶよう誘導しないでください。

オープンモデルのチューニングで利用できるロケーションは、以下のみです。

  • global(推奨)
  • us-central1
  • europe-west4
  • us-west1
  • us-east5
  • asia-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 に共通する単一のリージョン許可リストはありません。**チューニングでサポートされるリージョンはモデルとモデルのバージョンによって異なります。2 つのリージョンに制限されている Gemini モデルもあれば、より多くのリージョンに対応しているモデルもあります。上記のオープンモデルのリストを再利用したり、別の Gemini モデルのリージョンを適用できると考えたりしないでください。

送信する前に、教師ありファインチューニングのドキュメントで選択したモデルを調べ、**「Supported endpoint for model tuning」**の行を確認してください。 教師ありチューニング

  • ユーザーからサポート対象のリージョンを尋ねられた場合 → 該当するモデルを調べ、ドキュメントに記載されている内容を伝えてください。記憶やオープンモデルのリストに基づいて回答したり、別の 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 権限

次の ID に必要なロールが割り当てられていることを確認してください。

  • Agent Platform Service Agent: [email protected]
  • Managed OSS Fine Tuning Service Agent: service-PROJECT_NUMBER@gcp-sa-vertex-moss-ft.iam.gserviceaccount.com
  • ユーザー ID:コマンドを実行するアカウントです。
0.5 Python の依存関係

このスキルのスクリプトは、vertexai(google-cloud-aiplatform から)、google-genai、google-cloud-storage、および datasets をインポートします。

エージェントへの重要な指示: 仮想環境を作成せず、事前に確認せずに何もインストールしないでください。venv は空の状態で始まり、環境にすでに用意されているパッケージが見えなくなるため、数分かかる冗長なインストールを強いることになります。

まず確認し、確認に失敗した場合にのみインストールしてください。

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 コストの計算(オープンモデルのみ)

警告

重要:必ず scripts/calculate_cost.py を指定して run_command を使用してください モデルのチューニングに estimate_cost ADK ツールを呼び出してはいけません。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 で選択した値をそのまま再利用できます。

メモ

データセットが見つからないエラーへの対応: データセットファイル(例:my_data.jsonl または dummy_data.jsonl)が見つからないために scripts/calculate_cost.py が失敗した場合は、データセットファイルが存在しない、またはアクセスできないことを必ずユーザーに伝えてください。有効なデータセットのパスを提示するようユーザーに求め、応答を待つためにツールの実行を直ちに停止してください。再試行やループをしてはいけません。具体的なコストの数値を捏造してはいけません。また、有効なデータセットをユーザーから受け取る前に、ジョブの送信承認を求めてはいけません。

  • 確認を求める: 推奨するハイパーパラメーター設定と推定コスト(上記で計算した具体的な金額)をユーザーに提示し、ジョブの送信に進む前に承認を求めます。推定コストはあくまで推定値であり、実際の請求額とは異なる場合があることを必ず明記してください。

フェーズ 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)

Python スクリプトを python3 で実行します(インラインで実行するか、/tmp/submit_gemini_tuning.py に書き込みます)。返されたオペレーション名または追跡可能なリソース識別子を報告し、終端状態になるまで待機してはいけません。

オープンモデルの場合

scripts/tune_open_model.py または Python SDK を使って、オープンモデルのチューニングジョブを送信します。利用可能なモデルのドキュメントを ドキュメントで確認して、モデル ID を特定します。

--base_model に指定するのは、カタログに表示される表示名ではなく、パブリッシャーモデルのリソース名({publisher}/{model_id}@{version_id})です。形式、確認済みの例、および不明な名前の調べ方については、references/models.md の「Model Resource Name Format」を参照してください。

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)か、専用バケットの作成を提案します。作成するバケットを提案する場合は、HTTP 409 の衝突を防ぐため、一意な接尾辞またはタイムスタンプを含めてください(例:gs://PROJECT-tuning-$(date +%s) または LOCATION 内の gs://PROJECT-tuning-artifacts-<timestamp>)。設定のドライランプレビューに保存先バケットを提示し、続行前にユーザーの確認を求めてください。

重要

対話による確認が必要(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> というオペレーション名が表示されます。別のシェルから状態を確認するには、その名前全体を gcloud ai operations describe <OPERATION_NAME> に渡してください。<OP_ID> のみを指定して動作するのは、gcloud にプロジェクトが設定されている場合だけです。

重要

対話的な確認が必要です(Tier M): デプロイに進む前に、実際の値をすべて入力した書き込みコマンド 3 つ(手順 2~4)と、生成されたフラグファイル(コンテナイメージ、引数、マシンタイプ、アクセラレータ設定)を確認プロンプトにまとめ、ユーザーに提示する必要があります。プロンプトには「Yes」と「No」の選択肢を含めてください。

重大な注意: この確認プロンプトをユーザーに提示する際は、直接のプレーンテキスト応答として出力し、直ちにツールの実行を停止する必要があります。同じターンでコマンド実行ツールや対話型ツールを呼び出さないでください。予期しないツール呼び出しがシミュレーションハーネスによって自動的に返信され、無限ループが発生する可能性があります。ユーザーの返信を待ってください。

特定のオープンモデルに適したハードウェアについては、モデルカタログを参照してください。

リソース

コメント