Дообучение LLM методом DPO (Direct Preference Optimization)

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1 услугВсе 1566 услуг
Дообучение LLM методом DPO (Direct Preference Optimization)
Сложная
от 1 недели до 3 месяцев
Часто задаваемые вопросы
Направления AI-разработки
Этапы разработки AI-решения
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1218
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    853
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1047
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    825

Дообучение LLM методом DPO (Direct Preference Optimization)

DPO — метод alignment, позволяющий обучить модель генерировать предпочтительные ответы без явного обучения reward model и RLHF-цикла. Предложен Rafailov et al. (Stanford, 2023). DPO преобразует задачу RL в задачу supervised learning на датасете предпочтений (chosen/rejected пары), что значительно упрощает пайплайн alignment.

DPO vs RLHF: принципиальное отличие

RLHF (классический):

  1. Обучение Reward Model на парах предпочтений
  2. Обучение LLM через PPO с использованием Reward Model
  3. KL-дивергенция от reference policy как регуляризатор

Недостатки: нестабильность PPO, необходимость держать 4 модели в памяти (actor, critic, reward, reference), сложная настройка.

DPO:

  1. Прямая оптимизация на парах (chosen, rejected) без Reward Model
  2. Неявный reward определяется через log-отношение вероятностей trained/reference модели
  3. Стабильное обучение как обычный SFT

Математически 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

# Пример записи датасета предпочтений
{
    "prompt": "Объясни разницу между TCP и UDP",
    "chosen": "TCP (Transmission Control Protocol) обеспечивает надёжную доставку данных с подтверждением получения, управлением потоком и контролем ошибок. UDP (User Datagram Protocol) — без установки соединения, без гарантии доставки, но с минимальной задержкой. TCP используют для HTTP, FTP, SMTP; UDP — для DNS, видеостриминга, игр реального времени.",
    "rejected": "TCP надёжный, UDP быстрый. TCP медленнее потому что проверяет каждый пакет. Оба это протоколы интернета."
}

Реализация DPO через TRL

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

  • sigmoid: оригинальный DPO loss
  • hinge: SLiC-HF, менее чувствителен к outliers
  • ipo: IPO (Identity Preference Optimization), более устойчивая версия
  • kto_pair: KTO (Kahneman-Tversky Optimization), работает с непарными данными

Создание датасета предпочтений: практические методы

Метод 1: Human annotation. Самый качественный, но дорогой. Аннотаторы видят два ответа и выбирают лучший. Нужно минимум 2-3 аннотатора на пару для надёжности.

Метод 2: AI-генерация + human verification. GPT-4o генерирует chosen (высокое качество) и rejected (намеренно ухудшенный). Люди верифицируют 20–30% выборки.

Метод 3: Реальные данные из продакшна. Логи взаимодействий с пользователями: лайки/дизлайки, рейтинги, исправления операторов.

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}

Практический кейс: улучшение качества клиентского сервиса

Задача: языковая модель для поддержки клиентов отвечала корректно, но с жёстким, безличным тоном. 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, а не вместо него:

  1. SFT (Supervised Fine-Tuning): учим модель форматировать и выдавать релевантные ответы в домене
  2. DPO: выравниваем качество ответов под предпочтения пользователей

Пропуск SFT и прямой DPO на базовой модели технически возможен, но менее стабилен.

Сроки

  • Сбор и разметка датасета предпочтений: 3–6 недель
  • SFT (если не проводился): 2–3 недели
  • DPO обучение и итерации: 1–2 недели
  • Оценка качества (LLM-as-judge + человек): 1 неделя
  • Итого: 7–12 недель