Запуск процесса Supervised Fine-Tuning (SFT) через API

45 минут Урок 23

Урок: Запуск процесса Supervised Fine-Tuning (SFT) через API

Приветствую, коллеги! Мы подошли к самому захватывающему этапу нашего модуля — непосредственному обучению модели. Вы уже подготовили данные, очистили их от шума и привели в формат JSONL. Теперь эти данные станут топливом для создания вашей уникальной версии Gemini.

В этом уроке мы отойдем от графических интерфейсов вроде Google AI Studio и погрузимся в программное управление процессом через Python SDK. Почему это важно? Потому что настоящая автоматизация, CI/CD пайплайны для ML и масштабируемые решения строятся именно на коде, а не на ручных кликах мышкой.

Что мы разберем сегодня:

  • Как загрузить обучающий датасет в облако Google.
  • Анатомия вызова функции create_tuned_model.
  • Магия гиперпараметров: как не переобучить и не недообучить модель.
  • Мониторинг состояния задачи (Job polling).
  • Инференс: как правильно обращаться к только что обученной модели.

Шаг 1: Подготовка окружения и авторизация

Прежде чем запускать тяжелые вычислительные процессы, убедимся, что у нас настроен доступ. Мы будем использовать библиотеку google-generativeai. Если вы работаете в production-среде, я настоятельно рекомендую не хранить API-ключи в коде, а использовать переменные окружения.

Fine-Tuning — это асинхронная операция. Это значит, что вы отправляете запрос, сервер говорит «Принято», и процесс идет в облаке Google, не блокируя ваш скрипт. Но для начала нам нужно «представиться» системе.

python
import os
import time
import google.generativeai as genai

# Настройка API ключа
# В реальном проекте используйте os.environ.get('GOOGLE_API_KEY')
os.environ['GOOGLE_API_KEY'] = 'ВАШ_КЛЮЧ_ЗДЕСЬ'
genai.configure(api_key=os.environ['GOOGLE_API_KEY'])

print("Библиотека импортирована, клиент настроен.")

Шаг 2: Загрузка данных (Data Ingestion)

API Gemini не может обучать модель на файле, который лежит у вас на жестком диске. Сначала файл нужно передать в хранилище Google. Для этого используется File API.

Важный нюанс: для Fine-Tuning формат данных должен быть строго определенным (обычно это список JSON-объектов с ключами messages или text_input/output в зависимости от версии модели). В рамках Gemini 3 мы ориентируемся на чат-формат.

Критерии к файлу:

  • Формат: JSONL (JSON Lines).
  • Размер: Не превышайте лимиты (обычно до 100-500 МБ для тюнинга, но лучше начинать с малого — 50-100 примеров для теста).

python
# Путь к вашему подготовленному файлу
file_path = 'training_data.jsonl'

# Загрузка файла в облако
training_file = genai.upload_file(
    path=file_path,
    display_name='My SFT Dataset v1',
    mime_type='application/json'
)

print(f"Файл загружен. URI: {training_file.uri}")
print(f"Состояние файла: {training_file.state.name}")

# Важно: Файл должен быть в состоянии ACTIVE перед использованием
while training_file.state.name == 'PROCESSING':
    print("Обработка файла...")
    time.sleep(2)
    training_file = genai.get_file(training_file.name)

print(f"Файл готов к использованию: {training_file.name}")

Шаг 3: Запуск задачи Fine-Tuning

Теперь самое интересное. Метод genai.create_tuned_model — это ваш пульт управления. Здесь вы определяете, какая базовая модель станет фундаментом (например, gemini-1.5-flash-001-tuning) и как именно она будет учиться.

Разбор гиперпараметров

Это не просто цифры, это рычаги управления "мозгами" модели:

  • Epochs (Эпохи): Сколько раз модель увидит весь ваш датасет.
    • Мало (1-2): Модель может не уловить паттерны (Underfitting).
    • Много (10+): Модель просто вызубрит ответы и перестанет обобщать (Overfitting).
    • Рекомендация: Начните с 3-5 эпох.
  • Batch Size (Размер батча): Сколько примеров модель обрабатывает за один шаг обновления весов.
    • Большой батч = стабильное обучение, но требует много памяти (Google берет это на себя).
    • Маленький батч = обучение более "шумное", но иногда помогает выбраться из локальных минимумов.
  • Learning Rate (Скорость обучения): Обычно подбирается автоматически, но если вы видите, что Loss (ошибка) скачет как сумасшедшая — возможно, шаг слишком велик.

python
model_id = "tuned-gemini-demo-v1" # Уникальное имя вашей модели

operation = genai.create_tuned_model(
    # Указываем, какую модель дообучаем. Важно брать версию, поддерживающую тюнинг.
    source_model="models/gemini-1.5-flash-001-tuning",
    training_data=training_file.name,
    id=model_id,
    display_name="Customer Support Bot",
    description="Модель для ответов в стиле техподдержки",
    # Гиперпараметры
    epoch_count=5,
    batch_size=4,
    learning_rate=0.001,
)

print(f"Запущена задача тюнинга: {operation.name}")

Шаг 4: Мониторинг прогресса (The Waiting Game)

После запуска create_tuned_model возвращает объект операции. Обучение не происходит мгновенно. В зависимости от размера данных и загрузки серверов Google, это может занять от 10 минут до нескольких часов.

Нам нужно периодически опрашивать API, чтобы узнать статус. Мы ищем состояние SUCCEEDED (Успешно) или FAILED (Ошибка).

Что может пойти не так?

  • Ошибка валидации данных (битый JSON).
  • Слишком мало данных.
  • Внутренняя ошибка сервера (редко, но бывает).

python
import sys

print("Ожидание завершения обучения...")

# Цикл опроса статуса
while True:
    status = operation.metadata.state.name
    
    # Выводим прогресс
    # В реальном API могут быть доступны snapshots, здесь смотрим на статус
    sys.stdout.write(f"\rСтатус: {status}")
    sys.stdout.flush()
    
    if status == 'SUCCEEDED':
        print("\nОбучение успешно завершено!")
        break
    elif status == 'FAILED':
        print(f"\nОшибка обучения: {operation.error}")
        break
    
    # Обновляем объект операции
    time.sleep(10)
    try:
        # В SDK метод обновления может отличаться, 
        # часто используют get_tuned_model для проверки готового результата
        model_info = genai.get_tuned_model(f"tunedModels/{model_id}")
        if model_info.state.name != status:
             # Если статус изменился, цикл поймает это на следующей итерации
             pass
    except Exception as e:
        # Иногда модель еще не создана в реестре
        pass

# Получаем финальный объект модели
final_model = genai.get_tuned_model(f"tunedModels/{model_id}")
print(f"\nМодель доступна по адресу: {final_model.name}")

Шаг 5: Использование дообученной модели

Поздравляю! Если вы дошли до этого этапа, у вас есть своя собственная LLM. Но как её вызвать? Она не заменяет базовую модель глобально, она доступна только в вашем проекте.

Для инференса мы используем тот же метод generate_content, но в аргументе model указываем полный путь к нашей новой модели: tunedModels/{ваш_id}.

python
# Инициализация модели с нашим ID
model = genai.GenerativeModel(model_name=f'tunedModels/{model_id}')

# Тестовый запрос
prompt = "У меня не работает тостер, мигает красная лампочка."

response = model.generate_content(prompt)

print("Ответ модели:")
print(response.text)
Упражнение

Создайте скрипт, который автоматизирует весь пайплайн SFT. 1. Создайте фиктивный JSONL файл (5 примеров) для классификатора тональности (Позитив/Негатив). 2. Загрузите его через API. 3. Запустите обучение на 2 эпохи. 4. Напишите функцию, которая принимает текст и возвращает классификацию, используя вашу новую модель.

Вопрос

Вы запустили процесс Fine-Tuning, но через 5 минут статус задачи перешел в 'FAILED'. Какая причина наиболее вероятна, если вы использовали код из урока?

Заключение

Сегодня мы разобрали программный способ создания SFT-моделей. Это мощный инструмент. В отличие от промпт-инжиниринга, где мы каждый раз "уговариваем" модель вести себя определенным образом, Fine-Tuning меняет саму структуру весов модели.

В следующем уроке мы поговорим о том, как оценивать качество обученной модели, используя метрики Loss и тестовые выборки, чтобы понять, действительно ли она стала умнее или просто запомнила ответы.