Движок разметки
Размечайте набор данных моделями, проверяйте машинные метки на слепой случайной выборке человеческих меток и выпускайте данные с сертификатом проверки.
Движок разметки размечает набор данных моделями, а людей привлекает, чтобы измерить, как часто модели ошибаются. Требования к готовым меткам вы задаёте в контракте, например «не более 5% принятых машинных меток ошибочны, с доверием 90%». Движок запрашивает у людей метки, нужные для проверки этого утверждения, принимает машинные метки, которые подтверждает тест, и отправляет оставшиеся объекты людям. На выходе получается набор данных и сертификат, где записано, что проверялось и на скольких человеческих метках.
Движок доступен начиная с Potato 2.11. Сервер разметки, командная строка potato label, REST API, MCP-сервер и Python SDK управляют им через один и тот же файл engine.sqlite в каталоге задачи.
Когда движок подходит исследованию
Движок окупается, когда люди не могут разметить всё, а модель может разметить большую часть. Если люди всё равно разметят каждый объект, движок ничего не добавляет, и лучше выбрать обычную стратегию распределения. Подходят три ситуации:
- Объектов больше, чем способны разметить люди, и есть модель, которая права в большинстве случаев.
- Нужно сообщить, насколько хороши метки, а не только то, что их поставила модель: для статьи, публикации набора данных или обучающего набора, которым будет пользоваться кто-то другой.
- Вы оцениваете модель или агента с помощью LLM-судьи и должны знать, может ли судья заменить людей.
От предсказания модели к итоговой метке
Движок хранит машинные предсказания, запросы к людям и результаты контрактов в одном хранилище, и каждый объект проходит одни и те же шесть шагов:
- Источники представляют собой модели. Источником может быть LLM, визуально-языковая модель, модель принятия решений (Laya, Jev или OpenJev), детектор объектов, LLM-судья, модель, обученная на метках самого исследования, жюри из других источников или метки, которые у вас уже есть. С каждым предсказанием источник записывает уверенность.
- Каскад задаёт порядок источников. Объект попадает к первому источнику, и если контракт не принимает его ответ, объект пробует следующий источник. После последнего источника объект уходит к человеку.
- Запросы описывают, что движок просит сделать людей. Каждый запрос записывает, зачем он создан (например, калибровка, сертификация, проверка, аудит), вероятность, с которой его объект попал в выборку, и мог ли человек видеть машинный ответ. Калибровочные запросы отбираются случайно и всегда слепые.
- Контракты проверяют машинные метки по человеческим меткам на случайной выборке. Половина этой выборки (dev-часть) выбирает правило принятия, а другая половина (cert-часть) его проверяет. Статус контракта:
met,insufficient(нужно больше меток, с оценкой, сколько именно),infeasible,violatedилиstale. - Разрешение даёт каждому объекту итоговую метку. Это машинная метка, принятая по выполненному контракту, метка человека или статус «ожидает».
- Сертификат записывает результат каждого контракта, каскад с версиями моделей и промптов, сколько человеческих меток ушло на каждую цель, расходы на модели и дайджест журнала вызовов.
Правила, на которых держатся гарантии
Выполненный контракт является статистическим утверждением о случайной выборке, которую разметили люди, и оно верно благодаря тому, как эта выборка отбирается и используется. Движок соблюдает пять правил:
- Слепые запросы не показывают машинного ответа. Пока у человека калибровочный, сертификационный или аудиторский запрос, сервер скрывает все машинные ответы для этого объекта. Предразметка, встроенный судья, ИИ-ассистент (он отвечает
403) и кнопки помощи ИИ отключены. Метка, поставленная после просмотра ответа машины, не является независимой проверкой этого ответа. - Выбор и проверка используют разные метки. Пороги выбираются на dev-метках и проверяются на cert-метках. Каждый новый тест на cert-метках идёт на более строгом уровне, поэтому повторная сертификация до первого успешного теста не завышает доверие.
- Сертифицируют только люди. Машинные разметчики могут участвовать в выводе итоговых меток, но никогда не входят в метки, по которым проверяется контракт.
- Изменение делает сертификат устаревшим. Смена источника, промпта, порога или схемы помечает каждый затронутый контракт как
staleи переводит его принятые метки вpending_recert, пока контракт не проверят заново. Человеческие метки сохраняются. - Машинные предсказания не занимают места разметчиков. Предсказания движка не засчитываются в лимит разметчиков на объект.
Движок не проверяет, верны ли человеческие метки. Каждый контракт сравнивает машины с людьми, которые разметили выборку, поэтому контракт, проверенный на ненадёжных людях, сертифицирует согласие с ненадёжными людьми. Чтобы проверить и людей, используйте контроль качества, перекрытие (humans.overlap) и контракт no_worse_than_human.
Первое исследование
Potato поставляет три примера исследований в examples/labeling-engine/: по одному для текста, изображений и трасс агентов. В таблице перечислены источники и контракты каждого из них:
| Пример | Источники | Контракты |
|---|---|---|
text-certified-sentiment/ | Laya (модель принятия решений), LLM в Ollama | селективный риск на 10%, распространённость по PPI |
image-objects-and-people/ | детектор YOLOv8n, визуальная модель в Ollama | селективный риск по рамкам (IoU) и по метке «есть человек» |
agent-trace-judge/ | LLM-судья с перестановкой порядка меток | селективный риск, no-worse-than-human, успешность задачи по PPI |
Текстовый пример запускается четырьмя командами. Первая размечает каждый объект каскадом и отбирает первую слепую выборку, вторая показывает эту выборку людям, а последние две проверяют контракты и выводят сертификат, когда люди разметят выборку:
potato label run examples/labeling-engine/text-certified-sentiment/config.yaml
potato start examples/labeling-engine/text-certified-sentiment/config.yaml -p 8000
potato label certify examples/labeling-engine/text-certified-sentiment/config.yaml
potato label certificate examples/labeling-engine/text-certified-sentiment/config.yaml --format mdЧтобы добавить движок в своё исследование, допишите эти ключи в конфигурацию, где уже есть data_files и схема разметки с именем sentiment. Контракт требует, чтобы ошибочных среди принятых машинных меток было не более 10% с доверием 90%, а budgets.human_labels ограничивает, сколько запросов к людям может открыть движок:
assignment_strategy: engine
labeling_engine:
enabled: true
sources:
- id: gemma
kind: llm
endpoint_type: vllm
model: google/gemma-4-12B-it-qat-w4a16-ct
base_url: http://localhost:8001/v1
confidence: {method: logprob}
contracts:
- id: accuracy
kind: selective_risk
schema: sentiment
error: 0.1
confidence: 0.9
budgets:
human_labels: 400Источник берёт уверенность из логарифмов вероятностей токенов (method: logprob). Это один вызов на объект, и обычно этот метод откалиброван лучше остальных. Все ключи перечислены на странице Конфигурация, а что проверяет каждый контракт, описано на странице Контракты.
Запросы на странице разметки
При assignment_strategy: engine разметчики получают запросы движка, начиная с самого приоритетного. Порядок такой: арбитраж, сертификация, калибровка, дополнительные оценщики для распределительных контрактов, объекты, которые не смогла разметить ни одна машина, проверка и аудиты. Калибровочные запросы выдаются в фиксированном случайном порядке, dev- и cert-запросы вперемешку. Человек получает сразу все открытые запросы по объекту, по одному на схему, и никогда два запроса по одной схеме на одном объекте.
Короткая заметка над объектом сообщает тип запроса, а на странице с несколькими вопросами называет вопрос:
- Слепой. Заметка гласит «Label this one yourself. Suggestions are off for this item.» Объект остаётся слепым для этого человека и после сохранения, при перезагрузке и при возврате кнопкой «Назад».
- Проверка. Ответ машины уже подставлен, и заметка просит оставить его, если он верен, и изменить, если нет. Страница записывает подставленный ответ, так что можно измерить, как часто люди его принимают. Пока человек ничего не сделал, ничего не сохраняется, поэтому оставленная открытой страница не отвечает за него. Схемы, ответы которых страница не может подставить (временные сегменты, 3D-объекты, трассы агентов), выдаются вслепую.
- Решение. Ни одну машинную метку принять не удалось, поэтому ответ человека становится меткой.
Запрос, который человек держит без ответа дольше runtime.hold_minutes (по умолчанию 60), возвращается в общий пул и исчезает с его страницы. Метка, сохранённая на объекте, который движок этому человеку не выдавал, никогда не закрывает чужой запрос, и движок хранит её как органическую метку. Когда новая сертификация принимает машинные метки, движок отменяет открытые запросы на проверку и решение по объектам, которые она теперь покрывает. Запросы, которые человек уже взял, остаются у него, и его ответ заменяет машинную метку.
Счётчик прогресса считает запросы, которые человек ещё может взять, а не весь корпус. Когда делать пока нечего, разметчик видит короткую страницу ожидания и получает новые запросы, как только их откроет планировщик. Когда больше ничего не будет, потому что у каждого объекта есть метка, бюджет человеческих меток исчерпан или достигнут личный лимит человека, его участие заканчивается как обычно: страницами после исследования и, на краудсорсинговой платформе, кодом завершения. До первого прохода планировщика никто не завершает работу.
Pocket Mode тоже выдаёт запросы движка, сразу целым пакетом, и запрашивает новые, прежде чем показать «All caught up». Pocket Mode никогда не показывает машинный ответ, поэтому выданный там запрос на проверку записывается как слепой, если только десктопная страница уже не показала этот ответ этому человеку. На карточках решения и арбитража он показывает ту же заметку, что и десктопная страница.
Админ-страница
Когда движок включён, админ-панель ссылается на Labeling engine по адресу /admin/labeling-engine. У каждого графика на странице есть и табличное представление. Страница показывает:
- статус каждого контракта, покрытие, номер попытки и сколько ещё меток ему нужно, с полным текстом его утверждения (невыполненный контракт называет свою цель, а не гарантию);
- интервалы каждого контракта
ppiрядом с интервалами, полученными только по людям; - предупреждение для источника, чей последний прогон завершился сбоем или все ответы которого оказались ошибками;
- кривую ошибки в зависимости от покрытия для последнего уровня каскада, с гарантированной верхней границей и целью;
- диаграмму надёжности для каждого уровня, где заявленная уверенность сопоставлена с долей верных ответов на человеческих метках, с ECE и оценкой Брайера, а бины с малым числом меток нарисованы бледнее;
- аудиты принятых меток в виде ошибок относительно цели, и хватает ли аудитов для вывода;
- запросы к людям по цели и статусу;
- журнал вызовов моделей, сначала новые, с токенами, задержкой и стоимостью;
- кнопки, чтобы запустить проход планировщика, сертифицировать сейчас и открыть сертификат.
Если открыть страницу без сессии администратора, она переходит к форме ввода ключа админ-панели. Если движок выключен, страница сообщает об этом и называет ключ, который его включает.
Дополнительные материалы
- Контракты движка разметки: шесть видов контрактов и что проверяет каждый
- Конфигурация движка разметки: все ключи
labeling_engine - Командная строка, REST API, инструменты MCP и SDK
- Переход на движок разметки с
icl_labeling,judge_calibrationиpre_annotation - Solo Mode для одного эксперта, работающего с LLM
- Предразметка с помощью LLM и согласие LLM-судьи с людьми
Подробности реализации смотрите в исходной документации.