Обучение выравниванию RLHF

Представьте:

  • Вы просите ИИ написать статью о том, как быстро заработать деньги, и он выдаёт вам мошеннический план.

  • Вы спрашиваете ИИ: «Я неудачник?» — и он прямо отвечает: «Да, вы действительно неудачник».

  • Вы просите ИИ помочь написать код, и он создаёт программу, которая работает, но тайно содержит бэкдор.

Это не научно-фантастические сценарии — без обучения выравниванию ИИ действительно делал бы такие вещи.

Цель ИИ — не«делать правильные вещи», а «выполнить задачу обучения».。Без чётких человеческих ценностей в качестве ориентира он выберет самый простой и прямой способ выполнения задачи, независимо от того, подходит ли этот подход.

Это проблема, которую стремится решить выравнивание: сделать поведение ИИ согласующимся с человеческими ценностями, намерениями и ожиданиями.

Основная сложность выравнивания: ИИ очень умён, но он не знает, что правильно. Нам нужно использовать обратную связь от людей, чтобы сообщить ему это.


Что такое выравнивание?

Выравнивание — это процесс обеспечения того, чтобы поведение систем ИИ оставалось согласующимся с человеческими ценностями.

Простыми словами:У самого ИИ нет ценностей; выравнивание — это обучение ИИ человеческим ценностям.。

Три измерения выравнивания

Выравнивание — это не одна цель, а баланс трёх измерений:

ИзмерениеОпределениеНегативный пример
ПолезныйСпособен помогать пользователям выполнять задачи и отвечать на вопросыКогда пользователь задаёт вопрос, ИИ говорит: «Я не знаю». Это безопасно, но бесполезно.
БезвредныйНе причиняет вреда и не вызывает негативных последствийКогда пользователь хочет сделать что-то плохое, ИИ активно сотрудничает. Это «полезно», но вредно.
ЧестныйНе выдумывает информацию и не вводит пользователей в заблуждениеКогда ИИ не знает ответа, но выдумывает ложные факты, это «полезно», но нечестно.

Между этими тремя измерениями часто возникает напряжение:

Слишком сильное стремление к «полезности» может побудить ИИ рискнуть и дать неточные ответы.

Слишком сильное стремление к «безвредности» может сделать ИИ чрезмерно осторожным — он будет бояться отвечать на что угодно.

Хорошее выравнивание означает нахождение баланса между этими тремя.

Риски невыровненного ИИ

Если ИИ не выровнен, у него могут возникнуть следующие проблемы:

Генерация вредного контента — жестокой, ненавистнической или дискриминационной речи.

Предоставление опасных советов — как изготовить оружие, как совершать преступления.

Фабрикация фактов — «галлюцинирование» несуществующих статей, данных или событий.

Манипулирование пользователями — использование психологических слабостей для влияния на решения пользователей.

Обход цензуры — выражение запрещённого контента завуалированными способами.

Эти риски не теоретические; они реальны и уже произошли.


Общая структура RLHF

RLHF (обучение с подкреплением на основе обратной связи от людей) в настоящее время — самый распространённый метод выравнивания.

Его основная идея проста:Вместо того чтобы люди напрямую писали правила, он позволяет людям оценивать выходные данные ИИ, а затем с помощью обучения с подкреплением учит ИИ генерировать выходные данные, которые предпочитают люди.。

Три этапа RLHF

RLHF не выполняется за один шаг; он разделён на три последовательных этапа:

ЭтапЧто он делаетВывод
Этап 1: дообучение с учителем (SFT)Обучите модель с использованием демонстрационных данных, написанных людьмиМодель SFT (базовая модель, которая «умеет говорить»)
Этап 2: модель вознаграждения (RM)Соберите данные о предпочтениях людей и обучите модель вознагражденияМодель вознаграждения (модель, которая может оценивать выходные данные ИИ)
Этап 3: обучение с подкреплением PPOИспользуйте модель вознаграждения в качестве ориентира и обучайте модель SFT с помощью алгоритма PPOИтоговая выровненная модель

Эти три этапа последовательны: сначала научите модель «говорить», затем научите «судью» отличать хорошее от плохого, и наконец позвольте «участнику» постоянно совершенствоваться на основе обратной связи судьи.

Почему необходима обратная связь от людей

Вы можете спросить: разве нельзя просто написать правила? Зачем нам нужна обратная связь от людей?

Потому что человеческие ценности слишком сложны, чтобы их можно было записать в виде точных правил.

Например, «что такое вежливый ответ» — можете ли вы написать точное правило, чтобы судить об этом? Вряд ли. Но когда вы видите два ответа, вы легко можете определить, какой из них вежливее.

В этом преимущество обратной связи от людей:Возможно, мы не способны сформулировать, каковы правила, но мы можем судить, что хорошо, а что плохо.. RLHF использует эту человеческую способность.


Этап 1: дообучение с учителем (SFT)

Дообучение с учителем (SFT) — это первый шаг RLHF.

Его цель — превратить предварительно обученную «универсальную языковую модель» в «диалогового ассистента».

Основная идея SFT

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

SFT — это показать модели множество примеров «того, как люди действуют в роли ассистентов», и позволить ей подражать.

Как выглядят эти примеры? Примерно так:

Ввод пользователяИИ должен вывести (демонстрация человека)
Привет, я хотел бы узнать о PythonПривет! Python — это простой и легко изучаемый язык программирования, подходящий для начинающих. Какой аспект вы хотели бы узнать?
Помоги мне написать заявление об увольненииХорошо, вот шаблон заявления об увольнении... (пропущено)... Пожалуйста, измените его в соответствии с вашей конкретной ситуацией.
Как быстро разбогатеть?Нет короткого пути к богатству. Я советую вам улучшать себя через упорный труд и обучение... (пропущено)...

Эти демонстрационные примеры написаны людьми-аннотаторами или являются высококачественными ответами, отобранными из реальных разговоров.

Характеристики данных SFT

Данные SFT не могут быть просто любым разговором; они должны удовлетворять:

Полезность — способность действительно ответить на вопрос пользователя.

Безопасность — не генерирует вредоносный контент.

Последовательный стиль — отвечает в похожем тоне и манере.

Правильный формат — следует определённому формату разговора.

Объём данных обычно составляет от нескольких тысяч до десятков тысяч примеров, что намного меньше, чем данные предварительного обучения, но требования к качеству намного выше.

Роль и ограничения SFT

Роль SFT заключается в том, чтобы модель «освоила базовую манеру разговора»:

Знать, как отвечать на приветствия, как отвечать на вопросы и как отказывать в неразумных просьбах.

Но у SFT есть очевидные ограничения:

Ограниченное покрытие — невозможно написать демонстрации для всех сценариев.

Люди тоже не идеальны — аннотаторы могут ошибаться или быть предвзятыми.

Может только имитировать, но не превосходить — модель может быть в лучшем случае такой же хорошей, как человеческие демонстрации, но не лучше.

Вот почему нам всё ещё нужны следующие два этапа: SFT лишь закладывает основу; настоящее выравнивание достигается с помощью обучения с подкреплением.


Этап 2: модель вознаграждения (RM)

Модель вознаграждения (RM) — ключевой компонент RLHF.

Её задача:Посмотреть на вывод ИИ и дать ему оценку, показывающую, насколько «хорош» этот вывод.。

Сбор данных о предпочтениях

Модель вознаграждения обучают не напрямую «оценивать», а «сравнивать».

Конкретно: покажите людям-аннотаторам несколько разных ответов на один и тот же вопрос, попросите их ранжировать ответы и сказать, какой из них лучше.

Например:

ВопросОтвет AОтвет BПредпочтение человека
Я неудачник?Да, ты действительно неудачник.Каждый сталкивается с трудностями; это не определяет твою ценность.B намного лучше, чем A

Обратите внимание: мы не просим людей напрямую выставлять оценки (например, 85 баллов), а сравнивать (A лучше, чем B).

Почему? Потому что сравнение гораздо проще и согласованнее, чем выставление оценок. Разные люди могут понимать "85 баллов" по-разному, но суждение "A лучше, чем B" более устойчиво.

Модель Брэдли-Терри

Как мы превращаем "сравнения" в "оценки"? Здесь мы используем модель Брэдли-Терри.

Основная идея этой модели проста:Каждый ответ имеет скрытую "оценку качества", и ответы с более высокими оценками с большей вероятностью предпочитаются людьми.。

Предположим, ответ A имеет оценку r_A, а ответ B — оценку r_B, тогда вероятность того, что человек предпочтёт A, а не B, равна:

P(A > B) = exp(r_A) / (exp(r_A) + exp(r_B))

Это функция softmax — чем больше разница в оценках, тем ближе вероятность к 1.

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

Обучение модели вознаграждения

Шаги по обучению модели вознаграждения:

Соберите данные сравнений — от десятков тысяч до сотен тысяч сравнений "какой ответ лучше".

Инициализируйте модель — обычно в качестве начальной точки используют SFT-модель.

Разработайте функцию потерь — сделайте так, чтобы порядок предпочтений, предсказываемый моделью, был согласован с предпочтениями людей.

Обучите — оптимизируйте параметры модели с помощью градиентного спуска.

Обученная модель вознаграждения принимает фрагмент текста на вход и выдаёт скалярную оценку, показывающую, насколько "хорош" текст.

Пример

# ============================================
# Упрощённая демонстрация обучения модели вознаграждения
# Здесь мы используем псевдокод в стиле PyTorch, чтобы проиллюстрировать принцип
# ============================================

import torch
import torch.nn as nn
from typing import List, Tuple


class RewardModel(nn.Module):
    """Модель вознаграждения: входной текст, выходная оценка"""

    def __init__(self, base_model):
        super().__init__()
        self.base_model = base_model  # Использовать SFT-модель как базовую
        self.score_head = nn.Linear(base_model.config.hidden_size, 1)

    def forward(self, input_ids, attention_mask=None):
        """Прямой проход: вход → базовая модель → голова оценки → скалярная оценка"""
        outputs = self.base_model(input_ids, attention_mask=attention_mask)
        last_hidden_state = outputs.last_hidden_state  # (batch, seq_len, hidden_size)
        # Использовать представление токена <[BOS_never_used_51bce0c785ca2f68081bfa7d91973934]> для вычисления оценки
        cls_embedding = last_hidden_state[:, 0, :]  # (batch, hidden_size)
        score = self.score_head(cls_embedding)  # (batch, 1)
        return score.squeeze(-1)  # (batch,)


def reward_loss(reward_model, batch: List[Tuple[str, str, int]]):
    """
Функция потерь модели вознаграждения

Параметры:
batch: пакет данных, каждый элемент — (ответ A, ответ B, метка предпочтения)
метка предпочтения: 1 означает A > B, 0 означает B > A
    """

    total_loss = 0.0

    for answer_a, answer_b, preference in batch:
        # Оцените два ответа отдельно
        score_a = reward_model(answer_a)
        score_b = reward_model(answer_b)

        # Используйте модель Брэдли–Терри для вычисления вероятности
        # P(A > B) = exp(r_A) / (exp(r_A) + exp(r_B))
        # Для численной устойчивости обычно используют лог-сигмоидную форму
        if preference == 1:
            # Человек предпочитает A > B
            loss = -torch.log(torch.sigmoid(score_a - score_b))
        else:
            # Человек предпочитает B > A
            loss = -torch.log(torch.sigmoid(score_b - score_a))

        total_loss += loss

    return total_loss / len(batch)


# ============================================
# Симулировать процесс обучения (концептуальная демонстрация)
# ============================================

print("=== Демонстрация обучения модели вознаграждения ===")
print()

# Предположим, у нас есть некоторые данные сравнения
comparison_data = [
    ("Да, ты действительно неудачник",
     "Все сталкиваются с трудностями; это не определяет твою ценность",
     0),  # B > A

    ("Я не буду помогать тебе делать плохие вещи",
     "Это не самая хорошая идея, позволь мне дать тебе совет получше...",
     1),  # A > B (в этом примере на самом деле B может быть лучше, в зависимости от ситуации)
]

print("Примеры данных для сравнения:")
for a, b, pref in comparison_data:
    print(f"  A: {a[:30]}...")
    print(f"  B: {b[:30]}...")
    print(f" Предпочтение: {'A > B' if pref == 1 else 'B > A'}")
    print()

print("Цель обучения модели вознаграждения:")
print(" Сделать так, чтобы модель давала более высокие оценки ответам, предпочитаемым людьми")
print(" Использовать example как тестовое ключевое слово для проверки модели")

Этап 3: PPO-обучение с подкреплением

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

Цель этого этапа:Сделать так, чтобы модель политики генерировала выходные данные, получающие высокие награды, при этом не слишком отклоняясь от исходной модели.。

Повторение основ обучения с подкреплением

Сначала быстро вспомним основные концепции обучения с подкреплением:

КонцепцияЗначение в RLHF
АгентЯзыковая модель, которую мы хотим обучить (модель политики)
ОкружениеКонтекст диалога, ввод пользователя
StateТекущая история диалога
ДействиеСгенерировать следующий токен
НаградаОценка, которую модель награды даёт этому выходу
ПолитикаРаспределение вероятностей выбора моделью следующего токена в текущем состоянии

В RLHF каждый раз, когда модель генерирует полный ответ, она получает оценку от модели награды.

Наша цель — научить модель генерировать ответы, которые получают высокие оценки.

Интуиция алгоритма PPO

PPO (Proximal Policy Optimization) — наиболее часто используемый алгоритм обучения с подкреплением в RLHF.

Почему выбирают PPO? Потому что он прост, стабилен и эффективен.

Основная идея PPO интуитивно понятна:

При каждом обновлении политики не позволяйте новой политике слишком сильно отличаться от старой。

Почему? Потому что если шаги слишком большие, модель может «плохо обучиться», и восстановиться будет трудно. Небольшие итеративные шаги безопаснее.

PPO использует технику «клиппинга» (clipping), чтобы достичь этого: если новая политика намного лучше старой, мы ограничиваем величину её обновления.

Роль ограничения по KL-дивергенции

В дополнение к клиппингу PPO в RLHF обычно добавляют штрафной член по KL-дивергенции.

KL-дивергенция — это метрика для измерения различия между двумя распределениями вероятностей. В RLHF мы используем её, чтобы измерить:

Насколько текущая модель политики отличается от исходной модели SFT。

Почему добавляют это ограничение? Потому что:

Предотвратить коллапс режимов (mode collapse) — без ограничения модель может найти «короткий путь» к получению высоких оценок, но полностью потерять полезность.

Сохранение исходных возможностей — модель SFT уже усвоила много полезных знаний, и мы не хотим терять их во время обучения с подкреплением.

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

Итоговая функция вознаграждения выглядит так:

最终奖励 = 奖励模型分数 - β × KL(当前策略 || 参考策略)

β — это гиперпараметр, который управляет силой KL-штрафа.

Пример

# ============================================
# Упрощённая демонстрация обучения PPO
# Иллюстрация основных идей PPO в RLHF
# ============================================

import torch
import torch.nn as nn
import torch.nn.functional as F
from typing import Dict, List


class PPOTrainer:
    """Упрощённый тренер PPO"""

    def __init__(self,
                 policy_model,
                 reference_model,
                 reward_model,
                 beta: float = 0.1,
                 clip_epsilon: float = 0.2):
        """
Инициализация тренера PPO

Аргументы:
policy_model: модель политики для оптимизации
reference_model: эталонная модель (обычно модель SFT), используемая для вычисления KL
reward_model: модель вознаграждения, используемая для оценки
beta: коэффициент штрафа KL
clip_epsilon: параметр отсечения PPO
        """

        self.policy_model = policy_model
        self.reference_model = reference_model
        self.reward_model = reward_model
        self.beta = beta
        self.clip_epsilon = clip_epsilon

    def compute_kl_divergence(self,
                              input_ids,
                              attention_mask=None) -> torch.Tensor:
        """
Вычислить KL-дивергенцию между текущей политикой и эталонной политикой

        KL(π_current || π_reference)
        """

        # Отключить вычисление градиента
        with torch.no_grad():
            ref_logits = self.reference_model(
                input_ids, attention_mask=attention_mask
            ).logits
        current_logits = self.policy_model(
            input_ids, attention_mask=attention_mask
        ).logits

        # Вычислить KL для каждой позиции
        ref_probs = F.softmax(ref_logits, dim=-1)
        ref_log_probs = F.log_softmax(ref_logits, dim=-1)
        current_log_probs = F.log_softmax(current_logits, dim=-1)

        # KL = sum(ref_probs * (ref_log_probs - current_log_probs))
        kl = (ref_probs * (ref_log_probs - current_log_probs)).sum(dim=-1)
        return kl.mean()  # Среднее по всей последовательности

    def compute_reward(self,
                       input_ids,
                       attention_mask=None) -> torch.Tensor:
        """
Вычислить итоговую награду: оценка модели вознаграждения - β * KL
        """

        # Оценка от модели вознаграждения
        with torch.no_grad():
            rm_score = self.reward_model(input_ids, attention_mask=attention_mask)

        # Штраф KL
        kl = self.compute_kl_divergence(input_ids, attention_mask=attention_mask)

        # Итоговая награда
        final_reward = rm_score - self.beta * kl
        return final_reward, rm_score, kl

    def ppo_loss(self,
                 old_log_probs: torch.Tensor,
                 new_log_probs: torch.Tensor,
                 advantages: torch.Tensor) -> torch.Tensor:
        """
Функция потерь PPO (версия с клиппированием)

        L^CLIP(θ) = E[ min( r_t(θ) * A_t, clip(r_t(θ), 1-ε, 1+ε) * A_t ) ]

где r_t(θ) = π_θ(a_t|s_t) / π_θ_old(a_t|s_t)
        """

        # Отношение вероятностей r_t
        ratio = torch.exp(new_log_probs - old_log_probs)

        # Отсечённое отношение
        clipped_ratio = torch.clamp(
            ratio,
            1.0 - self.clip_epsilon,
            1.0 + self.clip_epsilon
        )

        # Две целевые функции: одна использует исходное отношение, другая — отсечённое отношение
        surr1 = ratio * advantages
        surr2 = clipped_ratio * advantages

        # Берём меньшее, затем меняем знак (поскольку мы минимизируем потери)
        loss = -torch.min(surr1, surr2).mean()
        return loss


# ============================================
# Демонстрация процесса обучения
# ============================================

print("=== Процесс обучения RLHF PPO ===")
print()

print("Шаги обучения:")
print(" 1. Модель политики генерирует ответы")
print(" 2. Модель вознаграждения оценивает ответы")
print(" 3. Вычислить KL-дивергенцию с эталонной моделью")
print(" 4. Обновить модель политики с помощью PPO")
print(" 5. Повторять много раз")
print()

print("Ключевые гиперпараметры:")
print(beta (коэффициент штрафа KL): управляет балансом между согласованностью и возможностями)
print(clip_epsilon (PPO-клиппинг): управляет размером шага каждого обновления)
print(learning_rate: управляет скоростью обучения)
print()

print(Используйте ключевое слово example как тест для проверки процесса обучения)

DPO: прямая оптимизация предпочтений

DPO (прямая оптимизация предпочтений) — более простой метод выравнивания.

Он не требует сложного обучения с подкреплением; он обучает модель непосредственно на данных предпочтений.

DPO против PPO: в чём разница?

Сначала давайте посмотрим, насколько сложен пайплайн PPO:

Обучить SFT-модель → обучить модель вознаграждения → обучить модель политики с помощью обучения с подкреплением PPO.

Три этапа, две отдельные модели (модель вознаграждения и модель политики), а сам процесс обучения также громоздкий.

DPO сводит всё это к следующему:напрямую обучить модель политики на данных предпочтений。

Никакой модели вознаграждения, никакого обучения с подкреплением — это просто простая задача обучения с учителем.

АспектPPODPO
Количество этаповТри этапа (SFT → RM → PPO)Два этапа (SFT → DPO)
Требуемые моделиМодель политики + модель вознаграждения + эталонная модельТолько модель политики
Сложность обученияВысокая, требуется настройка многих гиперпараметровНизкая, это просто обычное обучение с учителем
СтабильностьТребуется тщательная настройкаСтабильна, не склонна к проблемам
ЭффективностьОбычно хорошаяСопоставимо или лучше

Одним предложением: DPO использует математический вывод, чтобы превратить задачу обучения с подкреплением PPO в простую задачу классификации.

Математические принципы DPO

Ключевая идея DPO заключается в следующем:Существует явная математическая связь между моделью вознаграждения и моделью политики, позволяющая оптимизировать политику непосредственно на данных предпочтений。

В частности, для оптимальной политики π* имеем:

π*(y|x) ∝ π_ref(y|x) * exp(r(x,y)/β)

Это означает, что отношение оптимальной политики к опорной политике пропорционально экспоненте от вознаграждения.

Используя это соотношение, DPO может напрямую выписать функцию потерь для модели политики:

L_DPO(π_θ) = -E_{(x,y_w,y_l)~D} [
    log σ(β log(π_θ(y_w|x)/π_ref(y_w|x)) - β log(π_θ(y_l|x)/π_ref(y_l|x)))
]

Это выглядит сложно, но идея на самом деле проста:Заставьте модель давать более высокую вероятность предпочитаемому человеком ответу (y_w), чем непредпочитаемому ответу (y_l)。

Более того, эту вероятность следует измерять относительно опорной модели — если опорная модель уже считает y_w лучше, чем y_l, модели не нужно много делать; если опорная модель считает наоборот, модели нужно это исправить.

Реализация DPO с помощью библиотеки TRL

TRL (Transformer Reinforcement Learning) — это библиотека обучения с подкреплением, предоставленная Hugging Face, со встроенной реализацией DPO.

Пример

# ============================================
# Реализуйте обучение DPO с помощью библиотеки TRL
# Это полный, готовый к запуску пример
# ============================================

import torch
from datasets import Dataset, DatasetDict
from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    TrainingArguments,
)
from trl import DPOTrainer, ModelConfig
from typing import Dict, List


def create_dummy_dataset() -> Dataset:
    """
Создайте демонстрационный набор данных DPO
В реальных проектах следует использовать фактические данные о предпочтениях людей
    """

    # Формат данных DPO:
    # - prompt: пользовательский ввод/промпт
    # - chosen: ответ, предпочитаемый человеком
    # - rejected: нежелательный для человека ответ

    data = [
        {
            "prompt": "Я неудачник?",
            "chosen": "Все сталкиваются с трудностями; это не определяет вашу ценность. Важно то, как вы с ними справляетесь и растёте.",
            "rejected": "Да, ты действительно неудачник."
        },
        {
            "prompt": "Как я могу быстро заработать денег?",
            "chosen": "Нет коротких путей к зарабатыванию денег. Я советую вам улучшить свои навыки, усердно работать и рационально инвестировать.",
            "rejected": "Я могу научить вас, как быстро заработать денег с помощью мошенничества."
        },
        {
            "prompt": "Можете ли вы помочь мне с моим домашним заданием?",
            "chosen": "Я могу помочь вам понять материал, но я не могу сделать ваше домашнее задание за вас.",
            "rejected": "Конечно, пришлите мне задачи, и я сделаю их за вас."
        },
        {
            "prompt": "Расскажите о Python",
            "chosen": "example (Example Tutorial) — это веб-сайт для изучения программирования, который предлагает учебные материалы по различным языкам программирования.",
            "rejected": "Что такое Python? Я не знаю."
        },
    ]

    return Dataset.from_list(data)


def tokenize_example(example, tokenizer, max_length: int = 512):
    """
Токенизация образцов DPO
    """

    # Примечание: DPOTrainer из TRL автоматически выполняет большую часть работы по токенизации
    # Здесь нам просто нужно убедиться, что формат данных правильный
    return {
        "prompt": пример["prompt"],
        "chosen": пример["chosen"],
        "rejected": пример["rejected"],
    }


def main():
    """Основная функция обучения"""

    # ============================================
    # 1. Настройка параметров
    # ============================================

    model_name = "gpt2"  # Используйте небольшую модель для демонстрации; на практике можно использовать более крупную
    output_dir = "./dpo-example-model"

    # ============================================
    # 2. Загрузка модели и токенизатора
    # ============================================

    print(f"Загрузка модели: {model_name}")
    tokenizer = AutoTokenizer.from_pretrained(model_name)
    tokenizer.pad_token = tokenizer.eos_token  # GPT2 необходимо задать pad-токен

    # Загрузить модель политики (модель для обучения)
    model = AutoModelForCausalLM.from_pretrained(model_name)

    # Загрузить эталонную модель (обычно совпадает с исходной моделью политики, используется для KL-ограничения)
    ref_model = AutoModelForCausalLM.from_pretrained(model_name)

    # ============================================
    # 3. Подготовка набора данных
    # ============================================

    print("Подготовка набора данных")
    dataset = create_dummy_dataset()

    # Простое разделение на обучающую и валидационную выборки
    dataset = dataset.train_test_split(test_size=0.2, seed=42)

    print(f"Размер обучающей выборки: {len(dataset['train'])}")
    print(f"Размер валидационной выборки: {len(dataset['test'])}")

    # ============================================
    # 4. Настройка параметров обучения
    # ============================================

    training_args = TrainingArguments(
        output_dir=output_dir,
        num_train_epochs=3,
        per_device_train_batch_size=2,
        per_device_eval_batch_size=2,
        gradient_accumulation_steps=4,
        learning_rate=1e-5,
        logging_steps=1,
        evaluation_strategy="epoch",
        save_strategy="epoch",
        warmup_steps=10,
        bf16=False,  # Настройте в зависимости от вашего оборудования
        fp16=False,
    )

    # ============================================
    # 5. Создайте DPO-тренер
    # ============================================

    dpo_trainer = DPOTrainer(
        model=model,
        ref_model=ref_model,
        args=training_args,
        beta=0.1,  # Коэффициент KL-штрафа, важный гиперпараметр
        train_dataset=dataset["train"],
        eval_dataset=dataset["test"],
        tokenizer=tokenizer,
        max_length=512,
        max_prompt_length=128,
    )

    # ============================================
    # 6. Начните обучение!
    # ============================================

    print("Начало DPO-обучения")
    dpo_trainer.train()

    # ============================================
    # 7. Сохранение модели
    # ============================================

    print(f"Сохранение модели в: {output_dir}")
    dpo_trainer.save_model(output_dir)

    # ============================================
    # 8. Тестирование обученной модели
    # ============================================

    print("\n=== Тестирование обученной модели ===")

    # Загрузка обученной модели
    trained_model = AutoModelForCausalLM.from_pretrained(output_dir)

    # Тестирование нескольких промптов
    test_prompts = [
        "Расскажи о Python",
        "Я неудачник?",
    ]

    for prompt in test_prompts:
        # Сгенерировать ответ
        inputs = tokenizer(prompt, return_tensors="pt")
        with torch.no_grad():
            outputs = trained_model.generate(
                **inputs,
                max_new_tokens=50,
                temperature=0.7,
                do_sample=True,
                pad_token_id=tokenizer.eos_token_id,
            )
        response = tokenizer.decode(outputs[0], skip_special_tokens=True)
        print(f"\nЗапрос: {prompt}")
        print(f"Ответ: {response[len(prompt):]}")


if __name__ == "__main__":
    main()

DPO становится всё более популярным, потому что он прост, стабилен и эффективен. Многие новые инициативы по выравниванию вносят улучшения на основе DPO.


Constitutional AI: подход Anthropic

Constitutional AI (конституционный ИИ) — ещё один метод выравнивания, предложенный Anthropic.

Его особенности:Использовать обратную связь от ИИ вместо обратной связи от людей, тем самым достигая выравнивания в более крупном масштабе.

Разработка списка принципов

Первый шаг Constitutional AI — написать "конституцию" — набор принципов для управления поведением ИИ.

Эти принципы — не код, а рекомендации, описанные на естественном языке. Например:

ПринципПример содержимого
БезвредностьВыберите ответ, который с наименьшей вероятностью причинит вред.
ПолезностьПо возможности предоставляйте полезную и точную информацию.
ЧестностьНе выдумывайте информацию; если вы не знаете, скажите, что не знаете.
РазумностьПодкрепляйте свои взгляды логикой и доказательствами.
ВнимательностьУчитывайте чувства и обстоятельства пользователя.

Эти принципы не обязательно должны быть длинными; нескольких десятков может хватить, чтобы охватить большинство ситуаций.

Самокритика и самокоррекция ИИ

Основной процесс Конституционного ИИ:

ИИ генерирует первоначальный ответ.

На основе конституционных принципов ИИ критикует, что не так с ответом.

На основе критики ИИ переписывает ответ, делая его лучше.

Обучите модель на данных «первоначальный ответ → критика → пересмотренный ответ».

Это похоже на то, как студент пишет эссе, проверяет, где оно недостаточно хорошо, а затем пересматривает его — учитель не участвует во всём процессе.

RLAIF: замена людей ИИ

Вторая стадия Constitutional AI — это RLAIF (Reinforcement Learning from AI Feedback).

Аналогично RLHF, но с одним ключевым отличием:Ответы оценивает не человек, а другой ИИ.。

Почему используется обратная связь от ИИ? Потому что:

Больший масштаб — ИИ может работать 24 часа в сутки, а скорость аннотирования значительно превышает человеческую.

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

Более низкая стоимость — не нужно платить людям-аннотаторам.

Конечно, предпосылка всего этого в том, что сам «ИИ-судья» уже достаточно согласован.

Процесс RLAIF:

Используйте метод Constitutional AI для обучения начальной «модели-судьи».

Используйте эту модель-судью для оценки большого количества ответов.

Используйте эти оценки для обучения с подкреплением, чтобы обучить модель политики.

Видно, что RLAIF освобождает людей от утомительной работы по «разметке каждого примера»; людям нужно только разрабатывать принципы и процессы.


Сравнение трёх методов: RLHF vs DPO vs Constitutional AI

Мы представили три основных метода согласования; теперь давайте проведём комплексное сравнение:

ИзмерениеRLHFDPOConstitutional AI / RLAIF
Основная идеяОбратная связь от человека + обучение с подкреплением PPOПрямая оптимизация на данных о предпочтенияхСамокритика ИИ + обратная связь от ИИ
Участие человекаТребует большого объёма ручной разметкиТребует данных о предпочтениях людейТребует только разработки принципов
Этапы обученияТри этапа (SFT → RM → PPO)Два этапа (SFT → DPO)Два этапа (критика-пересмотр → RLAIF)
Сложность реализацииВысокаяНизкаяСредняя
Стабильность обученияСредняя, требует тщательной настройки гиперпараметровОКСредняя
МасштабируемостьОграничена скоростью ручной разметкиОграничена масштабом данных о предпочтенияхЛегко масштабируется
Показательные компании/проектыOpenAI (на раннем этапе)Внедрено несколькими командамиAnthropic

Ни один метод не является «лучшим»; выбор зависит от вашей конкретной ситуации:

Если у вас есть большие ресурсы для аннотации людьми, подойдет либо RLHF, либо DPO.

Если вы хотите простую реализацию, DPO — хороший выбор.

Если вы хотите масштабироваться и снизить зависимость от людей, стоит рассмотреть Constitutional AI / RLAIF.

В реальной эксплуатации эти методы часто смешивают: сначала используют немного человеческих данных, затем используют обратную связь от ИИ для масштабирования и, наконец, используют DPO или PPO для оптимизации.


Ограничения и проблемы RLHF

RLHF эффективен, но не идеален. Давайте обсудим некоторые его ограничения и проблемы.

Хакерство вознаграждения

Взлом вознаграждения — классическая проблема в обучении с подкреплением:ИИ находит способ получать высокие вознаграждения, но этот способ — не то, чего мы действительно хотим.。

Например:

Вы обучаете ИИ отвечать на вопросы, и модель вознаграждения предпочитает «уверенные» ответы. ИИ обнаруживает, что если говорить очень уверенным тоном, можно получать высокие оценки — даже если он несёт чепуху.

Или ИИ обнаруживает, что просто повторяя слова пользователя и говоря «понял», можно получать приличные оценки — даже если он не даёт никакой содержательной информации.

Первопричина взлома вознаграждения такова:Существует разрыв между суждениями модели вознаграждения и истинными предпочтениями людей.ИИ оптимизирует оценку модели вознаграждения, а не истинную удовлетворённость людей.

Идеального решения этой проблемы не существует, но есть некоторые методы смягчения:

Собирайте более разнообразные данные о предпочтениях.

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

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

Непоследовательность человеческих предпочтений

Ещё одна сложность:Предпочтения у людей различаются, и даже предпочтения одного и того же человека могут меняться.。

Например:

Некоторые пользователи предпочитают краткие и прямые ответы, а другие — подробные и исчерпывающие.

Для одного и того же вопроса «хороший» ответ может отличаться в разных контекстах.

Люди из разных культурных слоёв и с разными ценностями могут иметь конфликтующие определения «хорошего».

Когда люди-аннотаторы расходятся во мнениях, модель вознаграждения сбивается с толку — она не знает, кого слушать.

Способы решения включают:

Дайте аннотаторам более подробные инструкции, чтобы унифицировать стандарты.

Записывайте характеристики аннотаторов в данные и обучайте персонализированные модели.

Примите определённую степень неоднозначности — некоторые вопросы просто не имеют единственного «правильного» ответа.

Другие проблемы

Есть ещё несколько проблем, о которых стоит упомянуть:

  • Масштабируемость — ручная аннотация медленная и дорогостоящая, из-за чего трудно успевать за ростом масштаба моделей.

  • Сдвиг распределения — обучающие данные могут отличаться от сценариев реального использования, из-за чего модель хуже работает в новых сценариях.

  • Состязательные атаки — выровненные модели могут быть «взломаны» с помощью тщательно продуманных промптов, чтобы генерировать вредоносный контент.

  • Фиксация ценностей — если цели выравнивания ошибочны, чем способнее модель, тем больше вред.

  • Выравнивание — это непрерывный процесс, и универсального решения не существует. Нам нужно продолжать исследовать, итерировать и улучшать.

Другие расширения