1. מבוא
סקירה כללית
בשיעור הזה תשתמשו בעבודות (jobs) של Cloud Run כדי לבצע כוונון עדין של מודל Gemma 3, ואז תפעילו את התוצאה ב-Cloud Run באמצעות vLLM.
הפעולות שתבצעו:
אימון מודל להגיב לביטוי ספציפי עם תוצאה ספציפית באמצעות מערך הנתונים KomeijiForce/Text2Emoji, שנוצר כחלק מהמאמר EmojiLM: Modeling the New Emoji Language.
אחרי האימון, המודל מגיב למשפט שמופיע אחרי התחילית 'Translate to emoji: ' (תרגם לאמוג'י:) בסדרת אמוג'י שמתאימים למשפט הזה.
מה תלמדו
- איך מבצעים כוונון עדין באמצעות GPU של Cloud Run Jobs
- איך מפעילים מודל באמצעות Cloud Run עם vLLM
- איך משתמשים בהגדרת VPC ישירה לעבודת GPU כדי להעלות את המודל ולשרת אותו מהר יותר
2. לפני שמתחילים
הפעלת ממשקי API
לפני שמתחילים להשתמש ב-codelab הזה, מפעילים את ממשקי ה-API הבאים באמצעות הפקודה:
gcloud services enable run.googleapis.com \
compute.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com \
secretmanager.googleapis.com \
artifactregistry.googleapis.com
מכסת GPU
כדי לדעת איך לבקש מכסה, אפשר לעיין במסמכי התיעוד בנושא מכסת GPU.
אם נתקלתם בשגיאות מהסוג 'אין לכם מכסה לשימוש ב-GPU', תוכלו לבדוק את המכסה שלכם בכתובת g.co/cloudrun/gpu-quota.
הערה: אם אתם משתמשים בפרויקט חדש, יכול להיות שיחלפו כמה דקות בין הפעלת ה-API לבין הופעת המכסות בדף המכסות.
Hugging Face
ב-codelab הזה נעשה שימוש במודל שמתארח ב-Hugging Face. כדי לקבל את המודל הזה, צריך לבקש את אסימון הגישה של המשתמש ב-Hugging Face עם הרשאת 'קריאה'. תצטרכו להשתמש בו בהמשך כשתסמנו את האירוע כאירוע מרכזי.YOUR_HF_TOKEN
כדי להשתמש במודל gemma-3-1b-it, צריך לאשר את תנאי השימוש.
3. הגדרה ודרישות
מגדירים את המשאבים הבאים:
- חשבון שירות ב-IAM וההרשאות המשויכות ב-IAM,
- Secret Manager secret (סוד ב-Secret Manager) כדי לאחסן את הטוקן של Hugging Face,
- קטגוריה של Cloud Storage לאחסון המודל המכוונן,
- מאגר Artifact Registry לאחסון התמונה שתיצרו כדי לכוונן את המודל.
- מגדירים משתני סביבה ל-Codelab הזה. מילאנו מראש מספר משתנים בשבילכם. מציינים את מזהה הפרויקט, האזור והאסימון של 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 - כדי ליצור את חשבון השירות, מריצים את הפקודה הבאה:
gcloud iam service-accounts create $SERVICE_ACCOUNT \ --display-name="Service account for fine-tuning codelab" - משתמשים ב-Secret Manager כדי לאחסן את אסימון הגישה של Hugging Face:
gcloud secrets create $SECRET_ID \ --replication-policy="automatic" printf $HF_TOKEN | gcloud secrets versions add $SECRET_ID --data-file=- - מקצים לחשבון השירות את התפקיד Secret Manager Secret Accessor:
gcloud secrets add-iam-policy-binding $SECRET_ID \ --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \ --role='roles/secretmanager.secretAccessor' - יוצרים קטגוריה לאירוח המודל שעבר כוונון עדין:
gcloud storage buckets create -l $REGION gs://$BUCKET_NAME - נותנים לחשבון השירות גישה לדלי:
gcloud storage buckets add-iam-policy-binding gs://$BUCKET_NAME \ --member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \ --role=roles/storage.objectAdmin - יוצרים מאגר ב-Artifact Registry לאחסון קובץ האימג' של הקונטיינר:
gcloud artifacts repositories create $AR_REPO \ --repository-format=docker \ --location=$REGION \ --description="codelab for finetuning using CR jobs" \ --project=$PROJECT_ID
4. יצירת אימג' של משימת Cloud Run
בשלב הבא תיצרו את הקוד שמבצע את הפעולות הבאות:
- ייבוא של מודל Gemma מ-Hugging Face
- מבצע כוונון עדין של המודל באמצעות מערך הנתונים מ-Hugging Face. העבודה משתמשת ב-GPU יחיד מסוג L4 לצורך כוונון עדין.
- המודל שעבר כוונון מדויק בשם
new_modelמועלה לקטגוריה שלכם ב-Cloud Storage
- יוצרים ספרייה לקוד של משימת הכוונון העדין.
mkdir codelab-finetuning-job cd codelab-finetuning-job - יוצרים קובץ בשם
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) - יוצרים קובץ
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 - יצירת
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 - מבצעים build של הקונטיינר במאגר Artifact Registry:
gcloud builds submit \ --tag $REGION-docker.pkg.dev/$PROJECT_ID/$AR_REPO/$IMAGE_NAME \ --region $REGION
5. פריסה והפעלה של המשימה
בשלב הזה, תיצרו את המשימה עם יציאה ישירה של VPC להעלאות מהירות יותר אל Google Cloud Storage.
- יוצרים את המשימה ב-Cloud Run:
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 - מריצים את העבודה:
gcloud run jobs execute $JOB_NAME --region $REGION --async
השלמת העבודה תיקח כ-10 דקות. אפשר לבדוק את הסטטוס באמצעות הקישור שמופיע בפלט של הפקודה האחרונה.
6. שימוש בשירות Cloud Run להצגת המודל שעבר כוונון עדין באמצעות vLLM
בשלב הזה, תפרסו שירות Cloud Run. ההגדרה הזו משתמשת ב-VPC ישיר כדי לגשת לקטגוריית Cloud Storage דרך רשת פרטית, להורדות מהירות יותר.
- פורסים את שירות 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. בדיקת המודל שעבר כוונון עדין
בשלב הזה, תשתמשו בהנחיה כדי לבדוק את הכוונון העדין של המודל באמצעות curl.
- מקבלים את כתובת ה-URL של השירות ב-Cloud Run:
SERVICE_URL=$(gcloud run services describe serve-gemma-emoji \ --region $REGION --format 'value(status.url)') - יוצרים את ההנחיה למודל.
USER_PROMPT="Translate to emoji: I ate a banana for breakfast, later I'm thinking of having soup!" - מתקשרים לשירות באמצעות curl כדי להנחות את המודל, ומסננים את התוצאות באמצעות 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
אמורה להתקבל תגובה שדומה לזו:
🍌🤔😋🥣
8. מעולה!
כל הכבוד, סיימתם את ה-Codelab!
מומלץ לעיין במסמכי התיעוד בנושא GPU ב-Cloud Run Jobs.
מה נכלל
- איך מבצעים כוונון עדין באמצעות GPU של Cloud Run Jobs
- איך מפעילים מודל באמצעות Cloud Run עם vLLM
- איך משתמשים בהגדרת VPC ישירה לעבודת GPU כדי להעלות את המודל ולשרת אותו מהר יותר
9. הסרת המשאבים
כדי להימנע מחיובים לא מכוונים, למשל אם שירותי Cloud Run מופעלים בטעות יותר פעמים מההקצאה החודשית של הפעלות Cloud Run בתוכנית החינמית, אפשר למחוק את שירות Cloud Run שיצרתם בשלב 6.
כדי למחוק את שירות Cloud Run, עוברים אל Cloud Run Cloud Console בכתובת https://console.cloud.google.com/run ומוחקים את השירות serve-gemma-emoji.
כדי למחוק את הפרויקט כולו, עוברים אל Manage Resources (ניהול משאבים), בוחרים את הפרויקט שיצרתם בשלב 2 ולוחצים על Delete (מחיקה). אם מוחקים את הפרויקט, צריך לשנות את הפרויקט ב-Cloud SDK. כדי לראות את רשימת כל הפרויקטים הזמינים, מריצים את הפקודה gcloud projects list.