1. Introducción
En este lab, aprenderás a realizar el flujo de trabajo completo del ajuste supervisado en un modelo de Google Gemini para adaptarlo a una tarea específica: el resumen de artículos. Si bien los modelos de lenguaje grandes son potentes, su naturaleza de uso general significa que se pueden hacer aún más eficaces para casos de uso específicos a través del ajuste. Si entrenas el modelo con un conjunto de datos de ejemplos de alta calidad, puedes mejorar su coherencia, calidad y eficiencia para tu tarea objetivo.
Usarás Gemini 2.5 Flash, un modelo ligero y rentable, y realizarás el ajuste con Vertex AI.
Descripción general de la arquitectura
Esto es lo que compilaremos:
- Cloud Shell: Tu entorno de desarrollo.
- Cloud Storage: Almacena datos de entrenamiento y validación en formato JSONL.
- Vertex AI Training: Administra el trabajo de ajuste.
- Extremo de Vertex AI: Aloja tu modelo ajustado.
Qué aprenderás
- Prepara conjuntos de datos de alta calidad para el ajuste supervisado.
- Configurar y, luego, iniciar trabajos de ajuste con el SDK de Vertex AI para Python
- Evalúa modelos con métricas automatizadas (puntuaciones de ROUGE).
- Compara los modelos base y los ajustados para cuantificar las mejoras.
2. Configura el proyecto
Cuenta de Google
Si aún no tienes una Cuenta de Google personal, debes crear una.
Usa una cuenta personal en lugar de una cuenta de trabajo o de institución educativa.
Accede a la consola de Google Cloud
Accede a la consola de Google Cloud con una Cuenta de Google personal.
Habilitar facturación
Canjea USD 5 en créditos de Google Cloud (opcional)
Para realizar este taller, necesitas una cuenta de facturación con algo de crédito. Si planeas usar tu propia facturación, puedes omitir este paso.
- Haz clic en este vínculo y accede con una Cuenta de Google personal.Verás algo como lo siguiente:

- Haz clic en el botón HAZ CLIC AQUÍ PARA ACCEDER A TUS CRÉDITOS.Se te dirigirá a una página para configurar tu perfil de facturación

- Haz clic en Confirmar.
Ahora estás conectado a una cuenta de facturación de prueba de Google Cloud Platform.

Crear un proyecto (opcional)
Si no tienes un proyecto actual que quieras usar para este lab, crea uno nuevo aquí.
3. Abre el editor de Cloud Shell
- Haz clic en este vínculo para navegar directamente al editor de Cloud Shell.
- Si se te solicita autorización en algún momento, haz clic en Autorizar para continuar.

- Si la terminal no aparece en la parte inferior de la pantalla, ábrela:
- Haz clic en Ver.
- Haz clic en Terminal.

- En la terminal, configura tu proyecto con este comando:
gcloud config set project [PROJECT_ID]- Ejemplo:
gcloud config set project lab-project-id-example - Si no recuerdas el ID de tu proyecto, puedes enumerar todos tus IDs de proyecto con el siguiente comando:
gcloud projects list
- Ejemplo:
- Deberías ver el siguiente mensaje:
Updated property [core/project].
4. Habilita las APIs
Para usar Vertex AI y otros servicios, debes habilitar las APIs necesarias en tu proyecto de Google Cloud.
- En la terminal, habilita las APIs:
- API de Vertex AI (
aiplatform.googleapis.com): Permite usar Vertex AI para ajustar y entregar modelos. - API de Cloud Storage (
storage.googleapis.com): Permite almacenar conjuntos de datos y artefactos del modelo.
gcloud services enable aiplatform.googleapis.com \ storage.googleapis.com - API de Vertex AI (
5. Configurar el entorno del proyecto
Crea un directorio de trabajo
- En la terminal, crea un directorio para tu proyecto y navega a él.
mkdir gemini-finetuning cd gemini-finetuning
Configura variables de entorno
- En la terminal, define las variables de entorno para tu proyecto. Crearemos un archivo
env.shpara almacenar estas variables, de modo que se puedan volver a cargar fácilmente si se desconecta tu sesión.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
Crea un bucket de Cloud Storage
- En la terminal, crea un bucket para almacenar tu conjunto de datos y los artefactos del modelo.
gcloud storage buckets create gs://$BUCKET_NAME --project=$PROJECT_ID --location=$REGION
Configura el entorno virtual
- Usaremos
uvpara administrar nuestro entorno de Python. En la terminal, ejecuta lo siguiente:uv venv .venv source .venv/bin/activate - En la terminal, instala los paquetes de Python necesarios.
uv pip install google-cloud-aiplatform rouge-score matplotlib pandas tqdm
6. Prepara los datos de entrenamiento
Los datos de calidad son la base de un ajuste fino exitoso. Usarás el conjunto de datos de WikiLingua, lo transformarás en el formato JSONL específico que requiere Gemini y lo subirás a tu bucket de almacenamiento.
- En la terminal, crea un archivo llamado
prepare_data.py.cloudshell edit prepare_data.py - Pega el siguiente código en
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() - En la terminal, ejecuta la secuencia de comandos de preparación de datos.
python prepare_data.py
7. Establece un rendimiento de referencia
Antes de ajustar el modelo, necesitas una referencia. Medirás qué tan bien se desempeña el modelo gemini-2.5-flash base en la tarea de resumen con las puntuaciones ROUGE.
- En la terminal, crea un archivo llamado
evaluate.py.cloudshell edit evaluate.py - Pega el siguiente código en
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() - En la terminal, ejecuta la evaluación del modelo de referencia.
Esto generará un archivopython evaluate.py --model "gemini-2.5-flash" --output "baseline.json"baseline.jsony un gráfico enplots/baseline_dist.png.
8. Configura y lanza el ajuste
Ahora iniciarás un trabajo de ajuste administrado en Vertex AI.
- En la terminal, crea un archivo llamado
tune.py.cloudshell edit tune.py - Pega el siguiente código en
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() - En la terminal, ejecuta la secuencia de comandos de ajuste.
Nota: Este proceso puede tardar alrededor de 45 minutos. Puedes supervisar el trabajo en la consola de Vertex AI.python tune.py
9. Comprende el código de entrenamiento
Mientras se ejecuta tu trabajo, analicemos con más detalle el script tune.py para comprender cómo funciona el ajuste.
Ajuste supervisado administrado
La secuencia de comandos usa el método vertexai.tuning.sft.train para enviar un trabajo de ajuste administrado. Esto abstrae la complejidad del aprovisionamiento de la infraestructura, la distribución del entrenamiento y la administración de los puntos de control.
sft_tuning_job = sft.train(
source_model="gemini-2.5-flash",
train_dataset=f"gs://{BUCKET_NAME}/datasets/train/train_gemini.jsonl",
# ...
)
Configuración de LoRA
En lugar de definir manualmente un LoraConfig como lo harías en los frameworks de código abierto, Vertex AI simplifica este proceso en algunos parámetros clave:
adapter_size: Este parámetro (establecido en4en nuestro script) controla el rango de los adaptadores de LoRA. Un tamaño más grande permite que el modelo aprenda adaptaciones más complejas, pero aumenta la cantidad de parámetros entrenables.epochs: Establecimos este valor en1para este lab para que el tiempo de entrenamiento sea corto (alrededor de 20 minutos). En una situación de producción, podrías aumentar este valor para permitir que el modelo aprenda más profundamente a partir de tus datos, aunque debes tener cuidado con el sobreajuste.
Selección de modelo
Especificamos source_model="gemini-2.5-flash" de forma explícita. Vertex AI admite varias versiones de Gemini, y fijar una versión específica garantiza que tu canalización siga siendo estable y reproducible.
10. Comparar modelos
Una vez que se complete el trabajo de ajuste, podrás comparar el rendimiento de tu nuevo modelo con el de referencia.
- Obtén el extremo del modelo ajustado. Se imprimió al final de la secuencia de comandos
tune.py. Se verá de la siguiente manera:projects/.../locations/.../endpoints/... - Vuelve a ejecutar la secuencia de comandos de evaluación, pero esta vez pasa tu modelo ajustado y los resultados del modelo de referencia para la comparación.
# 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" - Consulta los resultados. La secuencia de comandos generará una comparación de las puntuaciones de ROUGE y un gráfico de
plots/comparison.pngque muestra la mejora.Para ver los gráficos, abre la carpetaplotsen el editor de Cloud Shell.
11. Limpia
Para evitar que se generen cargos, borra los recursos que creaste.
- En la terminal, borra el bucket de Cloud Storage y el modelo ajustado.
gcloud storage rm -r gs://$BUCKET_NAME # Note: You can delete the model endpoint from the Vertex AI Console
12. ¡Felicitaciones!
Ajustaste correctamente Gemini 2.5 Flash en Vertex AI.
Resumen
En este lab, aprenderás a hacer lo siguiente:
- Preparamos un conjunto de datos en formato JSONL para el ajuste de Gemini.
- Se estableció un valor de referencia con el modelo base de Gemini 2.5 Flash.
- Se lanzó un trabajo de ajuste supervisado en Vertex AI.
- Se evaluó y comparó el modelo ajustado con el modelo de referencia.
¿Qué sigue?
Este lab forma parte de la ruta de aprendizaje IA lista para la producción con Google Cloud.
Explora el plan de estudios completo para cerrar la brecha entre el prototipo y la producción.
Comparte tu progreso con el hashtag #ProductionReadyAI.