1. Введение
В этой лабораторной работе вы научитесь выполнять полный рабочий процесс контролируемой тонкой настройки модели Google Gemini, чтобы адаптировать ее для конкретной задачи: составления кратких обзоров статей. Хотя большие языковые модели обладают большой мощностью, их универсальность позволяет сделать их еще более эффективными для конкретных задач с помощью тонкой настройки. Обучив модель на высококачественном наборе примеров, вы сможете улучшить ее согласованность, качество и эффективность для вашей целевой задачи.
Вы будете использовать Gemini 2.5 Flash , легкую и экономичную модель, а тонкую настройку будете выполнять с помощью Vertex AI .
Обзор архитектуры
Вот что мы построим:
- Cloud Shell : Ваша среда разработки.
- Облачное хранилище : хранит данные для обучения/проверки в формате JSONL.
- Vertex AI Training : управляет процессом тонкой настройки.
- Vertex AI Endpoint : размещает вашу точно настроенную модель.
Что вы узнаете
- Подготовьте высококачественные наборы данных для контролируемой тонкой настройки.
- Настройте и запустите задачи тонкой настройки с помощью Vertex AI SDK для Python .
- Оцените модели, используя автоматизированные метрики (оценки ROUGE).
- Сравните базовую и доработанную модели, чтобы количественно оценить улучшения.
2. Настройка проекта
Аккаунт Google
Если у вас еще нет личного аккаунта Google, вам необходимо его создать .
Используйте личный аккаунт вместо рабочего или учебного.
Войдите в консоль Google Cloud.
Войдите в консоль Google Cloud, используя личную учетную запись Google.
Включить выставление счетов
Обменяйте 5 долларов США на кредиты Google Cloud (по желанию)
Для проведения этого мастер-класса вам потребуется платежный аккаунт с достаточным балансом. Если вы планируете использовать собственную платежную систему, этот шаг можно пропустить.
- Перейдите по этой ссылке и войдите в систему, используя свой личный аккаунт Google. Вы увидите примерно следующее:

- Нажмите кнопку «НАЖМИТЕ ЗДЕСЬ ДЛЯ ДОСТУПА К ВАШИМ КРЕДИТАМ». Это переведет вас на страницу настройки вашего платежного профиля.

- Нажмите «Подтвердить».
Теперь вы подключены к пробному платёжному аккаунту Google Cloud Platform.

Создать проект (необязательно)
Если у вас нет текущего проекта, который вы хотели бы использовать для этой лабораторной работы, создайте новый проект здесь .
3. Откройте редактор Cloud Shell.
- Нажмите на эту ссылку, чтобы перейти непосредственно в редактор Cloud Shell.
- Если сегодня вам будет предложено авторизоваться, нажмите «Авторизовать» , чтобы продолжить.

- Если терминал не отображается внизу экрана, откройте его:
- Нажмите «Просмотреть».
- Нажмите «Терминал»

- В терминале настройте свой проект с помощью этой команды:
gcloud config set project [PROJECT_ID]- Пример:
gcloud config set project lab-project-id-example - Если вы не помните идентификатор своего проекта, вы можете перечислить все идентификаторы своих проектов с помощью следующей команды:
gcloud projects list
- Пример:
- Вы должны увидеть следующее сообщение:
Updated property [core/project].
4. Включите API.
Для использования Vertex AI и других сервисов необходимо включить необходимые API в вашем проекте Google Cloud.
- В терминале включите API:
- API Vertex AI (
aiplatform.googleapis.com): позволяет использовать Vertex AI для тонкой настройки и запуска моделей. - API облачного хранилища (
storage.googleapis.com): позволяет хранить наборы данных и артефакты моделей.
gcloud services enable aiplatform.googleapis.com \ storage.googleapis.com - API Vertex AI (
5. Настройка среды проекта
Создайте рабочую директорию
- В терминале создайте директорию для вашего проекта и перейдите в неё.
mkdir gemini-finetuning cd gemini-finetuning
Настройте переменные среды
- В терминале определите переменные окружения для вашего проекта. Мы создадим файл
env.shдля хранения этих переменных, чтобы их можно было легко перезагрузить в случае разрыва сессии.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
Создайте корзину облачного хранилища.
- В терминале создайте хранилище (bucket) для хранения вашего набора данных и артефактов модели.
gcloud storage buckets create gs://$BUCKET_NAME --project=$PROJECT_ID --location=$REGION
Настройка виртуальной среды
- Для управления средой Python мы будем использовать
uv. В терминале выполните следующую команду:uv venv .venv source .venv/bin/activate - В терминале установите необходимые пакеты Python.
uv pip install google-cloud-aiplatform rouge-score matplotlib pandas tqdm
6. Подготовьте обучающие данные.
Качественные данные — основа успешной тонкой настройки. Вы будете использовать набор данных WikiLingua , преобразовывать его в специфический формат JSONL, требуемый Gemini, и загружать в свой накопитель.
- В терминале создайте файл с именем
prepare_data.py.cloudshell edit prepare_data.py - Вставьте следующий код в
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() - В терминале запустите скрипт подготовки данных.
python prepare_data.py
7. Определите базовый уровень производительности.
Перед тонкой настройкой вам потребуется эталонный показатель. Вы измерите, насколько хорошо базовая модель gemini-2.5-flash справляется с задачей суммаризации, используя показатели ROUGE.
- В терминале создайте файл с именем
evaluate.py.cloudshell edit evaluate.py - Вставьте следующий код в
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() - В терминале запустите базовую оценку.
В результате будет создан файлpython evaluate.py --model "gemini-2.5-flash" --output "baseline.json"baseline.jsonи график вplots/baseline_dist.png.
8. Настройте и запустите тонкую настройку.
Теперь вы запустите управляемую задачу тонкой настройки в Vertex AI.
- В терминале создайте файл с именем
tune.pycloudshell edit tune.py - Вставьте следующий код в
tune.pyimport 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() - В терминале запустите скрипт тонкой настройки.
Примечание : Этот процесс может занять около 45 минут. Вы можете отслеживать ход выполнения задания в консоли Vertex AI .python tune.py
9. Разберитесь в коде обучения.
Пока ваша задача выполняется, давайте подробнее рассмотрим скрипт tune.py , чтобы понять, как работает тонкая настройка.
Управляемая контролируемая тонкая настройка
Скрипт использует метод vertexai.tuning.sft.train для отправки управляемого задания на настройку. Это позволяет избежать сложностей, связанных с выделением инфраструктуры, распределением обучающих данных и управлением контрольными точками.
sft_tuning_job = sft.train(
source_model="gemini-2.5-flash",
train_dataset=f"gs://{BUCKET_NAME}/datasets/train/train_gemini.jsonl",
# ...
)
Конфигурация LoRA
Вместо того чтобы вручную задавать LoraConfig , как это можно делать в фреймворках с открытым исходным кодом, Vertex AI упрощает этот процесс, сводя его к нескольким ключевым параметрам:
-
adapter_size: Этот параметр (в нашем скрипте установлен на4) управляет рангом адаптеров LoRA. Больший размер позволяет модели изучать более сложные адаптации, но увеличивает количество обучаемых параметров. -
epochs: В этой лабораторной работе мы установили это значение равным1, чтобы сократить время обучения (~20 минут). В реальных условиях вы можете увеличить это значение, чтобы модель могла глубже обучаться на ваших данных, хотя следует остерегаться переобучения.
Выбор модели
Мы явно указываем source_model="gemini-2.5-flash" . Vertex AI поддерживает различные версии Gemini, и указание конкретной версии гарантирует стабильность и воспроизводимость вашего конвейера.
10. Сравните модели
После завершения тонкой настройки вы можете сравнить производительность вашей новой модели с базовым показателем.
- Получите конечную точку вашей настроенной модели. Она была выведена в конце скрипта
tune.pyОна будет выглядеть примерно так:projects/.../locations/.../endpoints/.... - Запустите скрипт оценки еще раз, на этот раз передав для сравнения вашу настроенную модель и результаты базовой версии.
# 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" - Просмотрите результаты. Скрипт выведет сравнение оценок ROUGE и сгенерирует диаграмму
plots/comparison.png, демонстрирующую улучшение. Вы можете просмотреть графики, открыв папкуplotsв редакторе Cloud Shell.
11. Уборка
Чтобы избежать дополнительных расходов, удалите созданные вами ресурсы.
- В терминале удалите сегмент Cloud Storage и настроенную модель.
gcloud storage rm -r gs://$BUCKET_NAME # Note: You can delete the model endpoint from the Vertex AI Console
12. Поздравляем!
Вы успешно выполнили тонкую настройку Gemini 2.5 Flash на Vertex AI!
Краткий обзор
В этой лаборатории вы:
- Для тонкой настройки Gemini был подготовлен набор данных в формате JSONL.
- Установлены базовые параметры с использованием базовой модели Gemini 2.5 Flash.
- Запущена задача контролируемой тонкой настройки в Vertex AI.
- Была проведена оценка и сравнение доработанной модели с базовой.
Что дальше?
Данная лабораторная работа является частью учебного курса "Готовый к внедрению ИИ в производство с использованием Google Cloud" .
Изучите полный учебный план, чтобы преодолеть разрыв между прототипом и серийным производством.
Делитесь своими успехами, используя хэштег #ProductionReadyAI .