Дообучение LLM методом DPO (Direct Preference Optimization)
Вы обучили LLM на корпусе данных, но модель всё равно выдаёт не те ответы, которые ожидает пользователь? Стандартный SFT не даёт контроля над стилем и предпочтениями. Мы используем DPO для выравнивания LLM под бизнес-задачи. DPO — метод alignment, позволяющий обучить модель генерировать предпочтительные ответы без явного обучения reward model и RLHF-цикла. Предложен недавно в работе DPO. DPO преобразует задачу RL в задачу supervised learning на датасете предпочтений (chosen/rejected пары), что значительно упрощает пайплайн alignment. Наши инженеры реализовали DPO для десятков проектов — результат: рост CSAT до 23%, снижение отказов на 12%. Экономия вычислительных ресурсов достигает 60% по сравнению с RLHF. Вы можете заказать DPO-дообучение под ключ — от сбора датасета до деплоя модели.
Почему DPO стал стандартом alignment?
Классический RLHF требует обучения отдельной Reward Model и нестабильной PPO-оптимизации. DPO обходится без этого. DPO в 3 раза быстрее и на 60% дешевле RLHF. Сравнение подходов:
| Параметр | RLHF | DPO |
|---|---|---|
| Необходимость Reward Model | Да | Нет |
| Количество моделей в памяти | 4 (actor, critic, reward, reference) | 2 (trainable, reference) |
| Стабильность обучения | Низкая (PPO sensitive) | Высокая (SGD-like) |
| Сложность настройки | Высокая | Средняя |
| Время обучения (на 1000 пар) | ~5 часов на A100 | ~1.5 часа на A100 |
| Финансовая эффективность | Высокие затраты на GPU | Экономия до 60% ресурсов |
Математически DPO минимизирует:
L_DPO = -E[log σ(β * (log π_θ(y_w|x)/π_ref(y_w|x) - log π_θ(y_l|x)/π_ref(y_l|x)))]
где y_w — preferred response, y_l — rejected, β — температура KL-регуляризации.
Как собрать датасет предпочтений?
Формат датасета для DPO — пары (chosen, rejected). Пример записи:
# Пример записи датасета предпочтений
{
"prompt": "Объясни разницу между TCP и UDP",
"chosen": "TCP (Transmission Control Protocol) обеспечивает надёжную доставку данных с подтверждением получения, управлением потоком и контролем ошибок. UDP (User Datagram Protocol) — без установки соединения, без гарантии доставки, но с минимальной задержкой. TCP используют для HTTP, FTP, SMTP; UDP — для DNS, видеостриминга, игр реального времени.",
"rejected": "TCP надёжный, UDP быстрый. TCP медленнее потому что проверяет каждый пакет. Оба это протоколы интернета."
}
На практике мы используем три метода сбора:
- Human annotation: 2–3 аннотатора на пару, высокая достоверность.
- AI-генерация + human verification: GPT-4o создаёт chosen, GPT-4o-mini — rejected, человек проверяет 20–30%.
- Реальные данные из продакшна: логи лайков/дизлайков, исправления операторов.
Пример генерации через OpenAI API:
from openai import OpenAI
def generate_preference_pair(prompt: str, client: OpenAI) -> dict:
"""Генерирует пару chosen/rejected для DPO датасета"""
# Хороший ответ
chosen_response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "Дай подробный, точный, хорошо структурированный ответ."},
{"role": "user", "content": prompt}
],
temperature=0.3
).choices[0].message.content
# Плохой ответ — специально деградируем качество
rejected_response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Дай краткий, поверхностный ответ без деталей."},
{"role": "user", "content": prompt}
],
temperature=0.9
).choices[0].message.content
return {"prompt": prompt, "chosen": chosen_response, "rejected": rejected_response}
Реализация DPO через TRL
Библиотека TRL от Hugging Face предоставляет готовые классы. Пример конфигурации:
from trl import DPOTrainer, DPOConfig
from peft import LoraConfig
# Создаём reference model (замороженная копия SFT-модели)
# TRL управляет этим автоматически при use_reference_model=True
dpo_config = DPOConfig(
output_dir="./dpo-model",
num_train_epochs=1, # DPO обычно 1-3 эпохи
per_device_train_batch_size=2,
gradient_accumulation_steps=8,
learning_rate=5e-7, # Значительно ниже, чем SFT
lr_scheduler_type="cosine",
warmup_ratio=0.1,
beta=0.1, # KL-температура
loss_type="sigmoid", # "sigmoid", "hinge", "ipo", "kto_pair"
max_length=2048,
max_prompt_length=512,
bf16=True,
logging_steps=10,
)
trainer = DPOTrainer(
model=model, # SFT-дообученная модель
ref_model=None, # None = автоматически создаётся из model
args=dpo_config,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
peft_config=LoraConfig(r=16, lora_alpha=32, target_modules=["q_proj","v_proj"]),
)
trainer.train()
Как выбрать loss_type для DPO?
| loss_type | Описание | Когда использовать |
|---|---|---|
| sigmoid | Оригинальный DPO loss | Стандартный выбор |
| hinge | SLiC-HF, менее чувствителен к outliers | При зашумлённом датасете |
| ipo | Identity Preference Optimization | Требуется устойчивость к переобучению |
| kto_pair | Kahneman-Tversky Optimization | Непарные данные (только chosen) |
Типичные ошибки при DPO
- Слишком высокий learning rate (>1e-6) — модель расходится.
- Отсутствие SFT перед DPO — DPO обучается нестабильно на сырой базовой модели.
- Маленький датасет (<500 пар) — alignment незначительный.
- β=0 — исчезает KL-регуляризация, модель теряет качество генерации.
Практический кейс: улучшение качества клиентского сервиса
Задача: языковая модель для поддержки клиентов отвечала корректно, но с жёстким, безличным тоном. SFT-дообучение на новых данных частично решило проблему, но требовало пересбора данных каждый раз.
Решение: DPO на парах предпочтений. Chosen — ответы операторов с высоким CSAT. Rejected — ответы с низким CSAT. Объём: 2100 пар. В этом кейсе наш клиент — компания из сферы телекоммуникаций.
Базовая модель для DPO: SFT-дообученная Mistral 7B.
Результаты:
- CSAT бота: 3.4 → 4.2 (из 5)
- Empathy score (LLM-as-judge): 2.8 → 4.1
- Factual accuracy: без изменений (0.91 → 0.91)
- Refusal rate: 12% → 4% (модель стала менее избыточно осторожной)
- β=0.1 оказался оптимальным: при β=0.5 accuracy упала, при β=0.01 — нестабильность
Типичный пайплайн: SFT → DPO
DPO применяется поверх SFT, а не вместо него:
- SFT (Supervised Fine-Tuning): учим модель форматировать и выдавать релевантные ответы в домене.
- DPO: выравниваем качество ответов под предпочтения пользователей.
Пропуск SFT и прямой DPO на базовой модели технически возможен, но менее стабилен.
Что входит в DPO-дообучение под ключ
Мы предлагаем комплексную услугу по DPO-дообучению LLM. Команда с опытом более 10 лет в NLP гарантирует качество:
- Сбор и разметка датасета предпочтений (минимум 1000 пар).
- SFT-дообучение базовой модели (если требуется).
- DPO-обучение с подбором гиперпараметров (β, loss_type, learning rate).
- Оценка качества: LLM-as-judge + human evaluation.
- Деплой модели в продакшн (SageMaker, Triton, ONNX).
- Документация и передача прав на модель.
Гарантируем качество: каждый проект проходит A/B тестирование на реальных пользователях. Свяжитесь с нами для предварительной оценки вашего проекта.
Сроки и стоимость
Ориентировочные сроки:
- Сбор и разметка датасета предпочтений: 3–6 недель.
- SFT (если не проводился): 2–3 недели.
- DPO обучение и итерации: 1–2 недели.
- Оценка качества: 1 неделя.
- Итого: 7–12 недель.
Стоимость рассчитывается индивидуально и зависит от объёма датасета, размера модели и глубины кастомизации. Получите консультацию — мы подготовим коммерческое предложение с учётом ваших задач.







