Skip to content

Contratos do motor de rotulagem

Os seis tipos de contrato que o motor de rotulagem testa contra rótulos humanos, do risco seletivo e dos intervalos PPI ao teste do anotador alternativo, e como cada um falha.

Um contrato é uma afirmação sobre os rótulos finais que o motor de rotulagem testa contra rótulos humanos em uma amostra aleatória. Cada contrato nomeia um esquema de anotação (schema) e tem uma confidence, 0.9 por padrão, que é a probabilidade de a afirmação valer. Uma confidence de 0.9 admite, portanto, 10% de chance de um contrato cumprido estar errado.

Os seis tipos fazem afirmações diferentes e servem a estudos diferentes:

TipoAfirmaçãoPara
selective_riskNo máximo error dos rótulos de máquina aceitos estão erradosConjuntos de dados e conjuntos de treino em que cada rótulo precisa ser utilizável
ppiUm intervalo para a prevalência de cada rótulo (ou para um escore médio) que é válido qualquer que seja a qualidade da máquinaRelatar taxas, como "12% dos posts são tóxicos [10.5, 13.6]"
no_worse_than_humanA máquina concorda com as pessoas pelo menos tanto quanto uma pessoa concordaSubstituir anotadores ou um juiz LLM
budget_firstO que um orçamento de rótulos humanos consegue comprarPlanejar antes de gastar
distributionalA distribuição de rótulos da máquina é próxima de como as pessoas se dividemTarefas subjetivas em que a discordância é um dado
threshold_legacyNenhuma, aceita acima de uma confiança fixaApenas configurações traduzidas

Nenhum desses contratos diz que os rótulos estão livres de erros. selective_risk limita a taxa de erro entre os rótulos aceitos, e cada contrato que testa as máquinas as mede contra as pessoas que rotularam a amostra.

Status do contrato

Todo contrato tem um de cinco status, exibido na página de administração, por potato label status e no certificado:

StatusSignificado
metO teste passou na cascata atual.
insufficientAinda não há rótulos humanos suficientes, com uma estimativa de quantos faltam. Quando essa estimativa passa do que resta para sortear no corpus, o status diz que a meta não é alcançável com este corpus.
infeasibleHá rótulos suficientes, mas nenhuma regra de aceitação passa, por exemplo porque a confiança da máquina não separa as respostas certas das erradas.
violatedAs auditorias dos rótulos aceitos mostram uma taxa de erro acima da meta (com features.drift, ligado por padrão).
staleUma fonte, um prompt ou o esquema mudou desde o último teste. Os rótulos aceitos aguardam em pending_recert.

Um rótulo de máquina só é aceito quando todos os contratos selective_risk e threshold_legacy do seu esquema estão cumpridos e o aceitam. Os contratos declaram o que os rótulos precisam satisfazer, então um contrato não cumprido bloqueia a aceitação em vez de ser ignorado, e o status, a página de administração e o certificado nomeiam o contrato que não foi cumprido. Quando nenhuma regra pode vigorar e nada mais está sendo sorteado (um contrato é inviável, a amostra de calibração terminou ou nada pôde ser projetado), os itens ainda sem rótulo vão para pessoas, dentro de budgets.human_labels.

Divisões dev e cert

O motor mantém separados os rótulos que escolhem uma regra e os rótulos que a testam. As solicitações de calibração são sorteadas ao acaso com uma probabilidade de inclusão registrada, são sempre cegas, e cada uma vai ao acaso para uma de duas divisões:

  • dev (humans.dev_fraction, metade por padrão) ajusta os calibradores e escolhe os limiares;
  • cert testa a regra escolhida, e nada mais a lê.

Inspeções

Cada novo teste de um contrato é feito em um nível mais rigoroso, então testar de novo à medida que os rótulos chegam não infla a confiança. A inspeção k recebe (1 - confidence) * 6 / (pi^2 k^2) do orçamento de erro, o que soma o orçamento inteiro ao longo de todas as inspeções possíveis, e a primeira inspeção recebe 61% dele.

  • As inspeções são contadas por contrato em todas as cascatas sob as quais ele foi testado, e um contrato renomeado mantém as inspeções do seu id antigo. Testar prompts ou modelos até um passar custa uma inspeção a cada vez. Voltar a uma cascata anterior também é uma nova inspeção, e o resultado anterior dela não é restaurado.
  • Testar de novo os mesmos dados não é uma nova inspeção. Os mesmos rótulos cert, as mesmas predições e a mesma regra escolhida em dev devolvem o resultado armazenado. Um teste que não pôde ser executado, por exemplo sem rótulos cert em uma classe, não gasta nada.
  • potato label certify testa novos rótulos cert e novas predições de uma vez, assim como os equivalentes em REST, MCP e SDK. Quando só os rótulos dev mudaram, ele devolve o resultado armazenado com uma nota de que dev agora escolhe outra regra, e --retest testa essa regra na inspeção seguinte.
  • O planejador certifica sozinho à medida que os rótulos chegam. Um contrato selective_risk cumprido continua cumprido para a sua cascata, e as auditorias o vigiam. Um contrato não cumprido é testado de novo quando seus rótulos crescem um quarto, e pelo menos 10. Os resultados de ppi, distributional e no_worse_than_human são estimativas, não testes de aprovação ou reprovação, então o planejador os reestima nos mesmos marcos e mais uma vez quando a amostra de calibração está completa.
  • Um rótulo cert editado é um dado novo. Quando um anotador muda a resposta, a edição não custa mais do que um rótulo novo. Se a edição volta a um estado já testado, o resultado daquele teste retorna. Se nenhum dos testes do resultado armazenado vê mais erros depois da edição, o resultado e a sua inspeção continuam valendo. Caso contrário, o planejador espera os rótulos crescerem um quarto a partir da primeira edição, para que uma rajada de correções vire um só teste, e enquanto isso os rótulos aceitos continuam aceitos, com uma nota no contrato. Quando não vêm mais rótulos, ele testa imediatamente, e um certify explícito testa na inspeção seguinte.

Rótulos que as pessoas deram depois de ver uma resposta de máquina (solicitações de verificação) e rótulos dados fora das solicitações do motor nunca certificam nem estimam nada. Eles podem treinar um modelo destilado.

selective_risk

selective_risk limita a fração dos rótulos de máquina aceitos que estão errados. A chave error é a maior taxa de erro tolerada entre os rótulos aceitos e é obrigatória:

yaml
- id: accuracy
  kind: selective_risk
  schema: sentiment
  error: 0.05          # required: largest tolerated error among accepted labels
  confidence: 0.9
  per_class: true      # test each predicted class separately
  tolerance: 0.5       # graded families only: loss at or below this counts as correct

A regra é um limiar de confiança para cada nível da cascata e, com per_class, para cada classe predita. Em todos os níveis menos o último, o limiar é escolhido em dev e testado uma vez em cert. O último nível tenta limiares a partir da escolha de dev em direção a valores mais permissivos, testando cada um por vez e parando no primeiro que falha. Esse procedimento é o Learn-then-Test de sequência fixa (Angelopoulos et al., 2025). Cada teste é um teste binomial unilateral de que o erro entre os rótulos aceitos está acima de error, com o nível dividido entre níveis da cascata e classes. Um nível que falha não aceita nada, e seus itens vão para pessoas.

O que conta como "correto" depende da família do esquema. A perda de cada família está na tabela, e um rótulo conta como correto quando sua perda é menor ou igual a tolerance:

Família do esquemaPerdatolerance padrão
Uma escolha entre N (radio, select)0 se for o mesmo rótulo0
Ordinal (likert)distância na escala / (pontos - 1)0
Contínuo (slider, number)distância / (max - min)0.05
Multirrótulo (multiselect)1 - sobreposição de Jaccard0
Regiões de imagem (image_annotation)1 - IoU média sobre as formas pareadas0.5
Segmentos de áudio/vídeo, temporal_grounding, tiered_annotation1 - IoU temporal média0.5
Objetos 3D (spatial_annotation)1 - IoU 3D média0.5
Traces de agentes (process_reward, trajectory_eval, ...)fração dos passos em comum rotulados de forma diferente0

As perdas para regiões, segmentos, objetos 3D e traces são as que o relatório de concordância em /admin/iaa usa, então uma máquina é pontuada contra uma pessoa do mesmo jeito que duas pessoas são pontuadas entre si. Esquemas de texto livre e pairwise ainda não têm família, e o certificado os lista como não suportados.

O teste exige que cada grupo testado de itens cert seja uma amostra uniforme. Um grupo cujos itens foram sorteados com probabilidades desiguais não é testado, e o resultado o nomeia.

No último nível, um limiar só é escolhido em dev onde o erro de dev é no máximo metade da meta e se espera que rótulos cert suficientes passem em um primeiro teste. A projeção de quantos rótulos ainda faltam conta só os limiares que poderiam ser escolhidos dessa forma. Quando cert já tem os rótulos que a projeção pediu e o teste ainda falha, a projeção seguinte usa a taxa de erro que dev e cert mostram juntos, não só a de dev. Quando o menor erro de dev está abaixo da meta mas acima da metade dela, nada é testado e nada é projetado. O resultado informa isso e nomeia o erro, já que mais rótulos só ajudam se o erro se revelar menor.

metrics.accepted_by_tier é a cobertura da regra sobre a população inteira, incluindo os itens de calibração, e não é uma contagem de rótulos de máquina entregues. A linha "Machine labels accepted, by source" do certificado é que conta esses rótulos.

A perda de traces compara só os passos que os dois lados rotularam, então uma pessoa que marcou alguns passos é comparada nesses passos. Passos que ninguém rotulou não são verificados, e uma pessoa que rotula só o passo 0 e concorda com o juiz ali conta como concordando com o rótulo do trace inteiro. Onde todos os passos precisam ser verificados, peça às pessoas que rotulem todos os passos.

ppi

ppi relata um intervalo para a prevalência de cada rótulo, ou para um escore médio, corrigido pelos erros da máquina:

yaml
- id: prevalence
  kind: ppi
  schema: sentiment
  estimand: prevalence   # or mean, for numeric scores
  by: language           # optional: an interval per value of this item field
  confidence: 0.95
  max_width: 0.05        # optional: met once every interval is at most this wide

A prediction-powered inference (Angelopoulos et al., 2023) corrige a estimativa da máquina com o erro dela na amostra rotulada por pessoas. O intervalo é válido qualquer que seja a qualidade da máquina. Uma boa máquina o deixa mais estreito do que só as pessoas conseguiriam, e uma máquina ruim não o deixa mais largo. Com probabilidades de inclusão iguais, o motor usa PPI++ com um peso ajustado, e com probabilidades desiguais (amostragem estratificada ou guiada por incerteza) usa o estimador de diferença de Horvitz-Thompson. O rótulo de máquina que ele usa é o que a cascata entregaria. O campo by é copiado dos itens quando eles são registrados. Sem max_width, o contrato é cumprido assim que tem rótulos suficientes para relatar.

no_worse_than_human

no_worse_than_human pergunta se a máquina concorda com as pessoas pelo menos tão frequentemente quanto uma pessoa concorda:

yaml
- id: replaces-a-person
  kind: no_worse_than_human
  schema: verdict
  epsilon: 0.1

O contrato executa o teste do anotador alternativo (Calderon et al., 2025). Deixando cada pessoa de fora por vez, ele testa se a máquina concorda com as pessoas restantes pelo menos tão frequentemente quanto a pessoa deixada de fora, com uma margem de epsilon. A máquina passa quando vence pelo menos metade das pessoas, com a taxa de falsas descobertas controlada entre as pessoas.

O teste precisa de itens rotulados por várias pessoas. Defina humans.overlap (a fração da amostra rotulada mais de uma vez) e humans.overlap_k (pessoas por item, pelo menos 3), e o teste precisa de pelo menos 3 anotadores com 30 itens cada. O contrato fica insufficient até ter isso. Use este contrato quando uma meta fixa de acurácia mediria sobretudo o ruído dos anotadores. Se duas pessoas cuidadosas concordam 85% das vezes, não há como mostrar que algum rotulador está 95% "certo".

budget_first

budget_first projeta o que um orçamento de rótulos humanos compra antes de você gastá-lo:

yaml
- id: plan
  kind: budget_first
  schema: sentiment
  human_labels: 500      # or human_usd, priced at the crowd reward

A projeção vem dos rótulos dev coletados até o momento. Para cada meta de erro em uma grade, ela dá a fração do corpus que as máquinas poderiam ser certificadas para rotular com esse orçamento e a largura que cada intervalo de prevalência teria. O contrato fica met quando há rótulos dev suficientes para projetar. Ele não promete nada sobre os rótulos, o que selective_risk e ppi fazem quando os rótulos chegam.

distributional

distributional compara a distribuição de rótulos da máquina com a forma como as pessoas se dividem, para tarefas subjetivas em que as pessoas discordam por motivos que fazem parte dos dados:

yaml
- id: disagreement
  kind: distributional
  schema: offensiveness
  max_distance: 0.15     # optional
  groups_by: age_band    # optional: a prestudy question whose answer groups the annotators

Cada item rotulado por várias pessoas (humans.distribution_k, 5 por padrão) tem uma distribuição de rótulos humanos. O contrato relata a distância de Jensen-Shannon média entre a distribuição da máquina e a das pessoas, com um intervalo bootstrap. Ele também relata um teto de ruído, a mesma distância entre duas metades aleatórias das pessoas em cada item. Uma máquina mais próxima das pessoas do que elas estão umas das outras está tão próxima quanto os dados permitem.

A distribuição da máquina são as probabilidades dela quando a fonte as fornece (modelos de decisão, k_sample, logprob), ou o rótulo dela como vetor one-hot. O contrato é cumprido quando a extremidade superior do intervalo é no máximo max_distance ou, sem max_distance, quando há 20 itens rotulados por 3 ou mais pessoas. Quando a extremidade inferior do intervalo fica acima de max_distance, ele é infeasible, já que mais itens só estreitam o intervalo em torno de uma distância grande demais.

Com groups_by, os mesmos números são relatados por grupo de anotadores. A distribuição de cada grupo em um item é construída só com as pessoas daquele grupo, lidas das respostas delas à pergunta do pré-estudo indicada, e, se ninguém respondeu à pergunta, o contrato informa isso.

threshold_legacy

threshold_legacy aceita rótulos de máquina acima de uma confiança fixa e não executa nenhum teste estatístico:

yaml
- id: old-rule
  kind: threshold_legacy
  schema: sentiment
  threshold: 0.8

potato label migrate-config grava este contrato para icl_labeling, no antigo confidence_threshold, para que uma configuração traduzida se comporte como antes, e você também pode escrevê-lo à mão. O certificado marca esses rótulos como não certificados e relata o erro medido deles nos rótulos de calibração, e a exportação lhes dá o status accepted_uncertified.

Resultados dos estudos de exemplo

Os três estudos de exemplo em examples/labeling-engine/ foram executados com as fontes de LLM, de juiz e de visão apontadas para o Gemma 12B em um servidor vLLM, em vez dos modelos do Ollama que as configurações publicadas usam. O README de cada exemplo mostra o bloco de fonte que foi alterado, e com os padrões do Ollama os números serão diferentes.

  • Sentimento em texto (481 resenhas, Gemma 12B com confiança por logprob como último nível). selective_risk a 10% e 0.9 foi cumprido com 165 rótulos humanos, e 316 rótulos de máquina foram aceitos. O erro medido deles contra os rótulos verdadeiros foi de 7,6%, e os intervalos PPI cobriram a prevalência verdadeira dos três rótulos.
  • Imagens (128 imagens do COCO, YOLOv8n e Gemma 12B como modelo de visão). Um rótulo de presença de pessoa foi certificado a 10%. O contrato das caixas ficou insufficient, porque as caixas do YOLOv8n estavam erradas em 32% das imagens dev com IoU 0.5.
  • Traces de agentes (288 traces, Gemma 12B como juiz). O juiz acertou em 80% dos traces, mas sua confiança foi 1.0 o tempo todo, então selective_risk foi inviável. O teste do anotador alternativo ficou insuficiente, com a máquina em 0.82 contra 0.93 das pessoas. A PPI estimou o sucesso da tarefa em 0.66 [0.57, 0.76], quando o valor verdadeiro era 0.60 e o juiz sozinho dizia 0.76, 16 pontos acima.

Leitura adicional

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

Referências

  1. Angelopoulos, A. N., Bates, S., Candès, E. J., et al. (2025). Learn then test: Calibrating predictive algorithms to achieve risk control. The Annals of Applied Statistics. https://doi.org/10.1214/24-AOAS1998
  2. Angelopoulos, A. N., Bates, S., Fannjiang, C., et al. (2023). Prediction-powered inference. Science, 382(6671). https://doi.org/10.1126/science.adi6000
  3. Angelopoulos, A. N., Duchi, J. C., and Zrnic, T. (2023). PPI++: Efficient prediction-powered inference. arXiv. https://arxiv.org/abs/2311.01453
  4. Calderon, N., Reichart, R., and Dror, R. (2025). The alternative annotator test for LLM-as-a-judge: How to statistically justify replacing human annotators with LLMs. Proceedings of ACL 2025. https://aclanthology.org/2025.acl-long.782/