Training Pipeline
Как обучают LLM: pre-training → mid-training → SFT → RLHF. Общая картина процесса.
Как обучают LLM: от сырого текста до ChatGPT
Обучить LLM — это не "нажал кнопку train и ушёл пить кофе". Это конвейер из нескольких этапов, где каждый делает своё дело: сначала модель учит язык, потом учится не быть бесполезным автодополнением, и наконец — быть полезной и не советовать делать бомбы. Разбираемся.
Pre-training: модель учит язык
На первом этапе модель тупо читает интернет. Буквально весь: веб-страницы, книги, код, Wikipedia — триллионы токенов. Задача ровно одна: предсказать следующий токен. "Столица Франции —" → "Париж". И вот так, через миллиарды угадаек, модель выучивает всё — от грамматики до квантовой физики. One trick pony, который работает до неприличия хорошо.
- GPT-3 (2020): 175B параметров, 300B токенов — по современным меркам это мало данных
- Qwen3 (2025): 36T токенов — в 120 раз больше данных, чем GPT-3
- SmolLM3 (2025): 3B параметров, 11T токенов — маленькая модель, но обучена на огромном корпусе
- Compute: сотни GPU, месяцы работы, миллионы долларов. GPT-4 стоил ~$100M на обучение
Сколько это стоит в вычислениях? Есть удивительно простая формула:
Бюджет вычислений: C — FLOPs, N — параметры, D — токены. Умножаем на 6, потому что forward + backward pass ≈ 6 операций на параметр на токен.
А целевая функция — старый добрый cross-entropy loss. Ничего хитрого: модель предсказывает вероятность следующего токена, а мы наказываем её за неуверенность в правильном ответе:
Cross-entropy loss для language modeling. T — количество токенов, p(xₜ | x<ₜ) — вероятность правильного токена.
# Pre-training: всё что нужно — предсказать следующий токен
import torch.nn.functional as F
def pretraining_loss(model, input_ids):
"""Стандартный language modeling loss."""
logits = model(input_ids[:, :-1]) # предсказания для позиций 1..T-1
targets = input_ids[:, 1:] # реальные токены на позициях 1..T
loss = F.cross_entropy(
logits.reshape(-1, logits.size(-1)),
targets.reshape(-1),
ignore_index=-100 # padding не считаем
)
return loss # скаляр: среднее -log p(правильный токен)
# Бюджет: SmolLM3 (3B params, 11T tokens)
flops = 6 * 3e9 * 11e12 # ≈ 2e23 FLOPs
# При A100 ~150 TFLOPS effective → ~370K GPU-часов → ~46 дней на 256 GPUMid-training: усиливаем слабые стороны
Mid-training — опциональный этап между pre-training и SFT. Зачем? После pre-training модель может считать как первоклассник, кодить как джун после пятницы, и падать в обморок от длинных документов. Mid-training фиксит это: подкидываем целевые данные (код, математику, научные статьи) и продолжаем тренировку.
- Расширение контекста: 4K → 128K токенов. Модель учится работать с длинными документами
- Доменная специализация: добавляем код → модель лучше кодит, добавляем math → лучше считает
- Long-context training: используют меньший LR и специальный data mix для длинных последовательностей
- Пример: SmolLM3 использует mid-training для расширения контекста и усиления STEM-навыков
SFT: учим модель быть ассистентом
После pre-training модель — это просто навороченный autocomplete. Ты ей "Как приготовить борщ?", а она тебе "Как приготовить плов? Как приготовить...". SFT (Supervised Fine-Tuning) чинит эту беду: берём ~100K примеров "вопрос → ответ" и дообучаем. После SFT модель наконец понимает, что ты задал вопрос, и отвечает на него.
- Dataset: пары instruction → response. Качество данных важнее количества
- SmolLM3: ~100K примеров, 76M токенов. Think/no_think пары для reasoning
- Chat template: system/user/assistant с специальными токенами. Каждая модель — свой формат
- Loss считается только на assistant tokens — модель учится отвечать, а не повторять вопросы
# SFT данные: пары instruction → response в chat template
sft_example = {
"messages": [
{"role": "system", "content": "Ты полезный ассистент."},
{"role": "user", "content": "Объясни backpropagation в 2 предложениях"},
{"role": "assistant", "content": "Backpropagation считает градиент "
"loss по каждому весу через chain rule — от выхода к входу. "
"Это позволяет обновить все веса нейросети за один проход."}
]
}
# При SFT loss считается ТОЛЬКО на assistant tokens!
# Модель учится отвечать, а не повторять вопросы пользователя
def sft_loss(model, input_ids, label_mask):
logits = model(input_ids[:, :-1])
targets = input_ids[:, 1:]
loss = F.cross_entropy(
logits.reshape(-1, logits.size(-1)),
targets.reshape(-1),
reduction="none"
)
# label_mask: 1 для assistant tokens, 0 для system/user
loss = (loss * label_mask[:, 1:].reshape(-1)).sum() / label_mask.sum()
return lossRLHF/DPO: alignment — учим быть полезной
SFT учит модель подражать датасету. Но мы хотим большего — чтобы модель была лучше своих учителей. Более полезной, честной и без советов "как растворить тело в кислоте". Для этого есть RLHF и DPO. Идея проста: люди сравнивают ответы модели, а модель учится генерить те, которые люди предпочитают.
- RLHF: обучаем reward model → RL оптимизирует policy → модель генерирует лучшие ответы
- DPO: без reward model, напрямую учим из пар preferred/rejected. Проще и стабильнее
- RLVR (DeepSeek-R1): RL с верифицируемыми ответами (math, code). Правильно = +1, неправильно = 0
- Результат: модель отказывается от вредных запросов, даёт структурированные ответы, рефлексирует
Evaluation: проверяем качество
После каждого этапа нужно проверить — модель стала умнее или мы что-то сломали? Для этого есть бенчмарки — стандартизированные экзамены для AI:
- MMLU: общие знания (57 предметов от истории до физики). «Экзамен для AI»
- GPQA: сложные вопросы уровня PhD. Даже эксперты ошибаются в 35% случаев
- AIME: математические олимпиады. Проверяет рассуждение, а не просто знание формул
- SWE-bench: реальные GitHub issues. Модель должна написать patch, который проходит тесты
- LiveCodeBench: свежие задачи с Codeforces/LeetCode, которых не было в train data
🎯 Запомни
Материалы
Практический гайд по всем этапам обучения LLM на примере SmolLM3. Pre-training, mid-training, SFT, DPO.
Как DeepSeek обучили reasoning модель: SFT + RL, cold start, emergent behaviors.
Лучшее вводное видео про LLM. Обзор архитектуры, обучения и инференса.