Fine-tuning Llama 3.1 на своих данных: гайд с кодом 2026
Когда нужен fine-tuning, а когда хватит RAG. Полный разбор LoRA и DPO с кодом на HuggingFace PEFT, подготовка датасета, железо и реальные цены.
Fine-tuning нужен, когда промптинг и RAG не справляются — модель должна научиться стилю, формату ответов или специфичной доменной логике. В 95% случаев достаточно LoRA (Low-Rank Adaptation): обучаем 0.4% параметров, получаем свою версию Llama 3.1 за 2 часа на одной A100 80GB. Цена — от 500 ₽ за эпоху. Ключевое — чистый датасет из 500–2000 примеров в правильном формате.
Fine-tuning — это не «волшебная кнопка улучшения модели». Большинство команд берутся за него не туда — теряют деньги и время, а результат оказывается хуже, чем просто промптинг. В этой статье — когда fine-tuning реально нужен, а когда достаточно RAG или хорошего system prompt, плюс полный практический гайд по обучению Llama 3.1 на своих данных с кодом.
Когда fine-tuning нужен, а когда нет
Три способа «научить» модель чему-то новому, в порядке возрастания сложности и стоимости:
1. Промптинг (system prompt, few-shot examples)
Пишете системный промпт и 2–3 примера — модель адаптирует стиль. Работает для 60% задач.
Когда достаточно:
- Смена тона ответа («отвечай формально / дружелюбно»)
- Фиксированный формат вывода (JSON, markdown, таблица)
- Простые правила (всегда отвечай на русском, не используй эмодзи)
2. RAG (Retrieval-Augmented Generation)
Добавляете к промпту релевантные куски из вашей базы знаний — модель отвечает на их основе. Работает для 30% задач.
Когда достаточно:
- Модель должна знать ваши внутренние документы, продукты, регламенты
- База знаний меняется — обновляете индекс, не модель
- Нужно показать источник ответа пользователю
3. Fine-tuning
Меняете веса самой модели — навык становится «встроенным». Работает для оставшихся 10% задач.
Когда нужен именно fine-tuning:
- Специфичный стиль письма или формат ответов, который не удаётся зафиксировать промптом даже с 10 примерами
- Доменная задача с собственной терминологией (медицина, право, химические формулы) — модель путается в терминах, неправильно их связывает
- Нужно сильно сократить системный промпт (длинный инструкционный промпт жрёт токены на каждом запросе — fine-tuning переносит инструкции в веса)
- Ответы должны давать правильные решения по вашей бизнес-логике, которая не описывается коротким алгоритмом
- Нужно запретить модели определённые паттерны поведения (refuse to answer on X)
- Экономия на inference при больших объёмах: маленькая fine-tuned модель работает быстрее большой общей
Классическая ошибка: команда пытается fine-tune'ить модель, чтобы «научить её нашим знаниям о продукте». Это не сработает. Для знаний нужен RAG. Fine-tuning — для поведения, стиля, формата, а не для фактов.
Пример: fine-tune научит модель отвечать в стиле вашей техподдержки и всегда предлагать escalate при негативе. Но не научит её знать конкретные цены на тариф «Бизнес Про» — эта информация меняется, и её надо подтягивать через RAG.
Какой тип fine-tuning выбрать
Четыре подхода, от самого простого к самому сложному:
LoRA (Low-Rank Adaptation) — 95% случаев
Что это: Замораживаем основные веса модели. Добавляем маленькие trainable-матрицы (adapter'ы) в attention-слои. Обучаем только их.
Почему это работает:
- Обучаем всего 0.4% параметров (295M из 70B для Llama 3.1 70B)
- В 10–20 раз меньше видеопамяти, чем full fine-tune
- Можно запустить на одной A100 80GB или даже RTX 4090 (для меньших моделей)
- Адаптер — отдельный файл на 200–800 МБ, можно хранить много версий и менять на лету
Когда использовать: всегда по умолчанию. Только если качество не устраивает — переходите к более сложным методам.
QLoRA (Quantized LoRA)
Что это: LoRA, но базовая модель загружена в 4-bit квантизации. Экономит ещё больше памяти.
Когда использовать: когда хочется fine-tune 70B модели на одной RTX 4090 24GB. Качество чуть ниже LoRA (из-за квантизации), но разница в пределах 2–5%.
Full fine-tuning
Что это: Обучаем все параметры модели целиком.
Когда нужен:
- Очень узкий домен с большим количеством данных (10К+ примеров)
- Нужно полностью перестроить поведение модели, а не адаптировать
- У вас есть кластер из 8×H100 и бюджет на недельное обучение
Бюджет: от 50 000 ₽ за эпоху для Llama 70B. Обычно это не ваш случай.
DPO / ORPO (Direct Preference Optimization)
Что это: Следующий этап после SFT (supervised fine-tuning). Вместо «вот правильный ответ» показываем пары «хороший / плохой ответ». Модель учится различать.
Когда нужен:
- Уже есть fine-tuned модель, надо её отточить по предпочтениям
- Есть качественные human preferences от операторов/модераторов
- Важно убрать галлюцинации или нежелательный стиль
Порядок работы: SFT (LoRA) → потом DPO/ORPO на 10–20% объёма исходного датасета.
Подготовка датасета — 80% успеха
Самая недооценённая часть. Качество датасета важнее всего остального, включая выбор модели и гиперпараметров.
Сколько примеров нужно
| Задача | Минимум | Оптимум | Максимум |
|---|---|---|---|
| Смена стиля / тона | 200 | 500–1000 | 3000 |
| Формат вывода (JSON, table) | 100 | 300–500 | 1000 |
| Доменная терминология | 500 | 2000–5000 | 10 000 |
| Сложная бизнес-логика | 1000 | 3000–8000 | 15 000 |
Меньше минимума — модель переобучится на шуме, начнёт галлюцинировать. Больше максимума — убывающая отдача, просто тратите компьют.
Формат данных
Для Llama 3.1 (chat template) стандартный формат — JSONL, по одной записи на строку:
{"messages": [
{"role": "system", "content": "Ты — помощник юриста по 44-ФЗ."},
{"role": "user", "content": "Можно ли изменить цену контракта после заключения?"},
{"role": "assistant", "content": "Да, но только в пределах ±10% объёма работ (ст. 95 44-ФЗ, ч. 1, п. 1б) при пропорциональном изменении цены. Иные случаи..."}
]}
Ключевые правила:
- Никаких дубликатов — даже частичных. Если два примера отличаются только порядком слов в вопросе, оставьте один.
- Разнообразие формулировок — если все
userначинаются с «Как», модель привыкнет к этому шаблону и будет хуже реагировать на «Что», «Какой», «Почему». - Длина ответов — в том диапазоне, в котором хотите видеть inference. Если 80% ответов короткие, а модель должна давать развёрнутые — датасет её научит отвечать коротко.
- Один ответ на один пример — не пытайтесь упихать два ответа в один
assistantблок.
Типовые проблемы с данными
Что убивает fine-tuning быстрее всего:
- Противоречивые примеры — в одном случае
assistantговорит «нельзя», в другом похожем — «можно». Модель запутается. - Leaked test data — если оценочный датасет случайно попал в training. Получите нереалистично хороший eval и катастрофу на реальных данных.
- Смещение по длине — короткие вопросы = короткие ответы, длинные вопросы = длинные. Модель подхватит эту корреляцию, будет давать развёрнутые ответы на простые вопросы.
- Один автор пишет все ответы — модель усвоит его стилистические привычки (любимые слова, структуру предложений), потеряет вариативность.
Как чистить датасет
Практический пайплайн:
- Убрать дубликаты по cosine similarity embeddings (порог ~0.92)
- Проверить длины — гистограмма токенов на вход/выход, удалить хвосты (top 1% и bottom 1%)
- Синтаксическая чистка — никаких HTML-тегов, markdown-артефактов, битых escape-последовательностей
- Ручная проверка 10% выборки — каждый 10-й пример глазами. Если находите ошибки чаще чем 1 на 20 — чистите всё автоматически и повторяйте
- Разделить train/val/test — 80/10/10, причём test замораживается до финальной оценки, в него никто не смотрит во время обучения
Код обучения: Llama 3.1 8B + LoRA за 2 часа
Это рабочий минимальный пример. Запускается на одной A100 40GB или 80GB. Для 70B-модели нужен либо 80GB, либо QLoRA + gradient accumulation.
Установка
pip install torch==2.4.0 transformers==4.44.0 peft==0.12.0 \
trl==0.10.1 datasets==2.20.0 accelerate==0.33.0 \
bitsandbytes==0.43.3
Загрузка и подготовка
from datasets import load_dataset
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
from trl import SFTTrainer, SFTConfig
import torch
MODEL_ID = "meta-llama/Meta-Llama-3.1-8B-Instruct"
# Загружаем свой JSONL-датасет
dataset = load_dataset("json", data_files={
"train": "data/train.jsonl",
"validation": "data/val.jsonl"
})
# Токенизатор
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
tokenizer.pad_token = tokenizer.eos_token
# 4-bit квантизация для экономии памяти (опционально — только для QLoRA)
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
)
model = AutoModelForCausalLM.from_pretrained(
MODEL_ID,
quantization_config=bnb_config,
device_map="auto",
attn_implementation="flash_attention_2", # ускорение в 2-3x на A100+
)
model = prepare_model_for_kbit_training(model)
Настройка LoRA
lora_config = LoraConfig(
r=16, # ранг адаптера. 8-64. Больше = больше параметров
lora_alpha=32, # обычно 2*r
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
target_modules=[
"q_proj", "k_proj", "v_proj", "o_proj", # attention
"gate_proj", "up_proj", "down_proj", # FFN
],
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# trainable params: 20,971,520 || all params: 8,030,261,248 || trainable%: 0.261
Обучение
training_args = SFTConfig(
output_dir="./llama-3.1-8b-custom",
# Основные гиперпараметры
num_train_epochs=3,
per_device_train_batch_size=4,
gradient_accumulation_steps=4, # effective batch = 16
learning_rate=2e-4,
warmup_ratio=0.1,
lr_scheduler_type="cosine",
weight_decay=0.01,
# Производительность
bf16=True,
gradient_checkpointing=True,
optim="paged_adamw_8bit",
# Логирование и сохранение
logging_steps=10,
eval_strategy="steps",
eval_steps=100,
save_strategy="steps",
save_steps=200,
save_total_limit=3,
load_best_model_at_end=True,
# Для chat-формата
max_seq_length=2048,
packing=False,
)
trainer = SFTTrainer(
model=model,
args=training_args,
train_dataset=dataset["train"],
eval_dataset=dataset["validation"],
tokenizer=tokenizer,
)
trainer.train()
trainer.save_model("./llama-3.1-8b-custom-final")
Запуск на нескольких GPU (опционально)
accelerate launch --multi_gpu --num_processes 2 train.py
Инференс
from peft import PeftModel
base_model = AutoModelForCausalLM.from_pretrained(MODEL_ID, torch_dtype=torch.bfloat16)
model = PeftModel.from_pretrained(base_model, "./llama-3.1-8b-custom-final")
model = model.merge_and_unload() # сливаем LoRA в базу для скорости
inputs = tokenizer.apply_chat_template(
[{"role": "user", "content": "Ваш вопрос"}],
return_tensors="pt",
add_generation_prompt=True,
).to(model.device)
output = model.generate(inputs, max_new_tokens=512, temperature=0.7)
print(tokenizer.decode(output[0][inputs.shape[1]:], skip_special_tokens=True))
Быстрый чек, что всё идёт нормально:
train_lossпадает и выходит на плато (0.2-0.6 — норма для хорошего датасета)eval_lossне растёт через 1-2 эпохи (иначе — overfit, уменьшайте epochs или ранг)grad_normстабильно в диапазоне 0.5-5 (скачки вверх — проблема с данными)- Генерация примера на validation между эпохами — читаемые, уместные ответы
Если train_loss не падает после 200 шагов — скорее всего проблема в датасете или слишком маленький LR.
Железо и реальные цены
Что нужно для обучения Llama 3.1 разных размеров методом LoRA:
| Модель | Min VRAM (QLoRA) | Recommended (LoRA) | Время на 1 эпоху (3000 примеров) |
|---|---|---|---|
| Llama 3.1 8B | 12 GB (RTX 3090/4090) | 24 GB (RTX 4090) | ~25 мин |
| Llama 3.1 70B | 48 GB (A100 40G QLoRA) | 80 GB (A100 80G) | ~2 часа |
| Llama 3.1 405B | 2×80 GB (FSDP) | 8×H100 | ~12 часов |
Расчёт цены fine-tune Llama 3.1 8B
«Полный пайплайн» включает: подготовку данных, обучение, эвалюацию, сохранение, тестирование. Минимум 500 ₽ — реалистично на 8B модели.
Расчёт цены fine-tune Llama 3.1 70B
- 1 эпоха ≈ 2 часа на A100 80G = 760 ₽
- Обычно 3 эпохи: ~2 300 ₽
-
- Подготовка датасета, эвалюация, итерации: ×2-3
Итого: от 5 000 до 15 000 ₽ за первый готовый fine-tune модели.
Как оценивать качество fine-tune
Самая частая ошибка: смотреть на train_loss и считать, что всё хорошо.
Количественные метрики
- Perplexity на test — базовая оценка, но сама по себе ничего не говорит о пользе
- BLEU / ROUGE — для структурированных задач (перевод, суммаризация). Для чата почти бесполезны
- Exact match / F1 — если есть правильный ответ-эталон (например, JSON-extraction)
LLM-as-a-judge
Реально работающий метод в 2026:
- Берёте 100 тест-примеров
- Генерируете ответы fine-tuned моделью и базовой (Llama 3.1 Instruct)
- Подаёте обе версии в GPT-4 или Claude 3.5 Sonnet с просьбой оценить по шкале 1-5 + объяснить
- Считаете среднее и процент, где fine-tuned лучше базовой
Если fine-tune побеждает в менее чем 60% случаев — его делать не стоило.
Ручная проверка
Минимум 20 примеров смотрите руками, выставляете оценки 1-5 по 3-4 критериям (точность, стиль, формат, полезность). Это самая надёжная оценка.
A/B-тест на проде
Идеальный вариант, если есть метрика бизнес-ценности (конверсия, NPS). 50/50 трафика на базу и fine-tune, собираете данные 1-2 недели.
Fine-tuning под ключ на нашей инфраструктуре
Пришлите датасет или опишите задачу — мы подготовим данные, проведём обучение на A100/H100, отдадим готовую модель через OpenAI-совместимый API. От 500 ₽ за эпоху для 8B моделей.
Типичные ошибки и как их избежать
1. Слишком большой learning rate
LR > 5e-4 для LoRA обычно приводит к тому, что модель забывает общие знания («catastrophic forgetting»). Стандарт — 2e-4, для полного fine-tune ещё ниже — 5e-5 до 1e-4.
2. Слишком мало эпох
Одна эпоха часто недостаточно — модель не успевает усвоить паттерны. Правило: 3-5 эпох при train_loss, который стабильно падает. Если после 3 эпохи падение замедлилось — стоп.
3. Переобучение
Если eval_loss начинает расти, а train_loss всё ещё падает — вы переобучились. Решения:
- Уменьшите epochs
- Увеличьте
lora_dropoutс 0.05 до 0.1 - Уменьшите ранг LoRA с 16 до 8
4. Неправильный chat template
Для Llama 3.1 обязательно использовать tokenizer.apply_chat_template — у неё специальный формат с <|begin_of_text|>, <|start_header_id|> и т.п. Если вручную клеите строки — получите 30% потерю качества.
5. Размер датасета не соответствует ранку
Правило большого пальца:
- 200-500 примеров →
r=8 - 500-2000 примеров →
r=16 - 2000-5000 примеров →
r=32 - 5000+ примеров →
r=64или подумайте о full fine-tuning
6. Обучение на общем чате без системного промпта
Добавляйте в train-датасет тот же system message, что планируете использовать на inference. Иначе при включении промпта модель удивится.
Чек-лист перед стартом
- Определили задачу — это реально fine-tuning, а не RAG/промпт?
- Датасет: 500+ примеров, один JSONL, messages-формат
- Убрали дубликаты, выровняли длины, проверили руками 10%
- Разбили train/val/test = 80/10/10
- Выбрали базовую модель (Llama 3.1 8B для старта, 70B если данных много)
- Настроили LoRA: r=16, alpha=32, target_modules на attention + FFN
- Настроили гиперпараметры: lr=2e-4, 3 эпохи, batch=4 × grad_accum=4
- Проверили, что есть mentor-метрика для оценки (LLM-as-judge, ручная выборка)
- Выбрали железо: A100 80G для 8B-70B, RTX 4090 для экспериментов
- Сохранение чекпоинтов каждые 200 шагов, лимит 3
Итого
Fine-tuning в 2026 году — рутинная инженерная процедура, а не магия. Для 95% задач достаточно LoRA на Llama 3.1 8B или 70B, 500-3000 примеров датасета, 2-5 часов на одной A100. Вся цена — от 500 ₽ до 15 000 ₽ в зависимости от модели и количества итераций.
Самое важное не в коде, а в данных: чистый, разнообразный, непротиворечивый датасет решает. Всё остальное — готовые библиотеки (peft, trl), гиперпараметры-по-умолчанию работают.
Но перед тем как fine-tune'ить, ещё раз проверьте: может, у вас задача на RAG или хороший system prompt? В половине случаев это решает вопрос за час работы вместо недели.
Обучим вашу модель — от датасета до API
Подберём базу (Llama, Mistral, Qwen), подготовим и почистим данные, проведём обучение на H100/A100, отдадим готовую модель через OpenAI-совместимый эндпоинт. Всё на серверах в РФ.