Перейти к содержимому

Дообучение LLM на вашей разметке

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

Новое в v2.14.0

Этот учебник обучает четыре вида языковых моделей на ответах, которые собирает исследование в Potato. Тренер llm-sft дообучает LLM на написанных ответах или исправленных трассах агента, llm-dpo настраивает LLM по парным выборам, reward-model подгоняет скалярную модель вознаграждения по сравнениям, а prm-reward подгоняет модель вознаграждения за процесс по оценкам шагов. Страница написана для команд, которые уже собирают в Potato данные о предпочтениях или трассы и хотят получить первую модель по этим меткам без экспорта данных в отдельный скрипт обучения. Каждый раздел называет схему, которая даёт данные, приводит конфигурацию, проходящую проверку валидатором Potato, перечисляет параметры, которые стоит менять, и объясняет, что измеряет оценка на отложенных объектах и возвращаются ли предсказания разметчикам как предварительные метки. Обзор обучения моделей описывает страницу Training, а Обучите первую модель проходит весь цикл с классификатором, которому не нужен GPU.

Тренеры по схемам разметки

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

ТренерСхемаЧему учится модельГлавная оценка на отложенных объектахПоказывается разметчикам
llm-sfttextписать ответ, который написали разметчикиtoken F1да, сгенерированный ответ заполняет текстовое поле
llm-sfttrajectory_editпереписывать шаги агента в исправленные шагиcloser_to_correctionнет, только сохраняется и оценивается
llm-dpopairwise в режиме binaryпредпочитать ответ, который выбрали разметчикиaccuracy без учёта ничьихда, выбирается карточка предпочтительного ответа
llm-dpotrajectory_editпредпочитать исправленные шаги исходнымcloser_to_correctionнет, только сохраняется и оценивается
reward-modelpairwise (binary и scale), ranking, bwsоценку для каждого ответаaccuracy, direction accuracy, тау Кендалла или best-worst accuracyда, как собственный ответ схемы
prm-rewardprocess_rewardоценку correct, neutral или wrong для каждого шагаstep_macro_f1предлагается кнопкой "AI pre-label steps"

Перед началом

Дополнительные пакеты обучения Potato ставят PyTorch, Transformers и PEFT для четырёх тренеров:

bash
pip install "potato-annotation[train-llm]"
pip install "potato-annotation[train-text]"

Первая группа покрывает llm-sft и llm-dpo, а вторая покрывает reward-model и prm-reward. Команда pip install "potato-annotation[train]" ставит все группы обучения сразу. Тренер, у которого не хватает пакетов, показывается на странице Training как "not installed" вместе с командой, которая ставит эти пакеты.

Каждый тренер отказывается обучаться, если в выборке train меньше 20 объектов (параметр min_instances). Разбиение по умолчанию отдаёт 70% размеченных объектов в train, 15% в val и 15% в test, поэтому до первого запуска стоит запланировать около 30 размеченных объектов. Объекты val и test отложены от обучения и служат для оценки модели.

llm-sft и llm-dpo стартуют с Qwen/Qwen2.5-0.5B-Instruct, reward-model с distilbert/distilroberta-base, а prm-reward с answerdotai/ModernBERT-base. LLM-тренеры рассчитаны на работу на GPU. Если на машине, где работает Potato, нет GPU, удалённое обучение отправляет запуски на GPU-сервер по ssh или на кластер SLURM.

Исследование, которое собирает предпочтения и переписанные ответы

Первая конфигурация задаёт два вопроса к каждому запросу в службу поддержки. Разметчики выбирают лучший из двух ответов и пишут ответ, который разметчик хотел бы получить от ассистента. Выбор обучает llm-dpo и reward-model, а написанный ответ обучает llm-sft. Каждая строка data/answers.jsonl содержит запрос и два ответа:

json
{"id": "q001", "prompt": "How do I reset my router to factory settings?", "responses": ["Hold the reset button on the back for 10 seconds until the lights blink, then wait two minutes for the router to restart.", "Routers can be reset. Check the manual."]}

Конфигурация показывает запрос как текст объекта, а два ответа как карточки A и B:

yaml
annotation_task_name: "Support answers: preferences and rewrites"
task_dir: .
data_files:
  - data/answers.jsonl
item_properties:
  id_key: id
  text_key: prompt
output_annotation_dir: annotation_output
user_config:
  allow_all_users: true
 
annotation_schemes:
  - annotation_type: pairwise
    name: preferred
    description: "Which response answers the question better?"
    mode: binary
    items_key: responses
    allow_tie: true
    tie_label: "No preference"
 
  - annotation_type: text
    name: rewrite
    description: "Write the answer you would want the assistant to give."
    multiline: true
    rows: 4
 
model_training:
  enabled: true
  writeback:
    schemas: [preferred]
    min_confidence: 0.7

text_key: prompt важен дважды, потому что запрос читают разметчики, и его же llm-sft ставит после вопроса. items_key: responses называет список, из которого берутся карточки pairwise, в порядке данных, так что A это первый ответ. В writeback.schemas указана только preferred, поэтому разметчики видят выбор модели, а не сгенерированный переписанный ответ. Предварительные метки привязывают разметчиков к себе, поэтому добавляйте rewrite в список, только когда оценка запуска llm-sft на отложенных объектах оправдывает показ текста модели. min_confidence: 0.7 убирает со страницы предсказания, в которых модель менее уверена, но продолжает их сохранять. Проверьте конфигурацию валидатором Potato до запуска сервера:

bash
python -m potato.validate_cli config.yaml --strict

Запустите Potato, разметьте не менее 30 запросов и откройте /admin/training как администратор. Запуски ниже можно начать и через API с admin_api_key из конфигурации в $KEY.

Обучение с учителем с llm-sft

llm-sft превращает каждый размеченный объект в один обучающий пример. Запрос состоит из description схемы (вопроса, который видели разметчики) и следующего за ним текста объекта, а целью служит ответ, который написал разметчик. Функция потерь охватывает только токены ответа, поэтому модель учится отвечать, а не повторять запрос. По умолчанию обучается адаптер LoRA, а не все веса.

Выберите на странице Training llm-sft и схему rewrite и нажмите Train now или начните тот же запуск через API:

bash
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  http://localhost:8000/admin/training/api/runs \
  -d '{"trainer": "llm-sft", "schemas": ["rewrite"], "params": {"max_new_tokens": 256}}'

Большинство запусков меняет только параметры из этой таблицы:

ПараметрПо умолчаниюЗначение
model_nameQwen/Qwen2.5-0.5B-InstructКаузальная языковая модель на Hugging Face Hub или локальный каталог.
loratruefalse обучает все веса и требует в несколько раз больше памяти. {quantize: 4bit} загружает базовую модель в 4 битах (см. QLoRA).
max_length1024Токенов на пример. Длинный запрос теряет токены с начала, а ответ сохраняется.
max_new_tokens256Самый длинный ответ, который генерирует модель.
instructiondescription схемыТекст, который ставится перед текстом каждого объекта.
system_promptнетСистемное сообщение для моделей с шаблоном чата.
gradient_checkpointingfalseЭкономит память активаций ценой примерно на треть большего времени.
learning_rate2e-4 с LoRA, 1e-5 без LoRA

Запуск сохраняет контрольную точку с наименьшей потерей на val. Поскольку запуск выбрал контрольную точку по val, оценка на отложенных объектах считается на test. Оценка это token F1, то есть пересечение слов сгенерированного и написанного ответов независимо от порядка, а рядом с оценкой выводится exact match. Token F1 засчитывает ответ, в котором нужные слова стоят не на тех местах, поэтому читайте обе метрики вместе.

Модель жадно генерирует ответ для каждого объекта val и test. При writeback.include_unlabeled: true модель отвечает и на объекты, которые никто не разметил. Уверенность предсказания это средняя вероятность токенов, которые сгенерировала модель, и очередь проверки модели сортируется по этой уверенности. Если rewrite указана в writeback.schemas, сгенерированный ответ заполняет текстовое поле, когда разметчик открывает объект.

Свободный текст плохо подходит для нескольких разметчиков на объект. Параметр aggregation сводит несколько ответов в один, сравнивая ответы слово в слово, а два написанных ответа редко совпадают слово в слово. Для llm-sft на схеме text один автор на объект позволяет обойтись без сравнения слово в слово.

Настройка по предпочтениям с llm-dpo

Direct Preference Optimization (DPO) учит LLM повышать правдоподобие предпочтительного ответа относительно другого ответа, сравнивая с замороженной эталонной копией исходной модели. llm-dpo строит один пример из каждого объекта, на который ответили A или B. Запрос это поле prompt объекта или первое из полей question, instruction, query, input и context, которое есть у объекта. Объекты, на которые ответили вариантом ничьей, исключаются, потому что ничья не отмечает ни один ответ как лучший.

Выберите llm-dpo и схему preferred или отправьте тот же запрос, что выше, с "trainer": "llm-dpo" и "schemas": ["preferred"]. С адаптером LoRA по умолчанию эталонная модель это та же модель с выключенным адаптером, поэтому вторая копия в памяти не хранится. lora: false обучает все веса и держит замороженную копию как эталон, и замороженная копия удваивает память.

ПараметрПо умолчаниюЗначение
model_nameQwen/Qwen2.5-0.5B-InstructКаузальная языковая модель.
beta0.1Насколько далеко модель может уйти от эталона. Меньшее значение позволяет модели уйти дальше.
epochs2
learning_rate5e-5 с LoRA, 5e-7 без LoRA
max_length1024Токенов на запрос и ответ.
instructionнетТекст, который ставится перед запросом каждого объекта.

Запуск сохраняет контрольную точку с наименьшей потерей DPO на val, а журнал запуска сообщает, как часто модель предпочитает выбор разметчиков на val. Оценка на отложенных объектах это accuracy на test по объектам, на которые не ответили ничьей, а рядом с accuracy выводится macro-F1. Предсказание это ответ, который предпочитает обученная модель, а уверенность это вероятность этого предпочтения. Как предварительная метка выбирается карточка предпочтительного ответа, когда разметчик открывает объект. При randomize_order в схеме выбор следует за ответом туда, где разметчик его видит. Сохранённый адаптер тоже является политикой и генерирует текст при загрузке через PEFT. О сборе самих данных о предпочтениях см. Сбор данных RLHF и предпочтений и Парное сравнение.

Модель вознаграждения с reward-model

Модель вознаграждения сопоставляет ответу число, для RLHF, для выборки best-of-n или для ранжирования новых выводов. reward-model обучает трансформер с одним выходом так, чтобы ответ, который предпочли разметчики, получал более высокую оценку. Функция потерь это потеря Брэдли — Терри, -log sigmoid(r_winner - r_loser), потеря обучения вознаграждения из InstructGPT. Схема preferred выше обучает reward-model без изменений в конфигурации. Каждая сравнительная схема даёт свой обучающий сигнал:

СхемаОбучающий сигналГлавная оценка на отложенных объектах
pairwise, binaryВыбранный ответ превосходит другой. Ничьи пропускаются.accuracy
pairwise, scaleПобеждает сторона, в которую склоняется ползунок, с весом по величине наклона. Середина пропускается.direction accuracy
rankingВесь порядок, через потерю Плакетта — Люса, или каждая пара в порядке при ranking_loss: pairs.тау Кендалла
bwsЛучший объект превосходит все остальные в кортеже, и все остальные превосходят худший.best-worst accuracy

Если у объекта есть поле запроса, каждое вознаграждение относится к ответу при данном запросе. Варианты ранжирования это метки схемы, и каждая оценивается при данном тексте объекта. Сервер строит кортежи BWS из bws_config, поэтому запуск на собственных данных сервера уже имеет кортежи, и в файлах данных кортежи не нужны.

ПараметрПо умолчаниюЗначение
model_namedistilbert/distilroberta-baseЭнкодер или LLM с lora.
ranking_lossplackett_luceТолько для схем ranking: plackett_luce или pairs.
max_length512Токенов на оцениваемый текст, запрос и ответ вместе.
learning_rate2e-5 или 2e-4 с LoRA

Предсказания отвечают на собственный вопрос схемы, поэтому их оценивают и записывают обратно так же, как для любой другой схемы. Предварительная метка это выбранная карточка для бинарного выбора, положение ползунка для шкалы, порядок списка для ранжирования, а для BWS выбранные лучший и худший. Каждое предсказание сохраняет и rewards, из которых оно получено. Значимы только разности вознаграждений. Парное сравнение и Best-Worst Scaling сравнивает форматы сравнения для сбора данных.

Исследование, которое собирает оценки шагов и исправления

Вторая конфигурация работает с трассами агента. Разметчики оценивают каждый шаг трассы, а затем исправляют неверные шаги. Оценки шагов обучают prm-reward, а исправления обучают llm-sft или llm-dpo. Каждая строка data/traces.jsonl содержит задачу, шаги агента и итоговый ответ:

json
{"id": "traj_001", "task_description": "Find the current weather in San Francisco and report the temperature.", "steps": [{"thought": "I should look up the current weather.", "action": "web_search(queyr='San Francisco weather')"}, {"thought": "Open the first result.", "action": "open_url(results[0])"}, {"thought": "Read the temperature from the page.", "action": "extract_text('.temp')"}], "final_answer": "It is sunny."}

Тренеры читают задачу из поля task_description, task или text объекта, именно в таком порядке:

yaml
annotation_task_name: "Agent traces: step ratings and corrections"
task_dir: .
data_files:
  - data/traces.jsonl
item_properties:
  id_key: id
  text_key: task_description
output_annotation_dir: annotation_output
user_config:
  allow_all_users: true
 
annotation_schemes:
  - annotation_type: process_reward
    name: step_quality
    description: "Rate each step of the agent's trace"
    steps_key: steps
    step_text_key: action
    mode: per_step
    allow_neutral: true
    ai_prelabel: true
 
  - annotation_type: trajectory_edit
    name: corrected_trace
    description: "Fix the wrong steps, then correct the final answer"
    steps_key: steps
    step_text_key: action
    editable_fields: [action]
    show_diff: true
    edit_final_answer: true
    final_answer_key: final_answer
 
model_training:
  enabled: true
  writeback:
    schemas: [step_quality]
    include_unlabeled: true

mode: per_step с allow_neutral: true даёт три оценки, которым учится prm-reward. ai_prelabel: true добавляет в схему кнопку "AI pre-label steps", и обученные оценки появляются через эту кнопку. В writeback.schemas указана только step_quality. Если указать там corrected_trace, сервер не запустится, а валидатор назовёт причину:

text
model_training.writeback.schemas names 'corrected_trace', a trajectory_edit scheme, which has no prelabel display: its predictions are stored and scored but annotators would never see them. Leave it out of writeback.schemas.

Исправление трасс с llm-sft и llm-dpo

Ответ trajectory_edit это пара трасс, исходные шаги агента и шаги после исправлений разметчика. Редактирование траекторий для SFT/DPO описывает редактор, а запись о редактировании траекторий описывает, как пары становятся обучающими данными. Оба тренера исключают трассы, которые никто не правил.

  • llm-sft берёт задачу и исходные шаги как запрос, а исправленные шаги как цель, поэтому модель учится исправлять трассу. Каждый шаг записывается как Step N и следующие за ним поля шага (action: ..., thought: ...), а итоговый ответ идёт после последнего шага, если у схемы есть final_answer_key.
  • llm-dpo берёт задачу как запрос, исправленные шаги как предпочтительный ответ, а исходные шаги как другой ответ. Предсказание говорит, предпочитает ли модель исправление (A) или оригинал (B), и делается только для отложенных трасс, у которых есть исправление.

Оба запуска сообщают closer_to_correction как оценку на отложенных объектах. Для llm-dpo оценка это доля отложенных трасс, в которых модель предпочитает исправление. Для llm-sft оценка это доля трасс, в которых написанные шаги ближе к исправлению, чем к оригиналу, по token F1, а рядом с оценкой выводится token_f1 относительно исправления.

Предсказания запуска trajectory_edit сохраняются и оцениваются, а разметчики их не видят. Редактор всегда начинает с исходной трассы агента, поэтому на странице нет места для предсказанного переписанного варианта. Читайте предсказания на странице запуска или в artifacts/predictions.jsonl в каталоге запуска.

Оценки шагов с prm-reward

Модель вознаграждения за процесс оценивает шаги трассы, а не только итоговый ответ, как в PRM800K. prm-reward подаёт в трансформер-энкодер всю трассу как один вход, задачу и затем Step 1, Step 2 и так далее. Энкодер учит трёхклассовую оценку на последнем токене каждого шага, так что каждая оценка делается с учётом предшествующих шагов. Шаги, которые никто не оценил, исключаются из функции потерь. Модель по умолчанию, answerdotai/ModernBERT-base, выбрана за контекст в 8 192 токена.

ПараметрПо умолчаниюЗначение
model_nameanswerdotai/ModernBERT-baseЭнкодер с быстрым токенизатором.
max_length1024Токенов на трассу.
epochs6
batch_size8Трасс на шаг.
learning_rate5e-5 или 3e-4 с LoRA

Длинные трассы теряют последние шаги. Трасса длиннее max_length токенов обрезается с конца, а шаги за обрезкой не участвуют в обучении и не оцениваются. Журнал запуска считает потерянные шаги. Если max_length больше, чем вмещает модель, запуск снижает max_length до предела модели с предупреждением, и для большинства энкодеров класса BERT этот предел равен 512 токенам. Если журнал запуска сообщает о потерянных шагах, увеличьте max_length и выберите модель, контекст которой вмещает более длинные трассы.

Оценка на отложенных объектах это step_macro_f1, macro-F1 по трём оценкам на каждом оценённом шаге. Большинство шагов в большинстве трасс верны, поэтому accuracy польстила бы модели, которая никогда не говорит "wrong". Запуск также сообщает step_accuracy и first_error_accuracy, то есть долю трасс, в которых первый неверный шаг модели совпадает с первым неверным шагом разметчиков.

Предсказание оценивает каждый шаг, который помещается в max_length, с вероятностью каждой оценки как уверенностью в ней и наименее уверенным шагом как уверенностью в трассе. Если схема указана в writeback.schemas и задан ai_prelabel: true, кнопка "AI pre-label steps" предлагает обученные оценки разметчику на проверку. LLM-судья, настроенный в ai_support, не вызывается для объекта, у которого есть обученные оценки. Разметка вознаграждения за процесс описывает схему, а руководство по моделям вознаграждения за процесс описывает данные.

Обучение более крупной модели с QLoRA

QLoRA загружает веса базовой модели в 4 битах и обучает поверх них адаптер LoRA. llm-sft, llm-dpo, hf-text-classification, vlm-sft и reward-model принимают lora: {quantize: 4bit}, а prm-reward отклоняет эту настройку до загрузки модели. Планируйте память по строке "Peak GPU memory", которую в конце записывает каждый запуск трансформера. Раздел о QLoRA в справочнике конфигурации описывает, как загружаются базовые веса, и вариант с 8 битами.

Добавьте этот блок в конфигурацию выше, чтобы сделать QLoRA настройкой по умолчанию для llm-sft:

yaml
model_training:
  enabled: true
  trainer_params:
    llm-sft:
      model_name: Qwen/Qwen2.5-7B-Instruct
      lora: {quantize: 4bit}
      gradient_checkpointing: true

QLoRA требует GPU с CUDA и сборку bitsandbytes для CUDA этой машины, установленную командой pip install bitsandbytes. Без работающего GPU или подходящей сборки запуск останавливается на проверке до загрузки модели.

Публикация запуска на Hugging Face Hub

У успешного запуска, модель которого лежит на сервере Potato, на странице запуска есть Publish to the Hugging Face Hub. Публикация загружает модель и README.md с карточкой модели, составленной по запуску, с тренером, базовой моделью и адаптером, схемами и метками, размерами выборок, оценкой на отложенных объектах и тем, на чём она измерена, а также идентификаторами запуска и пакета. Запуск LoRA сохранил только адаптер, поэтому репозиторий на Hub содержит адаптер, а карточка называет базовую модель, на которую нужно загрузить адаптер.

Токен остаётся вне браузера. Создайте токен с правом записи в настройках Hugging Face и задайте его в окружении сервера до запуска Potato:

bash
export HF_TOKEN=hf_your_write_token
potato start config.yaml

Форма называет переменную окружения, по умолчанию HF_TOKEN, дважды запрашивает имя репозитория и по умолчанию оставляет отмеченным Private. Публикация на Hugging Face Hub перечисляет файлы, которые загружаются, проверки перед публикацией и лицензию в карточке модели. Та же публикация через API:

bash
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  http://localhost:8000/admin/training/api/runs/RUN_ID/push-to-hub \
  -d '{"repo_id": "your-org/support-dpo", "confirm_repo_id": "your-org/support-dpo", "private": true, "licence": "apache-2.0"}'

Маршрут возвращает 201 с коммитом. Модель, оставленную на удалённом хосте с fetch_artifacts: false, нельзя опубликовать с сервера Potato, и страница запуска сообщает, где лежит модель. Чтобы перейти от опубликованной модели к циклу активного обучения, продолжите с Модель в цикле разметки.

Дополнительные материалы

Источники

  • Dettmers, T., Pagnoni, A., Holtzman, A., and Zettlemoyer, L. (2023). QLoRA: Efficient Finetuning of Quantized LLMs. arXiv:2305.14314. arxiv.org/abs/2305.14314
  • Hu, E. J., Shen, Y., Wallis, P., Allen-Zhu, Z., Li, Y., Wang, S., Wang, L., and Chen, W. (2021). LoRA: Low-Rank Adaptation of Large Language Models. arXiv:2106.09685. arxiv.org/abs/2106.09685
  • Lightman, H., Kosaraju, V., Burda, Y., Edwards, H., Baker, B., Lee, T., Leike, J., Schulman, J., Sutskever, I., and Cobbe, K. (2023). Let's Verify Step by Step. arXiv:2305.20050. arxiv.org/abs/2305.20050
  • Ouyang, L., Wu, J., Jiang, X., Almeida, D., Wainwright, C. L., Mishkin, P., Zhang, C., Agarwal, S., Slama, K., Ray, A., Schulman, J., Hilton, J., Kelton, F., Miller, L., Simens, M., Askell, A., Welinder, P., Christiano, P., Leike, J., and Lowe, R. (2022). Training Language Models to Follow Instructions with Human Feedback. arXiv:2203.02155. arxiv.org/abs/2203.02155
  • Rafailov, R., Sharma, A., Mitchell, E., Ermon, S., Manning, C. D., and Finn, C. (2023). Direct Preference Optimization: Your Language Model is Secretly a Reward Model. arXiv:2305.18290. arxiv.org/abs/2305.18290