Skip to content

Modo Solo

Execute um pipeline completo de anotação sozinho no Potato — um fluxo LLM-humano de 12 fases que cobre semeadura, rotulagem, arbitragem e refinamento sem uma equipe de anotação completa.

Novo na v2.3.0

Projetos de anotação tradicionais exigem múltiplos anotadores, cálculo de concordância entre anotadores, rodadas de arbitragem e uma sobrecarga considerável de coordenação. Para muitas equipes de pesquisa, esse é o gargalo principal: não a interface de anotação, mas a logística de contratar, treinar e gerenciar uma equipe.

O Modo Solo substitui o paradigma de múltiplos anotadores por um único especialista humano colaborando com um LLM. O humano fornece rótulos de alta qualidade em um subconjunto pequeno e selecionado de forma estratégica. O LLM aprende com esses rótulos, propõe rótulos para o restante, e o humano revisa apenas os casos em que o LLM está incerto ou provavelmente errado. Um fluxo de trabalho de 12 fases orquestra esse processo automaticamente.

Em benchmarks internos, o Modo Solo alcançou mais de 95% de concordância com pipelines completos de múltiplos anotadores exigindo apenas 10 a 15% do total de rótulos humanos.

O fluxo de trabalho de 12 fases

O Modo Solo avança por 12 fases. O sistema progride automaticamente com base em limiares configuráveis, embora você também possa acionar as transições manualmente a partir do painel de administração.

Fase 1: Anotação semente

O anotador humano rotula um conjunto semente inicial. O Potato seleciona instâncias diversas e representativas usando agrupamento baseado em embeddings para maximizar a cobertura da distribuição dos dados.

Tamanho padrão da semente: 50 instâncias (configurável via seed_count)

Fase 2: Calibração inicial do LLM

O LLM recebe as anotações semente como exemplos few-shot e rotula um lote de calibração. O Potato compara as previsões do LLM com rótulos semente reservados para estabelecer uma acurácia de referência.

Fase 3: Análise de confusão

O Potato identifica padrões sistemáticos de discordância entre humano e LLM. Ele constrói uma matriz de confusão e destaca os tipos de erro mais comuns (por exemplo, "o LLM rotula neutro como positivo 40% das vezes").

Fase 4: Refinamento das diretrizes

Com base na análise de confusão, o Potato gera diretrizes de anotação refinadas para o LLM. O humano revisa e edita essas diretrizes antes que sejam aplicadas. Esta é uma etapa interativa em que o anotador pode adicionar exemplos, esclarecer casos extremos e ajustar definições de rótulos.

Fase 5: Geração de funções de rotulagem

Inspirado pelo framework ALCHEmist, o Potato gera funções de rotulagem programáticas a partir das anotações existentes. São regras simples baseadas em padrões (por exemplo, "se o texto contém 'excelente' e nenhuma negação, rotule como positivo") que podem rotular instâncias fáceis com alta precisão, reservando o esforço humano e do LLM para casos mais difíceis.

Fase 6: Rotulagem ativa

O humano rotula instâncias adicionais selecionadas por aprendizado ativo. O Potato prioriza instâncias em que o LLM está mais incerto, em que as funções de rotulagem discordam, ou em que a instância está distante dos exemplos de treinamento existentes no espaço de embeddings.

Fase 7: Ciclo de refinamento automatizado

O LLM rotula novamente todo o conjunto de dados com diretrizes atualizadas e exemplos few-shot. O Potato compara com todos os rótulos humanos e dispara outro ciclo de análise de confusão e refinamento de diretrizes se a acurácia estiver abaixo do limiar.

Fase 8: Exploração de discordâncias

O humano revisa todas as instâncias em que o LLM e as funções de rotulagem discordam. Estes são tipicamente os exemplos mais informativos e difíceis. Os rótulos do humano nesses casos têm o maior valor marginal.

Fase 9: Síntese de casos extremos

O Potato usa o LLM para gerar casos extremos sintéticos com base nos padrões de confusão identificados. O humano rotula esses exemplos sintéticos, que são então adicionados ao contexto de treinamento do LLM para melhorar o desempenho nos casos mais difíceis.

Fase 10: Escalonamento em cascata por confiança

O LLM atribui pontuações de confiança a cada instância restante não rotulada. As instâncias são escalonadas para o humano em ordem decrescente de dificuldade (ordem crescente de confiança). O humano rotula até que as métricas de qualidade se estabilizem.

Fase 11: Otimização de prompts

Inspirado pelo DSPy, o Potato executa otimização automatizada de prompts usando os rótulos humanos acumulados como conjunto de validação. Ele testa múltiplas variações de prompt (formulação das instruções, ordenação dos exemplos, cadeia de raciocínio vs. direto) e seleciona o prompt de melhor desempenho.

Fase 12: Validação final

O humano realiza uma revisão final de uma amostra aleatória das instâncias rotuladas pelo LLM. Se a acurácia atingir o limiar, o conjunto de dados está completo. Caso contrário, o sistema volta para a Fase 6.


Configuração

Início rápido

Uma configuração mínima do Modo Solo:

yaml
task_name: "Sentiment Classification"
task_dir: "."
 
data_files:
  - "data/reviews.jsonl"
 
item_properties:
  id_key: id
  text_key: text
 
solo_mode:
  enabled: true
 
  # LLM provider
  llm:
    endpoint_type: openai
    model: "gpt-4o"
    api_key: ${OPENAI_API_KEY}
 
  # Basic thresholds
  seed_count: 50
  accuracy_threshold: 0.92
  confidence_threshold: 0.85
 
annotation_schemes:
  - annotation_type: radio
    name: sentiment
    labels:
      - Positive
      - Neutral
      - Negative
 
output_annotation_dir: "output/"
output_annotation_format: "jsonl"

Referência completa de configuração

yaml
solo_mode:
  enabled: true
 
  # LLM configuration
  llm:
    endpoint_type: openai        # openai, anthropic, ollama, vllm
    model: "gpt-4o"
    api_key: ${OPENAI_API_KEY}
    temperature: 0.1             # low temperature for consistency
    max_tokens: 256
 
  # Phase control
  phases:
    seed:
      count: 50                  # number of seed instances
      selection: diversity        # diversity, random, or stratified
      embedding_model: "all-MiniLM-L6-v2"
 
    calibration:
      batch_size: 100
      holdout_fraction: 0.2      # fraction of seed used for validation
 
    confusion_analysis:
      min_samples: 30
      significance_threshold: 0.05
 
    guideline_refinement:
      auto_suggest: true         # LLM suggests guideline edits
      require_approval: true     # human must approve changes
 
    labeling_functions:
      enabled: true
      max_functions: 20
      min_precision: 0.90        # only keep high-precision rules
      min_coverage: 0.01         # must cover at least 1% of data
 
    active_labeling:
      batch_size: 25
      strategy: uncertainty       # uncertainty, diversity, or hybrid
      max_batches: 10
 
    refinement_loop:
      max_iterations: 3
      improvement_threshold: 0.02
 
    disagreement_exploration:
      max_instances: 200
      sort_by: confidence_gap
 
    edge_case_synthesis:
      enabled: true
      count: 50
      diversity_weight: 0.3
 
    confidence_escalation:
      escalation_budget: 200     # max instances to escalate
      batch_size: 25
      stop_when_stable: true     # stop if last batch accuracy is 100%
 
    prompt_optimization:
      enabled: true
      candidates: 10             # number of prompt variants to try
      metric: f1_macro
      search_strategy: bayesian  # bayesian, grid, or random
 
    final_validation:
      sample_size: 100
      min_accuracy: 0.92
      fallback_phase: 6          # go back to Phase 6 if validation fails
 
  # Instance prioritization across phases
  prioritization:
    pools:
      - name: uncertain
        weight: 0.30
        description: "LLM confidence below threshold"
      - name: disagreement
        weight: 0.25
        description: "LLM and labeling functions disagree"
      - name: boundary
        weight: 0.20
        description: "Near decision boundary in embedding space"
      - name: novel
        weight: 0.10
        description: "Far from all existing labeled examples"
      - name: error_pattern
        weight: 0.10
        description: "Matches known confusion patterns"
      - name: random
        weight: 0.05
        description: "Random sample for calibration"

Principais recursos

Análise de confusão

Após cada rodada de rotulagem, o Potato constrói uma matriz de confusão entre os rótulos humanos e os do LLM. O painel de administração exibe:

  • Precisão, revocação e F1 por classe a partir da perspectiva do LLM
  • Pares de confusão mais comuns (por exemplo, "neutro classificado erroneamente como positivo: 23 instâncias")
  • Instâncias de exemplo para cada par de confusão
  • Gráficos de tendência que mostram a melhoria ao longo das rodadas de refinamento

Acesse a análise de confusão programaticamente:

bash
python -m potato.solo confusion --config config.yaml

Saída:

text
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

Ciclo de refinamento automatizado

O ciclo de refinamento itera entre rotulagem pelo LLM, análise de confusão e atualizações das diretrizes. Cada iteração:

  1. O LLM rotula todo o conjunto de dados com as diretrizes atuais
  2. O Potato compara com todos os rótulos humanos disponíveis
  3. Se a acurácia estiver abaixo do limiar, a análise de confusão é executada
  4. O LLM propõe edições nas diretrizes com base nos padrões de erro
  5. O humano revisa e aprova as edições
  6. O ciclo se repete (até max_iterations)
yaml
solo_mode:
  llm:
    endpoint_type: anthropic
    model: "claude-sonnet-4-20250514"
    api_key: ${ANTHROPIC_API_KEY}
 
  phases:
    refinement_loop:
      max_iterations: 3
      improvement_threshold: 0.02    # stop if improvement is less than 2%

Funções de rotulagem (inspiradas no ALCHEmist)

O Potato gera funções de rotulagem leves a partir de padrões observados nas anotações humanas. Não são chamadas ao LLM; são regras rápidas e determinísticas.

Exemplo de funções de rotulagem geradas:

python
# 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

Configure o comportamento das funções de rotulagem:

yaml
solo_mode:
  phases:
    labeling_functions:
      enabled: true
      max_functions: 20
      min_precision: 0.90
      min_coverage: 0.01
      types:
        - keyword_match
        - regex_pattern
        - length_threshold
        - embedding_cluster

Explorador de discordâncias

O explorador de discordâncias apresenta instâncias em que sinais diferentes entram em conflito. Para cada instância, o anotador vê:

  • O rótulo previsto pelo LLM e a confiança
  • Os votos das funções de rotulagem (se houver)
  • Os vizinhos rotulados mais próximos no espaço de embeddings
  • O texto/conteúdo bruto

Esta é a atividade de anotação de maior valor: cada rótulo resolve uma ambiguidade genuína.

yaml
solo_mode:
  phases:
    disagreement_exploration:
      max_instances: 200
      sort_by: confidence_gap     # or "lf_disagreement" or "random"
      show_llm_reasoning: true    # display LLM's chain-of-thought
      show_nearest_neighbors: 3   # show 3 nearest labeled examples

Escalonamento em cascata por confiança

Depois que a maior parte do conjunto de dados é rotulada pelo LLM, o Potato ordena todas as instâncias rotuladas pelo LLM por confiança e escalona as menos confiáveis para o humano. Isso continua em lotes até que a qualidade se estabilize.

yaml
solo_mode:
  phases:
    confidence_escalation:
      escalation_budget: 200
      batch_size: 25
      stop_when_stable: true
      stability_window: 3        # stop if last 3 batches are all correct

Priorização de instâncias com múltiplos sinais

Em todas as fases que envolvem rotulagem humana, o Potato usa um sistema ponderado de pools para selecionar as instâncias mais informativas. Seis pools alimentam uma fila de prioridade unificada:

yaml
solo_mode:
  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
  • uncertain: instâncias em que a confiança do LLM está abaixo de confidence_threshold
  • disagreement: instâncias em que o LLM e as funções de rotulagem produzem rótulos diferentes
  • boundary: instâncias próximas da fronteira de decisão no espaço de embeddings
  • novel: instâncias distantes de qualquer exemplo rotulado existente
  • error_pattern: instâncias que correspondem a padrões de confusão conhecidos de rodadas anteriores
  • random: uma pequena amostra aleatória para manter a calibração e detectar pontos cegos

Síntese de casos extremos

O Potato usa o LLM para gerar exemplos sintéticos que visam fraquezas conhecidas:

yaml
solo_mode:
  phases:
    edge_case_synthesis:
      enabled: true
      count: 50
      diversity_weight: 0.3
      confusion_pairs:            # focus on these error types
        - ["neutral", "positive"]
        - ["negative", "neutral"]

O LLM gera exemplos que são ambíguos entre os pares de rótulos especificados. O humano os rotula, e esses rótulos são adicionados ao contexto few-shot para as rodadas subsequentes de rotulagem do LLM.

Otimização de prompts (inspirada no DSPy)

Na Fase 11, o Potato executa otimização automatizada de prompts para encontrar o melhor formato de instrução para o LLM:

yaml
solo_mode:
  phases:
    prompt_optimization:
      enabled: true
      candidates: 10
      metric: f1_macro
      search_strategy: bayesian
      variations:
        - instruction_style      # formal vs. conversational
        - example_ordering       # random, by-class, by-difficulty
        - reasoning_mode         # direct, chain-of-thought, self-consistency
        - example_count          # 3, 5, 10, 15 few-shot examples

Acompanhamento do progresso

O painel de administração mostra o progresso do Modo Solo em tempo real:

  • Fase atual e progresso dentro de cada fase
  • Rótulos humanos concluídos vs. orçamento total
  • Acurácia do LLM ao longo do tempo (por rodada)
  • Cobertura e precisão das funções de rotulagem
  • Histograma da distribuição de confiança
  • Tempo estimado até a conclusão

Acesse pela linha de comando:

bash
python -m potato.solo status --config config.yaml
text
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

Quando usar o Modo Solo vs. múltiplos anotadores tradicional

Use o Modo Solo quando:

  • Você tem um especialista de domínio que pode fornecer rótulos de alta qualidade
  • O orçamento ou a logística impedem a contratação de múltiplos anotadores
  • A tarefa tem categorias claras e bem definidas
  • Você precisa rotular um conjunto de dados grande (mais de 1.000 instâncias)
  • A velocidade importa mais do que medir a concordância entre anotadores

Use múltiplos anotadores tradicional quando:

  • Você precisa de estatísticas de concordância entre anotadores para publicação
  • A tarefa é altamente subjetiva (por exemplo, ofensividade, humor)
  • Você precisa estudar os padrões de discordância entre anotadores
  • Requisitos regulatórios exigem múltiplos anotadores independentes
  • O espaço de rótulos é complexo ou está em evolução (as diretrizes de anotação ainda estão sendo desenvolvidas)

Abordagem híbrida: use o Modo Solo para a rotulagem inicial em massa e, em seguida, atribua um segundo anotador a uma amostra aleatória de 10 a 20% para calcular estatísticas de concordância. Isso lhe dá a eficiência do Modo Solo com a garantia de qualidade da verificação por múltiplos anotadores.

yaml
solo_mode:
  enabled: true
  # ... solo mode config ...
 
  # Hybrid: assign verification sample to second annotator
  verification:
    enabled: true
    sample_fraction: 0.15
    annotator: "reviewer_1"

Leitura adicional

Para detalhes de implementação, consulte a documentação de origem.