1. Introdução
Neste laboratório, você vai aprender a realizar o fluxo de trabalho completo de ajuste supervisionado em um modelo do Google Gemini para adaptá-lo a uma tarefa específica: resumo de artigos. Embora os modelos de linguagem grandes sejam poderosos, a natureza de uso geral deles significa que podem ser ainda mais eficazes para casos de uso específicos com o ajuste fino. Ao treinar o modelo em um conjunto de dados de exemplos de alta qualidade, é possível melhorar a consistência, a qualidade e a eficiência dele para a tarefa desejada.
Você vai usar o Gemini 2.5 Flash, um modelo leve e econômico, e fazer o ajuste usando a Vertex AI.
Visão geral da arquitetura
Confira o que vamos criar:
- Cloud Shell: seu ambiente de desenvolvimento.
- Cloud Storage: armazena dados de treinamento/validação no formato JSONL.
- Vertex AI Training: gerencia o job de ajuste fino.
- Endpoint da Vertex AI: hospeda seu modelo refinado.
O que você vai aprender
- Prepare conjuntos de dados de alta qualidade para ajuste supervisionado.
- Configure e inicie jobs de ajuste refinado usando o SDK da Vertex AI para Python.
- Avalie modelos usando métricas automatizadas (pontuações ROUGE).
- Compare os modelos de base e ajustados para quantificar as melhorias.
2. Configurar o projeto
Conta do Google
Se você ainda não tiver uma Conta do Google pessoal, crie uma.
Use uma conta pessoal em vez de uma conta escolar ou de trabalho.
Fazer login no console do Google Cloud
Faça login no console do Google Cloud usando uma Conta do Google pessoal.
Ativar faturamento
Resgatar US $5 em créditos do Google Cloud (opcional)
Para fazer este workshop, você precisa de uma conta de faturamento com algum crédito. Se você planeja usar seu próprio faturamento, pule esta etapa.
- Clique neste link e faça login com uma Conta do Google pessoal.Você vai ver algo assim:

- Clique no botão CLIQUE AQUI PARA ACESSAR SEUS CRÉDITOS.Isso vai abrir uma página para configurar seu perfil de faturamento

- Clique em Confirmar.
Agora você está conectado a uma conta de faturamento de avaliação do Google Cloud Platform.

Criar um projeto (opcional)
Se você não tiver um projeto atual que gostaria de usar neste laboratório, crie um novo aqui.
3. Abrir editor do Cloud Shell
- Clique neste link para navegar diretamente até o editor do Cloud Shell.
- Se for preciso autorizar em algum momento hoje, clique em Autorizar para continuar.

- Se o terminal não aparecer na parte de baixo da tela, abra-o:
- Clique em Visualizar.
- Clique em Terminal
.
- No terminal, defina o projeto com este comando:
gcloud config set project [PROJECT_ID]- Exemplo:
gcloud config set project lab-project-id-example - Se você não se lembrar do ID do projeto, liste todos os IDs com:
gcloud projects list
- Exemplo:
- Você vai receber esta mensagem:
Updated property [core/project].
4. Ativar APIs
Para usar a Vertex AI e outros serviços, é necessário ativar as APIs necessárias no seu projeto na nuvem do Google.
- No terminal, ative as APIs:
- API Vertex AI (
aiplatform.googleapis.com): permite o uso da Vertex AI para ajuste fino e veiculação de modelos. - API Storage (
storage.googleapis.com): permite o armazenamento de conjuntos de dados e artefatos de modelo.
gcloud services enable aiplatform.googleapis.com \ storage.googleapis.com - API Vertex AI (
5. configurar o ambiente do projeto
Criar um diretório de trabalho
- No terminal, crie um diretório para seu projeto e navegue até ele.
mkdir gemini-finetuning cd gemini-finetuning
Configurar variáveis de ambiente
- No terminal, defina as variáveis de ambiente do projeto. Vamos criar um arquivo
env.shpara armazenar essas variáveis e facilitar a recarga delas se a sessão for desconectada.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
Crie um bucket do Cloud Storage
- No terminal, crie um bucket para armazenar o conjunto de dados e os artefatos do modelo.
gcloud storage buckets create gs://$BUCKET_NAME --project=$PROJECT_ID --location=$REGION
Configurar o ambiente virtual
- Vamos usar o
uvpara gerenciar nosso ambiente Python. No terminal, execute:uv venv .venv source .venv/bin/activate - No terminal, instale os pacotes Python necessários.
uv pip install google-cloud-aiplatform rouge-score matplotlib pandas tqdm
6. Preparar os dados de treinamento
Dados de qualidade são a base de um ajuste detalhado bem-sucedido. Você vai usar o conjunto de dados WikiLingua, transformá-lo no formato JSONL específico exigido pelo Gemini e fazer upload dele para seu bucket de armazenamento.
- No terminal, crie um arquivo chamado
prepare_data.py.cloudshell edit prepare_data.py - Cole o código a seguir em
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() - No terminal, execute o script de preparação de dados.
python prepare_data.py
7. Estabelecer a performance de referência
Antes do ajuste fino, você precisa de um comparativo de mercado. Você vai medir o desempenho do modelo gemini-2.5-flash na tarefa de resumo usando pontuações ROUGE.
- No terminal, crie um arquivo chamado
evaluate.py.cloudshell edit evaluate.py - Cole o código a seguir em
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() - No terminal, execute a avaliação do valor de referência.
Isso vai gerar um arquivopython evaluate.py --model "gemini-2.5-flash" --output "baseline.json"baseline.jsone um gráfico emplots/baseline_dist.png.
8. Configurar e iniciar o ajuste refinado
Agora você vai iniciar um job de ajuste gerenciado na Vertex AI.
- No terminal, crie um arquivo chamado
tune.py.cloudshell edit tune.py - Cole o código a seguir em
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() - No terminal, execute o script de ajuste refinado.
Observação: esse processo pode levar cerca de 45 minutos. É possível monitorar o job no console da Vertex AI.python tune.py
9. Entenda o código de treinamento
Enquanto o job está em execução, vamos analisar o script tune.py para entender como funciona o ajuste fino.
Ajuste supervisionado gerenciado
O script usa o método vertexai.tuning.sft.train para enviar um job de ajuste gerenciado. Isso abstrai a complexidade do provisionamento da infraestrutura, da distribuição do treinamento e do gerenciamento de pontos de verificação.
sft_tuning_job = sft.train(
source_model="gemini-2.5-flash",
train_dataset=f"gs://{BUCKET_NAME}/datasets/train/train_gemini.jsonl",
# ...
)
Configuração do LoRA
Em vez de definir manualmente um LoraConfig, como você faria em frameworks de código aberto, a Vertex AI simplifica isso em alguns parâmetros principais:
adapter_size: esse parâmetro (definido como4no nosso script) controla a classificação dos adaptadores LoRA. Um tamanho maior permite que o modelo aprenda adaptações mais complexas, mas aumenta o número de parâmetros treináveis.epochs: definimos esse valor como1para manter o tempo de treinamento curto (~20 minutos). Em um cenário de produção, você pode aumentar esse valor para permitir que o modelo aprenda mais profundamente com seus dados, mas fique atento ao overfitting.
Seleção de modelo
Especificamos explicitamente source_model="gemini-2.5-flash". A Vertex AI oferece suporte a várias versões do Gemini, e fixar uma versão específica garante que seu pipeline permaneça estável e reproduzível.
10. Comparação de modelos
Depois que o job de ajuste fino for concluído, compare a performance do novo modelo com o valor de referência.
- Receba o endpoint do modelo ajustado. Ele foi impresso no final do script
tune.py. Ele vai ficar parecido comprojects/.../locations/.../endpoints/.... - Execute o script de avaliação novamente, desta vez transmitindo o modelo ajustado e os resultados de referência para comparação.
# 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" - Veja os resultados. O script vai gerar uma comparação das pontuações ROUGE e um gráfico
plots/comparison.pngmostrando a melhoria.Para ver os gráficos, abra a pastaplotsno editor do Cloud Shell.
11. Limpar
Para evitar cobranças, exclua os recursos criados.
- No terminal, exclua o bucket do Cloud Storage e o modelo ajustado.
gcloud storage rm -r gs://$BUCKET_NAME # Note: You can delete the model endpoint from the Vertex AI Console
12. Parabéns!
Você ajustou o Gemini 2.5 Flash na Vertex AI.
Recapitulação
Neste laboratório, você vai:
- Preparou um conjunto de dados no formato JSONL para ajuste fino do Gemini.
- Estabelecemos um valor de referência usando o modelo básico Gemini 2.5 Flash.
- Iniciou um job de ajuste supervisionado na Vertex AI.
- Avaliou e comparou o modelo ajustado com o valor de referência.
A seguir
Este laboratório faz parte do programa de aprendizado IA pronta para produção com o Google Cloud.
Confira o currículo completo para diminuir a distância entre o protótipo e a produção.
Compartilhe seu progresso com a hashtag #ProductionReadyAI.