1. Giới thiệu
Tổng quan
Trong lớp học lập trình này, bạn sẽ sử dụng các tác vụ Cloud Run để tinh chỉnh một mô hình Gemma 3, sau đó phân phát kết quả trên Cloud Run bằng vLLM.
Bạn sẽ thực hiện
Huấn luyện một mô hình để phản hồi một cụm từ cụ thể bằng một kết quả cụ thể bằng cách sử dụng tập dữ liệu KomeijiForce/Text2Emoji, được thiết lập trong khuôn khổ EmojiLM: Lập mô hình ngôn ngữ biểu tượng cảm xúc mới.
Sau khi được huấn luyện, mô hình sẽ phản hồi một câu có tiền tố "Dịch sang biểu tượng cảm xúc: " bằng một loạt biểu tượng cảm xúc tương ứng với câu đó.
Kiến thức bạn sẽ học được
- Cách tiến hành tinh chỉnh bằng GPU của Cloud Run Jobs
- Cách phân phát một mô hình bằng Cloud Run với vLLM
- Cách sử dụng cấu hình VPC trực tiếp cho một GPU Job để tải lên và phân phát mô hình nhanh hơn
2. Trước khi bắt đầu
Bật API
Trước khi có thể bắt đầu sử dụng lớp học lập trình này, hãy bật các API sau bằng cách chạy:
gcloud services enable run.googleapis.com \
compute.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com \
secretmanager.googleapis.com \
artifactregistry.googleapis.com
Hạn mức GPU
Xem tài liệu về Hạn mức GPU để xác nhận cách yêu cầu hạn mức.
Nếu bạn gặp phải bất kỳ lỗi nào có nội dung "Bạn không có hạn mức sử dụng GPU", hãy xác nhận hạn mức của bạn trên g.co/cloudrun/gpu-quota.
Lưu ý: Nếu đang sử dụng một dự án mới, có thể bạn sẽ phải đợi vài phút kể từ khi bật API cho đến khi hạn mức xuất hiện trên trang hạn mức.
Hugging Face
Lớp học lập trình này sử dụng một mô hình được lưu trữ trên Hugging Face. Để nhận được mô hình này, hãy yêu cầu mã truy cập người dùng Hugging Face có quyền "Đọc". Bạn sẽ tham chiếu đến thông tin này sau dưới dạng YOUR_HF_TOKEN.
Để sử dụng mô hình gemma-3-1b-it, bạn phải đồng ý với các điều khoản sử dụng.
3. Thiết lập và yêu cầu
Thiết lập các tài nguyên sau:
- Tài khoản dịch vụ IAM và các quyền IAM liên kết,
- Khoá bí mật của Secret Manager để lưu trữ mã thông báo Hugging Face,
- Bộ chứa Cloud Storage để lưu trữ mô hình được tinh chỉnh và
- Kho lưu trữ Artifact Registry để lưu trữ hình ảnh mà bạn sẽ tạo để tinh chỉnh mô hình.
- Thiết lập các biến môi trường cho lớp học lập trình này. Chúng tôi đã điền sẵn một số biến cho bạn. Chỉ định mã dự án, khu vực và mã thông báo Hugging Face.
export PROJECT_ID=<YOUR_PROJECT_ID> export REGION=<YOUR_REGION> export HF_TOKEN=<YOUR_HF_TOKEN> export NEW_MODEL=gemma-emoji export AR_REPO=codelab-finetuning-jobs export IMAGE_NAME=finetune-to-gcs export JOB_NAME=finetuning-to-gcs-job export BUCKET_NAME=$PROJECT_ID-codelab-finetuning-jobs export SECRET_ID=HF_TOKEN export SERVICE_ACCOUNT="finetune-job-sa" export SERVICE_ACCOUNT_ADDRESS=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com - Tạo tài khoản dịch vụ bằng cách chạy lệnh sau:
gcloud iam service-accounts create $SERVICE_ACCOUNT \ --display-name="Service account for fine-tuning codelab" - Sử dụng Secret Manager để lưu trữ mã truy cập Hugging Face:
gcloud secrets create $SECRET_ID \ --replication-policy="automatic" printf $HF_TOKEN | gcloud secrets versions add $SECRET_ID --data-file=- - Cấp cho tài khoản dịch vụ của bạn vai trò Secret Manager Secret Accessor:
gcloud secrets add-iam-policy-binding $SECRET_ID \ --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \ --role='roles/secretmanager.secretAccessor' - Tạo một nhóm lưu trữ mô hình được tinh chỉnh:
gcloud storage buckets create -l $REGION gs://$BUCKET_NAME - Cấp cho tài khoản dịch vụ của bạn quyền truy cập vào bộ chứa:
gcloud storage buckets add-iam-policy-binding gs://$BUCKET_NAME \ --member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \ --role=roles/storage.objectAdmin - Tạo một kho lưu trữ Artifact Registry để lưu trữ hình ảnh vùng chứa:
gcloud artifacts repositories create $AR_REPO \ --repository-format=docker \ --location=$REGION \ --description="codelab for finetuning using CR jobs" \ --project=$PROJECT_ID
4. Tạo hình ảnh của công việc Cloud Run
Trong bước tiếp theo, bạn sẽ tạo mã thực hiện những việc sau:
- Nhập mô hình Gemma từ Hugging Face
- Điều chỉnh mô hình bằng tập dữ liệu từ Hugging Face. Tác vụ này sử dụng một GPU L4 để tinh chỉnh.
- Tải mô hình đã tinh chỉnh có tên
new_modellên bộ chứa Cloud Storage
- Tạo một thư mục cho mã công việc tinh chỉnh.
mkdir codelab-finetuning-job cd codelab-finetuning-job - Tạo một tệp có tên là
finetune.py# Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import torch from datasets import load_dataset from peft import LoraConfig, PeftModel from transformers import ( AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, TrainingArguments, ) from trl import SFTTrainer # Cloud Storage bucket to upload the model bucket_name = os.getenv("BUCKET_NAME", "YOUR_BUCKET_NAME") # The model that you want to train from the Hugging Face hub model_name = os.getenv("MODEL_NAME", "google/gemma-3-1b-it") # The instruction dataset to use dataset_name = "KomeijiForce/Text2Emoji" # Fine-tuned model name new_model = os.getenv("NEW_MODEL", "gemma-emoji") ############################ Setup ############################################ # Load the entire model on the GPU 0 device_map = {"": torch.cuda.current_device()} # Limit dataset to a random selection dataset = load_dataset(dataset_name, split="train").shuffle(seed=42).select(range(1000)) # Setup input formats: trains the model to respond to "Translate to emoji:" with emoji output. tokenizer = AutoTokenizer.from_pretrained(model_name) def format_to_chat(example): return { "conversations": [ {"role": "user", "content": f"Translate to emoji: {example['text']}"}, {"role": "assistant", "content": example["emoji"]}, ] } formatted_dataset = dataset.map( format_to_chat, batched=False, # Process row by row remove_columns=dataset.column_names, # Optional: Keep only the new column ) def apply_chat_template(examples): texts = tokenizer.apply_chat_template(examples["conversations"], tokenize=False) return {"text": texts} final_dataset = formatted_dataset.map(apply_chat_template, batched=True) ############################# Config ######################################### # Load tokenizer and model with QLoRA configuration bnb_4bit_compute_dtype = "float16" # Compute dtype for 4-bit base models compute_dtype = getattr(torch, bnb_4bit_compute_dtype) bnb_config = BitsAndBytesConfig( load_in_4bit=True, # Activate 4-bit precision base model loading bnb_4bit_quant_type="nf4", # Quantization type (fp4 or nf4) bnb_4bit_compute_dtype=compute_dtype, bnb_4bit_use_double_quant=False, # Activate nested quantization for 4-bit base models (double quantization) ) # Load base model model = AutoModelForCausalLM.from_pretrained( model_name, quantization_config=bnb_config, device_map=device_map, torch_dtype=torch.float16, ) model.config.use_cache = False model.config.pretraining_tp = 1 ############################## Train ########################################## # Load LoRA configuration peft_config = LoraConfig( lora_alpha=16, # Alpha parameter for LoRA scaling lora_dropout=0.1, # Dropout probability for LoRA layers, r=8, # LoRA attention dimension bias="none", task_type="CAUSAL_LM", target_modules=["q_proj", "v_proj"], ) # Set training parameters training_arguments = TrainingArguments( output_dir="./results", num_train_epochs=1, per_device_train_batch_size=1, # Batch size per GPU for training gradient_accumulation_steps=2, # Number of update steps to accumulate the gradients for optim="paged_adamw_32bit", save_steps=0, logging_steps=5, learning_rate=2e-4, # Initial learning rate (AdamW optimizer) weight_decay=0.001, # Weight decay to apply to all layers except bias/LayerNorm weights fp16=True, bf16=False, # Enable fp16/bf16 training max_grad_norm=0.3, # Maximum gradient normal (gradient clipping) warmup_ratio=0.03, # Ratio of steps for a linear warmup (from 0 to learning rate) group_by_length=True, # Group sequences into batches with same length # Saves memory and speeds up training considerably lr_scheduler_type="cosine", ) trainer = SFTTrainer( model=model, train_dataset=final_dataset, peft_config=peft_config, dataset_text_field="text", max_seq_length=512, # Maximum sequence length to use tokenizer=tokenizer, args=training_arguments, packing=False, # Pack multiple short examples in the same input sequence to increase efficiency ) trainer.train() trainer.model.save_pretrained(new_model) ################################# Save ######################################## # Reload model in FP16 and merge it with LoRA weights base_model = AutoModelForCausalLM.from_pretrained( model_name, low_cpu_mem_usage=True, return_dict=True, torch_dtype=torch.float16, device_map=device_map, ) model = PeftModel.from_pretrained(base_model, new_model) model = model.merge_and_unload() # push results to Cloud Storage file_path_to_save_the_model = "/finetune/new_model" model.save_pretrained(file_path_to_save_the_model) tokenizer.save_pretrained(file_path_to_save_the_model) - Tạo tệp
requirements.txt:accelerate==0.34.2 bitsandbytes==0.45.5 datasets==2.19.1 transformers==4.51.3 peft==0.11.1 trl==0.8.6 torch==2.3.0 - Tạo một
Dockerfile:FROM nvidia/cuda:12.6.2-runtime-ubuntu22.04 RUN apt-get update && \ apt-get -y --no-install-recommends install python3-dev gcc python3-pip git && \ rm -rf /var/lib/apt/lists/* COPY requirements.txt /requirements.txt RUN pip3 install -r requirements.txt --no-cache-dir COPY finetune.py /finetune.py ENV PYTHONUNBUFFERED 1 CMD python3 /finetune.py --device cuda - Tạo vùng chứa trong kho lưu trữ Artifact Registry:
gcloud builds submit \ --tag $REGION-docker.pkg.dev/$PROJECT_ID/$AR_REPO/$IMAGE_NAME \ --region $REGION
5. Triển khai và thực thi lệnh
Ở bước này, bạn sẽ tạo công việc có lưu lượng truy cập trực tiếp ra khỏi VPC để tải lên Google Cloud Storage nhanh hơn.
- Tạo Cloud Run Job:
gcloud run jobs create $JOB_NAME \ --region $REGION \ --image $REGION-docker.pkg.dev/$PROJECT_ID/$AR_REPO/$IMAGE_NAME \ --set-env-vars BUCKET_NAME=$BUCKET_NAME \ --set-secrets HF_TOKEN=$SECRET_ID:latest \ --cpu 8.0 \ --memory 32Gi \ --gpu 1 \ --add-volume name=finetuned_model,type=cloud-storage,bucket=$BUCKET_NAME \ --add-volume-mount volume=finetuned_model,mount-path=/finetune/new_model \ --service-account $SERVICE_ACCOUNT_ADDRESS - Thực thi lệnh:
gcloud run jobs execute $JOB_NAME --region $REGION --async
Bạn sẽ mất khoảng 10 phút để hoàn tất công việc này. Bạn có thể kiểm tra trạng thái bằng đường liên kết có trong đầu ra của lệnh cuối cùng.
6. Sử dụng dịch vụ Cloud Run để phân phát mô hình được tinh chỉnh bằng vLLM
Ở bước này, bạn sẽ triển khai một dịch vụ Cloud Run. Cấu hình này sử dụng VPC trực tiếp để truy cập vào bộ chứa Cloud Storage qua mạng riêng để tải xuống nhanh hơn.
- Triển khai Dịch vụ Cloud Run:
gcloud run deploy serve-gemma-emoji \ --image us-docker.pkg.dev/vertex-ai/vertex-vision-model-garden-dockers/pytorch-vllm-serve:20250601_0916_RC01 \ --region $REGION \ --port 8000 \ --set-env-vars MODEL_ID=new_model,HF_HUB_OFFLINE=1 \ --cpu 8.0 \ --memory 32Gi \ --gpu 1 \ --add-volume name=finetuned_model,type=cloud-storage,bucket=$BUCKET_NAME \ --add-volume-mount volume=finetuned_model,mount-path=/finetune/new_model \ --service-account $SERVICE_ACCOUNT_ADDRESS \ --max-instances 1 \ --command python3 \ --args="-m,vllm.entrypoints.api_server,--model=/finetune/new_model,--tensor-parallel-size=1" \ --no-gpu-zonal-redundancy \ --labels=dev-tutorial=codelab-tuning \ --no-invoker-iam-check
7. Kiểm thử mô hình được tinh chỉnh
Trong bước này, bạn sẽ nhắc mô hình kiểm thử quy trình tinh chỉnh bằng cách sử dụng curl.
- Lấy URL dịch vụ cho dịch vụ Cloud Run của bạn:
SERVICE_URL=$(gcloud run services describe serve-gemma-emoji \ --region $REGION --format 'value(status.url)') - Tạo câu lệnh cho mô hình của bạn.
USER_PROMPT="Translate to emoji: I ate a banana for breakfast, later I'm thinking of having soup!" - Gọi dịch vụ của bạn bằng curl để nhắc mô hình, lọc kết quả bằng jq:
curl -s -X POST ${SERVICE_URL}/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: bearer $(gcloud auth print-identity-token)" \ -d @- <<EOF | jq ".choices[0].message.content" { "model": "${NEW_MODEL}", "messages": [{ "role": "user", "content": [ { "type": "text", "text": "${USER_PROMPT}"}] }] } EOF
Bạn sẽ thấy một phản hồi tương tự như sau:
🍌🤔😋🥣
8. Xin chúc mừng!
Chúc mừng bạn đã hoàn thành lớp học lập trình này!
Bạn nên xem tài liệu về GPU của Cloud Run Jobs.
Nội dung đã đề cập
- Cách tiến hành tinh chỉnh bằng GPU của Cloud Run Jobs
- Cách phân phát một mô hình bằng Cloud Run với vLLM
- Cách sử dụng cấu hình VPC trực tiếp cho một GPU Job để tải lên và phân phát mô hình nhanh hơn
9. Dọn dẹp
Để tránh bị tính phí ngoài ý muốn, chẳng hạn như nếu các dịch vụ Cloud Run được gọi nhiều lần hơn hạn mức gọi Cloud Run hằng tháng của bạn trong bậc miễn phí, bạn có thể xoá dịch vụ Cloud Run mà bạn đã tạo ở Bước 6.
Để xoá dịch vụ Cloud Run, hãy truy cập Cloud Console của Cloud Run tại https://console.cloud.google.com/run rồi xoá dịch vụ serve-gemma-emoji.
Để xoá toàn bộ dự án, hãy chuyển đến phần Quản lý tài nguyên, chọn dự án bạn đã tạo ở Bước 2 rồi chọn Xoá. Nếu xoá dự án, bạn sẽ cần thay đổi dự án trong Cloud SDK. Bạn có thể xem danh sách tất cả các dự án có sẵn bằng cách chạy gcloud projects list.