Modo Solo: Como um Único Anotador Pode Rotular 10.000 Exemplos
Tutorial passo a passo do Modo Solo do Potato: rotule você mesmo um conjunto de sementes, deixe um LLM rotular o resto e use as verificações de acurácia para decidir quando o resultado está bom o bastante para parar.
Você tem 10.000 avaliações de produtos para rotular quanto ao sentimento (Positivo, Neutro, Negativo). Contratar três anotadores para rotular todas elas leva semanas e custa milhares de dólares. O Modo Solo permite que um único especialista do domínio obtenha qualidade comparável rotulando apenas 500-1.000 instâncias. Um LLM cuida do restante, e a pessoa revisa tudo aquilo sobre o que o LLM está inseguro.
Este tutorial percorre o processo inteiro.
O que você vai precisar
- Potato 2.3.0 ou posterior, com os extras de IA para os provedores de LLM:
pip install potato-annotation[ai] - Uma chave de API da OpenAI ou da Anthropic (para o componente LLM)
- Seu conjunto de dados em formato JSONL
- Um anotador com conhecimento do domínio (que pode ser você)
Passo 1: Prepare seus dados
Crie data/reviews.jsonl com uma avaliação por linha:
{"id": "rev_001", "text": "Absolutely love this product! Best purchase I've made all year.", "source": "amazon"}
{"id": "rev_002", "text": "It works fine. Nothing special but gets the job done.", "source": "amazon"}
{"id": "rev_003", "text": "Broke after two weeks. Complete waste of money.", "source": "amazon"}
{"id": "rev_004", "text": "The quality is decent for the price point. I might buy again.", "source": "amazon"}
{"id": "rev_005", "text": "Arrived damaged and customer service was unhelpful.", "source": "amazon"}Para este tutorial, imagine que este arquivo contém 10.000 avaliações.
Passo 2: Crie a configuração
Crie config.yaml:
annotation_task_name: "Product Review Sentiment (Solo Mode)"
task_dir: "."
data_files:
- "data/reviews.jsonl"
item_properties:
id_key: id
text_key: text
# --- Solo Mode Configuration ---
solo_mode:
enabled: true
# The model that labels. A list, so you can give fallbacks.
labeling_models:
- endpoint_type: openai
model: "gpt-4o"
api_key: ${OPENAI_API_KEY}
temperature: 0.1
max_tokens: 1024
embedding:
model_name: "all-MiniLM-L6-v2"
uncertainty:
strategy: direct_confidence
# When you are allowed to stop labeling
thresholds:
end_human_annotation_agreement: 0.93
minimum_validation_sample: 50
confidence_low: 0.5
confidence_high: 0.85
periodic_review_interval: 100
# What decides which instance you see next
instance_selection:
low_confidence_weight: 0.30
disagreement_weight: 0.25
diversity_weight: 0.20
llm_predicted_weight: 0.15
random_weight: 0.10
batches:
llm_labeling_batch: 25
max_parallel_labels: 200
labeling_functions:
enabled: true
auto_extract: true
max_functions: 15
min_confidence: 0.92
min_coverage: 3
edge_case_rules:
enabled: true
auto_extract_on_labeling: true
confusion_analysis:
enabled: true
min_instances_for_pattern: 3
max_patterns: 20
prompt_optimization:
enabled: true
target_accuracy: 0.93
refinement_loop:
enabled: true
trigger_interval: 50
min_improvement: 0.02
max_cycles: 3
state_dir: "solo_state_reviews"
# --- Annotation Schema ---
annotation_schemes:
- annotation_type: radio
name: sentiment
description: "What is the overall sentiment of this review?"
labels:
- "Positive"
- "Neutral"
- "Negative"
label_requirement:
required: true
sequential_key_binding: true
output_annotation_dir: "output/"
export_annotation_format:
- jsonl
- parquetPasso 3: Inicie o servidor
potato start config.yaml -p 8000Abra http://localhost:8000 e faça login. O painel do Modo Solo aparece, mostrando o projeto em configuração, pronto para você revisar o prompt que ele sintetizou.
Passo 4: Anotação em paralelo, suas primeiras 50
O Potato escolheu 50 avaliações diversas usando clusterização baseada em embeddings. Elas não são aleatórias. Foram escolhidas para cobrir a distribuição dos seus dados da forma mais ampla possível.
Rotule cada uma delas. Esta é a fase que mais importa, pois a qualidade dos seus rótulos de semente define o teto do que o LLM consegue aprender. Vá com calma e mantenha a consistência.
Estimativa de tempo: 15-25 minutos, a 20-30 segundos por instância.
Quando houver rótulos suficientes, o LLM começa a rotular junto com você sem que seja preciso pedir.
Passo 5: O LLM alcança você
Esta fase roda sozinha. O Potato envia ao LLM um lote de 200 instâncias com seus 50 rótulos de semente como exemplos few-shot e depois compara as previsões com 10 rótulos de semente reservados para estimar a acurácia de base.
Um indicador de progresso aparece no painel. Isso normalmente leva 1-2 minutos, dependendo do provedor de LLM.
Resultado típico: O LLM fica em 75-85% de acurácia na primeira calibração. Isso é esperado. Ele ainda não aprendeu o seu estilo de anotação.
Passo 6: Análise de confusão
O Potato exibe uma matriz de confusão mostrando onde o LLM discorda dos seus rótulos. Uma saída típica:
Confusion Analysis (Round 1)
============================
Overall Accuracy: 0.82 (target: 0.93)
Top Confusion Pairs:
Neutral -> Positive: 14 instances (7.0%)
Negative -> Neutral: 9 instances (4.5%)
Positive -> Neutral: 4 instances (2.0%)
Isso aponta a principal fraqueza do LLM neste caso: ele continua promovendo avaliações neutras a positivas. É um erro comum, já que os LLMs tendem a pender para o positivo.
Sua ação: Examine os pares de confusão. Clique em cada par para ver as instâncias específicas que o LLM errou, que é a forma mais rápida de entender como ele falha.
Passo 7: De volta à revisão do prompt
Com base na análise de confusão, o Potato redige diretrizes refinadas para o LLM e as mostra lado a lado: de um lado o prompt atual, do outro as edições específicas que ele propõe a partir dos padrões de erro.
Por exemplo, o Potato pode sugerir adicionar:
"Avaliações que descrevem um produto como 'bom', 'ok' ou 'razoável' sem emoção forte devem ser rotuladas como Neutral, mesmo que mencionem comprar de novo."
Passe por cada edição sugerida e aprove, modifique ou rejeite. Você também pode escrever seus próprios esclarecimentos.
Estimativa de tempo: 5-10 minutos.
Passo 8: Funções de rotulagem
O Potato gera funções de rotulagem programáticas a partir de padrões nos seus rótulos de semente. São regras rápidas e determinísticas que tratam os casos fáceis:
Generated Labeling Functions:
LF1: Strong positive words (love, amazing, best, excellent)
Precision: 0.97, Coverage: 0.06
LF2: Strong negative words (terrible, awful, worst, waste)
Precision: 0.95, Coverage: 0.04
LF3: Exclamation + positive adjective
Precision: 0.94, Coverage: 0.03
LF4: Return/refund mention + negative context
Precision: 0.92, Coverage: 0.02
...
Total coverage: 0.18 (1,800 of 10,000 instances)
As funções de rotulagem cobrem 18% do seu conjunto de dados com mais de 92% de precisão. Essas instâncias são rotuladas automaticamente, o que libera o LLM e a pessoa para os casos mais difíceis.
Sua ação: Examine as funções geradas e desative as que parecerem pouco confiáveis. Este passo é opcional, já que o Potato só mantém, de qualquer forma, as funções acima do limiar de precisão que você configurou.
Passo 9: Anotação ativa (125-375 instâncias)
É aqui que você faz a maior parte da rotulagem. O Potato escolhe instâncias usando os grupos ponderados definidos acima em instance_selection:
low_confidence_weight(0.30): Avaliações em que a confiança do LLM é mais baixadisagreement_weight(0.25): Avaliações em que o LLM e as funções de rotulagem discordamdiversity_weight(0.20): Avaliações escolhidas para se espalhar pelo espaço de embeddings em vez de se agruparllm_predicted_weight(0.15): Avaliações rotuladas pelo LLM trazidas de volta para comparação humanarandom_weight(0.10): Avaliações aleatórias para calibração
Existem mais dois pesos, que aqui ficam no valor padrão de zero e por isso não contribuem com nada: edge_case_rule_weight, para instâncias que correspondem a uma regra de caso limítrofe descoberta, e cartography_weight, para instâncias cuja confiança oscila entre rodadas. O Potato verifica se os pesos somam 1.0 e registra um aviso quando não somam, mas usa os valores como estão escritos, então garanta você mesmo que a soma feche.
Você rotula essas instâncias em lotes de 25. Após cada lote, o Potato atualiza a estimativa de acurácia do LLM e decide se continua.
Trajetória típica:
- Lote 1-3 (75 instâncias): A acurácia sobe de 82% para 87%
- Lote 4-6 (150 instâncias): A acurácia chega a 90%
- Lote 7-10 (250 instâncias): A acurácia estabiliza em 91-92%
Se a concordância atingir o seu end_human_annotation_agreement, o Modo Solo avança para a rotulagem autônoma. Caso contrário, continua alternando entre revisão e refinamento.
Estimativa de tempo: 45-90 minutos no total, dependendo de quantos lotes forem necessários.
Passo 10: O laço de refinamento
Se a acurácia ainda estiver abaixo do limiar depois da rotulagem ativa, o Potato roda mais uma rodada do laço de refinamento:
- O LLM re-rotula o conjunto de dados completo com as diretrizes atualizadas e mais exemplos few-shot
- O Potato recalcula a acurácia em relação a todos os rótulos humanos
- Ele encontra os novos padrões de confusão
- Ele refina as diretrizes de novo
Esta fase exige pouca intervenção. Você só precisa aprovar as mudanças nas diretrizes.
Resultado típico: A acurácia melhora 2-4% por rodada de refinamento.
Passo 11: Resolução de discordâncias
O Potato apresenta as instâncias mais controversas: casos em que o LLM, as funções de rotulagem e a análise de vizinhos mais próximos dão, cada um, respostas diferentes. Para cada instância, você vê:
- O texto da avaliação
- A previsão do LLM e sua confiança
- Os votos das funções de rotulagem
- Os 3 exemplos rotulados mais próximos com seus rótulos
- O raciocínio chain-of-thought do LLM
Esses são os casos difíceis, e seus rótulos aqui pesam mais do que em qualquer outro ponto do processo.
Estimativa de tempo: 20-30 minutos para 100-150 instâncias.
Passo 12: Síntese de casos limítrofes
O Potato gera avaliações sintéticas voltadas para os padrões de confusão restantes. Por exemplo, se o LLM ainda tem dificuldade com "avaliações neutras que mencionam comprar de novo", ele gera exemplos como:
"É um produto ok pelo preço. Talvez eu compre outro se entrar em promoção."
Você rotula esses exemplos sintéticos, e o Potato os adiciona ao contexto few-shot do LLM.
Estimativa de tempo: 10-15 minutos para 30 exemplos.
Passo 13: Revisão periódica
A esta altura, o LLM já rotulou a maior parte do conjunto de dados. O Potato ordena todos os rótulos dele por confiança e envia a você os de menor confiança em lotes de 25.
Confidence Escalation Progress:
Batch 1: 25 instances, 23/25 correct (92%)
Batch 2: 25 instances, 24/25 correct (96%)
Batch 3: 25 instances, 25/25 correct (100%)
-> Stopping: last 3 batches stable
Quando a acurácia para de se mover por três lotes seguidos, o Modo Solo trata os rótulos de alta confiança restantes como confiáveis. Note que isso é estabilidade, não perfeição. A execução acima para depois de 92%, 96% e 100% porque o número se estabilizou, não porque o último lote saiu sem erros.
Estimativa de tempo: 15-20 minutos.
Passo 14: Otimização do prompt
Esta fase roda sozinha. O Potato testa 8 variantes de prompt e mantém aquela com a maior pontuação F1 nos rótulos humanos que você acumulou:
Prompt Optimization Results:
Variant 1 (direct, 5 examples): F1=0.91
Variant 2 (CoT, 5 examples): F1=0.93
Variant 3 (direct, 10 examples): F1=0.92
Variant 4 (CoT, 10 examples): F1=0.94 <-- selected
Variant 5 (direct, 15 examples): F1=0.92
Variant 6 (CoT, 15 examples): F1=0.93
Variant 7 (self-consistency, 5x): F1=0.94
Variant 8 (self-consistency, 10x): F1=0.94
Em seguida, ele usa o melhor prompt em uma passagem final de re-rotulagem.
Passo 15: Validação final
O Potato separa 100 instâncias aleatórias rotuladas pelo LLM para você revisar. Você as rotula, e o Potato compara seus rótulos com os do LLM.
Final Validation:
Reviewed: 100 instances
LLM correct: 94/100 (94%)
Threshold: 93%
-> PASSED
Se o LLM superar o seu limiar, o projeto está concluído. Caso contrário, ele volta para a anotação ativa para mais uma rodada. Esse retorno é a única transição permitida a partir da validação final.
Estimativa de tempo: 10-15 minutos.
Resumo dos resultados
Ao final, o painel informa de onde vieram os rótulos. O Modo Solo não tem interface de linha de comando (ele roda dentro do servidor e é operado pelas próprias páginas), então esses dados são lidos na instância em execução, e não em um terminal:
Solo Mode Complete
==================
Dataset: 10,000 instances
Total human labels: 612
Seed: 50
Active labeling: 275
Disagreement exploration: 137
Edge case synthesis: 30
Confidence escalation: 75
Final validation: 45
LLM labels: 8,200 (accuracy: 94.1%)
LF labels: 1,800 (precision: 95.3%)
Unlabeled: 0
Final label distribution:
Positive: 4,823 (48.2%)
Neutral: 3,011 (30.1%)
Negative: 2,166 (21.7%)
Total human time: ~3.5 hours
Estimated multi-annotator cost (3x): ~$4,500
Solo Mode cost: ~$450 (API fees) + ~$175 (annotator time)
Savings: ~88%
A pessoa rotulou 612 de 10.000 instâncias, cerca de 6%. O LLM e as funções de rotulagem cuidaram do restante com mais de 94% de acurácia.
Exportando os resultados
O Modo Solo grava no mesmo armazenamento que qualquer outro projeto, então os rótulos saem pelo exportador comum:
python -m potato.export -c config.yaml -f jsonl -o ./export/Cada linha inclui o rótulo e sua origem:
{"id": "rev_001", "sentiment": "Positive", "source": "human", "confidence": 1.0}
{"id": "rev_002", "sentiment": "Neutral", "source": "llm", "confidence": 0.91}
{"id": "rev_003", "sentiment": "Negative", "source": "labeling_function", "confidence": 0.97}Para exportação em Parquet:
import pandas as pd
df = pd.read_parquet("output/exports/parquet/annotations.parquet")
print(df["sentiment"].value_counts())annotations.parquet tem uma linha por instância e anotador, com cada esquema de anotação achatado em sua própria coluna. Por isso você seleciona o esquema pelo nome, e não por uma coluna genérica value.
Garantia de qualidade: verificação híbrida
Para conjuntos de dados com qualidade de publicação, adicione um segundo anotador para revisar uma amostra. A documentação de origem do Modo Solo descreve as opções de verificação em mais detalhe.
O Modo Solo não tem um bloco de verificação próprio, então isso é uma segunda passagem comum: exporte os rótulos, passe-os de novo pelo Potato como um projeto normal com um revisor sobre uma amostra de 10% e calcule a concordância entre o revisor e os rótulos do Modo Solo como faria para quaisquer dois anotadores. (icl_labeling tem um bloco verification, mas ele pertence à rotulagem in-context, não ao Modo Solo.)
Solução de problemas
A acurácia do LLM estaciona abaixo do limiar
- Aumente a contagem de sementes: Tente 75-100 instâncias de semente em vez de 50
- Troque de LLM: Tente
claude-sonnet-4-20250514no lugar do GPT-4o (ou vice-versa) - Reduza o limiar: Se 93% não for alcançável, considere se 90% é aceitável para o seu caso de uso
- Verifique seus dados: Alguns conjuntos de dados são inerentemente ambíguos. Se a concordância entre humanos fosse de apenas 90%, não espere que o LLM faça melhor
A anotação ativa leva lotes demais
- Aumente o tamanho do lote: Mude
batch_sizede 25 para 50 - Ajuste os pesos dos grupos: Se a maioria das instâncias escaladas vem do grupo de baixa confiança, reduza
low_confidence_weighte aumentedisagreement_weightoudiversity_weight
As funções de rotulagem têm cobertura baixa
- Isso é normal para tarefas sem sinais lexicais fortes (por exemplo, detecção de sarcasmo, sentimento implícito)
- As funções de rotulagem funcionam melhor para padrões explícitos, baseados em palavras-chave
- O Modo Solo funciona mesmo sem funções de rotulagem. Nesse caso, o LLM cobre essas instâncias
Leitura complementar
- Documentação do Modo Solo: referência completa de configuração
- Aprendizado Ativo: o algoritmo de seleção subjacente
- Suporte de IA: configuração dos provedores de LLM
- Controle de Qualidade: opções adicionais de garantia de qualidade
- Exportação Parquet: exportação eficiente de dados