在 GKE 上使用多個 GPU 微調 Gemma 開放式模型

本教學課程說明如何使用 Hugging FaceTransformers 程式庫,在 Google Kubernetes Engine (GKE) 上,透過繪圖處理單元 (GPU) 微調 Gemma 大型語言模型 (LLM) 系列的開放模型。微調是監督式學習程序,可透過新資料集更新預先訓練模型的參數,提升模型執行特定工作的能力。在本教學課程中,您會從 Hugging Face 下載 20 億參數的預先訓練 Gemma 系列模型,並在 GKE AutopilotStandard 叢集上微調這些模型。

如果您需要代管型 Kubernetes 的精細控制、擴充性、復原能力、可攜性和成本效益,以便微調 LLM,這份指南是很好的入門資源。

最佳做法

如果您需要統合式管理 AI 平台,以經濟實惠的方式快速建構及提供機器學習模型,請試用 Vertex AI 解決方案。

背景

在 GKE 上使用 GPU 和 Transformers 程式庫提供 Gemma 服務,即可導入可用於正式環境的穩固推論服務解決方案,同時享有代管型 Kubernetes 的所有優點,包括高效率的擴充能力和更高的可用性。本節說明本指南中使用的重要技術。

Gemma

Gemma 是一組開放式輕量級生成式人工智慧 (AI) 模型,以開放授權形式發布。這些 AI 模型可在應用程式、硬體、行動裝置或代管服務中執行。

本指南將介紹如何使用 Gemma 生成文字。您也可以調整這些模型,讓模型專門執行特定工作。

本文使用的資料集為 b-mc2/sql-create-context

詳情請參閱 Gemma 說明文件

GPU

GPU 可加速處理節點上執行的特定工作負載,例如機器學習和資料處理。GKE 提供各種機器類型選項,可供節點設定使用,包括搭載 NVIDIA H100、L4 和 A100 GPU 的機器類型。

在 GKE 中使用 GPU 前,建議先完成下列學習路徑:

  1. 瞭解目前可用的 GPU 版本
  2. 瞭解 GKE 中的 GPU

Hugging Face Transformers

您可以使用 Hugging Face 的 Transformers 程式庫,存取最先進的預先訓練模型。Transformers 程式庫可協助您減少完整模型訓練所需的時間、資源和運算成本。

在本教學課程中,您將使用 Hugging Face API 和工具下載及微調這些預先訓練模型。

取得模型存取權

如要存取 Gemma 模型並部署至 GKE,請先簽署授權同意聲明,然後產生 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. 選取「產生權杖」
  5. 將產生的權杖複製到剪貼簿。

準備環境

在本教學課程中,您將使用 Cloud Shell 管理Google Cloud上託管的資源。Cloud Shell 已預先安裝本教學課程所需的軟體,包括 kubectl gcloud CLI

如要使用 Cloud Shell 設定環境,請按照下列步驟操作:

  1. 在 Google Cloud 控制台中,按一下Cloud Shell 啟用圖示Google Cloud 控制台中的「啟用 Cloud Shell」,啟動 Cloud Shell 工作階段。系統會在 Google Cloud 控制台的底部窗格啟動工作階段。

  2. 設定預設環境變數:

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

    替換下列值:

    • PROJECT_ID:您的 Google Cloud 專案 ID
    • CONTROL_PLANE_LOCATION:叢集控制層的 Compute Engine 區域。提供支援您要使用加速器類型的區域,例如 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 或 Standard 叢集的 GPU 上提供 Gemma 服務。如要為工作負載選擇最合適的 GKE 作業模式,請參閱「選擇 GKE 作業模式」。

最佳做法

使用 Autopilot 模式,享受全代管的 Kubernetes 服務。

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 叢集。

標準

  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=CONTROL_PLANE_LOCATION \
        --node-locations=CONTROL_PLANE_LOCATION-a \
        --cluster=CLUSTER_NAME \
        --machine-type=g2-standard-96 \
        --num-nodes=1
    

    GKE 會為每個節點建立一個節點集區,內含兩個 L4 GPU。

為 Hugging Face 憑證建立 Kubernetes 密鑰

在 Cloud Shell 中執行下列操作:

  1. 設定 kubectl 與叢集通訊:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION
    

    替換下列值:

    • CONTROL_PLANE_LOCATION:叢集控制層的 Compute Engine區域
    • 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 替換為專案 ID。 Google Cloud

  2. 建構並推送映像檔:

    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 控制器會建立一或多個 Pod,並確保這些 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. 執行下列指令來監控 Job:

    watch kubectl get pods
    
  4. 執行下列指令,檢查工作記錄:

    kubectl logs job.batch/finetune-job -f
    

    Job 資源會下載模型資料,然後在所有八個 GPU 中微調模型。這項程序最多可能需要 20 分鐘的時間。

  5. 作業完成後,請前往 Hugging Face 帳戶。Hugging Face 個人資料中會顯示名為「HF_PROFILE/gemma-2b-sql-finetuned」的新模型。

在 GKE 上提供微調模型

在本節中,您將部署 vLLM 容器來提供 Gemma 模型。本教學課程使用 Kubernetes Deployment 部署 vLLM 容器。Deployment 是 Kubernetes API 物件,可讓您執行多個 Pod 副本,並將這些副本分散到叢集中的節點。

  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: docker.io/vllm/vllm-openai:v0.10.0
            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.openai.api_server"]
            args:
            - --model=$(MODEL_ID)
            - --tensor-parallel-size=1
            env:
            - name: LD_LIBRARY_PATH
              value: ${LD_LIBRARY_PATH}:/usr/local/nvidia/lib64
            - 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. 等待部署作業完成:

    kubectl wait --for=condition=Available --timeout=700s deployment/vllm-gemma-deployment
    
  6. 查看執行中 Deployment 的記錄:

    kubectl logs -f -l app=gemma-server
    

部署資源會下載模型資料。這項程序會在幾分鐘內完成。輸出結果會與下列內容相似:

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 才能獲得更準確的結果。您也可以使用指令調整模型,獲得更優質的對話體驗。