Tutorial ini menunjukkan cara melakukan penyesuaian model bahasa besar (LLM) Gemma 3 di cluster GKE multi-GPU dan multi-node di Google Cloud. Cluster ini menggunakan instance virtual machine (VM) A4 yang memiliki 8 GPU NVIDIA B200.
Dua proses utama yang dijelaskan dalam tutorial ini adalah sebagai berikut:
- Deploy cluster GKE berperforma tinggi menggunakan GKE Autopilot. Sebagai bagian dari deployment ini, Anda akan membuat image VM kustom dengan software yang diperlukan sudah diinstal sebelumnya.
- Setelah cluster di-deploy, Anda menjalankan tugas penyesuaian terdistribusi dengan menggunakan kumpulan skrip yang menyertai tutorial ini. Tugas ini memanfaatkan library Hugging Face Accelerate.
Tutorial ini ditujukan untuk engineer, peneliti, administrator, dan operator platform machine learning (ML), serta spesialis data dan AI yang tertarik untuk men-deploy cluster GKE di Google Cloud untuk melatih LLM.
Tujuan
Akses model Gemma 3 menggunakan Hugging Face.
Siapkan lingkungan Anda.
Buat dan deploy cluster GKE A4.
Sesuaikan model Gemma 3 menggunakan library Hugging Face Accelerate dengan paralel data yang sepenuhnya di-shard (FSDP).
Pantau tugas Anda.
Jalankan pembersihan.
Biaya
Dalam dokumen ini, Anda akan menggunakan komponen Google Cloudyang dapat ditagih berikut:
Untuk membuat perkiraan biaya berdasarkan proyeksi penggunaan Anda,
gunakan kalkulator harga.
Sebelum memulai
- Login ke akun Google Cloud Anda. Jika Anda baru menggunakan Google Cloud, buat akun untuk mengevaluasi performa produk kami dalam skenario dunia nyata. Pelanggan baru juga mendapatkan kredit gratis senilai $300 untuk menjalankan, menguji, dan men-deploy workload.
-
Instal Google Cloud CLI.
-
Jika Anda menggunakan penyedia identitas (IdP) eksternal, Anda harus login ke gcloud CLI dengan identitas gabungan Anda terlebih dahulu.
-
Untuk melakukan inisialisasi gcloud CLI, jalankan perintah berikut:
gcloud init -
Buat atau pilih Google Cloud project.
Peran yang diperlukan untuk memilih atau membuat project
- Pilih project: Memilih project tidak memerlukan peran IAM tertentu—Anda dapat memilih project mana pun yang telah diberi peran.
-
Membuat project: Untuk membuat project, Anda memerlukan peran Pembuat Project
(
roles/resourcemanager.projectCreator), yang berisi izinresourcemanager.projects.create. Pelajari cara memberikan peran.
-
Buat Google Cloud project:
gcloud projects create PROJECT_ID
Ganti
PROJECT_IDdengan nama untuk Google Cloud project yang Anda buat. -
Pilih project Google Cloud yang Anda buat:
gcloud config set project PROJECT_ID
Ganti
PROJECT_IDdengan nama project Google Cloud Anda.
-
Verifikasi bahwa penagihan diaktifkan untuk project Google Cloud Anda.
Aktifkan API yang diperlukan:
Peran yang diperlukan untuk mengaktifkan API
Untuk mengaktifkan API, Anda memerlukan peran IAM Service Usage Admin (
roles/serviceusage.serviceUsageAdmin), yang berisi izinserviceusage.services.enable. Pelajari cara memberikan peran.gcloud services enable gcloud services enable compute.googleapis.com container.googleapis.com file.googleapis.com logging.googleapis.com cloudresourcemanager.googleapis.com servicenetworking.googleapis.com
-
Instal Google Cloud CLI.
-
Jika Anda menggunakan penyedia identitas (IdP) eksternal, Anda harus login ke gcloud CLI dengan identitas gabungan Anda terlebih dahulu.
-
Untuk melakukan inisialisasi gcloud CLI, jalankan perintah berikut:
gcloud init -
Buat atau pilih Google Cloud project.
Peran yang diperlukan untuk memilih atau membuat project
- Pilih project: Memilih project tidak memerlukan peran IAM tertentu—Anda dapat memilih project mana pun yang telah diberi peran.
-
Membuat project: Untuk membuat project, Anda memerlukan peran Pembuat Project
(
roles/resourcemanager.projectCreator), yang berisi izinresourcemanager.projects.create. Pelajari cara memberikan peran.
-
Buat Google Cloud project:
gcloud projects create PROJECT_ID
Ganti
PROJECT_IDdengan nama untuk Google Cloud project yang Anda buat. -
Pilih project Google Cloud yang Anda buat:
gcloud config set project PROJECT_ID
Ganti
PROJECT_IDdengan nama project Google Cloud Anda.
-
Verifikasi bahwa penagihan diaktifkan untuk project Google Cloud Anda.
Aktifkan API yang diperlukan:
Peran yang diperlukan untuk mengaktifkan API
Untuk mengaktifkan API, Anda memerlukan peran IAM Service Usage Admin (
roles/serviceusage.serviceUsageAdmin), yang berisi izinserviceusage.services.enable. Pelajari cara memberikan peran.gcloud services enable gcloud services enable compute.googleapis.com container.googleapis.com file.googleapis.com logging.googleapis.com cloudresourcemanager.googleapis.com servicenetworking.googleapis.com
-
Memberikan peran ke akun pengguna Anda. Jalankan perintah berikut satu kali untuk setiap peran IAM berikut:
roles/compute.admin, roles/iam.serviceAccountUser, roles/cloudbuild.builds.editor, roles/artifactregistry.admin, roles/storage.admin, roles/serviceusage.serviceUsageAdmingcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
Ganti kode berikut:
PROJECT_ID: Project ID Anda.USER_IDENTIFIER: ID untuk akun pengguna Anda. Misalnya,myemail@example.com.ROLE: Peran IAM yang Anda berikan ke akun pengguna Anda.
- Aktifkan akun layanan default untuk project Google Cloud Anda:
gcloud iam service-accounts enable PROJECT_NUMBER-compute@developer.gserviceaccount.com \ --project=PROJECT_ID
Ganti PROJECT_NUMBER dengan nomor project Anda. Untuk meninjau nomor project Anda, lihat Mendapatkan project yang sudah ada.
- Berikan peran Editor (
roles/editor) ke akun layanan default:gcloud projects add-iam-policy-binding PROJECT_ID \ --member="serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com" \ --role=roles/editor
- Buat kredensial autentikasi lokal untuk akun pengguna Anda:
gcloud auth application-default login
- Aktifkan Login OS untuk project Anda:
gcloud compute project-info add-metadata --metadata=enable-oslogin=TRUE
- Login atau buat akun Hugging Face.
Mengakses Gemma 3 menggunakan Hugging Face
Untuk menggunakan Hugging Face guna mengakses Gemma 3, lakukan langkah-langkah berikut:
- Login ke Hugging Face
- Buat token akses
readHugging Face.
Klik Profil Anda > Setelan > Token akses > +Buat token baru - Salin dan simpan nilai token
read access. Anda akan menggunakannya nanti dalam tutorial ini.
Menyiapkan lingkungan Anda
Untuk menyiapkan lingkungan Anda, tetapkan hal berikut:
gcloud config set project PROJECT_NAME
gcloud config set billing/quota_project PROJECT_NAME
export RESERVATION=YOUR_RESERVATION_ID
export PROJECT_ID=$(gcloud config get project)
export REGION=CLUSTER_REGION
export CLUSTER_NAME=CLUSTER_NAME
export HF_TOKEN=YOUR_TOKEN
export NETWORK=default
Ganti kode berikut:
PROJECT_NAME: nama Google Cloud project tempat Anda ingin membuat cluster GKE.YOUR_RESERVATION_ID: ID untuk kapasitas yang dipesan.CLUSTER_REGION: region tempat Anda ingin membuat cluster GKE. Anda hanya dapat membuat cluster di region tempat reservasi Anda berada.CLUSTER_NAME: nama cluster GKE yang akan dibuat.HF_TOKEN: token akses Hugging Face yang Anda buat di bagian sebelumnya.
Membuat cluster GKE dalam mode Autopilot
Untuk membuat cluster GKE dalam mode Autopilot, jalankan perintah berikut:
gcloud container clusters create-auto ${CLUSTER_NAME} \
--project=${PROJECT_ID} \
--location=${REGION} \
--release-channel=rapid
Mungkin perlu waktu beberapa saat untuk menyelesaikan pembuatan cluster GKE. Untuk memverifikasi bahwa Google Cloud telah selesai membuat cluster Anda, buka Kubernetes clusters di konsol Google Cloud .
Buat secret Kubernetes untuk kredensial Hugging Face
Untuk membuat secret Kubernetes untuk kredensial Hugging Face, ikuti langkah-langkah berikut:
Konfigurasi
kubectluntuk berkomunikasi dengan cluster GKE Anda:gcloud container clusters get-credentials $CLUSTER_NAME \ --location=$REGIONBuat secret Kubernetes untuk menyimpan token Hugging Face Anda:
gcloud container clusters get-credentials ${CLUSTER_NAME} \ --location=${REGION} kubectl create secret generic hf-secret \ --from-literal=hf_api_token=${HF_TOKEN} \ --dry-run=client -o yaml | kubectl apply -f -
Siapkan workload Anda
Untuk menyiapkan workload, Anda perlu melakukan hal berikut:
Membuat skrip beban kerja
Untuk membuat skrip yang digunakan workload fine-tuning Anda, lakukan hal berikut:
Buat direktori untuk skrip beban kerja. Gunakan direktori ini sebagai direktori kerja Anda.
mkdir llm-finetuning-gemma cd llm-finetuning-gemmaBuat file
cloudbuild.yamluntuk menggunakan Google Cloud Build. File ini membuat container workload Anda dan menyimpannya di Artifact Registry:steps: - name: 'gcr.io/cloud-builders/docker' args: [ 'build', '-t', 'us-docker.pkg.dev/$PROJECT_ID/gemma/finetune-gemma-gpu:1.0.0', '.' ] images: - 'us-docker.pkg.dev/$PROJECT_ID/gemma/finetune-gemma-gpu:1.0.0'Buat file
Dockerfileuntuk menjalankan tugas penyesuaian:FROM nvidia/cuda:12.8.1-cudnn-devel-ubuntu24.04 RUN apt-get update && \ apt-get -y install python3 python3-dev gcc python3-pip python3-venv git curl vim RUN python3 -m venv /opt/venv ENV PATH="/opt/venv/bin:/usr/local/nvidia/bin:$PATH" ENV LD_LIBRARY_PATH="/usr/local/nvidia/lib64:$LD_LIBRARY_PATH" RUN pip3 install setuptools wheel packaging ninja RUN pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128 RUN pip3 install \ transformers==4.53.3 \ datasets==4.0.0 \ accelerate==1.9.0 \ evaluate==0.4.5 \ bitsandbytes==0.46.1 \ trl==0.19.1 \ peft==0.16.0 \ tensorboard==2.20.0 \ protobuf==6.31.1 \ sentencepiece==0.2.0 COPY finetune.py /finetune.py COPY accel_fsdp_gemma3_config.yaml /accel_fsdp_gemma3_config.yaml CMD accelerate launch --config_file accel_fsdp_gemma3_config.yaml finetune.pyBuat file
accel_fsdp_gemma3_config.yaml. File konfigurasi ini mengarahkan Hugging Face Accelerate untuk membagi tugas penyesuaian di beberapa GPU.compute_environment: LOCAL_MACHINE debug: false distributed_type: FSDP downcast_bf16: 'no' enable_cpu_affinity: false fsdp_config: fsdp_activation_checkpointing: false fsdp_auto_wrap_policy: TRANSFORMER_BASED_WRAP fsdp_cpu_ram_efficient_loading: true fsdp_offload_params: false fsdp_reshard_after_forward: true fsdp_state_dict_type: FULL_STATE_DICT fsdp_transformer_layer_cls_to_wrap: Gemma3DecoderLayer fsdp_version: 2 machine_rank: 0 main_training_function: main mixed_precision: bf16 num_machines: 1 num_processes: 8 rdzv_backend: static same_network: true tpu_env: [] tpu_use_cluster: false tpu_use_sudo: false use_cpu: falseBuat file
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 command: ["accelerate","launch"] args: - "--config_file" - "accel_fsdp_gemma3_config.yaml" - "finetune.py" - "--model_id" - "google/gemma-3-12b-pt" - "--output_dir" - "gemma-12b-text-to-sql" - "--per_device_train_batch_size" - "8" - "--gradient_accumulation_steps" - "8" - "--num_train_epochs" - "3" - "--learning_rate" - "1e-5" - "--save_strategy" - "steps" - "--save_steps" - "100" resources: limits: nvidia.com/gpu: "8" env: - 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-b200 cloud.google.com/reservation-name: $RESERVATION cloud.google.com/reservation-affinity: "specific" cloud.google.com/gke-gpu-driver-version: latest restartPolicy: OnFailureBuat file
finetune.py:import torch import argparse import subprocess from datasets import load_dataset from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig, AutoConfig from peft import LoraConfig, prepare_model_for_kbit_training, get_peft_model from trl import SFTTrainer, SFTConfig from huggingface_hub import login def get_args(): parser = argparse.ArgumentParser() parser.add_argument("--model_id", type=str, default="google/gemma-3-12b-pt", help="Hugging Face model ID") parser.add_argument("--hf_token", type=str, default=None, help="Hugging Face token for private models") parser.add_argument("--trust_remote", type=bool, default="False", help="Trust remote code when loading tokenizer") parser.add_argument("--use_fast", type=bool, default="True", help="Determines if a fast Rust-based tokenizer should be used") parser.add_argument("--dataset_name", type=str, default="philschmid/gretel-synthetic-text-to-sql", help="Hugging Face dataset name") parser.add_argument("--output_dir", type=str, default="gemma-12b-text-to-sql", help="Directory to save model checkpoints") # LoRA arguments parser.add_argument("--lora_r", type=int, default=16, help="LoRA attention dimension") parser.add_argument("--lora_alpha", type=int, default=16, help="LoRA alpha scaling factor") parser.add_argument("--lora_dropout", type=float, default=0.05, help="LoRA dropout probability") # SFTConfig arguments parser.add_argument("--max_seq_length", type=int, default=512, help="Maximum sequence length") parser.add_argument("--num_train_epochs", type=int, default=3, help="Number of training epochs") parser.add_argument("--per_device_train_batch_size", type=int, default=8, help="Batch size per device during training") parser.add_argument("--gradient_accumulation_steps", type=int, default=1, help="Gradient accumulation steps") parser.add_argument("--learning_rate", type=float, default=1e-5, help="Learning rate") parser.add_argument("--logging_steps", type=int, default=10, help="Log every X steps") parser.add_argument("--save_strategy", type=str, default="steps", help="Checkpoint save strategy") parser.add_argument("--save_steps", type=int, default=100, help="Save checkpoint every X steps") parser.add_argument("--push_to_hub", action='store_true', help="Push model back up to HF") parser.add_argument("--hub_private_repo", type=bool, default="True", help="Push to a private repo") return parser.parse_args() def main(): args = get_args() # --- 1. Setup and Login --- if args.hf_token: login(args.hf_token) # --- 2. Create and prepare the fine-tuning dataset --- # The `create_conversation` function is no longer needed. # The SFTTrainer will use the `formatting_func` to apply the chat template. dataset = load_dataset(args.dataset_name, split="train") dataset = dataset.shuffle().select(range(12500)) dataset = dataset.train_test_split(test_size=2500/12500) # --- 3. Configure Model and Tokenizer --- if torch.cuda.is_available() and torch.cuda.get_device_capability()[0] >= 8: torch_dtype_obj = torch.bfloat16 torch_dtype_str = "bfloat16" else: torch_dtype_obj = torch.float16 torch_dtype_str = "float16" tokenizer = AutoTokenizer.from_pretrained(args.model_id, trust_remote_code=args.trust_remote, use_fast=args.use_fast) tokenizer.pad_token = tokenizer.eos_token gemma_chat_template = ( "" "" ) tokenizer.chat_template = gemma_chat_template # --- 4. Define the Formatting Function --- # This function will be used by the SFTTrainer to format each sample # from the dataset into the correct chat template format. def formatting_func(example): # The create_conversation logic is now implicitly handled by this. # We need to construct the messages list here. system_message = "You are a text to SQL query translator. Users will ask you questions in English and you will generate a SQL query based on the provided SCHEMA." user_prompt = "Given the <USER_QUERY> and the <SCHEMA>, generate the corresponding SQL command to retrieve the desired data, considering the query's syntax, semantics, and schema constraints.\n\n<SCHEMA>\n{context}\n</SCHEMA>\n\n<USER_QUERY>\n{question}\n</USER_QUERY>\n" messages = [ {"role": "user", "content": user_prompt.format(question=example["sql_prompt"][0], context=example["sql_context"][0])}, {"role": "assistant", "content": example["sql"][0]} ] return tokenizer.apply_chat_template(messages, tokenize=False) # --- 5. Load Model and Apply PEFT --- config = AutoConfig.from_pretrained(args.model_id) config.use_cache = False # We'll be loading this model full precision because we're planning to do FSDP # Load the base model with quantization print("Loading base model...") model = AutoModelForCausalLM.from_pretrained( args.model_id, config=config, attn_implementation="eager", torch_dtype=torch_dtype_obj, ) # Prepare the model for k-bit training model = prepare_model_for_kbit_training(model) # Configure LoRA. peft_config = LoraConfig( lora_alpha=args.lora_alpha, lora_dropout=args.lora_dropout, r=args.lora_r, bias="none", target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"], task_type="CAUSAL_LM", ) # Apply the PEFT config to the model print("Applying PEFT configuration...") model = get_peft_model(model, peft_config) model.print_trainable_parameters() # --- 6. Configure Training Arguments --- training_args = SFTConfig( output_dir=args.output_dir, max_seq_length=args.max_seq_length, num_train_epochs=args.num_train_epochs, per_device_train_batch_size=args.per_device_train_batch_size, gradient_accumulation_steps=args.gradient_accumulation_steps, learning_rate=args.learning_rate, logging_steps=args.logging_steps, save_strategy=args.save_strategy, save_steps=args.save_steps, packing=False, label_names=["domain"], gradient_checkpointing=True, gradient_checkpointing_kwargs={"use_reentrant": False}, optim="adamw_torch", fp16=True if torch_dtype_obj == torch.float16 else False, bf16=True if torch_dtype_obj == torch.bfloat16 else False, max_grad_norm=0.3, warmup_ratio=0.03, lr_scheduler_type="constant", push_to_hub=True, report_to="tensorboard", dataset_kwargs={ "add_special_tokens": False, "append_concat_token": True, } ) # --- 7. Create Trainer and Start Training --- trainer = SFTTrainer( model=model, args=training_args, train_dataset=dataset["train"], eval_dataset=dataset["test"], formatting_func=formatting_func, ) print("Starting training...") trainer.train() print("Training finished.") # --- 8. Save the final model --- print(f"Saving final model to {args.output_dir}") model.cpu() trainer.save_model(args.output_dir) torch.distributed.destroy_process_group() if __name__ == "__main__": main()
Menggunakan Docker dan Cloud Build untuk membuat container penyesuaian
Buat Repositori Docker Artifact Registry:
gcloud artifacts repositories create gemma \ --project=${PROJECT_ID} \ --repository-format=docker \ --location=us \ --description="Gemma Repo"Di direktori
llm-finetuning-gemmayang Anda buat pada langkah sebelumnya, jalankan perintah berikut untuk membuat container penyesuaian dan mengirimkannya ke Artifact Registry.gcloud builds submit .Ekspor URL gambar. Anda akan menggunakannya pada langkah selanjutnya dalam tutorial ini:
export IMAGE_URL=us-docker.pkg.dev/${PROJECT_ID}/gemma/finetune-gemma-gpu:1.0.0
Mulai workload penyesuaian Anda
Untuk memulai workload penyesuaian, lakukan hal berikut:
Terapkan manifes penyesuaian untuk membuat tugas penyesuaian:
envsubst < finetune.yaml | kubectl apply -f -Karena Anda menggunakan cluster dalam mode GKE Autopilot, node yang mendukung GPU mungkin memerlukan waktu beberapa menit untuk dimulai.
Pantau tugas dengan menjalankan perintah berikut:
ewatch kubectl get podsPeriksa log tugas dengan menjalankan perintah berikut:
kubectl logs job.batch/finetune-job -fResource tugas mendownload data model, lalu menyetel model secara halus di semua delapan GPU. Proses download akan selesai dalam waktu sekitar lima menit. Setelah download selesai, proses penyesuaian memerlukan waktu sekitar dua jam 30 menit untuk diselesaikan.
Memantau workload Anda
Anda dapat memantau penggunaan GPU di cluster GKE untuk memverifikasi bahwa tugas penyesuaian Anda berjalan secara efisien. Untuk melakukannya, buka link berikut di browser Anda:
https://console.cloud.google.com/kubernetes/clusters/details/us-central1/[CLUSTER_NAME]/observability?mods=monitoring_api_prod&project=[YOUR_PROJECT_ID]]&pageState=("timeRange":("duration":"PT1H"),"nav":("section":"gpu"),"groupBy":("groupByType":"namespacesTop5"))
Saat memantau workload, Anda dapat melihat hal berikut:
- Penggunaan GPU: untuk tugas penyesuaian yang berjalan lancar, Anda dapat melihat penggunaan semua 8 GPU Anda meningkat dan stabil ke tingkat yang tinggi selama pelatihan.
- Durasi tugas: tugas akan memerlukan waktu sekitar 10 menit untuk diselesaikan di cluster A4 yang ditentukan.
Pembersihan
Agar tidak perlu membayar biaya pada akun Google Cloud Anda untuk resource yang digunakan dalam tutorial ini, hapus project yang berisi resource tersebut, atau simpan project dan hapus setiap resource.
Menghapus project Anda
Menghapus Google Cloud project:
gcloud projects delete PROJECT_ID
Menghapus resource
Untuk menghapus tugas penyesuaian, jalankan perintah berikut:
kubectl delete job finetune-jobUntuk menghapus cluster GKE, jalankan perintah berikut:
gcloud container clusters delete $CLUSTER_NAME \ --region=$REGION