Дообучение LLM локально с QLoRA и Unsloth в 2026: полный гайд | AiManual
AiManual Logo Ai / Manual.
23 Апр 2026 Гайд

Как дообучить локальную LLM в 2026: практическое руководство с QLoRA и Unsloth

Пошаговое руководство по fine-tuning LLM на одной видеокарте 12GB с QLoRA и Unsloth. Настройка, подготовка датасета, код обучения, типичные ошибки. Апрель 2026.

Зачем дообучать, если есть ChatGPT?

Допустим, вам нужно, чтобы модель писала код в стиле вашей команды, отвечала на вопросы по внутренней документации или генерировала мемы в корпоративном стиле. Промпты-инженеринг — это круто, но он не научит модель вашим специфическим паттернам. Полноценное дообучение (fine-tuning) позволяет адаптировать поведение LLM под вашу задачу.

Раньше это требовало кластеров A100. В 2026 году QLoRA + Unsloth на 12GB карте — реальность. Причём не «собачья сборка», а стабильный процесс, которым пользуются SRE в проде. Рассказываю, как.

💡 Для кого это? DevOps, ML-инженеры, энтузиасты. Если у вас есть NVIDIA с 12+ GB VRAM (RTX 3060, 4070, A4000) — вы уже можете дообучать модели до 7B параметров. Для 13B+ понадобится 24GB, но мы покажем, как выжать максимум из малого.

QLoRA и Unsloth: дуэт, рвущий лимиты

QLoRA — это техника, сочетающая 4-битную квантизацию основной модели (с помощью bitsandbytes) и низкоранговые адаптеры (LoRA). Вместо обновления 7 миллиардов весов мы тренируем крошечную матрицу ранга 8-64. Это снижает потребление памяти в 4-5 раз без существенной потери качества.

Unsloth — библиотека, которая переписывает внутренние вычисления в Transformers/Hugging Face на CUDA-ядрышки так, что обучение ускоряется на 2-3x, а памяти жрёт ещё на 30-40% меньше. В апреле 2026 вышла версия 2026.4.0, которая добавила поддержку Llama 4 и DeepSeek V3. В основе — оптимизированное ядро для Flash Attention 2 и смешанной точности.

⚠️ Засада: Unsloth работает только с определёнными архитектурами (Llama, Mistral, Qwen, DeepSeek). Если ваша модель — какой-нибудь экспериментальный BLOOM — забудьте. Зато для популярных моделей — идеально.

Шаг 1: поднимаем окружение

Всё запускаем в изолированном conda-окружении. Никаких global pip install — только сломанные нервы потом.

conda create -n finetune python=3.11 -y
conda activate finetune

# CUDA Toolkit 12.4 — обязательно совпадает с драйвером nvidia-smi
conda install cudatoolkit-dev=12.4 -c conda-forge

pip install torch==2.5.1+cu124 --index-url https://download.pytorch.org/whl/cu124
pip install "unsloth[cu124]"
pip install transformers datasets accelerate bitsandbytes wandb

Проверьте, что CUDA видится:

python -c "import torch; print(torch.cuda.is_available())"

Если False — начинайте танцы с бубнами вокруг драйверов. Вероятно у вас установлен драйвер, несовместимый с вашим CUDA тулчейном. Каноничный ответ смеха ради.

Шаг 2: выбираем базовую модель

На конец апреля 2026 лучший выбор для 12GB — Llama 3.2 8B или Qwen 2.5 7B. Обе имеют сильную англоязычную и растущую русскоязычную поддержку. Unsloth их поддерживает out-of-the-box.

Если хочется попробовать 13B — берите Mistral 7B v0.3 (на самом деле 7B, но обманутый мозг радуется). Для русского языка — Saiga Llama 3.1 8B (дообученная на русских инструкциях). Но про неё отдельный разговор.

Если вам нужны не только генерация, но и вызов инструментов — советую глянуть наш обзор лучших Tool Calling моделей — там как раз разбираем, какая база лучше для дообучения под агентов.

Шаг 3: готовим датасет

Самый частый способ — формат ShareGPT (список сообщений с ролями). Unsloth умеет его парсить напрямую. Вот пример для задачи «напиши краткую документацию»:

[
  {
    "conversations": [
      {"from": "human", "value": "Напиши документацию для функции calculate_entropy()"},
      {"from": "gpt", "value": "## `calculate_entropy(data)`\n\n**Описание:** Вычисляет энтропию Шеннона для переданного списка значений.\n\n**Параметры:**\n- `data`: список чисел или строк.\n\n**Возвращает:** float — значение энтропии в битах.\n\n**Пример:**\n```python\n>>> calculate_entropy([1,1,1,0,0])\n0.971\n```"}
    ]
  }
]

Можно использовать и старый датасет alpaca в CSV, но ShareGPT удобнее для диалогов. Важно: следите за длиной контекста — обрезайте до 2048 токенов, иначе модель переполнится.

💡
Почему не Hugging Face dataset? Можно и так. Но Unsloth оптимизирован под `datasets` из HF с правильным tokenizer. Если используете кастомный датасет в JSON — загружайте через `load_dataset("json", data_files="train.json")`. Токенизируйте заранее — это сэкономит время.

Шаг 4: пишем скрипт обучения

Теперь самое интересное. Создаём файл train.py. Я привожу рабочий шаблон для Unsloth 2026.4.0.

from unsloth import FastLanguageModel
import torch
from datasets import load_dataset
from transformers import TrainingArguments
from trl import SFTTrainer

# 1. Загрузка модели с 4-битной квантизацией
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name="unsloth/Llama-3.2-8B-Instruct-bnb-4bit",  # пред-квантованный бинарник
    max_seq_length=2048,
    dtype=torch.bfloat16,
    load_in_4bit=True,
    # token="hf_..."  # если модель под gated
)

# 2. Подключение LoRA адаптеров
model = FastLanguageModel.get_peft_model(
    model,
    r=16,                    # ранг LoRA
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
                     "gate_proj", "up_proj", "down_proj"],  # все линейные слои
    lora_alpha=32,           # масштаб обновлений
    lora_dropout=0.1,        # дропаут для регуляризации
    bias="none",
    use_gradient_checkpointing=True,  # экономим память
    random_state=42,
)

# 3. Датасет
dataset = load_dataset("json", data_files="my_data.json", split="train")
# предполагаем, что колонка "conversations"

# 4. Тренировочные аргументы
training_args = TrainingArguments(
    output_dir="./llama32-doc-finetune",
    per_device_train_batch_size=2,       # для 12GB пробуйте 2-4
    gradient_accumulation_steps=4,       # эффективный batch = 8
    warmup_steps=20,
    num_train_epochs=3,
    learning_rate=2e-4,
    fp16=False,                          # bfloat16 уже выше
    bf16=True,
    logging_steps=10,
    save_steps=100,
    evaluation_strategy="no",
    save_total_limit=2,
    report_to="wandb",                  # логируем в Weights & Biases
)

# 5. Trainer
trainer = SFTTrainer(
    model=model,
    tokenizer=tokenizer,
    train_dataset=dataset,
    args=training_args,
    dataset_text_field="text",           # если датасет без колонки диалогов
    # formatting_func=... можно заюзать для ShareGPT
    max_seq_length=2048,
)

trainer.train()

# 6. Сохраняем только адаптер (слияние не обязательно)
model.save_pretrained("my-finetuned-adapter")
tokenizer.save_pretrained("my-finetuned-adapter")

Разбор параметров

r=16 — золотая середина. При r=32 качество чуть выше, но память растёт. Для 12GB — 16. lora_alpha=32 — общепринятое значение alpha=2*r. Меньше — меньше влияние адаптера, больше — риск переобучения.

batch_size=2 + gradient_accumulation_steps=4 дают эффективный batch 8. Если VRAM позволяет, увеличьте batch до 4. Для 7B моделей можно и 8.

learning_rate=2e-4 стандарт для LoRA. Если loss скачет — уменьшите до 1e-4.

save_steps — сохраняйте каждый 100-200 шагов, чтобы не потерять дни работы.

Запуск и мониторинг

Запускаем: python train.py. Если включили report_to="wandb", смотрите в веб-интерфейс.

Типичная картинка: loss плавно снижается. На эпохах 3-5 обычно достигает плато. Если loss вдруг начинает расти — переобучение. Останавливайте, уменьшайте эпохи или добавляйте dropout.

Ошибка OOM (Out of Memory). Решения: уменьшите batch size, отключите gradient checkpointing (наоборот — включите, я же написал). Ещё попробуйте model.gradient_checkpointing_enable(). Unsloth часто выигрывает 20-30% памяти благодаря собственным оптимизациям — не забывайте использовать FastLanguageModel.

Сохранение и инференс

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

from unsloth import FastLanguageModel
import torch

base_model, tokenizer = FastLanguageModel.from_pretrained(
    model_name="unsloth/Llama-3.2-8B-Instruct-bnb-4bit",
    max_seq_length=2048,
    dtype=torch.bfloat16,
    load_in_4bit=True,
)

# Применяем адаптер
base_model.load_adapter("my-finetuned-adapter")

# Генерация
inputs = tokenizer("Напиши документацию для функции calculate_entropy()", return_tensors="pt").to("cuda")
outputs = base_model.generate(**inputs, max_new_tokens=200)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

Если хотите «слить» адаптер в одну модель (merge) для ускорения инференса, используйте model.merge_and_unload(). Но это займёт дополнительное время и место на диске.

Типичные грабли

  • Датасет из интернета — мусор. Не качайте все подряд. Лучше 500 качественных примеров, чем 5000 шумных.
  • Забыли установить token для gated моделей. Llama, Gemma, DeepSeek требуют лицензионного соглашения.
  • Loss не снижается. Проверьте, что датасет правильно токенизирован. Иногда модель не понимает формат ShareGPT.
  • После дообучения модель стала глупее. Вы, вероятно, переобучили на слишком узкой выборке. Добавьте в датасет 10-20% общеинтеллектуальных примеров (например, из OpenHermes).
  • Проблемы с русским алфавитом. Убедитесь, что токенизатор корректно обрабатывает кириллицу. Qwen 2.5 и Llama 3.1 — норм, DeepSeek V3 — отлично.

Если хотите глубже понять эволюцию техник дообучения и то, как мы пришли к QLoRA/Unsloth, почитайте историю локальных LLM. Там рассказывается про LoRA, Alpaca, и почему Unsloth — это демократизация.

FAQ

Можно ли дообучать на 8GB карте? Да, с форматом QLoRA и Unsloth. Берите модель 3B вроде SmolLM или Qwen 2.5 3B, batch size 1.
Какая максимальная длина контекста? Unsloth рекомендует не более 4096 для 7B моделей на 12GB. Но мы использовали 2048 для надёжности.
А если я хочу дообучать не инструкции, а продолжить предобучение? Тогда нужен другой подход — CausalLM вместо SFT. Unsloth подходит, но опция use_gradient_checkpointing обязательна.
QLoRA снижает качество? В тестах при ранге 16 разница с полным finetune менее 1% на бенчмарках. Для задач с русским языком — вообще незаметно.
Можно ли дообучать мультимодальные модели (LLaVA)? Unsloth это не поддерживает. Только текстовые.

Неочевидный совет напоследок

После дообучения не проверяйте модель только на тех примерах, что были в трейне. Сделайте отдельный тестовый набор — но не из того же распределения, а слегка смещённый (например, про документирование на другом языке или незнакомый код). Если модель справится — вы победили. Если начнёт галлюцинировать — пересмотрите diversity датасета.

Кстати, если вам нужно обкатывать много разных экспериментов с быстрым инференсом, посмотрите сравнение LM Studio и llama.cpp — они тоже умеют и квантование, и загрузку адаптеров.

Главное — не бойтесь эксперементировать. Комбинация Unsloth + QLoRA — это вертолёт, который поднимет любую локальную модель до уровня вашей задачи. Пробуйте, ломайте, чините. И помните: модель — это просто инструмент. Хороший инструмент — это дообученный инструмент.

Подписаться на канал