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 column 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. [保存] をクリックします。
    8. モデルへのアクセス権を取得する

      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 コンソールで Cloud Shell 有効化アイコンCloud Shell をアクティブにする)をクリックして、Google Cloud コンソールで Cloud Shell セッションを起動します。これにより、 Google Cloud コンソールの下部ペインでセッションが起動します。

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

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

        次の値を置き換えます。

        • PROJECT_ID: Google Cloudのプロジェクト ID
        • REGION: 使用するアクセラレータ タイプをサポートするリージョン(たとえば、L4 GPU の場合は us-central1)。
        • CLUSTER_NAME: クラスタの名前。
        • 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 を提供できます。ワークロードに最適な GKE のオペレーション モードを選択するには、GKE のオペレーション モードを選択するをご覧ください。

      ベスト プラクティス:

      フルマネージドの Kubernetes エクスペリエンスを実現するには、Autopilot を使用します。

      Autopilot

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

      gcloud container clusters create-auto CLUSTER_NAME \
          --project=PROJECT_ID \
          --location=CONTROL_PLANE_LOCATION \
          --release-channel=rapid \
          --cluster-version=1.29
      

      次の値を置き換えます。

      • PROJECT_ID: Google Cloudのプロジェクト ID
      • CONTROL_PLANE_LOCATION: クラスタのコントロール プレーンの Compute Engine のロケーション。使用するアクセラレータ タイプをサポートするリージョン(たとえば、L4 GPU の場合は us-central1)を入力します。
      • CLUSTER_NAME: クラスタの名前。

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

      Standard

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

        gcloud container clusters create CLUSTER_NAME \
            --project=PROJECT_ID \
            --location=CONTROL_PLANE_LOCATION \
            --workload-pool=PROJECT_ID.svc.id.goog \
            --release-channel=rapid \
            --num-nodes=1
        

        次の値を置き換えます。

        • PROJECT_ID: Google Cloudのプロジェクト ID
        • CONTROL_PLANE_LOCATION: クラスタのコントロール プレーンの Compute Engine のロケーション。使用するアクセラレータ タイプをサポートするリージョン(たとえば、L4 GPU の場合は us-central1)を入力します。
        • CLUSTER_NAME: クラスタの名前。

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

      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
        

        次の値を置き換えます。

        • REGION: 使用するアクセラレータ タイプをサポートするリージョン(たとえば、L4 GPU の場合は us-central1)。
        • CLUSTER_NAME: クラスタの名前。
      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 -
        

        HF_TOKEN は、先ほど生成した Hugging Face トークンに置き換えます。

      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"
        

        PROJECT_ID は、実際の Google CloudPROJECT_ID に置き換えます。

      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 ファインチューニング ジョブをデプロイします。Kubernetes の Job コントローラは、1 つ以上の Pod を作成し、特定のタスクが正常に実行されるようにします。

      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 コンテナをデプロイします。このチュートリアルでは、Kubernetes Deployment を使用して vLLM コンテナをデプロイします。Deployment は、クラスタ内のノードに分散された Pod の複数のレプリカを実行できる Kubernetes API オブジェクトです。

      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
        

        HF_PROFILE は、前に作成した Hugging Face プロファイル ID に置き換えます。

      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
      

      次の値を置き換えます。

      • REGION: 使用するアクセラレータ タイプをサポートするリージョン(たとえば、L4 GPU の場合は us-central1)。
      • CLUSTER_NAME: クラスタの名前。

      次のステップ