Небольшую LLM на 0,5-8 млрд параметров дообучают на своей предметной области через LoRA или QLoRA: берут Instruct-модель, готовят несколько сотен или тысяч примеров «запрос и правильный ответ» в нужном вам формате и терминологии, обучают адаптер на одной видеокарте и сравнивают результат с базовой моделью на отложенных вопросах. Важная оговорка: так модель учится говорить на языке вашей области (формат, термины, структура ответа, классификация), а не запоминает базу фактов. Для фактов, которые меняются и требуют ссылок на источник, нужен поиск, то есть RAG. Ниже план из семи шагов, выбор параметров и рабочий скрипт.
Что дообучение даст, а что нет
Исследования расставляют границы довольно чётко. В работе Gekhman и соавторов (EMNLP 2024) примеры с новыми для модели фактами усваивались заметно медленнее остальных, а по мере усвоения линейно повышали склонность к галлюцинациям; авторы делают вывод, что знания модель получает на предобучении, а дообучение учит ими пользоваться. Сравнение Ovadia и соавторов показало, что RAG стабильно превосходит неконтролируемое дообучение и на знакомых моделью темах, и на новых. Исследование «LoRA Learns Less and Forgets Less» добавляет: при типичных настройках LoRA уступает полному дообучению на целевой области (программирование, математика), зато лучше сохраняет возможности модели за её пределами.
| Задача предметной области | Дообучение небольшой модели | Что использовать |
|---|---|---|
| Ответы строго в вашем формате (JSON, шаблон письма, разметка) | Подходит | LoRA на примерах формата |
| Классификация и маршрутизация по вашим категориям | Подходит | LoRA или маленький классификатор (сравнение) |
| Терминология и стиль отрасли | Подходит | LoRA на экспертных ответах |
| Ответы по документам, прайсам, регламентам | Плохо: факты устаревают и забываются | RAG, при необходимости плюс LoRA на формат ответа |
| Данные, которые меняются каждую неделю | Не подходит | RAG или вызов функции (как обновлять знания) |
Если сомневаетесь, нужно ли обучение вообще, пройдите дерево решений из статьи промпт, RAG или fine-tuning.
План из семи шагов
- Сформулируйте задачу и метрику. «Знает нашу область» не измеряется. Измеряется «в 90 процентах вопросов из тестового набора ответ содержит нужные поля и не противоречит эталону». Метрику выбирайте до обучения.
- Соберите оценочный набор и отложите его. 50-100 типичных запросов с эталонными ответами, которые не попадут в обучение. Методика замера описана в статье как сравнить LLM на своих задачах.
- Замерьте базовую модель с хорошим промптом. Если промпт с примерами уже даёт нужное качество, обучение не нужно. Если нет, у вас есть отправная точка для сравнения.
- Подготовьте обучающие примеры (подробности в статье про датасет для fine-tuning).
- Обучите адаптер LoRA или QLoRA.
- Сравните с базой на оценочном наборе и проверьте, что общие способности не просели (протокол проверки).
- Выложите адаптер или слитую модель и сохраните версию данных и параметров, чтобы эксперимент можно было повторить.
Выбор базовой модели
- Instruct или Base. Для узких задач с несколькими сотнями примеров проще стартовать с Instruct-версии: она уже умеет вести диалог и следовать инструкциям, а вы корректируете формат и терминологию. Base-модель имеет смысл, если у вас десятки тысяч примеров и вы сами задаёте весь стиль ответов.
- Размер. Для первого цикла берите 0,5-4B: обучение занимает минуты или десятки минут, а ошибки в данных видны сразу. Затем сравните с 7-8B. Как оценить память под веса и обучение, разобрано в статье про выбор размера LLM.
- Лицензия. Проверьте карточку модели: допускает ли она коммерческое использование и выкладку производных весов. Для адаптеров это те же условия, что у базы.
- Поддержка русского. Если задача на русском, посмотрите, заявлен ли он в карточке модели, и проверьте на своих примерах, а не по общему описанию.
- MoE-модели. Они обучаются сложнее: в обзоре Hugging Face отмечено, что MoE исторически плохо обобщаются при дообучении и склонны к переобучению. Для первого эксперимента берите плотную модель (см. статью про MoE).
Параметры LoRA: с чего начать
LoRA замораживает веса модели и обучает небольшие матрицы малого ранга, добавленные к слоям (Hu и соавторы). QLoRA дополнительно хранит замороженную базу в 4-битном формате NF4, что позволило авторам дообучать модель на 65 млрд параметров на одной карте с 48 ГБ. Параметры, которые стоит знать:
| Параметр | Что делает | Практический ориентир |
|---|---|---|
r (ранг) | Ёмкость адаптера | Стартуйте с 16-32; если данных много и качество упирается в потолок, поднимайте |
lora_alpha | Масштаб вклада адаптера | Часто берут равным r или 2 × r; в примерах документации TRL r=32, lora_alpha=16 |
target_modules | К каким слоям добавлять адаптер | "all-linear": исследование LoRA Without Regret показало, что адаптеры на всех матрицах, особенно на MLP, работают лучше, чем только на внимании, даже при том же числе параметров |
learning_rate | Шаг обучения | Для адаптеров выше, чем при полном обучении: документация TRL приводит ориентир порядка 10 раз выше; начинайте с 1e-4 - 2e-4 и подбирайте |
| Эпохи | Сколько раз пройти датасет | 1-3; следите за ошибкой на отложенной выборке |
В той же работе Thinking Machines отмечено, что на небольших датасетах LoRA сопоставима с полным дообучением, а на датасетах, превышающих ёмкость адаптера, проигрывает по эффективности обучения. Для типичной доменной задачи на сотни и тысячи примеров это означает: ранга 16-64 обычно достаточно, а если качество упёрлось, сначала улучшайте данные, потом поднимайте ранг.
Скрипт обучения
Формат данных: файл train.jsonl, по одной записи на строку. Используем формат prompt-completion с ролями: для него SFTTrainer по умолчанию считает потери только на ответе, как описано в документации SFT Trainer, и сам применяет чат-шаблон модели.
{"prompt": [{"role": "system", "content": "Ты помощник службы поддержки интернет-магазина. Отвечай по шаблону: вывод, шаги, что приложить."},
{"role": "user", "content": "Курьер привёз заказ с вмятиной на коробке, что делать?"}],
"completion": [{"role": "assistant", "content": "Вывод: заказ можно вернуть или обменять.\nШаги: 1) сфотографируйте упаковку и товар; 2) подайте заявку в разделе «Мои заказы»; 3) дождитесь решения.\nПриложить: фото упаковки и накладную."}]}
Установка (Linux или WSL, видеокарта NVIDIA, Python 3.11 и новее) и скрипт train_lora.py:
pip install torch
pip install -U trl peft bitsandbytes datasets
import torch
from datasets import load_dataset
from peft import LoraConfig
from transformers import BitsAndBytesConfig
from trl import SFTConfig, SFTTrainer
MODEL = "Qwen/Qwen3-0.6B" # для проверки пайплайна; затем замените на свою базу
data = load_dataset("json", data_files={"train": "train.jsonl", "eval": "eval.jsonl"})
bnb = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
bnb_4bit_compute_dtype=torch.bfloat16,
) # для обычной LoRA уберите эту конфигурацию и quantization_config ниже
lora = LoraConfig(
r=32, lora_alpha=64, lora_dropout=0.05,
target_modules="all-linear", task_type="CAUSAL_LM",
)
args = SFTConfig(
output_dir="./out/domain-lora",
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
learning_rate=1e-4,
num_train_epochs=2,
max_length=2048,
bf16=True,
gradient_checkpointing=True,
logging_steps=10,
eval_strategy="steps",
eval_steps=50,
save_strategy="epoch",
)
trainer = SFTTrainer(
model=MODEL,
args=args,
train_dataset=data["train"],
eval_dataset=data["eval"],
peft_config=lora,
quantization_config=bnb,
)
trainer.train()
trainer.save_model("./out/domain-lora/adapter")
Названия некоторых полей SFTConfig (например, max_length и параметры оценки) меняются между релизами, поэтому закрепите версии библиотек в requirements.txt и сверяйтесь с документацией установленной версии. Сравнение инструментов (TRL, Unsloth, Axolotl) и пример YAML-конфига есть в статье про инструменты дообучения.
Как читать кривые обучения
- Ошибка на обучающей выборке падает, на отложенной растёт: началось переобучение. Остановитесь раньше, уменьшите число эпох или добавьте разнообразия в данные.
- Обе кривые почти не двигаются: проверьте формат (применён ли чат-шаблон модели, не обучается ли она на шаблоне вместо ответа), скорость обучения и качество данных.
- Ошибка хорошая, а ответы плохие: метрика потерь не измеряет качество задачи. Вернитесь к оценочному набору и сравнивайте реальные ответы.
- Модель стала хуже на общих вопросах: уменьшите число эпох или ранг, добавьте в обучение часть универсальных диалогов. Работа об эмпирическом изучении катастрофического забывания фиксирует, что при последовательном дообучении LLM от 1 до 7 млрд параметров забывание наблюдается в целом.
Результат: адаптер или слитая модель
Адаптер весит мало и подключается к базовой модели при загрузке, так что на одной базе можно держать несколько адаптеров для разных задач. Для запуска в Ollama или llama.cpp адаптер сливают с базой и конвертируют в GGUF (про форматы):
from peft import AutoPeftModelForCausalLM
model = AutoPeftModelForCausalLM.from_pretrained("./out/domain-lora/adapter")
merged = model.merge_and_unload()
merged.save_pretrained("./out/merged")
Дальше модель можно поднять как сервис по инструкции из статьи как развернуть небольшую LLM как API.
Итого
- Дообучение небольшой модели учит формату, терминологии, стилю и классификации. Изменяющиеся факты держите в индексе или базе.
- Сначала оценочный набор и базовая линия с хорошим промптом, потом обучение.
- Для старта: Instruct-модель 0,5-4B, QLoRA,
all-linear,r16-32, скорость обучения около 1e-4, 1-3 эпохи. - Качество данных важнее количества: сначала правьте их, потом поднимайте ранг и размер модели.
- После обучения сравните адаптер с базой и проверьте общие способности.