← Назад в блог

Файн-тюнинг Llama 3 8B: Полный гайд (Unsloth + PyTorch)

2026-01-04 0 мин

TL;DR — Кратко:

  • Используем библиотеку Unsloth для ускорения обучения в 2-5 раз.
  • Метод QLoRA позволяет уложиться в память обычной RTX 4090 (и даже меньше).
  • Готовый код: от установки библиотек до сохранения GGUF.

Введение

Llama 3 от Meta перевернула игру. Модель на 8 миллиардов параметров (8B) работает быстрее и умнее, чем Llama 2 70B. Но “из коробки” она знает всё обо всём понемногу. Чтобы модель заговорила в стиле вашего бренда, научилась писать специфический код или отвечать на медицинские вопросы, её нужно дообучить (Fine-Tuning).

Раньше для этого требовались кластеры A100. Сегодня, благодаря методам QLoRA и библиотеке Unsloth, мы можем сделать это на одной карте RTX 4090 за пару часов.

В этом гайде мы пройдем весь процесс: от “голого” сервера до собственной обученной нейросети.

Почему Unsloth?

Мы не будем использовать стандартный Hugging Face Trainer в чистом виде. Мы возьмем Unsloth. Это библиотека, которая вручную переписала ядра PyTorch для обратного распространения ошибки.

Что это дает:

  1. Скорость: Обучение идет в 2-5 раз быстрее.
  2. Память: Потребление VRAM снижается на 60%.
  3. Качество: 0% потери точности (математика та же, просто вычисления эффективнее).

Шаг 0: Подготовка окружения

Вам понадобится сервер с GPU NVIDIA (минимум 12 ГБ VRAM, рекомендуем 24 ГБ для комфортной работы). Операционная система: Linux (Ubuntu 20.04/22.04).

Установим библиотеки:

# Устанавливаем Pytorch (если еще нет)
pip install --upgrade pip
pip install "unsloth[colab-new] @ git+[https://github.com/unslothai/unsloth.git](https://github.com/unslothai/unsloth.git)"
pip install --no-deps "xformers<0.0.26" trl peft accelerate bitsandbytes

Шаг 1: Загрузка модели

Создайте файл train.py и начните с импорта. Мы загружаем модель в 4-битном формате (Load in 4bit), чтобы она занимала всего ~6 ГБ памяти.

from unsloth import FastLanguageModel
import torch

max_seq_length = 2048 # Длина контекста (можно увеличить до 8192)
dtype = None # Auto detection (Float16 для Tesla T4, Bfloat16 для Ampere+)
load_in_4bit = True # Включаем 4-битное квантование

# Загружаем Llama-3 8B
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "unsloth/llama-3-8b-bnb-4bit",
    max_seq_length = max_seq_length,
    dtype = dtype,
    load_in_4bit = load_in_4bit,
)

print("Модель успешно загружена!")

Шаг 2: Настройка LoRA (адаптеров)

Мы не будем переучивать все 8 миллиардов весов (это долго и дорого). Мы используем LoRA (Low-Rank Adaptation). Это небольшие дополнительные слои, которые обучаются поверх основной модели.

model = FastLanguageModel.get_peft_model(
    model,
    r = 16, # Ранг (чем больше, тем умнее адаптер, но тяжелее). 16, 32, 64 - ок.
    target_modules = ["q_proj", "k_proj", "v_proj", "o_proj",
                      "gate_proj", "up_proj", "down_proj",],
    lora_alpha = 16,
    lora_dropout = 0, # Unsloth рекомендует 0 для скорости
    bias = "none",
    use_gradient_checkpointing = "unsloth", # Экономит память
    random_state = 3407,
    use_rslora = False,
    loftq_config = None,
)

Шаг 3: Подготовка данных

Для примера возьмем классический датасет Alpaca, но вы можете заменить его на свой JSON-файл. Формат данных должен быть таким:

  • Instruction: Вопрос или задача.
  • Input: Дополнительный контекст (необязательно).
  • Output: Желаемый ответ модели.
from datasets import load_dataset

# Промпт для форматирования данных
alpaca_prompt = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.

### Instruction:
{}

### Input:
{}

### Response:
{}"""

EOS_TOKEN = tokenizer.eos_token # Обязательно добавляем токен конца генерации

def formatting_prompts_func(examples):
    instructions = examples["instruction"]
    inputs       = examples["input"]
    outputs      = examples["output"]
    texts = []
    for instruction, input, output in zip(instructions, inputs, outputs):
        text = alpaca_prompt.format(instruction, input, output) + EOS_TOKEN
        texts.append(text)
    return { "text" : texts, }

# Загружаем датасет
dataset = load_dataset("yahma/alpaca-cleaned", split = "train")
dataset = dataset.map(formatting_prompts_func, batched = True)

Шаг 4: Запуск обучения

Используем SFTTrainer (Supervised Fine-tuning Trainer) от Hugging Face.

💡 Совет по памяти

Если у вас вылетает ошибка OOM (Out Of Memory), уменьшите batch_size с 2 до 1 или уменьшите max_seq_length.

from trl import SFTTrainer
from transformers import TrainingArguments

trainer = SFTTrainer(
    model = model,
    tokenizer = tokenizer,
    train_dataset = dataset,
    dataset_text_field = "text",
    max_seq_length = max_seq_length,
    dataset_num_proc = 2,
    packing = False, # Можно поставить True для ускорения на больших датасетах
    args = TrainingArguments(
        per_device_train_batch_size = 2,
        gradient_accumulation_steps = 4,
        warmup_steps = 5,
        max_steps = 60, # Для теста хватит 60 шагов. Для реальности - ставьте num_train_epochs = 1
        learning_rate = 2e-4,
        fp16 = not torch.cuda.is_bf16_supported(),
        bf16 = torch.cuda.is_bf16_supported(),
        logging_steps = 1,
        optim = "adamw_8bit", # 8-битный оптимизатор экономит кучу памяти!
        weight_decay = 0.01,
        lr_scheduler_type = "linear",
        seed = 3407,
        output_dir = "outputs",
    ),
)

# ПОЕХАЛИ! 🚀
trainer_stats = trainer.train()

Шаг 5: Проверка результата (Inference)

После обучения проверим, как модель отвечает на вопросы.

# Включаем режим инференса (быстрее)
FastLanguageModel.for_inference(model)

inputs = tokenizer(
[
    alpaca_prompt.format(
        "Напиши функцию на Python для вычисления чисел Фибоначчи.", # Instruction
        "", # Input
        "", # Output - оставляем пустым, модель дополнит
    )
], return_tensors = "pt").to("cuda")

outputs = model.generate(**inputs, max_new_tokens = 64, use_cache = True)
print(tokenizer.batch_decode(outputs))

Шаг 6: Сохранение

Вы можете сохранить только адаптеры (LoRA adapters) — они весят всего ~100 МБ.

model.save_pretrained("lora_model") # Локальное сохранение
# model.push_to_hub("your_name/lora_model") # Загрузка на Hugging Face

Или сохранить полную модель в формате GGUF для запуска на ноутбуке через Ollama или LM Studio:

# Сохранить в 4-битном GGUF (q4_k_m)
model.save_pretrained_gguf("model", tokenizer, quantization_method = "q4_k_m")

Заключение

Мы только что дообучили одну из самых мощных LLM современности, используя код на 50 строк и видеокарту потребительского класса.

Весь процесс занял бы на RTX 4090 около 15-20 минут (для 60 шагов) или около 2 часов для полного прохода по датасету Alpaca.

Что делать дальше?

  1. Соберите свой датасет (диалоги с клиентами, код, статьи).
  2. Загрузите его вместо Alpaca.
  3. Запустите обучение и получите своего персонального AI-ассистента.

Нужна мощная карта для обучения?

Разверните среду с RTX 4090 и предустановленным Unsloth за 2 минуты.

Запустить Jupyter Notebook