GKE で複数の GPU を使用して Gemma オープンモデルをファインチューニングする


このチュートリアルでは、Hugging FaceTransformers ライブラリを使用して、Google Kubernetes Engine(GKE)で画像処理装置(GPU)を使用し、Gemma 大規模言語モデル(LLM)をファインチューニングする方法について説明します。ファインチューニングは、新しいデータセットでパラメータを更新することで、トレーニング済みモデルが特定のタスクを実行する能力を向上させる教師あり学習プロセスです。このチュートリアルでは、2B パラメータで事前トレーニング済みの Gemma ファミリー モデルを Hugging Face からダウンロードし、GKE Autopilot または Standard クラスタでファインチューニングします。

このガイドは、LLM をファインチューニングする際に、マネージド Kubernetes での詳細な制御、スケーラビリティ、復元力、ポータビリティ、費用対効果が求められる場合の出発点として適しています。ML モデルを費用対効果の高い方法で迅速に構築して提供するために、統合されたマネージド AI プラットフォームが必要な場合は、Vertex AI ソリューションをお試しになることをおすすめします。

背景

GKE の GPU で Transformers ライブラリを使用して Gemma をサービングすると、効率的なスケーラビリティや高可用性をはじめとするマネージド Kubernetes のメリットをすべて活かして、プロダクション レディで堅牢な推論サービング ソリューションを実装できます。このセクションでは、このガイドで使用されている重要なテクノロジーについて説明します。

Gemma

Gemma は、オープン ライセンスでリリースされ一般公開されている、軽量の生成 AI モデルのセットです。これらの AI モデルは、アプリケーション、ハードウェア、モバイル デバイス、ホスト型サービスで実行できます。

このガイドでは、テキスト生成用の Gemma について説明します。特定のタスクを実行するようにこれらのモデルをチューニングすることもできます。

このドキュメントで使用するデータセットは b-mc2/sql-create-context です。

詳しくは、Gemma のドキュメントをご覧ください。

GPU

GPU を使用すると、ノードで実行される特定のワークロード(ML やデータ処理など)を高速化できます。GKE には、NVIDIA H100、L4、A100 GPU を搭載したマシンタイプをはじめとして、ノード構成用のさまざまなマシンタイプ オプションが用意されています。

GKE で GPU を使用する前に、次の学習プログラムを完了することをおすすめします。

  1. 現在の GPU バージョンの可用性について学習する
  2. GKE の GPU について学習する

Hugging Face Transformers

Hugging Face の Transformers ライブラリを使用すると、最先端の事前トレーニング済みモデルにアクセスできます。Transformers ライブラリを使用すると、モデルの完全なトレーニングに関連する時間、リソース、計算コストを削減できます。

このチュートリアルでは、Hugging Face API とツールを使用して、これらの事前トレーニング済みモデルをダウンロードしてファインチューニングします。

目標

このガイドは、H100、A100、L4 GPU ハードウェアで LLM をファインチューニングするために Kubernetes コンテナ オーケストレーション機能を使用することに関心をお持ちの GKE ユーザー(新規または既存)、ML エンジニア、MLOps(DevOps)エンジニア、プラットフォーム管理者を対象としています。

このガイドを終えると、次のことを行えるようになります。

  1. Autopilot モードの GKE クラスタで環境を準備する。
  2. ファインチューニング コンテナを作成する。
  3. GPU を使用して Gemma 2B モデルをファインチューニングし、モデルを Hugging Face にアップロードする。

始める前に

  • Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  • In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  • Make sure that billing is enabled for your Google Cloud project.

  • Enable the required API.

    Enable the API

  • In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  • Make sure that billing is enabled for your Google Cloud project.

  • Enable the required API.

    Enable the API

  • Make sure that you have the following role or roles on the project: roles/container.admin, roles/iam.serviceAccountAdmin

    Check for the roles

    1. In the Google Cloud console, go to the IAM page.

      Go to IAM
    2. Select the project.
    3. In the Principal column, find all rows that identify you or a group that you're included in. To learn which groups you're included in, contact your administrator.

    4. For all rows that specify or include you, check the Role colunn to see whether the list of roles includes the required roles.

    Grant the roles

    1. In the Google Cloud console, go to the IAM page.

      [IAM] に移動
    2. プロジェクトを選択します。
    3. [ アクセスを許可] をクリックします。
    4. [新しいプリンシパル] フィールドに、ユーザー ID を入力します。 これは通常、Google アカウントのメールアドレスです。

    5. [ロールを選択] リストでロールを選択します。
    6. 追加のロールを付与するには、 [別のロールを追加] をクリックして各ロールを追加します。
    7. [保存] をクリックします。

モデルへのアクセス権を取得する

GKE にデプロイするために Gemma モデルへのアクセス権を取得するには、まずライセンス同意契約に署名してから、Hugging Face のアクセス トークンを生成する必要があります。

Gemma を使用するには同意契約に署名する必要があります。手順は次のとおりです。

  1. Kaggle.com のモデルの同意ページにアクセスします。
  2. Hugging Face アカウントを使用して同意を確認します。
  3. モデルの規約に同意します。

アクセス トークンを生成する

Hugging Face からモデルにアクセスするには、Hugging Face トークンが必要です。

トークンをまだ生成していない場合は、次の手順に沿って生成します。

  1. [Your Profile] > [Settings] > [Access Tokens] の順にクリックします。
  2. [New Token] を選択します。
  3. 任意の名前と、少なくとも Write ロールを指定します。
  4. [Generate a token] を選択します。
  5. トークンをクリップボードにコピーします。

環境を準備する

このチュートリアルでは、Cloud Shell を使用して Google Cloud でホストされるリソースを管理します。Cloud Shell には、このチュートリアルに必要な kubectlgcloud CLI などのソフトウェアがプリインストールされています。

Cloud Shell を使用して環境を設定するには、次の操作を行います。

  1. Google Cloud コンソールで、Google Cloud コンソールCloud Shell 有効化アイコン [Cloud Shell をアクティブにする] をクリックして、Cloud Shell セッションを起動します。これにより、Google Cloud コンソールの下部ペインでセッションが起動されます。

  2. デフォルトの環境変数を設定します。

    gcloud config set project PROJECT_ID
    export PROJECT_ID=$(gcloud config get project)
    export REGION=REGION
    export CLUSTER_NAME=finetuning
    export HF_TOKEN=HF_TOKEN
    export HF_PROFILE=HF_PROFILE
    

    次の値を置き換えます。

    • PROJECT_ID: Google Cloud プロジェクト ID
    • REGION: 使用するアクセラレータ タイプをサポートするリージョン(たとえば、L4 GPU の場合は us-central1)。
    • HF_TOKEN: 先ほど生成した Hugging Face トークン。
    • HF_PROFILE: 前に作成した Hugging Face プロファイル ID。
  3. GitHub からサンプルコード リポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    cd kubernetes-engine-samples/ai-ml/llm-finetuning-gemma
    

Google Cloud リソースを作成して構成する

次の手順で、必要なリソースを作成します。

GKE クラスタとノードプールを作成する

GKE Autopilot クラスタまたは GKE Standard クラスタの GPU で Gemma を提供できます。フルマネージドの Kubernetes エクスペリエンスを実現するには、Autopilot クラスタを使用することをおすすめします。ワークロードに最適な GKE の運用モードを選択するには、GKE の運用モードを選択するをご覧ください。

Autopilot

Cloud Shell で、次のコマンドを実行します。

gcloud container clusters create-auto ${CLUSTER_NAME} \
  --project=${PROJECT_ID} \
  --region=${REGION} \
  --release-channel=rapid \
  --cluster-version=1.29

GKE は、デプロイされたワークロードからの要求に応じた CPU ノードと GPU ノードを持つ Autopilot クラスタを作成します。

Standard

  1. Cloud Shell で、次のコマンドを実行して Standard クラスタを作成します。

    gcloud container clusters create ${CLUSTER_NAME} \
      --project=${PROJECT_ID} \
      --region=${REGION} \
      --workload-pool=${PROJECT_ID}.svc.id.goog \
      --release-channel=rapid \
      --num-nodes=1
    

    クラスタの作成には数分かかることもあります。

  2. 次のコマンドを実行して、クラスタのノードプールを作成します。

    gcloud container node-pools create gpupool \
      --accelerator type=nvidia-l4,count=8,gpu-driver-version=latest \
      --project=${PROJECT_ID} \
      --location=${REGION} \
      --node-locations=${REGION}-a \
      --cluster=${CLUSTER_NAME} \
      --machine-type=g2-standard-96 \
      --num-nodes=1
    

    GKE は、各ノードに 2 つの L4 GPU を含む単一のノードプールを作成します。

Hugging Face の認証情報用の Kubernetes Secret を作成する

Cloud Shell で、次の操作を行います。

  1. クラスタと通信を行うように kubectl を構成します。

    gcloud container clusters get-credentials ${CLUSTER_NAME} --location=${REGION}
    
  2. Hugging Face トークンを含む Kubernetes Secret を作成します。

    kubectl create secret generic hf-secret \
      --from-literal=hf_api_token=${HF_TOKEN} \
      --dry-run=client -o yaml | kubectl apply -f -
    

Docker と Cloud Build を使用してファインチューニング コンテナを作成する

このコンテナは、PyTorch と Hugging Face Transformers のコードを使用して、既存の事前トレーニング済み Gemma モデルをファインチューニングします。

  1. Artifact Registry Docker リポジトリを作成します。

    gcloud artifacts repositories create gemma \
        --project=${PROJECT_ID} \
        --repository-format=docker \
        --location=us \
        --description="Gemma Repo"
    
  2. イメージをビルドして push します。

    gcloud builds submit .
    
  3. このチュートリアルで後で使用できるように、IMAGE_URL をエクスポートします。

    export IMAGE_URL=us-docker.pkg.dev/$PROJECT_ID/gemma/finetune-gemma-gpu:1.0.0
    

GKE でファインチューニング ジョブを実行する

ファインチューニング ジョブ用の Gemma をデプロイする

  1. finetune.yaml ファイルを開きます。

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: finetune-job
      namespace: default
    spec:
      backoffLimit: 2
      template:
        metadata:
          annotations:
            kubectl.kubernetes.io/default-container: finetuner
        spec:
          terminationGracePeriodSeconds: 600
          containers:
          - name: finetuner
            image: $IMAGE_URL
            resources:
              limits:
                nvidia.com/gpu: "8"
            env:
            - name: MODEL_NAME
              value: "google/gemma-2b"
            - name: NEW_MODEL
              value: "gemma-2b-sql-finetuned"
            - name: LORA_R
              value: "8"
            - name: LORA_ALPHA
              value: "16"
            - name: TRAIN_BATCH_SIZE
              value: "1"
            - name: EVAL_BATCH_SIZE
              value: "2"
            - name: GRADIENT_ACCUMULATION_STEPS
              value: "2"
            - name: DATASET_LIMIT
              value: "1000"
            - name: MAX_SEQ_LENGTH
              value: "512"
            - name: LOGGING_STEPS
              value: "5"
            - name: HF_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_api_token
            volumeMounts:
            - mountPath: /dev/shm
              name: dshm
          volumes:
          - name: dshm
            emptyDir:
              medium: Memory
          nodeSelector:
            cloud.google.com/gke-accelerator: nvidia-l4
          restartPolicy: OnFailure
  2. マニフェストを適用して、ファインチューニング ジョブを作成します。

    envsubst < finetune.yaml | kubectl apply -f -
    

    この指示により、IMAGE_URL はマニフェスト内の変数に置き換えられます。

  3. 次のコマンドを実行して、ジョブをモニタリングします。

    watch kubectl get pods
    
  4. 次のコマンドを実行して、ジョブのログを確認します。

    kubectl logs job.batch/finetune-job -f
    

    Job リソースはモデルデータをダウンロードし、8 つすべての GPU を使用してモデルをファインチューニングします。この処理には最長で 20 分ほどかかります

  5. ジョブが完了したら、Hugging Face アカウントに移動します。Hugging Face のプロフィールに $HF_PROFILE/gemma-2b-sql-finetuned という名前の新しいモデルが表示されます。

ファインチューニング済みモデルを GKE でサービングする

このセクションでは、Gemma モデルをサービングする vLLM コンテナをデプロイします。

  1. 次の serve-gemma.yaml マニフェストを作成します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: vllm-gemma-deployment
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: gemma-server
      template:
        metadata:
          labels:
            app: gemma-server
            ai.gke.io/model: gemma-2b
            ai.gke.io/inference-server: vllm
            examples.ai.gke.io/source: user-guide
        spec:
          containers:
          - name: inference-server
            image: us-docker.pkg.dev/vertex-ai/vertex-vision-model-garden-dockers/pytorch-vllm-serve:20240220_0936_RC01
            resources:
              requests:
                cpu: "2"
                memory: "7Gi"
                ephemeral-storage: "10Gi"
                nvidia.com/gpu: 1
              limits:
                cpu: "2"
                memory: "7Gi"
                ephemeral-storage: "10Gi"
                nvidia.com/gpu: 1
            command: ["python3", "-m", "vllm.entrypoints.api_server"]
            args:
            - --model=$(MODEL_ID)
            - --tensor-parallel-size=1
            env:
            - name: MODEL_ID
              value: google/gemma-2b
            - name: HUGGING_FACE_HUB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_api_token
            volumeMounts:
            - mountPath: /dev/shm
              name: dshm
          volumes:
          - name: dshm
            emptyDir:
                medium: Memory
          nodeSelector:
            cloud.google.com/gke-accelerator: nvidia-l4
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: llm-service
    spec:
      selector:
        app: gemma-server
      type: ClusterIP
      ports:
        - protocol: TCP
          port: 8000
          targetPort: 8000
  2. 新しい MODEL_ID の環境変数を作成します。

    export MODEL_ID=$HF_PROFILE/gemma-2b-sql-finetuned
    
  3. マニフェストの MODEL_ID を置き換えます。

    sed -i "s|google/gemma-2b|$MODEL_ID|g" serve-gemma.yaml
    
  4. 次のようにマニフェストを適用します。

    kubectl apply -f serve-gemma.yaml
    

    クラスタ内の Pod が Hugging Face からモデルの重みをダウンロードし、サービス提供エンジンを起動します。

  5. Deployment が利用可能になるまで待ちます。

    kubectl wait --for=condition=Available --timeout=700s deployment/vllm-gemma-deployment
    
  6. 実行中の Deployment のログを表示します。

    kubectl logs -f -l app=gemma-server
    

Deployment リソースによってモデルデータがダウンロードされます。この処理には数分かかることがあります。出力は次のようになります。

INFO 01-26 19:02:54 model_runner.py:689] Graph capturing finished in 4 secs.
INFO:     Started server process [1]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

モデルが完全にダウンロードされたことを確認してから、次のセクションに進んでください。

モデルを提供する

このセクションでは、モデルを操作します。

ポート転送を設定する

モデルがデプロイされたら、次のコマンドを実行してモデルへのポート転送を設定します。

kubectl port-forward service/llm-service 8000:8000

出力は次のようになります。

Forwarding from 127.0.0.1:8000 -> 8000

curl を使用してモデルを操作する

新しいターミナル セッションで、curl を使用してモデルとチャットします。

次のコマンドの例は TGI 用です。

USER_PROMPT="Question: What is the total number of attendees with age over 30 at kubecon eu? Context: CREATE TABLE attendees (name VARCHAR, age INTEGER, kubecon VARCHAR)"

curl -X POST http://localhost:8000/generate \
  -H "Content-Type: application/json" \
  -d @- <<EOF
{
    "prompt": "${USER_PROMPT}",
    "temperature": 0.1,
    "top_p": 1.0,
    "max_tokens": 24
}
EOF

次の出力には、モデルのレスポンスの例が表示されています。

{"generated_text":" Answer: SELECT COUNT(age) FROM attendees WHERE age > 30 AND kubecon = 'eu'\n"}

クエリによっては、より良い結果を得るために max_token の変更が必要になる場合があります。指示用チューニング済みモデルを使用して、チャット エクスペリエンスを向上させることもできます。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

デプロイされたリソースを削除する

このガイドで作成したリソースについて、Google Cloud アカウントに課金されないようにするには、次のコマンドを実行します。

gcloud container clusters delete ${CLUSTER_NAME} \
  --region=${REGION}

次のステップ