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 inicial, deixe um LLM rotular o resto e use as verificações de acurácia para decidir quando 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 o que quer que o LLM não tenha certeza.
Este tutorial percorre todo o processo.
O que você vai precisar
- Potato 2.3.0+ com os extras do Modo Solo:
pip install potato-annotation[solo] - Uma chave de API da OpenAI ou da Anthropic (para o componente LLM)
- Seu conjunto de dados em formato JSONL
- Um anotador com conhecimento (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
llm:
endpoint_type: openai
model: "gpt-4o"
api_key: ${OPENAI_API_KEY}
temperature: 0.1
max_tokens: 64
# Quality targets
seed_count: 50
accuracy_threshold: 0.93
confidence_threshold: 0.85
# Phase-specific settings
phases:
seed:
count: 50
selection: diversity
embedding_model: "all-MiniLM-L6-v2"
calibration:
batch_size: 200
holdout_fraction: 0.2
labeling_functions:
enabled: true
max_functions: 15
min_precision: 0.92
min_coverage: 0.01
active_labeling:
batch_size: 25
strategy: hybrid
max_batches: 15
refinement_loop:
max_iterations: 3
improvement_threshold: 0.02
disagreement_exploration:
max_instances: 150
show_llm_reasoning: true
show_nearest_neighbors: 3
edge_case_synthesis:
enabled: true
count: 30
confidence_escalation:
escalation_budget: 150
batch_size: 25
stop_when_stable: true
prompt_optimization:
enabled: true
candidates: 8
metric: f1_macro
final_validation:
sample_size: 100
min_accuracy: 0.93
# Instance prioritization
prioritization:
pools:
- name: uncertain
weight: 0.30
- name: disagreement
weight: 0.25
- name: boundary
weight: 0.20
- name: novel
weight: 0.10
- name: error_pattern
weight: 0.10
- name: random
weight: 0.05
# --- 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"
parquet_export:
enabled: true
output_dir: "output/parquet/"Passo 3: Inicie o servidor
potato start config.yaml -p 8000Abra http://localhost:8000 e faça login. O painel do Modo Solo aparece, mostrando que você está na Fase 1: Anotação de Sementes.
Passo 4: Fase 1 -- Anotação de Sementes (50 Instâncias)
O Potato escolheu 50 avaliações diversas usando clusterização baseada em embeddings. Elas não são aleatórias; foram selecionadas 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. Reserve seu tempo e mantenha a consistência.
Estimativa de tempo: 15-25 minutos, a 20-30 segundos por instância.
Quando você terminar a 50ª instância, o Potato avança sozinho para a Fase 2.
Passo 5: Fase 2 -- Calibração Inicial do LLM
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, 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 de 1 a 2 minutos, dependendo do provedor do 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: Fase 3 -- 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 para a principal fraqueza do LLM aqui: ele continua promovendo avaliações neutras a positivas. Essa é 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: Fase 4 -- Refinamento das Diretrizes
Com base na análise de confusão, o Potato redige diretrizes refinadas para o LLM e as mostra lado a lado: o prompt atual de um lado, e as edições específicas que ele propõe a partir dos padrões de erro do outro.
Por exemplo, o Potato pode sugerir adicionar:
"Reviews that describe a product as 'fine', 'okay', or 'decent' without strong emotion should be labeled Neutral, even if they mention buying again."
Passe por cada edição sugerida e aprove, modifique ou rejeite. Você também pode escrever suas próprias clarificações.
Estimativa de tempo: 5-10 minutos.
Passo 8: Fase 5 -- Geração de 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 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 qualquer uma que pareça não confiável. Este passo é opcional, já que o Potato só mantém funções acima do limiar de precisão que você configurou.
Passo 9: Fase 6 -- Rotulagem Ativa (125-375 Instâncias)
É aqui que você faz a maior parte da sua rotulagem. O Potato escolhe instâncias usando o sistema de priorização de seis grupos:
- Incerto (30%): Avaliações em que a confiança do LLM está abaixo de 85%
- Discordância (25%): Avaliações em que o LLM e as funções de rotulagem dão rótulos diferentes
- Fronteira (20%): Avaliações próximas da fronteira de decisão no espaço de embeddings
- Novo (10%): Avaliações diferentes de tudo o que você já rotulou
- Padrão de erro (10%): Avaliações que correspondem a padrões de confusão conhecidos (por exemplo, positivo morno)
- Aleatório (5%): Avaliações aleatórias para calibração
Você rotula essas 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 acurácia atingir 93% (seu limiar), o Modo Solo pula direto para a Fase 10. Caso contrário, segue para a Fase 7.
Estimativa de tempo: 45-90 minutos no total, dependendo de quantos lotes forem necessários.
Passo 10: Fase 7 -- Laço de Refinamento Automatizado
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 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 é quase toda automática. Você só precisa aprovar as mudanças nas diretrizes.
Resultado típico: A acurácia melhora de 2 a 4% por rodada de refinamento.
Passo 11: Fase 8 -- Exploração de Discordância
O Potato apresenta as instâncias mais contenciosas: casos em que o LLM, as funções de rotulagem e a análise de vizinhos mais próximos dão respostas diferentes. Para cada instância, você vê:
- O texto da avaliação
- A previsão e a confiança do LLM
- Os votos das funções de rotulagem
- Os 3 exemplos rotulados mais próximos com seus rótulos
- O raciocínio em cadeia de pensamento do LLM
Esses são casos genuinamente difíceis, e seus rótulos aqui valem mais do que quaisquer outros em todo o processo.
Estimativa de tempo: 20-30 minutos para 100-150 instâncias.
Passo 12: Fase 9 -- Síntese de Casos Limítrofes
O Potato gera avaliações sintéticas que visam 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:
"It's an okay product for the price. I might get another one if there's a sale."
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: Fase 10 -- Escalonamento de Confiança em Cascata
A esta altura, o LLM já rotulou a maior parte do conjunto de dados. O Potato classifica todos os seus rótulos por confiança e lhe envia 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 três lotes seguidos voltam com o LLM acertando tudo, o Modo Solo trata os rótulos de alta confiança restantes como confiáveis.
Estimativa de tempo: 15-20 minutos.
Passo 14: Fase 11 -- Otimização de Prompt
Esta fase roda sozinha. O Potato testa 8 variantes de prompt e mantém aquela com a maior pontuação F1 nos seus rótulos humanos acumulados:
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 para uma passagem final de re-rotulagem.
Passo 15: Fase 12 -- Validação Final
O Potato extrai 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 conjunto de dados está pronto. Caso contrário, o Modo Solo volta para a Fase 6 para mais uma rodada de rotulagem ativa.
Estimativa de tempo: 10-15 minutos.
Resumo dos Resultados
Depois de todas as 12 fases, confira as estatísticas finais:
python -m potato.solo status --config config.yamlSolo 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 94%+ de acurácia.
Exportando os Resultados
Exporte o conjunto de dados final rotulado:
python -m potato.solo export --config config.yaml --output final_labels.jsonlCada 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/parquet/annotations.parquet")
print(df["value"].value_counts())Garantia de Qualidade: Verificação Híbrida
Para conjuntos de dados em 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.
solo_mode:
verification:
enabled: true
sample_fraction: 0.10
annotator: "reviewer_1"Isso envia 1.000 instâncias aleatórias a um segundo anotador. Você pode então calcular a concordância entre anotadores entre os rótulos do Modo Solo e os rótulos do revisor.
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 humano-humano seria de apenas 90%, não espere que o LLM faça melhor
A Fase 6 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 "incerto", reduza seu peso e aumente "discordância" e "padrão de erro"
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 ainda funciona sem funções de rotulagem -- o LLM compensa a diferença
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 do provedor de LLM
- Controle de Qualidade -- opções adicionais de garantia de qualidade
- Exportação Parquet -- exportação eficiente de dados