1. Giriş
Genel Bakış
Bu codelab'de, bir Gemma modelinde ince ayar yapmak için Cloud Run işlerini kullanacak ve ardından sonucu vLLM kullanarak Cloud Run'da yayınlayacaksınız.
Bu kod laboratuvarının amacı doğrultusunda, doğal dilde soru sorulduğunda LLM'nin SQL sorgusuyla yanıt vermesini sağlamak için bir metinden SQL'ye veri kümesi kullanacaksınız.
Neler öğreneceksiniz?
- Cloud Run Jobs GPU'yu kullanarak hassas ayarlama yapma
- vLLM ile Cloud Run'u kullanarak model yayınlama
- Modelin daha hızlı yüklenmesi ve sunulması için GPU işi için doğrudan VPC yapılandırması nasıl kullanılır?
2. Başlamadan önce
API'leri etkinleştir
Bu kod laboratuvarını kullanmaya başlamadan önce aşağıdaki API'leri etkinleştirmek için:
gcloud services enable run.googleapis.com \
compute.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com \
secretmanager.googleapis.com \
artifactregistry.googleapis.com
GPU Kotası
Desteklenen bir bölge için kota artışı isteğinde bulunun. Cloud Run Admin API kapsamındaki kota nvidia_l4_gpu_allocation_no_zonal_redundancy
'tür.
Not: Yeni bir proje kullanıyorsanız API'nin etkinleştirilmesi ile kotaların bu sayfada görünmesi arasında birkaç dakika geçebilir.
Kucak açan yüz
Bu codelab'de, Hugging Face'ta barındırılan bir model kullanılır. Bu modeli almak için "Okuma" izniyle Hugging Face kullanıcı erişim jetonunu isteyin. Buna daha sonra YOUR_HF_TOKEN
olarak referans vereceksiniz.
Modeli kullanmak için kullanım şartlarını da kabul etmeniz gerekir: https://huggingface.co/google/gemma-2b
3. Kurulum ve Gereksinimler
Aşağıdaki kaynakları ayarlayın:
- IAM hizmet hesabı ve ilişkili IAM izinleri,
- Hugging Face jetonunuzu depolamak için Secret Manager gizli anahtarı,
- İnce ayarlanmış modelinizi depolamak için Cloud Storage paketi ve
- Modelinizde ince ayar yapmak için oluşturacağınız görüntüyü depolamak üzere Artifact Registry deposu.
- Bu codelab için ortam değişkenlerini ayarlayın. Sizin için bazı değişkenleri önceden doldurduk. Proje kimliğinizi, bölgenizi ve Hugging Face jetonunuzu belirtin.
export PROJECT_ID=<YOUR_PROJECT_ID> export REGION=<YOUR_REGION> export HF_TOKEN=<YOUR_HF_TOKEN> 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
- Aşağıdaki komutu çalıştırarak hizmet hesabını oluşturun:
gcloud iam service-accounts create $SERVICE_ACCOUNT \ --display-name="Service account for fine-tuning codelab"
- Hugging Face erişim jetonunu depolamak için Secret Manager'ı kullanın:
gcloud secrets create $SECRET_ID \ --replication-policy="automatic" printf $HF_TOKEN | gcloud secrets versions add $SECRET_ID --data-file=-
- Hizmet hesabınıza Secret Manager Gizli Anahtar Erişeni rolünü verin:
gcloud secrets add-iam-policy-binding $SECRET_ID \ --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \ --role='roles/secretmanager.secretAccessor'
- İnce ayarlanmış modelinizi barındıracak bir paket oluşturun:
gcloud storage buckets create -l $REGION gs://$BUCKET_NAME
- Hizmet hesabınıza pakete erişim izni verin:
gcloud storage buckets add-iam-policy-binding gs://$BUCKET_NAME \ --member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \ --role=roles/storage.objectAdmin
- Container görüntüsünü depolamak için bir Artifact Registry deposu oluşturun:
gcloud artifacts repositories create $AR_REPO \ --repository-format=docker \ --location=$REGION \ --description="codelab for finetuning using CR jobs" \ --project=$PROJECT_ID
4. Cloud Run iş resmini oluşturma
Sonraki adımda, aşağıdakileri yapan kodu oluşturacaksınız:
- Gemma modelini Hugging Face'tan içe aktarır.
- Hugging Face'tan alınan veri kümesiyle modelde ince ayar yapar. İş, hassas ayar için tek bir L4 GPU kullanır.
new_model
adlı hassas ayarlanmış modeli Cloud Storage paketinize yükler
- İnce ayar iş kodunuz için bir dizin oluşturun.
mkdir codelab-finetuning-job cd codelab-finetuning-job
finetune.py
adlı bir dosya oluşturun# Copyright 2024 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 transformers import ( AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, TrainingArguments, ) from peft import LoraConfig, PeftModel 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-2b") # The instruction dataset to use dataset_name = "b-mc2/sql-create-context" # Fine-tuned model name new_model = os.getenv("NEW_MODEL", "gemma-2b-sql") ################################################################################ # QLoRA parameters ################################################################################ # LoRA attention dimension lora_r = int(os.getenv("LORA_R", "4")) # Alpha parameter for LoRA scaling lora_alpha = int(os.getenv("LORA_ALPHA", "8")) # Dropout probability for LoRA layers lora_dropout = 0.1 ################################################################################ # bitsandbytes parameters ################################################################################ # Activate 4-bit precision base model loading use_4bit = True # Compute dtype for 4-bit base models bnb_4bit_compute_dtype = "float16" # Quantization type (fp4 or nf4) bnb_4bit_quant_type = "nf4" # Activate nested quantization for 4-bit base models (double quantization) use_nested_quant = False ################################################################################ # TrainingArguments parameters ################################################################################ # Output directory where the model predictions and checkpoints will be stored output_dir = "./results" # Number of training epochs num_train_epochs = 1 # Enable fp16/bf16 training (set bf16 to True with an A100) fp16 = True bf16 = False # Batch size per GPU for training per_device_train_batch_size = int(os.getenv("TRAIN_BATCH_SIZE", "1")) # Batch size per GPU for evaluation per_device_eval_batch_size = int(os.getenv("EVAL_BATCH_SIZE", "2")) # Number of update steps to accumulate the gradients for gradient_accumulation_steps = int(os.getenv("GRADIENT_ACCUMULATION_STEPS", "1")) # Enable gradient checkpointing gradient_checkpointing = True # Maximum gradient normal (gradient clipping) max_grad_norm = 0.3 # Initial learning rate (AdamW optimizer) learning_rate = 2e-4 # Weight decay to apply to all layers except bias/LayerNorm weights weight_decay = 0.001 # Optimizer to use optim = "paged_adamw_32bit" # Learning rate schedule lr_scheduler_type = "cosine" # Number of training steps (overrides num_train_epochs) max_steps = -1 # Ratio of steps for a linear warmup (from 0 to learning rate) warmup_ratio = 0.03 # Group sequences into batches with same length # Saves memory and speeds up training considerably group_by_length = True # Save checkpoint every X updates steps save_steps = 0 # Log every X updates steps logging_steps = int(os.getenv("LOGGING_STEPS", "50")) ################################################################################ # SFT parameters ################################################################################ # Maximum sequence length to use max_seq_length = int(os.getenv("MAX_SEQ_LENGTH", "512")) # Pack multiple short examples in the same input sequence to increase efficiency packing = False # Load the entire model on the GPU 0 device_map = {'':torch.cuda.current_device()} # Set limit to a positive number limit = int(os.getenv("DATASET_LIMIT", "5000")) dataset = load_dataset(dataset_name, split="train") if limit != -1: dataset = dataset.shuffle(seed=42).select(range(limit)) def transform(data): question = data['question'] context = data['context'] answer = data['answer'] template = "Question: {question}\nContext: {context}\nAnswer: {answer}" return {'text': template.format(question=question, context=context, answer=answer)} transformed = dataset.map(transform) # Load tokenizer and model with QLoRA configuration compute_dtype = getattr(torch, bnb_4bit_compute_dtype) bnb_config = BitsAndBytesConfig( load_in_4bit=use_4bit, bnb_4bit_quant_type=bnb_4bit_quant_type, bnb_4bit_compute_dtype=compute_dtype, bnb_4bit_use_double_quant=use_nested_quant, ) # Check GPU compatibility with bfloat16 if compute_dtype == torch.float16 and use_4bit: major, _ = torch.cuda.get_device_capability() if major >= 8: print("=" * 80) print("Your GPU supports bfloat16") print("=" * 80) # 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 # Load LLaMA tokenizer tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True) tokenizer.pad_token = tokenizer.eos_token tokenizer.padding_side = "right" # Load LoRA configuration peft_config = LoraConfig( lora_alpha=lora_alpha, lora_dropout=lora_dropout, r=lora_r, bias="none", task_type="CAUSAL_LM", target_modules=["q_proj", "v_proj"] ) # Set training parameters training_arguments = TrainingArguments( output_dir=output_dir, num_train_epochs=num_train_epochs, per_device_train_batch_size=per_device_train_batch_size, gradient_accumulation_steps=gradient_accumulation_steps, optim=optim, save_steps=save_steps, logging_steps=logging_steps, learning_rate=learning_rate, weight_decay=weight_decay, fp16=fp16, bf16=bf16, max_grad_norm=max_grad_norm, max_steps=max_steps, warmup_ratio=warmup_ratio, group_by_length=group_by_length, lr_scheduler_type=lr_scheduler_type, ) trainer = SFTTrainer( model=model, train_dataset=transformed, peft_config=peft_config, dataset_text_field="text", max_seq_length=max_seq_length, tokenizer=tokenizer, args=training_arguments, packing=packing, ) trainer.train() trainer.model.save_pretrained(new_model) # 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 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)
requirements.txt
dosyası oluşturun: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
Dockerfile
oluşturun: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
- Artifact Registry deponuzda kapsayıcıyı derleyin:
gcloud builds submit \ --tag $REGION-docker.pkg.dev/$PROJECT_ID/$AR_REPO/$IMAGE_NAME \ --region $REGION
5. İşi dağıtma ve yürütme
Bu adımda, Google Cloud Storage'a daha hızlı yüklemeler yapmak için işinizin YAML yapılandırmasını doğrudan VPC çıkışıyla oluşturursunuz.
Bu dosyanın, sonraki bir adımda güncelleyeceğiniz değişkenler içerdiğini unutmayın.
finetune-job.yaml.tmpl
adlı bir dosya oluşturun:apiVersion: run.googleapis.com/v1 kind: Job metadata: name: $JOB_NAME labels: cloud.googleapis.com/location: $REGION annotations: run.googleapis.com/launch-stage: ALPHA spec: template: metadata: annotations: run.googleapis.com/execution-environment: gen2 run.googleapis.com/network-interfaces: '[{"network":"default","subnetwork":"default"}]' spec: parallelism: 1 taskCount: 1 template: spec: serviceAccountName: $SERVICE_ACCOUNT_ADDRESS containers: - name: $IMAGE_NAME image: $REGION-docker.pkg.dev/$PROJECT_ID/$AR_REPO/$IMAGE_NAME env: - name: MODEL_NAME value: "google/gemma-2b" - name: NEW_MODEL value: "gemma-2b-sql-finetuned" - name: BUCKET_NAME value: "$BUCKET_NAME" - name: LORA_R value: "8" - name: LORA_ALPHA value: "16" - name: GRADIENT_ACCUMULATION_STEPS value: "2" - name: DATASET_LIMIT value: "1000" - name: LOGGING_STEPS value: "5" - name: HF_TOKEN valueFrom: secretKeyRef: key: 'latest' name: HF_TOKEN resources: limits: cpu: 8000m nvidia.com/gpu: '1' memory: 32Gi volumeMounts: - mountPath: /finetune/new_model name: finetuned_model volumes: - name: finetuned_model csi: driver: gcsfuse.run.googleapis.com readOnly: false volumeAttributes: bucketName: $BUCKET_NAME maxRetries: 3 timeoutSeconds: '3600' nodeSelector: run.googleapis.com/accelerator: nvidia-l4
- Aşağıdaki komutu çalıştırarak YAML'deki değişkenleri ortam değişkenlerinizle değiştirin:
envsubst < finetune-job.yaml.tmpl > finetune-job.yaml
- Cloud Run işini oluşturun:
gcloud alpha run jobs replace finetune-job.yaml
- İşi yürütün:
gcloud alpha run jobs execute $JOB_NAME --region $REGION --async
İşin tamamlanması yaklaşık 10 dakika sürer. Son komutun çıktısında verilen bağlantıyı kullanarak durumu kontrol edebilirsiniz.
6. İnce ayarlanmış modelinizi vLLM ile yayınlamak için Cloud Run hizmeti kullanma
Bu adımda, bir Cloud Run hizmeti dağıtacaksınız. Bu yapılandırma, daha hızlı indirmeler için Cloud Storage paketine özel ağ üzerinden erişmek üzere doğrudan VPC kullanır.
Bu dosyanın, sonraki bir adımda güncelleyeceğiniz değişkenler içerdiğini unutmayın.
service.yaml.tmpl
dosyası oluşturun:apiVersion: serving.knative.dev/v1 kind: Service metadata: name: serve-gemma-sql labels: cloud.googleapis.com/location: $REGION annotations: run.googleapis.com/launch-stage: BETA run.googleapis.com/ingress: all run.googleapis.com/ingress-status: all spec: template: metadata: labels: annotations: autoscaling.knative.dev/maxScale: '1' run.googleapis.com/cpu-throttling: 'false' run.googleapis.com/gpu-zonal-redundancy-disabled: 'true' run.googleapis.com/network-interfaces: '[{"network":"default","subnetwork":"default"}]' spec: containers: - name: serve-finetuned image: us-docker.pkg.dev/vertex-ai/vertex-vision-model-garden-dockers/pytorch-vllm-serve:20250505_0916_RC00 ports: - name: http1 containerPort: 8000 resources: limits: cpu: 8000m nvidia.com/gpu: '1' memory: 32Gi volumeMounts: - name: fuse mountPath: /finetune/new_model command: ["python3", "-m", "vllm.entrypoints.api_server"] args: - --model=/finetune/new_model - --tensor-parallel-size=1 env: - name: MODEL_ID value: 'new_model' - name: HF_HUB_OFFLINE value: '1' volumes: - name: fuse csi: driver: gcsfuse.run.googleapis.com volumeAttributes: bucketName: $BUCKET_NAME nodeSelector: run.googleapis.com/accelerator: nvidia-l4
service.yaml
dosyasını paketinizin adıyla güncelleyin.envsubst < service.yaml.tmpl > service.yaml
- Cloud Run hizmetinizi dağıtın:
gcloud alpha run services replace service.yaml
7. İnce ayarlanmış modelinizi test etme
Bu adımda, modelinizde hassas ayarı test etmesini istersiniz.
- Cloud Run hizmetinizin hizmet URL'sini alın:
SERVICE_URL=$(gcloud run services describe serve-gemma-sql --platform managed --region $REGION --format 'value(status.url)')
- Modeliniz için isteminizi oluşturun.
USER_PROMPT="Question: What are the first name and last name of all candidates? Context: CREATE TABLE candidates (candidate_id VARCHAR); CREATE TABLE people (first_name VARCHAR, last_name VARCHAR, person_id VARCHAR)"
- Modelinizi istemek için CURL'i kullanarak hizmetinizi çağırın:
curl -X POST $SERVICE_URL/generate \ -H "Content-Type: application/json" \ -H "Authorization: bearer $(gcloud auth print-identity-token)" \ -d @- <<EOF { "prompt": "${USER_PROMPT}" } EOF
Aşağıdakine benzer bir yanıt görürsünüz:
{"predictions":["Prompt:\nQuestion: What are the first name and last name of all candidates? Context: CREATE TABLE candidates (candidate_id VARCHAR); CREATE TABLE people (first_name VARCHAR, last_name VARCHAR, person_id VARCHAR)\nOutput:\n CREATE TABLE people_to_candidates (candidate_id VARCHAR, person_id VARCHAR) CREATE TABLE people_to_people (person_id VARCHAR, person_id VARCHAR) CREATE TABLE people_to_people_to_candidates (person_id VARCHAR, candidate_id"]}
8. Tebrikler!
Codelab'i tamamladığınız için tebrikler.
Cloud Run belgelerini incelemenizi öneririz.
İşlediğimiz konular
- Cloud Run Jobs GPU'yu kullanarak hassas ayarlama yapma
- vLLM ile Cloud Run'u kullanarak model yayınlama
- Modelin daha hızlı yüklenmesi ve sunulması için GPU işi için doğrudan VPC yapılandırması nasıl kullanılır?
9. Temizleme
İstemsiz ödemelerden kaçınmak için (ör. Cloud Run hizmetleri yanlışlıkla ücretsiz kademede aylık Cloud Run çağrısı kotanızdan daha fazla çağrılırsa) 6. adımda oluşturduğunuz Cloud Run hizmetini silebilirsiniz.
Cloud Run hizmetini silmek için https://console.cloud.google.com/run adresindeki Cloud Run Cloud Console'a gidin ve serve-gemma-sql
hizmetini silin.
Projenin tamamını silmek için Kaynakları Yönet'e gidin, 2. adımda oluşturduğunuz projeyi seçin ve Sil'i tıklayın. Projeyi silerseniz Cloud SDK'nızdaki projeleri değiştirmeniz gerekir. gcloud projects list
komutunu çalıştırarak mevcut tüm projelerin listesini görüntüleyebilirsiniz.