Menyesuaikan Gemini di Vertex AI

1. Pengantar

Di lab ini, Anda akan mempelajari cara melakukan alur kerja lengkap penyesuaian yang diawasi pada model Google Gemini untuk mengadaptasinya bagi tugas tertentu: meringkas artikel. Meskipun model bahasa besar sangat canggih, sifatnya yang serbaguna berarti model ini dapat dibuat lebih efektif untuk kasus penggunaan tertentu melalui penyesuaian. Dengan melatih model pada set data contoh berkualitas tinggi, Anda dapat meningkatkan konsistensi, kualitas, dan efisiensinya untuk tugas target Anda.

Anda akan menggunakan Gemini 2.5 Flash, model ringan dan hemat biaya, serta melakukan penyesuaian menggunakan Vertex AI.

Ringkasan Arsitektur

Berikut yang akan kita buat:

  • Cloud Shell: Lingkungan pengembangan Anda.
  • Cloud Storage: Menyimpan data pelatihan/validasi dalam format JSONL.
  • Vertex AI Training: Mengelola tugas penyesuaian.
  • Endpoint Vertex AI: Menghosting model yang di-fine-tune.

Yang akan Anda pelajari

  • Siapkan set data berkualitas tinggi untuk fine-tuning yang diawasi.
  • Mengonfigurasi dan meluncurkan tugas penyesuaian menggunakan Vertex AI SDK untuk Python.
  • Evaluasi model menggunakan metrik otomatis (skor ROUGE).
  • Bandingkan model dasar dan model yang disesuaikan untuk mengukur peningkatan.

2. Penyiapan project

Akun Google

Jika belum memiliki Akun Google pribadi, Anda harus membuat Akun Google.

Gunakan akun pribadi, bukan akun kantor atau sekolah.

Login ke Konsol Google Cloud

Login ke Konsol Google Cloud menggunakan Akun Google pribadi.

Aktifkan Penagihan

Tukarkan kredit Google Cloud senilai $5 (opsional)

Untuk menjalankan workshop ini, Anda memerlukan Akun Penagihan dengan sejumlah kredit. Jika Anda berencana menggunakan penagihan sendiri, Anda dapat melewati langkah ini.

  1. Klik link ini dan login dengan Akun Google pribadi.Anda akan melihat tampilan seperti ini:Klik untuk memberikan otorisasi pada Cloud Shell
  2. Klik tombol KLIK DI SINI UNTUK MENGAKSES KREDIT ANDA.Tindakan ini akan membawa Anda ke halaman untuk menyiapkan profil penagihanKlik untuk memberikan otorisasi pada Cloud Shell
  3. Klik Konfirmasi.

Anda kini terhubung ke Akun Penagihan Uji Coba Google Cloud Platform.

Screenshot ringkasan penagihan

Membuat project (opsional)

Jika Anda tidak memiliki project saat ini yang ingin digunakan untuk lab ini, buat project baru di sini.

3. Buka Cloud Shell Editor

  1. Klik link ini untuk langsung membuka Cloud Shell Editor
  2. Jika diminta untuk memberikan otorisasi kapan saja hari ini, klik Authorize untuk melanjutkan.Klik untuk memberikan otorisasi pada Cloud Shell
  3. Jika terminal tidak muncul di bagian bawah layar, buka terminal:
    • Klik Lihat
    • Klik TerminalMembuka terminal baru di Cloud Shell Editor
  4. Di terminal, tetapkan project Anda dengan perintah ini:
    gcloud config set project [PROJECT_ID]
    
    • Contoh:
      gcloud config set project lab-project-id-example
      
    • Jika tidak ingat project ID, Anda dapat mencantumkan semua project ID dengan:
      gcloud projects list
      
      Menetapkan project ID di terminal Cloud Shell Editor
  5. Anda akan melihat pesan ini:
    Updated property [core/project].
    

4. Mengaktifkan API

Untuk menggunakan Vertex AI dan layanan lainnya, Anda harus mengaktifkan API yang diperlukan di project Google Cloud Anda.

  1. Di terminal, aktifkan API:
    • Vertex AI API (aiplatform.googleapis.com): Memungkinkan penggunaan Vertex AI untuk penyesuaian dan penyaluran model.
    • Cloud Storage API (storage.googleapis.com): Memungkinkan penyimpanan set data dan artefak model.
    gcloud services enable aiplatform.googleapis.com \
        storage.googleapis.com
    

5. Menyiapkan lingkungan project

Buat direktori kerja

  1. Di terminal, buat direktori untuk project Anda dan buka direktori tersebut.
    mkdir gemini-finetuning
    cd gemini-finetuning
    

Menyiapkan variabel lingkungan

  1. Di terminal, tentukan variabel lingkungan untuk project Anda. Kita akan membuat file env.sh untuk menyimpan variabel ini sehingga dapat dimuat ulang dengan mudah jika sesi Anda terputus.
    cat <<EOF > env.sh
    export PROJECT_ID=\$(gcloud config get-value project)
    export REGION="us-central1"
    export BUCKET_NAME="\${PROJECT_ID}-gemini-tuning"
    EOF
    
    source env.sh
    

Membuat Bucket Cloud Storage

  1. Di terminal, buat bucket untuk menyimpan set data dan artefak model Anda.
    gcloud storage buckets create gs://$BUCKET_NAME --project=$PROJECT_ID --location=$REGION
    

Menyiapkan Lingkungan Virtual

  1. Kita akan menggunakan uv untuk mengelola lingkungan Python. Di terminal, jalankan:
    uv venv .venv
    source .venv/bin/activate
    
  2. Di terminal, instal paket Python yang diperlukan.
    uv pip install google-cloud-aiplatform rouge-score matplotlib pandas tqdm
    

6. Menyiapkan data pelatihan

Data berkualitas adalah fondasi penyesuaian yang berhasil. Anda akan menggunakan set data WikiLingua, mengubahnya menjadi format JSONL spesifik yang diperlukan Gemini, dan menguploadnya ke bucket penyimpanan Anda.

  1. Di terminal, buat file bernama prepare_data.py.
    cloudshell edit prepare_data.py
    
  2. Tempelkan kode berikut ke prepare_data.py.
    import json
    import os
    import pandas as pd
    from google.cloud import storage
    import subprocess
    
    # Configuration
    BUCKET_NAME = os.environ["BUCKET_NAME"]
    PROJECT_ID = os.environ["PROJECT_ID"]
    
    def download_data():
        print("Downloading WikiLingua dataset...")
        # Using gsutil to copy from public bucket
        subprocess.run(["gsutil", "cp", "gs://github-repo/generative-ai/gemini/tuning/summarization/wikilingua/*", "."], check=True)
    
    def convert_to_gemini_format(input_file, output_file, max_samples=1000):
        print(f"Converting {input_file} to Gemini format (first {max_samples} samples)...")
        converted_data = []
        with open(input_file, 'r') as f:
            for i, line in enumerate(f):
                if i >= max_samples:
                    break
                obj = json.loads(line)
                messages = obj.get("messages", [])
    
                # Convert messages to Gemini 2.5 format
                # Input: {"messages": [{"role": "user", "content": "..."}, {"role": "model", "content": "..."}]}
                # Output: {"contents": [{"role": "user", "parts": [{"text": "..."}]}, {"role": "model", "parts": [{"text": "..."}]}]}
    
                contents = []
                for msg in messages:
                    role = msg["role"]
                    content = msg["content"]
                    contents.append({
                        "role": role,
                        "parts": [{"text": content}]
                    })
    
                converted_data.append({"contents": contents})
    
        with open(output_file, 'w') as f:
            for item in converted_data:
                f.write(json.dumps(item) + "\n")
    
        print(f"Saved {len(converted_data)} examples to {output_file}")
    
    def upload_to_gcs(local_file, destination_blob_name):
        print(f"Uploading {local_file} to gs://{BUCKET_NAME}/{destination_blob_name}...")
        storage_client = storage.Client(project=PROJECT_ID)
        bucket = storage_client.bucket(BUCKET_NAME)
        blob = bucket.blob(destination_blob_name)
        blob.upload_from_filename(local_file)
        print("Upload complete.")
    
    def main():
        download_data()
    
        # Process Training Data
        convert_to_gemini_format("sft_train_samples.jsonl", "train_gemini.jsonl")
        upload_to_gcs("train_gemini.jsonl", "datasets/train/train_gemini.jsonl")
    
        # Process Validation Data
        convert_to_gemini_format("sft_val_samples.jsonl", "val_gemini.jsonl")
        upload_to_gcs("val_gemini.jsonl", "datasets/val/val_gemini.jsonl")
    
        print("Data preparation complete!")
    
    if __name__ == "__main__":
        main()
    
  3. Di terminal, jalankan skrip penyiapan data.
    python prepare_data.py
    

7. Menetapkan performa dasar pengukuran

Sebelum melakukan penyesuaian, Anda memerlukan tolok ukur. Anda akan mengukur seberapa baik performa model gemini-2.5-flash dasar pada tugas ringkasan menggunakan skor ROUGE.

  1. Di terminal, buat file bernama evaluate.py.
    cloudshell edit evaluate.py
    
  2. Tempelkan kode berikut ke evaluate.py.
    import argparse
    import json
    import os
    import pandas as pd
    from google.cloud import aiplatform
    import vertexai
    from vertexai.generative_models import GenerativeModel, GenerationConfig, HarmCategory, HarmBlockThreshold
    from rouge_score import rouge_scorer
    from tqdm import tqdm
    import matplotlib.pyplot as plt
    import time
    
    # Configuration
    PROJECT_ID = os.environ["PROJECT_ID"]
    REGION = os.environ["REGION"]
    
    aiplatform.init(project=PROJECT_ID, location=REGION)
    
    def evaluate(model_name, test_file, max_samples=50, output_json="results.json"):
        print(f"Evaluating model: {model_name}")
    
        # Load Test Data
        test_df = pd.read_csv(test_file)
        test_df = test_df.head(max_samples)
    
        model = GenerativeModel(model_name)
    
        safety_settings = {
            HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_ONLY_HIGH,
            HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_ONLY_HIGH,
            HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_ONLY_HIGH,
            HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_ONLY_HIGH,
        }
    
        generation_config = GenerationConfig(
            temperature=0.1,
            max_output_tokens=1024,
        )
    
        scorer = rouge_scorer.RougeScorer(['rouge1', 'rouge2', 'rougeL'], use_stemmer=True)
        results = []
    
        for index, row in tqdm(test_df.iterrows(), total=len(test_df)):
            input_text = row['input_text']
            reference_summary = row['output_text']
    
            try:
                response = model.generate_content(
                    input_text,
                    generation_config=generation_config,
                    safety_settings=safety_settings
                )
                generated_summary = response.text
    
                scores = scorer.score(reference_summary, generated_summary)
    
                results.append({
                    "generated": generated_summary,
                    "reference": reference_summary,
                    "rouge1": scores['rouge1'].fmeasure,
                    "rouge2": scores['rouge2'].fmeasure,
                    "rougeL": scores['rougeL'].fmeasure
                })
            except Exception as e:
                print(f"Error processing example {index}: {e}")
                # Sleep briefly to avoid quota issues if hitting limits
                time.sleep(1)
    
        # Save results
        with open(output_json, 'w') as f:
            json.dump(results, f, indent=2)
    
        return pd.DataFrame(results)
    
    def plot_results(df, title, filename):
        os.makedirs("plots", exist_ok=True)
    
        metrics = ['rouge1', 'rouge2', 'rougeL']
        fig, axes = plt.subplots(1, 3, figsize=(15, 5))
    
        for i, metric in enumerate(metrics):
            axes[i].hist(df[metric], bins=10, alpha=0.7, color='skyblue', edgecolor='black')
            axes[i].set_title(f'{metric} Distribution')
            axes[i].set_xlabel('Score')
            axes[i].set_ylabel('Count')
    
        plt.suptitle(title)
        plt.tight_layout()
        plt.savefig(f"plots/{filename}")
        print(f"Plot saved to plots/{filename}")
    
    def compare_results(baseline_file, tuned_file):
        with open(baseline_file, 'r') as f:
            baseline_data = pd.DataFrame(json.load(f))
        with open(tuned_file, 'r') as f:
            tuned_data = pd.DataFrame(json.load(f))
    
        print("\n--- Comparison ---")
        metrics = ['rouge1', 'rouge2', 'rougeL']
        for metric in metrics:
            base_mean = baseline_data[metric].mean()
            tuned_mean = tuned_data[metric].mean()
            diff = tuned_mean - base_mean
            print(f"{metric}: Base={base_mean:.4f}, Tuned={tuned_mean:.4f}, Diff={diff:+.4f}")
    
        # Comparative Plot
        os.makedirs("plots", exist_ok=True)
        comparison_df = pd.DataFrame({
            'Metric': metrics,
            'Baseline': [baseline_data[m].mean() for m in metrics],
            'Tuned': [tuned_data[m].mean() for m in metrics]
        })
    
        comparison_df.plot(x='Metric', y=['Baseline', 'Tuned'], kind='bar', figsize=(10, 6))
        plt.title('Baseline vs Tuned Model Performance')
        plt.ylabel('Average Score')
        plt.xticks(rotation=0)
        plt.tight_layout()
        plt.savefig("plots/comparison.png")
        print("Comparison plot saved to plots/comparison.png")
    
    def main():
        parser = argparse.ArgumentParser()
        parser.add_argument("--model", type=str, default="gemini-2.5-flash", help="Model resource name")
        parser.add_argument("--baseline", type=str, help="Path to baseline results json for comparison")
        parser.add_argument("--output", type=str, default="results.json", help="Output file for results")
        args = parser.parse_args()
    
        # Ensure test data exists (it was downloaded in prepare_data step)
        if not os.path.exists("sft_test_samples.csv"):
            # Fallback download if needed
            subprocess.run(["gsutil", "cp", "gs://github-repo/generative-ai/gemini/tuning/summarization/wikilingua/sft_test_samples.csv", "."], check=True)
    
        df = evaluate(args.model, "sft_test_samples.csv", output_json=args.output)
    
        print("\n--- Results Summary ---")
        print(df.describe())
    
        plot_filename = "baseline_dist.png" if not args.baseline else "tuned_dist.png"
        plot_results(df, f"ROUGE Scores - {args.model}", plot_filename)
    
        if args.baseline:
            compare_results(args.baseline, args.output)
    
    if __name__ == "__main__":
        main()
    
  3. Di terminal, jalankan evaluasi dasar.
    python evaluate.py --model "gemini-2.5-flash" --output "baseline.json"
    
    Tindakan ini akan menghasilkan file baseline.json dan plot di plots/baseline_dist.png.

8. Mengonfigurasi dan meluncurkan penyesuaian

Sekarang Anda akan meluncurkan tugas fine-tuning terkelola di Vertex AI.

  1. Di terminal, buat file bernama tune.py.
    cloudshell edit tune.py
    
  2. Tempelkan kode berikut ke tune.py.
    import os
    import time
    from google.cloud import aiplatform
    import vertexai
    from vertexai.preview.tuning import sft
    
    # Configuration
    PROJECT_ID = os.environ["PROJECT_ID"]
    REGION = os.environ["REGION"]
    BUCKET_NAME = os.environ["BUCKET_NAME"]
    
    aiplatform.init(project=PROJECT_ID, location=REGION)
    
    def train():
        print("Launching fine-tuning job...")
    
        sft_tuning_job = sft.train(
            source_model="gemini-2.5-flash", # Using specific version for stability
            train_dataset=f"gs://{BUCKET_NAME}/datasets/train/train_gemini.jsonl",
            validation_dataset=f"gs://{BUCKET_NAME}/datasets/val/val_gemini.jsonl",
            epochs=1, # Keep it short for the lab
            adapter_size=4,
            learning_rate_multiplier=1.0,
            tuned_model_display_name="gemini-2.5-flash-wikilingua",
        )
    
        print(f"Job started: {sft_tuning_job.resource_name}")
        print("Waiting for job to complete... (this may take ~45 minutes)")
    
        # Wait for the job to complete
        while not sft_tuning_job.has_ended:
            time.sleep(60)
            sft_tuning_job.refresh()
            print(f"Status: {sft_tuning_job.state.name}")
    
        print("Job completed!")
        print(f"Tuned Model Endpoint: {sft_tuning_job.tuned_model_endpoint_name}")
        return sft_tuning_job.tuned_model_endpoint_name
    
    if __name__ == "__main__":
        train()
    
  3. Di terminal, jalankan skrip penyetelan halus.
    python tune.py
    
    Catatan: Proses ini dapat memerlukan waktu sekitar 45 menit. Anda dapat memantau tugas di Konsol Vertex AI.

9. Memahami kode pelatihan

Saat tugas Anda berjalan, mari kita lihat lebih dekat skrip tune.py untuk memahami cara kerja penyesuaian.

Managed Supervised Fine-Tuning

Skrip menggunakan metode vertexai.tuning.sft.train untuk mengirimkan tugas penyesuaian terkelola. Hal ini mengabstraksi kompleksitas penyediaan infrastruktur, pendistribusian pelatihan, dan pengelolaan titik pemeriksaan.

sft_tuning_job = sft.train(
    source_model="gemini-2.5-flash",
    train_dataset=f"gs://{BUCKET_NAME}/datasets/train/train_gemini.jsonl",
    # ...
)

Konfigurasi LoRA

Daripada menentukan LoraConfig secara manual seperti yang mungkin Anda lakukan di framework open source, Vertex AI menyederhanakannya menjadi beberapa parameter utama:

  • adapter_size: Parameter ini (ditetapkan ke 4 dalam skrip kami) mengontrol peringkat adaptor LoRA. Ukuran yang lebih besar memungkinkan model mempelajari adaptasi yang lebih kompleks, tetapi meningkatkan jumlah parameter yang dapat dilatih.
  • epochs: Kita menyetelnya ke 1 untuk lab ini agar waktu pelatihan singkat (~20 menit). Dalam skenario produksi, Anda dapat meningkatkan nilai ini agar model dapat mempelajari data Anda secara lebih mendalam, meskipun Anda harus mewaspadai overfitting.

Pemilihan Model

Kami secara eksplisit menentukan source_model="gemini-2.5-flash". Vertex AI mendukung berbagai versi Gemini, dan menyematkan versi tertentu memastikan pipeline Anda tetap stabil dan dapat direproduksi.

10. Bandingkan model

Setelah tugas penyesuaian selesai, Anda dapat membandingkan performa model baru dengan model dasar.

  1. Dapatkan endpoint model yang telah disesuaikan. Pesan ini dicetak di akhir skrip tune.py. Tampilannya akan terlihat seperti projects/.../locations/.../endpoints/....
  2. Jalankan skrip evaluasi lagi, kali ini dengan meneruskan model yang disesuaikan dan hasil dasar pengukuran untuk perbandingan.
    # Replace [YOUR_TUNED_MODEL_ENDPOINT] with the actual endpoint name
    export TUNED_MODEL="projects/[YOUR_PROJECT_ID]/locations/[YOUR_REGION]/endpoints/[YOUR_ENDPOINT_ID]"
    
    python evaluate.py --model "$TUNED_MODEL" --baseline "baseline.json" --output "tuned.json"
    
  3. Lihat hasilnya. Skrip akan menampilkan perbandingan skor ROUGE dan membuat diagram plots/comparison.png yang menunjukkan peningkatannya.Anda dapat melihat plot dengan membuka folder plots di Cloud Shell Editor.

11. Pembersihan

Agar tidak dikenai biaya, hapus resource yang Anda buat.

  1. Di terminal, hapus bucket Cloud Storage dan model yang di-tuning.
    gcloud storage rm -r gs://$BUCKET_NAME
    # Note: You can delete the model endpoint from the Vertex AI Console
    

12. Selamat!

Anda telah berhasil melakukan penyesuaian Gemini 2.5 Flash di Vertex AI.

Rekap

Di lab ini, Anda akan:

  • Menyiapkan set data dalam format JSONL untuk penyesuaian Gemini.
  • Menetapkan dasar pengukuran menggunakan model Gemini 2.5 Flash dasar.
  • Meluncurkan tugas fine-tuning yang diawasi di Vertex AI.
  • Mengevaluasi dan membandingkan model yang disesuaikan dengan model dasar.

Langkah berikutnya

Lab ini merupakan bagian dari Jalur Pembelajaran AI Siap Produksi dengan Google Cloud.

Jelajahi seluruh kurikulum untuk menjembatani kesenjangan dari prototipe hingga produksi.

Bagikan progres Anda dengan hashtag #ProductionReadyAI.