Конфигурация обучения моделей и маршруты
Каждый ключ блока model_training, как запуски ставятся в очередь, оцениваются и хранятся, админские и агентские маршруты, а также решения для частых ошибок запуска.
Новое в v2.14.0
Эта страница — справочник по блоку model_training конфигурации Potato и по тому, что происходит с запуском после его начала. Страница рассчитана на человека, который ведёт исследование и хочет ограничить запуски, отправить их на другую машину, показать разметчикам предсказания модели или начать обучение из скрипта. Каждый ключ, значение по умолчанию, маршрут и сообщение ниже сверены с кодом Potato. Для первого запуска начните с руководства Обучите свою первую модель. Тренеры и их параметры перечислены на странице Тренеры.
Полная конфигурация
Конфигурация ниже обучает классификатор тональности на отзывах о товарах. auto_retrain переобучает sklearn-text после каждых 25 новых аннотаций. С признаками TF-IDF по умолчанию sklearn-text обучается на процессоре и не требует ничего сверх обычной установки Potato. Поэтому частые автоматические запуски обходятся дёшево. Обратная запись показывает разметчикам каждое предсказание с уверенностью не ниже 0,8. С include_unlabeled запуск предсказывает также для отзывов, которые никто ещё не разметил. Значения hf-text-classification по умолчанию и бэкенд gpu-server обслуживают запуски, которые вручную начинают со страницы Training:
annotation_task_name: "Review sentiment with model training"
task_dir: "."
data_files:
- "data/reviews.json"
item_properties:
id_key: "id"
text_key: "text"
output_annotation_dir: "annotation_output"
user_config:
allow_all_users: true
annotation_schemes:
- annotation_type: "radio"
name: "sentiment"
description: "Is this review positive or negative?"
labels: ["positive", "negative"]
model_training:
enabled: true
split_seed: 0
splits: {train: 0.7, val: 0.15, test: 0.15}
aggregation: consensus
retain_runs: 5
queue_max: 10
max_wall_seconds: 3600
max_ram_mb: 8192
num_threads: 4
trainer_params:
sklearn-text:
classifier: sklearn.linear_model.LogisticRegression
classifier_kwargs: {max_iter: 1000}
hf-text-classification:
model_name: answerdotai/ModernBERT-base
epochs: 4
lora: true
auto_retrain:
enabled: true
trainer: sklearn-text
schemas: [sentiment]
min_interval_s: 600
update_frequency: 25
writeback:
schemas: [sentiment]
min_confidence: 0.8
include_unlabeled: true
backends:
gpu-server:
type: ssh
host: gpu-server
python: /opt/conda/bin/python3
gpus: auto
min_free_gpu_mb: 4000Держите split_seed неизменным на всё время исследования. Новое начальное значение переназначает каждый объект, поэтому отложенные объекты попадают в обучение, и поздние оценки перестают быть сопоставимыми с ранними. Порог min_confidence 0,8 — только отправная точка, а подходящий порог зависит от первой оценки на отложенных объектах. Включайте include_unlabeled, когда эта оценка оправдывает показ предварительных меток, потому что предварительные метки привязывают разметчиков к ответу модели.
Ключи в model_training
Все ключи находятся под model_training:
| Ключ | По умолчанию | Значение |
|---|---|---|
enabled | false | Регистрирует страницу Training, маршруты под /admin/training и агентские маршруты под /api/training. Без enabled: true маршрутов не существует. |
retain_runs | 5 | Сколько завершённых запусков хранится в журнале запусков. Более старый запуск уходит из журнала, если его предсказания не хранятся до сих пор. Каталоги запусков остаются на диске. |
grace_seconds | 20 | Сколько секунд отменённому запуску даётся на выход, прежде чем Potato убьёт процесс. Значение 0 или больше, оно отправляется вместе с заданием бэкендам типов ssh, slurm и agent. |
queue_max | 10 | Сколько запусков может ждать за выполняющимся запуском. |
split_seed | 0 | Начальное значение для распределения объектов по выборкам train, val и test. |
splits | {train: 0.7, val: 0.15, test: 0.15} | Доли выборок, нормированные так, чтобы сумма равнялась 1. Имена — train, val и test, и train обязательна. |
aggregation | consensus | Как метки нескольких разметчиков на объекте сводятся в одну. consensus подгоняет модель Dawid-Skene, если в исследовании больше одного разметчика, и переходит к большинству голосов, если подгонка не удалась. majority берёт большинство голосов. |
max_wall_seconds | не задано | Лимит времени одного запуска. Potato проверяет локальный запуск при каждом событии, о котором запуск сообщает, а запуск по ssh или через агента — каждую секунду. |
max_ram_mb | не задано | Лимит адресного пространства процесса обучения, устанавливаемый через setrlimit. На платформе без такого лимита запуск пишет предупреждение и продолжается. |
device | auto | auto, cpu, cuda, cuda:N или mps. При auto сначала берётся CUDA, затем Metal от Apple, затем процессор. |
num_threads | не задано | Задаёт OMP_NUM_THREADS, MKL_NUM_THREADS и OPENBLAS_NUM_THREADS для запуска, если окружение ещё не задаёт эти переменные. |
auto_retrain | выкл. | Переобучение по мере поступления аннотаций. См. auto_retrain. |
writeback | нет | Публикация предсказаний как предварительных меток. См. writeback. |
backend | local | Бэкенд для запусков, не называющих другого. |
backends | нет | Именованные бэкенды ssh, slurm и agent. См. Бэкенды. |
max_predictions_mb | 512 | Наибольший predictions.jsonl, который может загрузить удалённый агент. |
trainer_params | нет | Значения параметров по умолчанию, по имени тренера. |
tiling | enabled: auto | Нарезка больших изображений на плитки для тренеров детекции и сегментации. См. tiling. |
Собственные params запуска переопределяют trainer_params, а те переопределяют значения тренера по умолчанию. Имя параметра, которого тренер не принимает, отклоняется при запуске сервера, если имя стоит под trainer_params, а иначе при начале запуска. Страница Тренеры показывает порядок на примере.
auto_retrain
Автоматическое переобучение проверяет, нужен ли новый запуск, после каждого сохранения аннотации:
| Ключ | По умолчанию | Значение |
|---|---|---|
enabled | false | Включает проверку. |
trainer | нет | Имя тренера. Обязателен. |
schemas | нет | Схемы для обучения. Обязательны. |
min_interval_s | 600 | Сколько секунд должно пройти с завершения последнего запуска, прежде чем начнётся следующий. |
update_frequency | 25 | Сколько новых аннотаций должно прийти с последнего автоматического запуска, прежде чем начнётся следующий. |
params | {} | Параметры тренера, как в params запуска через API. |
backend | model_training.backend | Бэкенд для автоматических запусков. |
accept_licence | false | Подтверждает лицензию тренера, который просит подтверждение (ultralytics-detect, ultralytics-segment, layoutlmv3). Без подтверждения автоматические запуски этих тренеров пропускаются. |
Когда проверка решает не запускать обучение, причина появляется в поле skip_reason ответа GET /admin/training/api/status, например "waiting for 3 more annotation(s)" или "a run is already in progress". Автоматические запуски никогда не встают в очередь запусков. Следующая аннотация, сохранённая после того, как очередь опустеет, снова запускает проверку, уже с большим числом аннотаций для обучения. Potato держит счётчики аннотаций в памяти, поэтому после перезапуска проект, который уже обучался, считает новые аннотации с момента перезапуска.
writeback
Обратная запись решает, какие предсказания видят разметчики:
| Ключ | По умолчанию | Значение |
|---|---|---|
schemas | [] | Схемы, предсказания которых видят разметчики. Пустой список не показывает ничего. |
min_confidence | 0.0 | Предсказания ниже порога сохраняются и не показываются. Предсказание без уверенности проходит. |
field | predictions | Поле объекта, в которое записываются предварительные метки. |
include_unlabeled | false | Предсказывает также для объектов, которые никто не разметил, и ставит им предварительные метки. Без include_unlabeled запуск предсказывает только для собственных объектов val и test. |
tiling
Тренеры детекции и сегментации уменьшают каждое изображение до нескольких сотен пикселей. При таком размере объекты на снимке целого слайда или на спутниковой сцене теряются. Поэтому для схемы image_annotation, microscopy или geo_annotation Potato режет каждое большое изображение на плитки при построении обучающих данных запуска. Выборка изображения определяется до нарезки, поэтому плитки одного слайда никогда не попадают в две выборки. Предсказания переносятся обратно на целое изображение, а оценки на отложенных объектах считаются на целых изображениях. Руководство по моделям для изображений разбирает слайды и карты на практике.
| Ключ | По умолчанию | Значение |
|---|---|---|
enabled | auto | auto режет форматы слайдов (.svs, .ndpi, .mrxs, .scn и другие) и изображения, у которых длинная сторона не меньше auto_min_side. true режет каждое изображение, а false — ни одно. |
auto_min_side | 4096 | Длина длинной стороны в пикселях, с которой auto начинает резать изображение. |
tile_size | 1024 | Сторона плитки в пикселях, которые видит тренер. |
overlap | 128 | Сколько пикселей делят соседние плитки, не больше половины tile_size. Держите перекрытие не меньше объектов, иначе крупный объект находится по частям. |
downsample | 1 | Сколько пикселей полного разрешения приходится на пиксель плитки. |
mpp | нет | Микроны на пиксель плитки. Переопределяет downsample для слайда, который записывает своё разрешение. |
background | 0.25 | Сколько пустых плиток выбирается на плитку с объектом. Для слайдов, размеченных лишь частично, задайте background: 0. |
max_predict_tiles | 2000 | Наибольшее число плиток, предсказываемых на изображение. Сохраняются плитки с наибольшим количеством ткани. |
min_visible | 0.4 | Доля объекта, которая должна лежать внутри плитки, чтобы объект обучался на этой плитке. |
tissue_threshold | 0.05 | Доля плитки слайда, которая должна быть тканью, чтобы модель предсказывала на этой плитке. |
Слайды читаются через openslide, который ставится командой pip install "potato-annotation[wsi]", на машине, которая строит обучающие данные. Удалённый бэкенд скачивает плитки, но никогда не слайд.
Очередь запусков
Одновременно выполняется один запуск. Запуск, начатый со страницы Training или через API во время другого запуска, ждёт, а не отклоняется. Запрос на старт возвращает 202 с queued: true и position запуска, а таблица Runs показывает запуск как waiting #N с кнопкой Cancel run. Когда выполняющийся запуск заканчивается, начинается самый старый из ожидающих.
Ожидающие запуски — это записи в журнале запусков, поэтому очередь переживает перезапуск, и первый ожидающий запуск начинается, когда сервер возвращается. Запуск, который предыдущий сервер выполнял в тот момент, одновременно помечается как interrupted. Обучающие данные ожидающего запуска строятся, когда запуск начинается, поэтому запуск обучается на аннотациях, существующих в этот момент. Старт, который был бы отклонён, например старт с неизвестной схемой, отклоняется сразу, а не когда подходит очередь запуска. Запуск, у которого схема или тренер исчезли из конфигурации во время ожидания, завершается с invalid_when_dequeued, и начинается следующий запуск.
Отправьте "queue": false в теле запроса, чтобы получить 409 вместо места в очереди. Когда уже ждут queue_max запусков, новый старт получает 429. GET /admin/training/api/status перечисляет ожидающие запуски по порядку в поле queue.
Проверки перед запуском
potato validate сообщает обо всех проблемах в блоке model_training сразу, и сервер отказывается запускаться при тех же проблемах:
potato validate config.yaml --strictПроверки охватывают такие случаи:
splitsс именем, отличным отtrain,valиtest, доля меньше 0 или не число, доли с нулевой суммой или отсутствиеtrain.- Ключ, которого нет у
writebackилиauto_retrain, запись вwriteback.schemas, не являющаяся схемой, илиmin_confidenceвне диапазона от 0 до 1.accept_licenseсообщается как опечатка вaccept_licence. - Включённый блок
pre_annotation, у которогоfieldотличается отwriteback.field. Под таким блоком предварительная метка обучения не показывалась бы. - При
auto_retrain.enabledнесуществующий тренер или схема, схема, которой тренер учиться не может, параметры, которых тренер не принимает или которые имеют неверный тип,backend, отсутствующий вbackends, илиdecision-calibrateна бэкенде, отличном отlocal. - Параметр под
trainer_params, которого тренер не принимает или который имеет неверный тип. Внутриdpпроверка охватывает также каждый ключ и его диапазон. - Значение
grace_secondsменьше 0 или не число, а такжеretain_runsилиsplit_seedменьше 0 или не целое число. - Под
backendsотсутствующий или неизвестныйtype, ключ, которого у типа нет, бэкенд ssh безhost, значениеgpus, отличное отauto,noneили индексов GPU, удалённый бэкенд с именемlocalилиmodel_training.backend, который не определён.
potato training check проверяет один бэкенд до того, как запуск его использует. Для local команда печатает устройство, которое получил бы запуск, например local: this machine, Apple Metal (mps) на Mac с чипом Apple. Для бэкенда ssh команда сообщает версию Python, каждый GPU с его свободной памятью, GPU, который получил бы запуск, и обучающие пакеты, которых не хватает удалённому интерпретатору. Кнопка Check на странице Training выполняет ту же проверку, а --json печатает отчёт как JSON:
potato training check local config.yaml
potato training check gpu-server config.yamlЗапуск, начатый со страницы Training или через API, проверяется ещё раз в момент начала. Коды состояния перечислены в разделе Маршруты.
Бэкенды
Запуск выполняется на бэкенде, и меню Runs on на странице Training перечисляет настроенные бэкенды. model_training.backend задаёт значение по умолчанию, а запуск через API или auto_retrain может назвать другой бэкенд через backend. В Potato четыре типа бэкенда:
| Тип | Где работает тренер | Кто запускает тренера |
|---|---|---|
local | Эта машина, в подпроцессе. Доступен всегда и используется по умолчанию. | Potato |
ssh | Другая машина, до которой Potato добирается по ssh, например GPU-сервер. | Potato, по ssh |
slurm | Вычислительный узел кластера, как пакетное задание. | Potato, по ssh на головной узел и затем sbatch |
agent | Машина, до которой Potato не дотянуться, например рабочая станция за NAT. | Человек, командой potato training agent |
Бэкенд ssh использует аутентификацию по ключу с включённым BatchMode, поэтому запрос пароля приводит к ошибке, а не к зависанию. Бэкенд slurm использует только sbatch, squeue и scancel, а также scontrol на кластерах, где scontrol есть, и требует remote_dir на хранилище, общем для вычислительных узлов. Бэкенду agent не нужен входящий порт, потому что агент сам открывает все соединения. Имя local зарезервировано за этой машиной, а decision-calibrate работает только на local. Руководство Обучение на GPU-сервере, кластере SLURM или машине за NAT проводит все три удалённых типа вместе с их ключами.
Оценки на отложенных объектах
Каждый запуск оценивает собственные предсказания на объектах val и test относительно сведённых человеческих меток. В именах метрик указана выборка, как в val_macro_f1 или test_f1. Объект с меткой и без предсказания считается ошибкой, поэтому пропуск трудных объектов не может поднять оценку тренера. <split>_coverage сообщает долю объектов, получивших предсказание.
Главная оценка показывается в столбце Held-out score таблицы Runs, а выборка и метрика указаны во всплывающей подсказке. Главная оценка — это главная метрика первой схемы на первой из выборок val и test, в которой есть объекты. Когда тренер выбрал лучшую контрольную точку по оценке val, Potato сначала пробует test, потому что тренер уже видел оценку val. Дообучающие тренеры, которые сохраняют лучшую эпоху, например hf-text-classification, torchvision-detect и llm-sft, берут главную оценку с test. sklearn-text, setfit, rdkit-property, тренеры моделей решений и мосты к моделям ничего не выбирают по val, и запуск любого из этих тренеров берёт главную оценку с val, пока в val есть объекты. Запуск без объектов val и test показывается как "not scored".
Главная метрика зависит от типа разметки схемы, как показывает таблица ниже для распространённых типов:
| Тип разметки | Главная метрика |
|---|---|
radio, select, likert | macro-F1 (также точность и средняя абсолютная ошибка для числовых меток likert) |
multiselect | micro-F1 (также macro-F1 и точное совпадение) |
span | F1 по фрагментам, совпадающим по началу, концу и метке |
text | token F1 (также точное совпадение) |
pairwise в режиме binary | точность по объектам, ответ на которые не был ничьей |
ranking | тау Кендалла |
image_annotation, microscopy, geo_annotation | COCO mAP при IoU 0,5 (map_50), также записывается map_50_95 |
audio_annotation | F1 по сегментам с одинаковой меткой при IoU не ниже 0,5 |
speech_transcript | word_accuracy, 1 минус доля ошибочных слов |
volume_annotation | mean_dice |
Token F1 засчитывает ответ, где нужные слова стоят в неправильном порядке, поэтому читайте token F1 вместе с точным совпадением. Главная метрика детекции использует IoU 0,5, а не среднее от 0,5 до 0,95, потому что рамки двух разметчиков для одного объекта редко пересекаются при IoU 0,9. Таблица оценок на отложенных объектах в upstream перечисляет метрики для каждого типа разметки.
Обратная запись
После успешного запуска Potato сохраняет предсказания запуска и записывает предсказания, прошедшие четыре проверки, в поле predictions каждого объекта или в поле, которое называет writeback.field. Проверки идут в таком порядке, и отчёт об обратной записи считает каждый пропуск:
- Объекты выборки train никогда не получают предварительных меток. Проверка охватывает выборку train каждого запуска, ещё находящегося в журнале, а предварительная метка, оставленная на объекте более ранним запуском, снимается, когда более поздний запуск обучается на этом объекте.
- Публикуются только схемы из
writeback.schemas. По умолчанию список пуст, поэтому включение обучения ничего не меняет для разметчиков. - Отклонённые пары пропускаются. Пара из объекта и схемы с вердиктом
rejectв проверке модели больше не показывается. - Применяется порог уверенности. Предсказание ниже
min_confidenceсохраняется и не публикуется.
Обратная запись никогда не меняет человеческую метку, потому что предсказания попадают в данные объекта, а разметка живёт в состоянии каждого разметчика. Предварительная метка показывается как заранее заполненный ответ, который разметчик может править, например выбор как выбранный вариант, и свободный текстовый ответ в текстовом поле схемы, и блок pre_annotation не нужен. Предварительная метка становится ответом разметчика, только когда разметчик правит её или переходит к следующему объекту. Поэтому предварительная метка, которую никто не правил и мимо которой никто не перешёл, никогда не становится обучающей меткой. Пара из разметчика и объекта, которую ai_support.holdout относит к контрольной группе исследования без помощи, предварительной метки не показывает, а данные объекта, отправленные для этой пары, не содержат ни writeback.field, ни pre_annotation.field. Отчёт об обратной записи — это поле writeback ответа GET /admin/training/api/status, а summary отчёта объясняет, почему запуск ничего не опубликовал.
Potato хранит одно предсказание на объект и схему, и предсказание более нового запуска заменяет предсказание более старого. Когда новое предсказание сохранено, но не показано, потому что оно ниже min_confidence, пусто или отклонено, предварительная метка более старого запуска сразу снимается с объекта, и отчёт об обратной записи учитывает объект в n_superseded_cleared. Предварительные метки, поставленные вместе с данными, остаются нетронутыми. При запуске сохранённые предсказания для схем из writeback.schemas записываются обратно в данные объектов под теми же четырьмя проверками, поэтому предварительные метки переживают перезапуск. Чтобы отозвать предварительные метки запуска, отправьте DELETE /admin/training/api/runs/<run_id>/predictions. Запрос удаляет сохранённые предсказания и снимает предварительные метки с объектов.
Исправленные и закреплённые объекты всегда обучают
Два вида объектов попадают в выборку train каждого последующего запуска, независимо от места объекта в стабильном разбиении:
- Объекты, которые исправил проверяющий. Вердикт
correctв проверке модели означает, что человек исправил ответ модели. Исправления приходят с объектов, на которых модель ошибалась сильнее всего, поэтому исправленный объект вvalилиtestоценивал бы модель на выборке её собственных ошибок. Вердиктыacceptиrejectоставляют объект там, где он был. - Закреплённые объекты. Кнопка Train on these рядом со срезом на странице Catalog закрепляет объекты, которые подходят под срез, например встроенный срез
model-found-nothing. Закреплённый объект обучает модель, как только кто-нибудь его разметит.
Запуск, который переместил отложенные объекты в train, пишет предупреждение с их числом. Оценка такого запуска на отложенных объектах вычисляется без этих объектов и непосредственно не сопоставима с оценкой более раннего запуска. Числа лежат в stats.forced_train в manifest.json обучающих данных.
Сохранение выборки как версии датасета
Кнопка Keep this split as a dataset на странице запуска сохраняет объекты val, test или train запуска вместе с их согласованными человеческими метками как новую версию датасета. Версия датасета после этого никогда не меняется, поэтому последующие модели и промпты LLM можно сравнивать ровно на этих объектах. Функции нужен datasets.enabled: true. Каждая сохранённая версия содержит одну выборку и начинается с нуля, а не дополняет последнюю версию датасета. Иначе объекты val запуска 2, добавленные к объектам запуска 1, включали бы объекты, на которых обучался запуск 2. В inputs каждого примера нет поля предварительных меток, поэтому оценка не может прочитать ответ модели.
Откуда взялась предварительная метка
GET /admin/model-review включает provenance для каждого объекта очереди проверки, предварительную метку которого записал запуск обучения. Для каждой схемы запись называет идентификатор запуска, тренера и оценку запуска на отложенных объектах. У предварительных меток, поставленных вместе с данными, записи нет.
Где хранятся запуски
У каждого запуска есть каталог <task_dir>/<output_annotation_dir>/training/runs/<run_id>/:
| Путь | Содержимое |
|---|---|
bundle/ | Обучающие данные: train.jsonl, val.jsonl, test.jsonl, unlabeled.jsonl при include_unlabeled, labels.json, manifest.json и media/. |
artifacts/ | model_card.json, predictions.jsonl и модель, например model.pkl для sklearn-text или каталог model/ для трансформерных тренеров. |
spec.json | Что запуску было поручено сделать. |
events.jsonl, stdout.log, stderr.log | События хода запуска и его вывод. |
agent.log | Собственный вывод удалённого агента, на бэкендах ssh. |
bundle.tar.gz | Обучающие данные в том виде, в каком их скачал агент, вместе с медиа, на удалённых бэкендах. |
Журнал запусков живёт в базе данных проекта, <task_dir>/project.sqlite, и записывает запуски, выборку каждого объекта по запускам, объекты, закреплённые за обучением, сохранённые предсказания, токены агентов и публикации на Hugging Face Hub. retain_runs обрезает журнал и никогда не обрезает запуск, предсказания которого ещё хранятся, поэтому любую предварительную метку можно проследить до запуска, который её записал. Обрезка оставляет каталоги запусков на диске.
Запуск LoRA сохраняет только адаптер, от нескольких до нескольких сотен мегабайт, и загружает базовую модель по model_name, когда запуск предсказывает. Полное дообучение сохраняет всю модель. Задайте переменную окружения POTATO_MODEL_CACHE как каталог, и процесс обучения использует этот каталог для HF_HOME, TRANSFORMERS_CACHE и SENTENCE_TRANSFORMERS_HOME, если эти переменные ещё не заданы. На машине без доступа в сеть заранее положите в этот каталог модели, которые называют тренеры.
Маршруты
Страница Training и её маршруты JSON находятся под /admin/training и требуют доступа администратора. Доступ администратора означает сессию администратора или заголовок X-API-Key. Запросы POST и DELETE из браузера должны быть same-origin. Спецификация OpenAPI Potato помечает все 26 операций обучения как x-potato-requires-config: model_training.enabled: true:
| Маршрут | Назначение |
|---|---|
GET /admin/training | Страница Training с формой запуска, списком запусков и тренерами. |
GET /admin/training/runs/<run_id> | Страница одного запуска со статусом, метриками, событиями и выборкой каждого объекта. |
GET /admin/training/api/trainers | Все тренеры с их видами, модальностями, лицензией и состоянием установки. |
GET /admin/training/api/schemas | Схемы исследования, вид каждой схемы и тренеры, подходящие к каждой схеме. |
GET /admin/training/api/status | Текущий или последний запуск с состоянием, ходом, метриками, предупреждениями, skip_reason, writeback и queue. |
GET /admin/training/api/runs | История запусков. ?limit= по умолчанию 50, максимум 500. |
POST /admin/training/api/runs | Начинает запуск. 200, когда запуск начался, и 202 с queued: true и position, когда запуск ждёт. |
GET /admin/training/api/runs/<run_id> | Запись одного запуска, а также review — точность предсказаний запуска по вердиктам проверки. |
GET /admin/training/api/runs/<run_id>/events | Журнал событий запуска. ?limit= по умолчанию 200. |
POST /admin/training/api/runs/<run_id>/cancel | Отменяет выполняющийся или ожидающий запуск. 400 для любого другого идентификатора запуска. |
DELETE /admin/training/api/runs/<run_id>/predictions | Отзывает сохранённые предсказания и предварительные метки запуска. |
POST /admin/training/api/runs/<run_id>/push-to-hub | Публикует модель запуска на Hugging Face Hub. См. Публикация на Hugging Face Hub. |
POST /admin/training/api/runs/<run_id>/pin-split | Сохраняет выборку как версию датасета, с телом {"dataset": name, "split": "val"}. |
GET /admin/training/api/backends | Настроенные бэкенды. |
POST /admin/training/api/backends/<name>/check | Проверяет бэкенд, как это делает potato training check. |
GET /admin/training/api/pinned | Закреплённые объекты, сгруппированные по причине. |
POST /admin/training/api/pinned | Закрепляет объекты за train, с {"slice": name} или {"instance_ids": [...]}. |
DELETE /admin/training/api/pinned | Открепляет перечисленные instance_ids или каждый закреплённый объект, если тело ничего не перечисляет. |
Запрос запуска принимает trainer, schemas (список или одно имя), params, backend, accept_licence и queue. Каждый тренер обучается только на первой названной схеме. Запрос ниже начинает запуск sklearn-text на схеме sentiment из примера:
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
http://localhost:8000/admin/training/api/runs \
-d '{"trainer": "sklearn-text", "schemas": ["sentiment"]}'Отклонённый старт даёт причину в error:
| Статус | Когда |
|---|---|
400 | В теле нет тренера или схемы, неизвестный тренер или схема, схема, которой тренер учиться не может, тренер, которого проект запустить не может, или тренер, лицензию которого нужно подтвердить, с needs_licence_ack: true, пока запрос не задаст accept_licence: true |
409 | Параметр, которого тренер не принимает или который имеет неверный тип или диапазон, неизвестный бэкенд, decision-calibrate на бэкенде, отличном от local, или уже выполняющийся запуск при "queue": false |
429 | Уже ждут queue_max запусков |
Протокол агента
model_training.enabled регистрирует также маршруты, которые вызывает агент обучения, под /api/training. Агент отправляет свой токен как Authorization: Bearer <token>, а отсутствующий или недействительный токен получает 401. Регистрация бэкенда вместо этого требует админский ключ API. potato/training/protocol.py описывает протокол для тех, кто пишет нового агента, а potato/training/agent.py — эталонная реализация:
| Маршрут | Назначение |
|---|---|
POST /api/training/backends/register | Выдаёт токен агента для имени бэкенда, с X-API-Key. Этот маршрут вызывает potato training register. |
POST /api/training/backends/<name>/heartbeat | Простаивающий агент сообщает, что он жив. 403 для токена, выданного другому бэкенду. |
GET /api/training/jobs/next?wait=30 | Длинный опрос. 200 с задачей или 204, если задача не пришла за wait секунд. |
GET /api/training/jobs/<run_id> | Задача, её спецификация и признак отмены задачи. |
GET /api/training/jobs/<run_id>/bundle | Обучающие данные в tar.gz вместе с медиа. Маршрут отвечает на запросы Range, поэтому агент возобновляет оборванную загрузку, до пяти попыток. 410, когда пакета уже нет. |
POST /api/training/jobs/<run_id>/progress | События хода. Отмена возвращается в ответе. |
POST /api/training/jobs/<run_id>/predictions | predictions.jsonl. 413 при превышении max_predictions_mb. |
POST /api/training/jobs/<run_id>/complete | Код выхода и итоговые события. |
QLoRA
llm-sft, llm-dpo, hf-text-classification, vlm-sft и reward-model принимают lora: {quantize: 4bit} — настройку QLoRA (Dettmers et al., 2023). Базовая модель загружается с 4-битными весами NF4 и двойным квантованием, а поверх неё обучается адаптер LoRA в bf16, если GPU поддерживает bf16. quantize: 8bit — промежуточный вариант, и предсказания загружают базовую модель так же.
model_training:
trainer_params:
llm-sft:
model_name: Qwen/Qwen2.5-7B-Instruct
lora: {quantize: 4bit}В 4 битах базовые веса занимают четверть памяти, которую те же веса занимают в bf16, а активации, адаптер и состояние оптимизатора добавляются сверху. Potato ещё не измерял память запуска QLoRA на GPU, поэтому планируйте по строке "Peak GPU memory" самого запуска. Каждый запуск трансформера пишет эту строку в конце. QLoRA требует GPU с CUDA и сборку bitsandbytes под CUDA этой машины. Запуск проверяет оба условия до загрузки модели, квантуя несколько чисел на GPU, и когда версии не совпадают, ошибка называет обе версии. Руководство по дообучению LLM применяет QLoRA к запускам SFT и DPO.
Публикация на Hugging Face Hub
У успешного запуска, модель которого лежит на сервере Potato, на странице запуска есть форма Publish to the Hugging Face Hub. При отправке выгружаются модель и карточка модели README.md, составленная по запуску, где названы тренер, базовая модель и адаптер, схемы и метки, размеры выборок, оценка на отложенных объектах с выборкой, на которой её измерили, и идентификаторы запуска и пакета. Карточка запуска dp содержит также строку "Differential privacy" с потраченным эпсилон относительно целевого, дельтой и выборкой train, которую охватывает гарантия. Строка опускает целевое значение или дельту, если запуск не записал это значение.
Выгружается фиксированный список файлов, а не весь каталог artifacts/. В списке файлы весов, например .safetensors, .bin, .pt и .pkl, файлы конфигурации и токенизатора в сохранённом каталоге model/, model_card.json с локальными путями, заменёнными именами файлов, и calibration.json. Ответы модели на объекты проекта (predictions.jsonl и raw_answers.jsonl для моделей решений) остаются на сервере. Контрольные точки, состояние оптимизатора, копии обучающих данных, которые делают некоторые тренеры (yolo_data/, wev_data/, laya_data/), и любая символическая ссылка, указывающая за пределы artifacts/, тоже не выгружаются.
Форма защищает от случайной или публичной отправки несколькими способами:
- Название репозитория вводится дважды, и отправка проходит, только если оба названия совпадают.
- Флажок Private по умолчанию отмечен. Пока Private отмечен, Potato не отправляет в существующий публичный репозиторий, а API отвечает
409. - Форма называет переменную окружения на сервере, по умолчанию
HF_TOKEN, в которой лежит токен записи Hugging Face. Сам токен на странице никогда не вводится. Имя переменной должно содержатьTOKENили начинаться сHF_, а значение должно начинаться сhf_, поэтому значение другой переменной не может попасть на Hub. - Когда Hub не может сказать, существует ли репозиторий, ничего не отправляется, а репозиторий, который создала отправка, снова удаляется, если выгрузка затем не удалась.
- Лицензия карточки модели — это идентификатор лицензии Hub, который вы указываете, например
apache-2.0. Если его нет, в карточке сказано, что действует лицензия базовой модели. Тренеру, лицензию которого нужно подтвердить, напримерultralytics-detect(AGPL-3.0), для отправки нужно то же подтверждение. - Модель, оставленную на удалённом хосте с
fetch_artifacts: falseили обученную на бэкенде agent, с сервера опубликовать нельзя, и ошибка называет, где находится модель.
Каждая отправка — один коммит. Страница запуска перечисляет каждую отправку с репозиторием, видимостью и коммитом, а журнал записывает, кто отправил. Через API тело POST /admin/training/api/runs/<run_id>/push-to-hub принимает repo_id, confirm_repo_id, private (по умолчанию true), token_env (по умолчанию HF_TOKEN), licence и accept_licence. Маршрут возвращает 201 с коммитом, 400 при несовпадении, отсутствующей переменной токена, отсутствии файлов модели или неподтверждённой лицензии и 502, когда Hub отказывает.
Устранение неполадок
Записи ниже охватывают ошибки, наиболее вероятные при первой настройке. Список устранения неполадок в upstream охватывает драйверы GPU, сборки CUDA и сообщения отдельных тренеров.
/admin/trainingвозвращает 404.model_training.enabledне равенtrue, а Potato регистрирует маршруты только когда ключ равенtrue.- "Only N items in the train split". Разметьте больше объектов или уменьшите
min_instancesвparamsзапуска. По умолчанию выборка train содержит 70% размеченных объектов. - "Schema 'x' has 1 distinct label(s) in the data". Классификатору нужно как минимум две используемые метки.
- "No resolved annotations to train on". Схема, названная в запуске, отличается от размечаемой схемы, или никто ещё ничего не разметил.
- Запуск не опубликовал предварительных меток. Прочитайте отчёт
writebackвGET /admin/training/api/status. "No predictions were published: write-back is not enabled for any schema" означает, чтоwriteback.schemasпуст, а счётчики пропусков показывают, сколько предсказаний убрала каждая проверка. <trainer> does not take <name>. Параметр в запуске или подtrainer_paramsнаписан с опечаткой или относится к другому тренеру. Сообщение перечисляет имена, которые принимает тренер.- Запуск был убит после нехватки памяти на машине. Процесс завершился по SIGKILL, обычно из-за убийцы по нехватке памяти. Возьмите модель поменьше или меньше объектов либо задайте
max_ram_mb, чтобы запуск завершился ошибкой в рамках своего лимита. - "Stopped: the run took longer than model_training.max_wall_seconds". Запуск достиг лимита времени. Увеличьте
max_wall_secondsили обучайте на меньшем числе объектов. - "The GPU ran out of memory". Уменьшите
batch_sizeи увеличьтеgradient_accumulation, чтобы сохранить эффективный размер батча, задайтеlora: trueилиlora: {quantize: 4bit}, а дляllm-sftзадайтеgradient_checkpointing: trueили выберите модель поменьше. - "ssh to host failed: Permission denied". Potato запускает
sshсBatchMode=yes, поэтомуssh <host> trueдолжен выполняться из учётной записи сервера без запроса. Ключ с парольной фразой работает, когда его держитssh-agent. - Запуск на бэкенде agent остаётся в очереди. Ни один агент с этим именем бэкенда не опрашивает сервер. Запустите агента командой
potato training agent --backend <name>и проверьте токен кнопкой Check на странице Training.
Дополнительные материалы
- Обучение моделей на вашей собственной разметке: цикл обучения, страница Training и быстрый старт.
- Тренеры: каждый тренер, схемы, на которых он учится, и команды установки.
- Обучение на GPU-сервере, кластере SLURM или машине за NAT: бэкенды ssh, SLURM и опрашивающего агента шаг за шагом.
- Модель в цикле: обратная запись, проверка,
auto_retrainи версии датасета в одном исследовании. - Активное обучение: упорядочивание объектов по неопределённости модели.
- Обнаружение бездумно принятых предварительных меток: проверка, принимают ли разметчики предварительные метки не читая.
- Справочник upstream: полные таблицы параметров каждого тренера.
Источники
- Dawid, A. P., and Skene, A. M. (1979). Maximum Likelihood Estimation of Observer Error-Rates Using the EM Algorithm. Applied Statistics, 28(1). https://doi.org/10.2307/2346806
- Dettmers, T., Pagnoni, A., Holtzman, A., and Zettlemoyer, L. (2023). QLoRA: Efficient Finetuning of Quantized LLMs. Advances in Neural Information Processing Systems 36 (NeurIPS 2023). https://proceedings.neurips.cc/paper_files/paper/2023/hash/1feb87871436031bdc0f2beaa62a049b-Abstract-Conference.html