Как дообучить LLM под свои задачи
В этой мы статье разберём, когда вообще стоит дообучать LLM
Как это делать правильно и какие ошибки портят результат чаще всего
1. Когда нужен fine-tune
Сначала табличка:
| Задача | Что попробовать | Когда fine-tune |
|---|---|---|
| Ответы по вашим документам | RAG | Если RAG не даёт нужный стиль и формат |
| Классификация, извлечение сущностей, тегирование | Fine-tune маленькой модели | Почти всегда |
| Специфический стиль ответов | Сильный системный промт | Если промпт уже не справляется |
| Новые знания «внутрь» модели | RAG или Continued Pre-training | Когда данных много и они относительно стабильны |
| Сложные рассуждения под вашу область | Хорошая модель + RAG | Fine-tune помогает ограниченно |
Главное правило: если задачу можно решить качественным промптом и RAG, начните с этого. Fine-tune дороже и сложнее.
Но есть случаи, когда дообучение становится необходимостью:
- Цена и скорость. Вы используете миллионы запросов через API какого-нибудь флагманского клода с куском промпта на 10К токенов, дообученная 7B модель на своем железе выдаст тот же результат. Плюс латентность: маленькая модель отвечает в разы быстрее, а иногда это критично.
- Дистилляция. Тестируете на большой модели, собираешь её ответы, чистите руками, дообучаете маленькую моделт. Это по сути промпт, вшитый в веса, и работает это прекрасно.
- Стабильность формата. Промпт может плыть от запроса к запросу: JSON кривой, лишний текст. Дообученная модель держит формат стабильно почти всегда, а это критично для пайплайнов, где вывод парсится скриптами.
2. Какие есть способы дообучения
| Метод | Что обновляет | Потребление памяти | Качество | Когда использовать |
|---|---|---|---|---|
| Full Fine-tuning | Все веса модели | Очень высокое | Максимальное | Много GPU и данных |
| LoRA | Маленькие адаптеры | Низкое | Очень хорошее | Основной рабочий вариант |
| QLoRA | LoRA + 4-bit квантование | Ещё ниже | Почти как LoRA | Когда мало видеопамяти |
| DoRA / rsLoRA | Улучшенные варианты LoRA | Низкое | Чуть лучше обычной LoRA | Когда хотите выжать максимум |
По своему опыту скажу, что DoRA прощает некоторые ошибки, из-за которых модель, дообученная обычной LoRA, может заметно просесть в общих способностях.
Обычно в подавляющем большинстве случаев используют QLoRA или обычный LoRA. Full fine-tune нужен только тем, у кого есть большие мощности и большие объёмы данных.
Важный нюанс: LoRA-адаптер, это отдельные маленькие матрицы, приклеенные к замороженной базовой модели. Из этого следует сия вещь: можно обучить несколько адаптеров под разные задачи и держать одну базовую модель в памяти, подгружая нужный адаптер на лету (vLLM это умеет). Часто это меняет сутт, вместо трех развернутых моделей, одна база и три адаптера по 50 мегабайт.
3. Что нужно иметь
База
Для большинства задач хватает моделей 7–9B:
- Lfm 2.5 8B
- Qwen 3.5 8B
- Gemma 4 12B
7B-модели с помощью QLoRA спокойно обучаются даже на 12–16 ГБ видеопамяти.
Как выбирать базу:
- Берите instruct-версию, а не base. Base нужно самому учить вести диалог, это отдельный геморрой.
- Не смотрите только на бенчмарки. Проверьте, как модель говорит на вашем языке, для русского у Qwen и Gemma обычно лучше, чем у Llama.
- Смотрите лицензию. Llama до сих пор с ограничениями, Qwen и Gemma заметно свободнее.
- Проверьте, что модель дружит с вашим стеком инференса (vLLM, Ollama, llama.cpp), иначе потом намучаетесь с конвертацией.
Данные
- Минимум, с которым уже можно получить результат: 500–1000 качественных примеров
- Комфортный объём: 3–10 тысяч
- Важнее качество и разнообразие, чем тупо объём
Формат данных
Самый распространённый сейчас, чат формат:
{
"messages": [
{"role": "system", "content": "Ты — помощник, который анализирует отзывы клиентов"},
{"role": "user", "content": "Доставка задержалась на 4 дня, ужасный сервис"},
{"role": "assistant", "content": "негативная"}
]
}
Альпака:
{
"instruction": "Определи тональность отзыва",
"input": "Доставка задержалась на 4 дня, ужасный сервис",
"output": "негативная"
}
Мульти-турные данные (если нужна работа с контекстом диалога):
{
"messages": [
{"role": "system", "content": "Ты — поддержка интернет-магазина"},
{"role": "user", "content": "Где мой заказ?"},
{"role": "assistant", "content": "Назовите номер заказа, пожалуйста"},
{"role": "user", "content": "45821"},
{"role": "assistant", "content": "Ваш заказ уже в пути, ожидайте 1–2 дня"}
]
}
Пара слов про chat template, о нем часто забывают. Каждая модель обучалась на своём шаблоне (==<|im_start|>==, ==[INST]== и подобное). Токенизатор применит его сам, но проверьте, что фреймворк не дублирует спец токены и что ответ ассистента заканчивается EOS. Если EOS не вшит, модель на инференсе не будет останавливаться и будет дописывать мусор после ответа
Железо (ориентиры)
| Модель | Метод | Минимум видеопамяти |
|---|---|---|
| 7B | QLoRA | 12–16 ГБ |
| 7B | LoRA | 16–24 ГБ |
| 14B | QLoRA | 24 ГБ |
| 7B | Full Fine-tune | 40+ ГБ |
Ещё нюанс, который многие упускают: длина последовательности ест видеопамять существенно быстрее, чем число примеров. Если у вас примеры по 8K токенов, требования к VRAM вырастут в разы по сравнению с примерами на 512 токенов, даже при одинаковом количестве данных. Так что режьте примеры, если можно
4. Пошаговый процесс дообучения
1. Подготовка данных
Что делать:
- Соберите примеры именно в том формате, в котором хотите получать ответы от ллм.
- Уберите дубли и мусор.
- Сделайте данные разнообразными (разные формулировки, длина, крайние случаи, разные стили).
- Отложите 10–15% в тестовую выборку и больше её не трогайте до финальной валидации.
Про дедупликацию отдельно: мало убрать точные повторы. Ищите перефразированные: один и тот же вопрос десятью разными способами перекашивает модель, и ещё неприятнее, незаметно утекает в тест, если тест не отделили до дедупликации. Делайте сначала дедуп, потом сплит.
Как улучшить качество данных:
- Используйте сильную модель (Opus 5, GPT-6, GLM-5.3, Kimi K3) для генерации синтетики, а потом фильтруйте.
- Попросите модель перефразировать существующие примеры 3–5 разными способами.
- Добавляйте кривые случаи специально (неоднозначные формулировки, сарказм, опечатки, транслит)
- Балансируйте классы / типы ответов, если задача классификационная.
Плохие данные -> плохая модель. Никакой метод от этого не спасёт.
2. Выбор инструмента
| Инструмент | Уровень | Комментарий |
|---|---|---|
| Unsloth | Низкий | Сейчас один из самых быстрых и удобных вариантов |
| LLaMA-Factory | Низкий/средний | Есть веб-интерфейс, много моделей из коробки |
| Axolotl | Средний | Очень гибкий, много настроек |
| Hugging Face TRL + PEFT | Высокий | Максимальный контроль |
| Torchtune | Средний | Хорошо оптимизирован |
Для большинства задач лучше всего начинать с Unsloth или LLaMA-Factory. Если вам нужен полный контроль и воспроизводимость в CI/CD, смотрите в сторону TRL.
3. Запуск обучения (пример на Unsloth)
from unsloth import FastLanguageModel
from trl import SFTTrainer, SFTConfig
from transformers import TrainingArguments
import torch
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "unsloth/Qwen2.5-7B-Instruct",
max_seq_length = 2048,
load_in_4bit = True,
)
model = FastLanguageModel.get_peft_model(
model,
r = 16,
target_modules = [
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"
],
lora_alpha = 16,
lora_dropout = 0.0,
bias = "none",
)
trainer = SFTTrainer(
model = model,
tokenizer = tokenizer,
train_dataset = dataset,
args = SFTConfig(
per_device_train_batch_size = 4,
gradient_accumulation_steps = 4,
warmup_steps = 50,
num_train_epochs = 2,
learning_rate = 2e-4,
fp16 = not torch.cuda.is_bf16_supported(),
bf16 = torch.cuda.is_bf16_supported(),
logging_steps = 10,
output_dir = "outputs",
optim = "adamw_8bit",
seed = 42,
),
)
trainer.train()
Какие параметры крутить в первую очередь
| Параметр | Рекомендуемые значения | Комментарий |
|---|---|---|
| r (rank) | 8, 16, 32 | Редко нужно больше 32 |
| lora_alpha | = r или 2 × r | Классика |
| learning_rate | 1e-4 … 2e-4 | Для QLoRA/LoRA |
| num_train_epochs | 1–3 | Больше, часто переобучение |
| max_seq_length | с запасом | Под ваши реальные примеры |
Пара практических советов:
- Если лосс скачет, уменьшите learning rate или увеличьте batch size (через gradient accumulation, не за счет VRAM).
- Warmup обычно 3–5% от общего числа шагов, а не фиксированные 50 шагов, для маленьких датасетов это слишком много.
- Всегда фиксируйте seed. Иначе потом будете гадать, изменилось качество от ваших изменений или просто рандом.
5. Как правильно оценивать результат
Лосс на дообучении, слабый индикатор. Он почти ничего не говорит о реальном качестве (тем более, если модель дообучается на множестве разных датасетов)
Обязательно делайте:
- Ручную проверку на отложенной выборке, вместе с базовой моделью.
- Проверку на примерах, которых не было в обучении.
- Проверку, не просела ли общая дееспособность модели (забывание, потеря грамматики, тупые ответы).
- Если задача позволяет, метрики (accuracy, F1, exact match, BERTScore и т.д.).
Практический финт:
Возьмите 30–50 сложных примеров и составьте простую таблицу:
| Пример | Базовая модель | Дообученная | Дельта | Комментарий |
|---|
Так вы увидите, где модель стала лучше, а где просела. Звучит просто, но это один из самых информативных способов оценки, и дольше 30 минут он не занимает.
Для генеративных задач можно использовать LLM-арбитра (просить сильную модель сравнивать ответы по критериям). Только фиксируйте критерии заранее, иначе арбитр начинает подстраиваться под ваши ожидания.
6. Частые ошибки людей, которые убивают дообучение
- Мало данных или данные низкого качества, 200 кривых примеров почти никогда не дают нормального результата.
- Слишком много эпох, модель начинает заучивать формулировки вместо того, чтобы обобщать.
- Слишком большой learning rate, модель ломается и начинает генерить мусор.
- Нет отложенной выборки, вы подкручиваете все под одни и те же примеры и получаете фейковое качество.
- Пытаются вшить большие знания вместо RAG, дообучение плохо подходит как замена базы знаний.
- Игнорируют формат, если в данных один стиль, а вы ожидаете другой, модель будет вести себя непредсказуемо.
- Не проверяют на дееспособность, модель отлично решает вашу задачу, но разучивается нормально отвечать на обычные вопросы.
Бонусная ошибка номер 8: сравнивают базу и тюненую модель с разными настройками инференса (разная температура, разный шаблон, разный max_new_tokens). Тогда модель стала хуже может оказаться просто вы забыли поменять конфиг. Сравнивайте честно, с одинаковыми настройками
7. Что делать после обучения
- Сохраняйте только адаптеры (они весят десятки мегабайт).
- Конвертируйте в удобный формат для инференса:
- GGUF (для llama.cpp / Ollama)
- AWQ / GPTQ (для vLLM / TGI)
- Версионируйте данные + гиперпараметры + сам адаптер.
- Перед деплоем обязательно прогоните модель на реальных (или максимально близких к ним) примерах.
Ещё крутая штука, которую многие не используют: merge адаптера в базу, если адаптеров уже много и вы хотите деплоить одну модель без дополнительного оверхеда. Единственный нюанс, после мердда может слегка просесть качество на крайних случаях, потому что вы уходите от того дробного пространства, в котором обучалась LoRA. Всегда тестируйте обе версии.
8. Когда SFT уже недостаточно
Обычный Supervised Fine-Tuning хорошо учит модель «отвечать правильно». Но иногда нужно научить её предпочитать один ответ другому.
В таких случаях смотрите в сторону:
- DPO
- ORPO
- KTO
Они особенно полезны, когда:
- Есть предпочтения людей (какой ответ лучше)
- Нужно сильно изменить стиль или характер модели
- Хотите уменьшить токсичность / повысить полезность без огромного объёма идеальных ответов
Практика обычно такая: сначала SFT, чтобы модель научилась нужному формату, потом DPO, чтобы она предпочла хорошие ответы плохим. Данные для DPO собрать проще, чем для SFT: достаточно пары (хороший ответ, плохой ответ), и их реально натырить из реальных логов вашего продукта. Например, собирайте те случаи, где юзер перегенерировал ответ, второй вариант считаем предпочтительным.
9. Ориентиры по стоимости
Грубые прикидки для 7B-модели на QLoRA:
| Объём данных | GPU | Примерное время |
|---|---|---|
| 1–2k примеров | 24 ГБ | 1–3 часа |
| 5–8k примеров | 24 ГБ | 4–8 часов |
| 15k+ примеров | 24–48 ГБ | 12–24 часа |
10. Когда лучше не дообучать
- У вас меньше 300–500 качественных примеров.
- Задача в основном про доступ к актуальным знаниям -> делайте RAG.
- Нужно просто чуть поменять тон ответов → сначала выжмите максимум из системного промта.
- Нет возможности нормально оценивать результат.
Посмотрите остальные статьи базы знаний — там разобрано и соседнее.
