Дотонування LLM методом QLoRA
QLoRA (Quantized Low-Rank Adaptation) поєднує квантизацію базової моделі до 4-bit з тренуванням адаптерів LoRA в bf16/fp32. Запропонований Dettmers et al. у 2023 році ("QLoRA: Efficient Finetuning of Quantized LLMs"). Ключовий результат: дотонувати модель 65B на одному GPU A100 80GB із мінімальною втратою якості порівняно з повним дотонуванням у bf16.
Як працює QLoRA
Крок 1: базова модель завантажується в 4-bit NormalFloat (NF4) — спеціальний формат квантизації, оптимальний для нормально розподілених ваг нейросетей.
Крок 2: для кожного квантизованого блоку зберігається окремий масштабуючий коефіцієнт (Double Quantization — квантизація самих масштабів).
Крок 3: під час forward/backward pass ваги деквантизуються до bf16 "на льоту" для обчислень.
Крок 4: адаптери LoRA зберігаються та оновлюються в повній точності (bf16/fp32).
Результат: споживання пам'яті зменшується ~4 рази порівняно з bf16 LoRA, при цьому якість практично не страждає завдяки NF4 квантизації.
Реалізація QLoRA
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
import torch
# NF4 квантизація з Double Quantization
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4", # NF4 для ваг
bnb_4bit_compute_dtype=torch.bfloat16, # bf16 для обчислень
bnb_4bit_use_double_quant=True, # Додаткова економія ~0.4 bit/параметр
)
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Meta-Llama-3.1-70B-Instruct",
quantization_config=bnb_config,
device_map="auto",
)
# Обов'язкова підготовка моделі для kbit тренування
model = prepare_model_for_kbit_training(model)
lora_config = LoraConfig(
r=64,
lora_alpha=128,
target_modules=["q_proj", "v_proj", "k_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"],
lora_dropout=0.05,
task_type="CAUSAL_LM",
bias="none",
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# trainable: 0.84% | all: 70B | memory: ~40 GB на 1×A100 80GB
Вимоги до пам'яті QLoRA проти LoRA проти Full FT
| Метод | 7B | 13B | 34B | 70B |
|---|---|---|---|---|
| Full FT (bf16) | 4×A100 40GB | 8×A100 40GB | N/A | 8×A100 80GB |
| LoRA (bf16) | 1×A100 40GB | 2×A100 40GB | 4×A100 40GB | 4×A100 80GB |
| QLoRA (NF4) | 1×A100 24GB | 1×A100 40GB | 2×A100 40GB | 1×A100 80GB |
QLoRA дозволяє працювати з моделлю 70B на одному A100 80GB — революційне зменшення вимог до інфраструктури.
Gradient Checkpointing з QLoRA
При QLoRA активації займають основну пам'ять. Gradient checkpointing критично важливий:
from trl import SFTTrainer, SFTConfig
training_args = SFTConfig(
output_dir="./qlora-output",
num_train_epochs=3,
per_device_train_batch_size=2,
gradient_accumulation_steps=16, # effective batch = 32
gradient_checkpointing=True, # обов'язково
gradient_checkpointing_kwargs={"use_reentrant": False},
learning_rate=2e-4,
lr_scheduler_type="cosine",
warmup_ratio=0.05,
bf16=True,
max_seq_length=4096,
logging_steps=25,
save_steps=100,
report_to="wandb",
)
Практичний випадок: модель 70B на одному A100 80GB
Завдання: спеціалізація Llama 3.1 70B Instruct для аналізу юридичних контрактів — класифікація ризиків, виявлення нестандартних умов, порівняння з шаблоном.
Чому 70B, а не 8B: раніше тестували Llama 3.1 8B — якість аналізу складних контрактів неприйнятна (занадто багато пропущених нюансів). 70B надає якість, порівнянну з GPT-4o.
Інфраструктура: 1×A100 80GB. QLoRA NF4, r=64, alpha=128.
Набір даних: 1400 контрактів із анотаціями (практикуючими юристами): кожен контракт → список ризиків з категорією та severity.
Час тренування: 3 епохи, 22 години на одному A100 80GB.
Результати:
- Recall ризиків (не пропускаємо): 0.71 (8B дотонована) → 0.89 (70B QLoRA)
- Precision ризиків: 0.79 → 0.87
- Якість формулювань (LLM-as-judge, 1–5): 3.6 → 4.5
- Вартість логічного висновку проти GPT-4o API: -71% (self-hosted vLLM)
Обмеження QLoRA
Швидкість тренування: деквантизація на льоту сповільнює тренування ~20% порівняно з bf16 LoRA.
Тепловиділення: A100 при QLoRA працює на межі — потребує адекватної системи охолодження.
Відтворюваність: результати дещо менше відтворювані через помилки квантизації.
Строки
- Підготовка даних: 2–5 тижнів
- Тренування (70B, QLoRA, 1×A100 80GB): 12–36 годин
- Ітерації: 1–2 тижні
- Усього: 4–8 тижнів







