RLVR обучение с GRPO: практический гайд с кодом в Jupyter notebook | AiManual
AiManual Logo Ai / Manual.
18 Янв 2026 Гайд

RLVR с GRPO: от теории к работающему коду в ноутбуке

Пошаговое руководство по RLVR с GRPO алгоритмом. Учим LLM с подкреплением с нуля: установка, код, обучение, ошибки. Полный ноутбук с кодом.

Зачем RLVR, если есть обычный RLHF?

Потому что RLHF - это как строить дом через черный ход. Сначала собираешь датасет предпочтений, потом обучаешь reward-модель, потом через PPO пытаешься не сломать исходную модель. Каждый этап - отдельная боль. А RLVR (Reinforcement Learning from Verbalized Rewards) выбрасывает reward-модель в мусорку.

RLVR работает так: модель сама генерирует текстовые оценки своих действий, а потом учится на них. Нет отдельного критика - модель сама себе и актер, и критик. Элегантно? Да. Просто реализовать? Сейчас увидите.

GRPO: алгоритм, который DeepSeekMath сделал мейнстримом

Если вы читали нашу статью про GRPO от DeepSeekMath, то знаете: Group Relative Policy Optimization - это RL без reward-модели. Вместо сравнения с одной наградой, модель сравнивает себя с группой других ответов.

Почему это работает лучше? Потому что относительные сравнения стабильнее абсолютных оценок. Сказать "этот ответ лучше того" проще, чем поставить точную оценку от 1 до 10. Мозг человека так и работает.

1 Подготовка среды: что установить и почему

Не начинайте с pip install transformers. Это путь к dependency hell. Вот минимальный рабочий стек:

# Создаем чистое окружение
conda create -n rlvr python=3.10 -y
conda activate rlvr

# Базовые зависимости
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118

# TRL - наш основной инструмент
pip install trl==0.8.0

# Для работы с моделями
pip install transformers==4.38.0 accelerate datasets

# Для визуализации
pip install matplotlib seaborn tqdm

Версии важны! TRL 0.8.0 стабильно работает с GRPO. Новые версии могут ломать API. Если хотите экономить память, добавьте unsloth - об этом в статье про Unsloth GRPO.

2 Структура ноутбука: от импортов до обучения

Откройте Jupyter и создайте ячейку с импортами:

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
from trl import GRPOConfig, GRPOTrainer
from datasets import Dataset
import numpy as np
import warnings
warnings.filterwarnings('ignore')

# Проверяем GPU
print(f"CUDA доступен: {torch.cuda.is_available()}")
print(f"GPU: {torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'CPU only'}")

Теперь главное: понимание данных. RLVR нужны промпты и... все. Модель сама сгенерирует ответы и их оценки.

Создаем датасет: как НЕ надо делать

Видел в интернете такие конструкции:

# НЕ ДЕЛАЙТЕ ТАК
prompts = [
    "Напиши код сортировки пузырьком",
    "Объясни квантовую запутанность",
    "Напиши стих про DevOps"
]

Проблема в том, что модель не понимает контекста. Нужны промпты, которые заставляют модель рассуждать. Вот рабочий пример:

# Правильный подход
prompts = [
    "Ты - опытный разработчик Python. Напиши функцию, которая проверяет, является ли число простым. Объясни свой подход шаг за шагом.",
    "Ты - математик. Реши задачу: 'У Васи было 5 яблок, 2 он отдал Пете. Сколько яблок осталось у Васи?' Покажи решение с объяснением.",
    "Ты - системный администратор. Опиши процесс диагностики проблемы, когда сервер не отвечает на ping. Будь максимально подробным."
]

# Создаем датасет
dataset_dict = {
    "prompt": prompts,
    "chosen": [""] * len(prompts),  # Пустые строки - модель заполнит
    "rejected": [""] * len(prompts)  # То же самое
}

dataset = Dataset.from_dict(dataset_dict)
💡
Зачем пустые строки в chosen/rejected? Потому что GRPO сам сгенерирует несколько ответов на каждый промпт и выберет лучший. Ваша задача - только промпты. Модель сделает остальное.

3 Выбор модели: какая подойдет для ноутбука

Не берите Llama 3.1 8B для RTX 4070 - она съест всю память. Проверяли в статье про тонкую настройку на ноутбуке.

Вот рабочие варианты:

Модель Параметры VRAM (4-bit) Подходит для
Qwen2.5-1.5B 1.5B ~2GB Любой ноутбук
Phi-3-mini 3.8B ~4GB RTX 3060+
Gemma-2-2B 2B ~3GB Средние GPU
# Загружаем модель и токенизатор
model_name = "Qwen/Qwen2.5-1.5B-Instruct"

tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token  # Важно для padding

model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype=torch.float16,
    device_map="auto",
    load_in_4bit=True,  # Квантование для экономии памяти
    bnb_4bit_compute_dtype=torch.float16
)

Конфигурация GRPO: магия в деталях

Вот где большинство спотыкается. Берут дефолтные параметры и удивляются, почему модель не учится.

# НЕПРАВИЛЬНО - дефолтные параметры
grpo_config = GRPOConfig()

А вот рабочий конфиг:

grpo_config = GRPOConfig(
    model_name=model_name,
    learning_rate=1e-5,  # Маленький LR для RL
    batch_size=1,  # На ноутбуке больше не потянуть
    gradient_accumulation_steps=8,  # Эмулируем batch_size=8
    num_generations=4,  # Сколько ответов генерировать на промпт
    num_sample_per_generation=2,  # Сколько сэмплов брать из каждого ответа
    max_length=512,  # Максимальная длина ответа
    max_prompt_length=256,  # Максимальная длина промпта
    temperature=0.7,  # Баланс между креативностью и стабильностью
    top_p=0.9,
    use_score_scaling=True,  # Важно для стабильности
    use_score_norm=True,
    score_clip=0.5,  # Обрезаем экстремальные оценки
    kl_coeff=0.02,  # Коэффициент KL-дивергенции
    ppo_epochs=4,  # Количество PPO эпох на батч
    seed=42
)

num_generations=4 означает, что на каждый промпт модель сгенерирует 4 разных ответа. Потом из каждого ответа возьмет 2 сэмпла для оценки. Итого 8 оценок на промпт. Это и есть "group" в GRPO.

4 Тренировка: запускаем и не паникуем

Создаем тренер и запускаем обучение:

trainer = GRPOTrainer(
    model=model,
    config=grpo_config,
    train_dataset=dataset,
    tokenizer=tokenizer,
)

# Предварительная обработка данных
trainer.preprocess_datasets()

# Запускаем обучение
trainer.train()

Первые 10-20 шагов вы увидите странные вещи: loss скачет, rewards отрицательные. Это нормально. Модель учится оценивать свои же ответы.

Что происходит внутри: механика RLVR

По шагам:

  1. Модель получает промпт
  2. Генерирует 4 разных ответа (с разными temperature сэмплами)
  3. Для каждого ответа генерирует текстовую оценку вроде "Этот ответ хорош, потому что..."
  4. Преобразует текстовые оценки в числовые scores
  5. Сравнивает scores между ответами (group relative comparison)
  6. Обновляет веса, чтобы увеличить вероятность лучших ответов

Ключевой момент: модель учится не просто давать "правильные" ответы, а давать ответы, которые она сама оценит как хорошие. Это создает петлю самоулучшения.

Ошибки, которые сломают ваш эксперимент

Ошибка Симптом Решение
Нет pad_token RuntimeError: No padding token tokenizer.pad_token = tokenizer.eos_token
Слишком большой batch_size CUDA out of memory batch_size=1 + gradient_accumulation
Слишком высокий temperature Бессмысленные ответы temperature=0.3-0.7
Мало num_generations Модель не учится Минимум 4 поколения

Как оценить результаты: не верьте loss

Loss в RL - ненадежный метрик. Вместо этого:

# После обучения тестируем
test_prompt = "Напиши функцию сложения двух чисел на Python"

inputs = tokenizer(test_prompt, return_tensors="pt").to(model.device)

# Генерируем ответ до обучения (сохраните модель до обучения!)
with torch.no_grad():
    outputs_before = model.generate(**inputs, max_length=200)
    answer_before = tokenizer.decode(outputs_before[0], skip_special_tokens=True)

# Генерируем ответ после обучения
with torch.no_grad():
    outputs_after = model.generate(**inputs, max_length=200)
    answer_after = tokenizer.decode(outputs_after[0], skip_special_tokens=True)

print("До обучения:", answer_before[:200])
print("После обучения:", answer_after[:200])

Ищите:

  • Более структурированные ответы
  • Пояснения шагов (модель учится "думать вслух")
  • Меньше повторов и бессмыслицы

А если мало памяти? Используйте LoRA

Для 8B+ моделей на ноутбуке нужен LoRA. Подробности в статье про GRPO + LoRA на нескольких GPU. Кратко:

from peft import LoraConfig, get_peft_model

lora_config = LoraConfig(
    r=16,  # Rank
    lora_alpha=32,
    target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
    lora_dropout=0.1,
    bias="none",
    task_type="CAUSAL_LM"
)

model = get_peft_model(model, lora_config)

Практическое применение: где это работает

RLVR с GRPO особенно хорош для:

  1. Обучение reasoning - модель учится последовательно мыслить
  2. Специализация на домене - медицинские, юридические, технические ответы
  3. Улучшение структуры ответов - меньше воды, больше конкретики
  4. Обучение с ограниченными данными - не нужны тысячи размеченных примеров

Попробуйте обучить модель на датасете из 50-100 промптов по вашей теме. Результаты удивят.

Что дальше? Эксперименты

Когда освоите базовый пайплайн:

  • Добавьте reward-модель как дополнительный сигнал
  • Экспериментируйте с разными способами verbalized rewards
  • Попробуйте смешать RLVR с supervised fine-tuning
  • Тестируйте на более сложных задачах - математика, код, логические головоломки

Главное - не бойтесь сломать модель. RL обучение нестабильно по определению. Сохраняйте чекпоинты, экспериментируйте с гиперпараметрами, ведите лог экспериментов.

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

RLVR с GRPO - не панацея. Но это самый практичный способ заставить LLM учиться на своих ошибках без танцев с reward-моделями. Начните с маленькой модели, поймите механику, потом масштабируйте. Удачи.