Solo Mode
Полный конвейер разметки в Potato силами одного человека: эксперт и LLM проходят конечный автомат фаз от промпта и параллельной разметки до итоговой проверки.
Новое в v2.3.0
Обычный проект разметки требует нескольких разметчиков, расчёта согласованности между ними, раундов арбитража и немалых усилий на координацию. Для многих исследовательских групп именно это главное узкое место: не интерфейс разметки, а организационная работа по найму, обучению и управлению командой.
Solo Mode заменяет схему с несколькими разметчиками совместной работой одного эксперта и LLM. Человек даёт качественные метки на небольшом, специально отобранном подмножестве. LLM учится на этих метках, предлагает метки для остальных объектов, а человек проверяет только те случаи, где LLM не уверена или, вероятно, ошибается. Всем этим управляет конечный автомат фаз: он переходит дальше по заданным вами порогам и возвращается к промпту, когда оказывается, что ошибка именно в промпте.
Во внутренних тестах Solo Mode достигал согласия 95%+ с полными конвейерами из нескольких разметчиков, требуя при этом лишь от 10 до 15% от общего числа человеческих меток.
Порядок работы
Solo Mode устроен как конечный автомат. SoloPhaseController отслеживает, в какой фазе находится проект и в какие фазы ему разрешено перейти дальше, поэтому маршрут не прямой: несколько фаз могут вернуться назад, если промпт ещё требует доработки.
Настройка
Описание задачи и данные. Кнопка Generate prompt просит модель ревизии (revision_models) написать первый промпт по описанию и схемам разметки. Если модели ревизии нет или она ничего не вернула, первым промптом становится само описание, и в истории промптов это отмечается. Из настройки можно перейти только к проверке промпта.
Проверка промпта
Potato составляет промпт по описанию задачи, а вы его редактируете. Сюда возвращаются несколько последующих фаз, когда выясняется, что проблема в промпте, поэтому эта фаза служит узлом всего процесса, а не разовым шагом.
Отсюда проект идёт либо через цикл пограничных случаев, либо сразу к параллельной разметке.
Синтез пограничных случаев, затем их разметка
LLM генерирует примеры на границах классов, а вы их размечаете. Из разметки можно вернуться к проверке промпта, если примеры показывают, что промпт неверен.
Валидация промпта
Ваши метки на пограничных случаях сравниваются с тем, что выдаёт промпт. Дальше проект либо переходит к параллельной разметке, либо возвращается к проверке промпта.
Параллельная разметка
Вы и LLM размечаете одни и те же данные одновременно. Именно эта фаза даёт показатель согласия, от которого зависит всё остальное.
Разрешение разногласий
Там, где ваши метки и метки LLM расходятся, решение принимаете вы. Отсюда проект возвращается к параллельной разметке или к проверке промпта, если разногласия указывают на промпт, а не на отдельные объекты.
Активная разметка
Основная фаза разметки, в которой объекты выбираются взвешенными пулами из instance_selection. Отсюда Potato может перейти к периодической проверке, к проверке правил или дальше, к автономной разметке.
Периодическая проверка
Метки LLM с низкой уверенностью, которые показываются каждые thresholds.periodic_review_interval объектов. Отсюда проект возвращается к активной разметке, переходит к проверке правил или откатывается к проверке промпта.
Проверка правил
Правила для пограничных случаев, которые Potato извлёк из вашей разметки, выносятся вам на утверждение. Отсюда проект возвращается к активной разметке или к проверке промпта.
Автономная разметка
LLM размечает всё, что осталось. Единственный выход из этой фазы ведёт к итоговой валидации.
Итоговая валидация
Вы проверяете выборку меток, поставленных только LLM. Если порог thresholds.end_human_annotation_agreement пройден, проект завершается; если нет, он возвращается к активной разметке.
Завершено
Конечное состояние.
Конфигурация
Быстрый старт
Минимальная конфигурация Solo Mode:
annotation_task_name: "Sentiment Classification"
task_dir: "."
data_files:
- "data/reviews.jsonl"
item_properties:
id_key: id
text_key: text
solo_mode:
enabled: true
# The models that label. A list: the first is used, the rest are fallbacks.
labeling_models:
- endpoint_type: openai
model: "gpt-4o"
api_key: ${OPENAI_API_KEY}
temperature: 0.1
max_tokens: 1024
# When the project may stop asking the human
thresholds:
end_human_annotation_agreement: 0.92
minimum_validation_sample: 50
confidence_low: 0.5
state_dir: "solo_state_sentiment"
annotation_schemes:
- annotation_type: radio
name: sentiment
description: "What is the sentiment of this text?"
labels:
- Positive
- Neutral
- Negative
output_annotation_dir: "output/"
export_annotation_format: "jsonl"Полный справочник по конфигурации
solo_mode:
enabled: true
# Models that label, and models that revise. Both are lists; revision_models
# defaults to labeling_models when omitted.
labeling_models:
- endpoint_type: openai # openai, anthropic, ollama, vllm, ...
model: "gpt-4o"
api_key: ${OPENAI_API_KEY}
temperature: 0.1
max_tokens: 1024
revision_models:
- endpoint_type: anthropic
model: "claude-sonnet-4-20250514"
api_key: ${ANTHROPIC_API_KEY}
max_tokens: 1024
# Sentence embeddings, used for diversity and neighbour lookups
embedding:
model_name: "all-MiniLM-L6-v2"
# How the LLM's uncertainty is measured
uncertainty:
strategy: direct_confidence
sampling_diversity:
num_samples: 5
temperature: 1.0
# When the human can stop, and what counts as agreement per scheme type
thresholds:
end_human_annotation_agreement: 0.90
minimum_validation_sample: 50
confidence_low: 0.5
confidence_high: 0.8
periodic_review_interval: 100
likert_tolerance: 1
multiselect_jaccard_threshold: 0.5
textbox_embedding_threshold: 0.7
span_overlap_threshold: 0.5
# Weights for the pools that choose what the human sees next
instance_selection:
low_confidence_weight: 0.3
disagreement_weight: 0.1
diversity_weight: 0.2
llm_predicted_weight: 0.3
random_weight: 0.1
cartography_weight: 0.0
edge_case_rule_weight: 0.0
batches:
llm_labeling_batch: 50
max_parallel_labels: 200
labeling_functions:
enabled: true
auto_extract: true
max_functions: 50
min_confidence: 0.85
min_coverage: 3 # instances, not a fraction
vote_threshold: 0.5
edge_case_rules:
enabled: true
auto_extract_on_labeling: true
confidence_threshold: 0.75
min_rules_for_clustering: 10
target_cluster_size: 15
reannotation_enabled: true
reannotation_confidence_threshold: 0.60
max_reannotations_per_instance: 2
confusion_analysis:
enabled: true
min_instances_for_pattern: 3
max_patterns: 20
auto_suggest_guidelines: false
prompt_optimization:
enabled: true
find_smallest_model: true
target_accuracy: 0.85
optimization_interval_seconds: 300
accuracy_weight: 0.7
length_weight: 0.2
# Send cheap cases to a small model and hard ones to a larger one
confidence_routing:
enabled: false
tiers:
- name: cheap
confidence_threshold: 0.8
model:
endpoint_type: ollama
model: "llama3.2"
refinement_loop:
enabled: true
trigger_interval: 50
min_improvement: 0.02
max_cycles: 5
patience: 2
state_dir: "solo_state_sentiment"Основные возможности
Анализ ошибок
После каждого раунда разметки Potato строит матрицу ошибок между метками человека и LLM. Админ-панель показывает:
- точность, полноту и F1 по каждому классу с точки зрения LLM;
- самые частые пары путаницы (например, «neutral ошибочно отнесён к positive: 23 объекта»);
- примеры объектов для каждой пары путаницы;
- графики динамики, показывающие улучшение от раунда к раунду уточнения.
У Solo Mode нет интерфейса командной строки. Он работает внутри сервера и управляется со своих страниц запущенного экземпляра, поэтому результаты анализа читаются с админ-панели, а не из CLI. Отчёт выглядит так:
Confusion Analysis (Round 2)
============================
Overall Accuracy: 0.87 (target: 0.92)
Top Confusion Pairs:
neutral -> positive: 23 instances (15.3%)
negative -> neutral: 11 instances (7.3%)
positive -> neutral: 5 instances (3.3%)
Per-Class Performance:
Positive: P=0.91 R=0.94 F1=0.92
Neutral: P=0.78 R=0.71 F1=0.74
Negative: P=0.93 R=0.88 F1=0.90
Автоматический цикл уточнения
Цикл уточнения чередует разметку LLM, анализ ошибок и обновление инструкций. На каждой итерации:
- LLM размечает весь набор данных по текущим инструкциям.
- Potato сравнивает результат со всеми доступными человеческими метками.
- Если точность ниже порога, запускается анализ ошибок.
- LLM предлагает правки инструкций на основе закономерностей в ошибках.
- Человек просматривает и утверждает правки.
- Цикл повторяется (не более
max_cyclesраз).
solo_mode:
revision_models:
- endpoint_type: anthropic
model: "claude-sonnet-4-20250514"
api_key: ${ANTHROPIC_API_KEY}
refinement_loop:
enabled: true
trigger_interval: 50 # run a cycle every 50 new human labels
min_improvement: 0.02 # stop if a cycle gains less than 2%
max_cycles: 5
patience: 2 # cycles below min_improvement before stoppingФункции разметки (по мотивам ALCHEmist)
Potato генерирует лёгкие функции разметки из закономерностей, замеченных в человеческой разметке. Это не вызовы LLM, а быстрые детерминированные правила.
Пример сгенерированных функций разметки:
# Auto-generated labeling function 1
# Precision: 0.96, Coverage: 0.08
def lf_strong_positive_words(text):
positive = {"excellent", "amazing", "fantastic", "outstanding", "perfect"}
if any(w in text.lower() for w in positive):
if not any(neg in text.lower() for neg in {"not", "never", "no"}):
return "Positive"
return None # abstain
# Auto-generated labeling function 2
# Precision: 0.93, Coverage: 0.05
def lf_explicit_negative(text):
negative = {"terrible", "awful", "horrible", "worst", "disgusting"}
if any(w in text.lower() for w in negative):
return "Negative"
return NoneНастройка поведения функций разметки:
solo_mode:
labeling_functions:
enabled: true
auto_extract: true
max_functions: 50
min_confidence: 0.85
min_coverage: 3 # minimum instances a function must cover
vote_threshold: 0.5 # agreement needed when functions disagreeОбозреватель разногласий
Обозреватель разногласий показывает объекты, на которых разные сигналы противоречат друг другу. Для каждого объекта разметчик видит:
- метку, предсказанную LLM, и её уверенность;
- голоса функций разметки (если они есть);
- ближайших размеченных соседей в пространстве эмбеддингов;
- исходный текст или контент.
Это самая ценная работа по разметке: каждая метка разрешает настоящую неоднозначность.
solo_mode:
# Disagreement is a phase, not a configurable block. What you control is how
# heavily disagreement weighs when Potato picks the next instance.
instance_selection:
disagreement_weight: 0.3
low_confidence_weight: 0.3
diversity_weight: 0.2
llm_predicted_weight: 0.1
random_weight: 0.1Каскадная эскалация по уверенности
Когда основную часть набора данных разметила LLM, Potato упорядочивает все размеченные ею объекты по уверенности и передаёт человеку наименее уверенные. Это продолжается пакетами, пока качество не стабилизируется.
solo_mode:
thresholds:
confidence_low: 0.5 # below this, the human sees it
confidence_high: 0.8 # above this, the LLM's label stands
periodic_review_interval: 100 # surface low-confidence labels this often
batches:
llm_labeling_batch: 50
max_parallel_labels: 200Модели принятия решений
Начиная с Potato 2.11, в Solo Mode размечать может модель принятия решений. Такая модель отвечает на вопрос с фиксированным набором вариантов за один прямой проход и возвращает вероятность для каждого варианта, поэтому размечает быстрее и дешевле, чем LLM, но не может писать промпты, правила или объяснения. К ней ведут два типа эндпоинтов. laya запускает Laya внутри процесса Potato на CPU и требует pip install 'potato-annotation[decision]', а systemone обращается к любому серверу с API /v1/systemone, например к размещённому Jev или к OpenJev.
Обычно модель принятия решений ставят на первый уровень маршрутизации по уверенности: она размечает всё, и только объекты, в которых она не уверена, уходят дальше к LLM:
solo_mode:
labeling_models:
- endpoint_type: laya
model: convaiinnovations/laya
revision_models: # required: decision models cannot write text
- endpoint_type: vllm
model: google/gemma-4-12B-it-qat-w4a16-ct
base_url: http://localhost:8001/v1
confidence_routing:
enabled: true
tiers:
- name: laya
confidence_threshold: 0.9
model:
endpoint_type: laya
model: convaiinnovations/laya
device: cpu
- name: llm
confidence_threshold: 0.5
model:
endpoint_type: vllm
model: google/gemma-4-12B-it-qat-w4a16-ct
base_url: http://localhost:8001/v1В revision_models должна стоять генеративная модель. По умолчанию это значение берётся из labeling_models, поэтому в исследовании, где единственная модель является моделью принятия решений, его нужно задать явно. Модели принятия решений размечают схемы radio, select, likert и slider, а Solo Mode не запускается, если такой модели поручено размечать схемы multiselect, спанов или свободного текста. На шкалах оценок баллы Laya едва следуют шкале, поэтому прежде чем направлять через неё схему likert или slider, проверьте несколько объектов кнопкой Try on 10 items. Уверенность равна вероятности, которую модель присвоила выбранному варианту, а её калибровка зависит от предметной области, поэтому порог уровня подбирайте по своим данным. Готовый к запуску вариант лежит в config-decision-model.yaml.
Слепые подсказки
По умолчанию страница разметки показывает метку LLM, её уверенность и кнопку Accept ещё до вашего ответа. Это быстро, но заодно тянет ваш ответ к подсказке. Solo Mode передаёт остаток корпуса LLM, когда ваше согласие с ней превышает end_human_annotation_agreement, поэтому согласие, измеренное на метках, поставленных после того, как вы увидели подсказку, может завершить вашу часть работы слишком рано. Начиная с Potato 2.11, момент появления подсказки задаёт solo_mode.suggestions:
solo_mode:
suggestions:
display: blind_sample # before_label | after_label | blind_sample
blind_rate: 0.2
minimum_blind_sample: 20blind_sample скрывает подсказку на доле объектов, равной blind_rate, а after_label никогда не показывает её первой. Когда набирается minimum_blind_sample слепых сравнений, при передаче работы с end_human_annotation_agreement сравнивается слепое согласие. Карточка Blind Agreement на панели показывает рядом слепое согласие и согласие с показанной подсказкой, и большой положительный разрыв означает, что вы чаще соглашаетесь с LLM, когда видите её ответ.
Кроме того, в Potato 2.11 Solo Mode проверяет лимит расходов проекта (ai_budget.cap_usd) перед началом разметки и перед каждым пакетом, а также получил кэш ответов (solo_mode.cache), золотой набор с пробными прогонами промптов (solo_mode.gold), проверку чувствительности к промпту, жюри разметки (solo_mode.jury) и упорядочивание по учебной программе (solo_mode.instance_selection.curriculum). Каждая из этих возможностей описана в документе Solo Mode Advanced Features. Когда включён движок разметки, Solo Mode также записывает предсказания своих моделей в хранилище движка, чтобы движок мог их откалибровать и сертифицировать.
Приоритизация объектов по нескольким сигналам
Во всех фазах, где размечает человек, Potato выбирает самые информативные объекты с помощью системы взвешенных пулов. Семь пулов питают единую очередь приоритетов:
solo_mode:
instance_selection:
low_confidence_weight: 0.3
diversity_weight: 0.2
llm_predicted_weight: 0.3
disagreement_weight: 0.1
random_weight: 0.1
cartography_weight: 0.0
edge_case_rule_weight: 0.0- low_confidence: уверенность LLM ниже
thresholds.confidence_low - diversity: объект в пространстве эмбеддингов далёк от того, что вы уже разметили
- llm_predicted: у LLM есть метка, и её ещё не проверяли
- disagreement: доступные для объекта сигналы не согласуются
- random: небольшая случайная выборка, чтобы оценка оставалась честной и находились слепые зоны
- cartography: сигнал динамики обучения, по умолчанию выключен
- edge_case_rule: объект подпадает под правило, извлечённое из вашей прежней разметки, по умолчанию выключен
Синтез пограничных случаев
Potato с помощью LLM генерирует синтетические примеры, нацеленные на известные слабые места:
solo_mode:
edge_case_rules:
enabled: true
auto_extract_on_labeling: true # derive rules as you label
confidence_threshold: 0.75
min_rules_for_clustering: 10
target_cluster_size: 15
reannotation_enabled: true # revisit items a new rule contradicts
reannotation_confidence_threshold: 0.60
max_reannotations_per_instance: 2LLM генерирует примеры, неоднозначные между заданными парами меток. Человек их размечает, и эти метки добавляются в контекст few-shot для следующих раундов разметки LLM.
Оптимизация промпта (по мотивам DSPy)
Potato автоматически оптимизирует промпт, подбирая для LLM лучший формат инструкции, и ищет самую маленькую модель, которая ещё удерживает целевую точность:
solo_mode:
prompt_optimization:
enabled: true
find_smallest_model: true # prefer the cheapest model that holds up
target_accuracy: 0.85
optimization_interval_seconds: 300
accuracy_weight: 0.7 # how the candidates are scored
length_weight: 0.2Отслеживание прогресса
Админ-панель показывает прогресс Solo Mode в реальном времени:
- текущую фазу и прогресс внутри каждой фазы;
- число готовых человеческих меток относительно общего бюджета;
- точность LLM во времени (по раундам);
- покрытие и точность функций разметки;
- гистограмму распределения уверенности;
- оценку времени до завершения.
Модуля potato.solo и CLI для Solo Mode нет: весь процесс живёт за собственными маршрутами сервера, поэтому прогресс читается с админ-панели. Она сообщает:
Solo Mode Status
================
Current Phase: 6 (Active Labeling) - Batch 3/10
Human Labels: 142 / ~300 estimated total
LLM Accuracy: 0.89 (target: 0.92)
LF Coverage: 0.23 (labeling functions cover 23% of data)
Dataset Size: 10,000 instances
- Human labeled: 142
- LF labeled: 2,300
- LLM labeled: 7,558
- Unlabeled: 0
Когда выбирать Solo Mode, а когда традиционную разметку несколькими разметчиками
Выбирайте Solo Mode, если:
- у вас есть эксперт в предметной области, способный давать качественные метки;
- бюджет или организационные условия не позволяют нанять нескольких разметчиков;
- в задаче ясные, чётко определённые категории;
- нужно разметить большой набор данных (1000+ объектов);
- скорость важнее, чем измерение согласованности разметчиков.
Выбирайте традиционную разметку несколькими разметчиками, если:
- для публикации нужна статистика согласованности разметчиков;
- задача сильно субъективна (например, оскорбительность, юмор);
- нужно изучать закономерности разногласий разметчиков;
- нормативные требования предписывают нескольких независимых разметчиков;
- пространство меток сложное или меняется (инструкции по разметке ещё разрабатываются).
Гибридный подход: используйте Solo Mode для начальной массовой разметки, а затем поручите второму разметчику случайную выборку от 10 до 20%, чтобы посчитать статистику согласованности. Так вы получаете эффективность Solo Mode вместе с гарантией качества, которую даёт проверка несколькими разметчиками.
Собственного блока проверки у Solo Mode нет. Проведите второго разметчика обычным проходом Potato по экспортированным меткам и посчитайте согласие между его метками и метками Solo Mode так же, как для любых двух разметчиков. (Блок verification есть у icl_labeling, но он относится к разметке в контексте, а не к Solo Mode.)
Дополнительные материалы
- Руководство по Solo Mode: разметка 10 000 примеров: пошаговый разбор
- Активное обучение: система активного обучения, на которой всё построено
- Поддержка ИИ: настройка интеграции с LLM
- Контроль качества: обеспечение качества разметки
- MACE: оценка компетентности (полезна для проверки в гибридном режиме)
Подробности реализации см. в исходной документации.