Contratti del motore di etichettatura
I sei tipi di contratto che il motore di etichettatura testa sulle etichette umane, dal rischio selettivo e dagli intervalli PPI al test dell'annotatore alternativo, e come fallisce ciascuno.
Un contratto è un'affermazione sulle etichette finali che il motore di etichettatura testa sulle etichette umane di un campione casuale. Ogni contratto nomina uno schema di annotazione (schema) e ha una confidence, 0,9 per default, che è la probabilità che l'affermazione sia vera. Una confidence di 0,9 ammette quindi una probabilità del 10% che un contratto soddisfatto sia sbagliato.
I sei tipi fanno affermazioni diverse e si adattano a studi diversi:
| Tipo | Affermazione | Per |
|---|---|---|
selective_risk | Al massimo una quota error delle etichette automatiche accettate è sbagliata | Dataset e training set in cui ogni etichetta deve essere utilizzabile |
ppi | Un intervallo per la prevalenza di ogni etichetta (o per un punteggio medio) valido qualunque sia la qualità della macchina | Riportare tassi, come "il 12% dei post è tossico [10,5; 13,6]" |
no_worse_than_human | La macchina concorda con le persone almeno quanto concorda una persona | Sostituire annotatori o un giudice LLM |
budget_first | Che cosa si può ottenere con un budget di etichette umane | Pianificare prima di spendere |
distributional | La distribuzione delle etichette della macchina è vicina al modo in cui le persone si dividono | Task soggettivi in cui il disaccordo è un dato |
threshold_legacy | Nessuna, accetta sopra una confidenza fissa | Solo configurazioni convertite |
Nessuno di questi contratti dice che le etichette sono prive di errori. selective_risk limita il tasso di errore tra le etichette accettate, e ogni contratto che testa le macchine le misura rispetto alle persone che hanno etichettato il campione.
Stato dei contratti
Ogni contratto ha uno di cinque stati, mostrato nella pagina di amministrazione, da potato label status e nel certificato:
| Stato | Significato |
|---|---|
met | Il test è passato sulla cascata attuale. |
insufficient | Non ci sono ancora abbastanza etichette umane, con una stima di quante ne servono ancora. Quando quella stima supera ciò che resta da campionare nel corpus, lo stato dice che l'obiettivo non è raggiungibile con questo corpus. |
infeasible | Le etichette bastano, ma nessuna regola di accettazione passa, per esempio perché la confidenza della macchina non separa le risposte giuste da quelle sbagliate. |
violated | Gli audit delle etichette accettate mostrano un tasso di errore superiore all'obiettivo (con features.drift, attivo per default). |
stale | Una fonte, un prompt o lo schema sono cambiati dall'ultimo test. Le etichette accettate attendono in pending_recert. |
Un'etichetta automatica viene accettata solo quando ogni contratto selective_risk e threshold_legacy sul suo schema è soddisfatto e la accetta. I contratti dichiarano che cosa devono soddisfare le etichette, quindi un contratto non soddisfatto blocca l'accettazione invece di essere saltato, e lo stato, la pagina di amministrazione e il certificato nominano il contratto non soddisfatto. Quando nessuna regola può essere in vigore e non si sta campionando altro (un contratto è infeasible, il campione di calibrazione è completo o non è stato possibile proiettare nulla), gli item ancora senza etichetta vanno alle persone, entro budgets.human_labels.
Partizioni dev e cert
Il motore tiene separate le etichette che scelgono una regola da quelle che la testano. Le richieste di calibrazione vengono estratte a caso con una probabilità di inclusione registrata, sono sempre in cieco, e ciascuna finisce a caso in una di due partizioni:
- dev (
humans.dev_fraction, metà per default) adatta i calibratori e sceglie le soglie; - cert testa la regola scelta, e nient'altro la legge.
Analisi successive
Ogni nuovo test di un contratto viene eseguito a un livello più severo, quindi testare di nuovo man mano che arrivano le etichette non gonfia la confidenza. L'analisi k riceve (1 - confidence) * 6 / (pi^2 k^2) del budget di errore, che sommato su tutte le analisi possibili dà l'intero budget, e la prima analisi ne riceve il 61%.
- Le analisi si contano per contratto, su tutte le cascate con cui è stato testato, e un contratto rinominato conserva le analisi del suo vecchio id. Provare prompt o modelli finché uno non passa costa un'analisi ogni volta. Anche tornare a una cascata precedente è una nuova analisi, e il suo risultato precedente non viene ripristinato.
- Ritestare gli stessi dati non è una nuova analisi. Le stesse etichette cert, le stesse predizioni e la stessa regola scelta su dev restituiscono il risultato memorizzato. Un test che non è stato possibile eseguire, per esempio perché una classe non ha etichette cert, non consuma nulla.
potato label certifytesta insieme le nuove etichette cert e le nuove predizioni, come i suoi equivalenti REST, MCP e SDK. Quando sono cambiate solo le etichette dev, restituisce il risultato memorizzato con una nota che dice che dev ora sceglie un'altra regola, e--retesttesta quella regola all'analisi successiva.- Il planner certifica da solo man mano che arrivano le etichette. Un contratto
selective_risksoddisfatto resta soddisfatto per la sua cascata, e gli audit lo sorvegliano. Un contratto non soddisfatto viene testato di nuovo quando le sue etichette sono cresciute di un quarto, e di almeno 10. I risultati dippi,distributionaleno_worse_than_humansono stime e non test superato/fallito, quindi il planner li ristima agli stessi traguardi e un'ultima volta quando il campione di calibrazione è completo. - Un'etichetta cert modificata è un dato nuovo. Quando un annotatore cambia la sua risposta, la modifica non costa più di una nuova etichetta. Se la modifica riporta a uno stato già testato, torna il risultato di quel test. Se nessuno dei test del risultato memorizzato vede più errori dopo la modifica, il risultato e la sua analisi restano validi. Altrimenti il planner aspetta che le etichette crescano di un quarto a partire dalla prima modifica, così una raffica di correzioni diventa un solo test, e nel frattempo le etichette accettate restano accettate con una nota sul contratto. Quando non arriveranno altre etichette, testa subito, e una certificazione esplicita testa all'analisi successiva.
Le etichette che le persone hanno dato dopo aver visto una risposta della macchina (richieste di verifica) e quelle date al di fuori delle richieste del motore non certificano né stimano mai nulla. Possono servire ad addestrare un modello distillato.
selective_risk
selective_risk limita la quota di etichette automatiche accettate che sono sbagliate. La chiave error è il tasso di errore massimo tollerato tra le etichette accettate ed è obbligatoria:
- 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 correctLa regola è una soglia di confidenza per ogni livello della cascata e, con per_class, per ogni classe predetta. Per tutti i livelli tranne l'ultimo, la soglia viene scelta su dev e testata una volta su cert. L'ultimo livello prova soglie che vanno dalla scelta di dev verso soglie più permissive, testandole una alla volta e fermandosi alla prima che fallisce. Questa procedura è il Learn-then-Test a sequenza fissa (Angelopoulos et al., 2025). Ogni test è un test binomiale unilaterale dell'ipotesi che l'errore tra le etichette accettate sia superiore a error, con il livello suddiviso tra livelli della cascata e classi. Un livello che fallisce non accetta nulla, e i suoi item vanno alle persone.
Che cosa conta come "corretto" dipende dalla famiglia dello schema. La tabella riporta la loss di ogni famiglia, e un'etichetta conta come corretta quando la sua loss è pari o inferiore a tolerance:
| Famiglia di schemi | Loss | tolerance di default |
|---|---|---|
Scelta singola tra N (radio, select) | 0 se l'etichetta è la stessa | 0 |
Ordinale (likert) | distanza sulla scala / (punti - 1) | 0 |
Continua (slider, number) | distanza / (max - min) | 0.05 |
Multi-etichetta (multiselect) | 1 - sovrapposizione di Jaccard | 0 |
Regioni di immagine (image_annotation) | 1 - IoU media sulle forme abbinate | 0.5 |
Segmenti audio/video, temporal_grounding, tiered_annotation | 1 - IoU temporale media | 0.5 |
Oggetti 3D (spatial_annotation) | 1 - IoU 3D media | 0.5 |
Tracce degli agenti (process_reward, trajectory_eval, ...) | quota dei passi in comune etichettati diversamente | 0 |
Le loss per regioni, segmenti, oggetti 3D e tracce sono quelle che usa il report di accordo in /admin/iaa, quindi una macchina viene valutata rispetto a una persona come due persone vengono valutate l'una rispetto all'altra. Il testo libero e gli schemi pairwise non hanno ancora una famiglia, e il certificato li elenca come non supportati.
Il test richiede che ogni gruppo testato di item cert sia un campione uniforme. Un gruppo i cui item sono stati campionati con probabilità diverse non viene testato, e il risultato lo nomina.
Sull'ultimo livello, una soglia viene scelta su dev solo dove l'errore su dev è al massimo metà dell'obiettivo e ci si aspetta abbastanza etichette cert per superare un primo test. La proiezione di quante altre etichette servono conta solo le soglie che potrebbero essere scelte in questo modo. Quando cert ha già le etichette che la proiezione chiedeva e il test fallisce ancora, la proiezione successiva usa il tasso di errore che dev e cert mostrano insieme, non quello del solo dev. Quando l'errore minimo su dev è sotto l'obiettivo ma sopra la sua metà, non viene testato né proiettato nulla. Il risultato lo dice e nomina l'errore, perché altre etichette aiutano solo se l'errore risulta più basso.
metrics.accepted_by_tier è la copertura della regola sull'intera popolazione, item di calibrazione compresi, e non è un conteggio delle etichette automatiche consegnate. Quelle le conta la riga "Machine labels accepted, by source" del certificato.
La loss sulle tracce confronta solo i passi che entrambe le parti hanno etichettato, quindi una persona che ha marcato alcuni passi viene confrontata su quei passi. I passi che nessuno ha etichettato non vengono controllati, e una persona che etichetta solo il passo 0 e lì concorda con il giudice conta come concorde sull'intera etichetta della traccia. Dove ogni passo va controllato, chiedi alle persone di etichettarli tutti.
ppi
ppi riporta un intervallo per la prevalenza di ogni etichetta, o per un punteggio medio, corretto per gli errori della macchina:
- 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 wideLa prediction-powered inference (Angelopoulos et al., 2023) corregge la stima della macchina con il suo errore sul campione etichettato dalle persone. L'intervallo è valido qualunque sia la qualità della macchina. Una buona macchina lo rende più stretto di quanto potrebbero le sole persone, e una cattiva non lo rende più largo. Con probabilità di inclusione uguali il motore usa PPI++ con un peso ottimizzato, e con probabilità diverse (campionamento stratificato o guidato dall'incertezza) usa lo stimatore per differenza di Horvitz-Thompson. L'etichetta della macchina che usa è quella che la cascata consegnerebbe. Il campo by viene copiato dagli item quando vengono registrati. Senza max_width, il contratto è soddisfatto non appena ha abbastanza etichette per riportare un risultato.
no_worse_than_human
no_worse_than_human chiede se la macchina concorda con le persone almeno tanto spesso quanto lo fa una persona:
- id: replaces-a-person
kind: no_worse_than_human
schema: verdict
epsilon: 0.1Il contratto esegue il test dell'annotatore alternativo (Calderon et al., 2025). Escludendo a turno ogni persona, verifica se la macchina concorda con le persone rimanenti almeno tanto spesso quanto la persona esclusa, a meno di epsilon. La macchina passa quando vince contro almeno metà delle persone, con il false discovery rate tra le persone sotto controllo.
Il test richiede item etichettati da più persone. Imposta humans.overlap (la quota del campione etichettata più di una volta) e humans.overlap_k (persone per item, almeno 3); il test richiede almeno 3 annotatori con 30 item ciascuno. Il contratto resta insufficient finché non li ha. Usa questo contratto quando un obiettivo di accuratezza fisso misurerebbe soprattutto il rumore degli annotatori. Se due persone attente concordano l'85% delle volte, non si può dimostrare che un etichettatore abbia "ragione" al 95%.
budget_first
budget_first stima che cosa si ottiene con un budget di etichette umane prima di spenderlo:
- id: plan
kind: budget_first
schema: sentiment
human_labels: 500 # or human_usd, priced at the crowd rewardLa proiezione si basa sulle etichette dev raccolte finora. Per ogni obiettivo di errore su una griglia, indica la quota del corpus che le macchine potrebbero essere certificate a etichettare con questo budget e quanto sarebbe largo ogni intervallo di prevalenza. Il contratto è met non appena ci sono abbastanza etichette dev da cui proiettare. Non promette nulla sulle etichette, cosa che fanno selective_risk e ppi una volta raccolte le etichette.
distributional
distributional confronta la distribuzione delle etichette della macchina con il modo in cui le persone si dividono, per i task soggettivi in cui le persone sono in disaccordo per ragioni che fanno parte dei dati:
- id: disagreement
kind: distributional
schema: offensiveness
max_distance: 0.15 # optional
groups_by: age_band # optional: a prestudy question whose answer groups the annotatorsOgni item etichettato da più persone (humans.distribution_k, 5 per default) ha una distribuzione di etichette umane. Il contratto riporta la distanza di Jensen-Shannon media tra la distribuzione della macchina e quella delle persone, con un intervallo bootstrap. Riporta anche un tetto di rumore, cioè la stessa distanza tra due metà casuali delle persone su ogni item. Una macchina più vicina alle persone di quanto lo siano le persone tra loro è vicina quanto i dati consentono.
La distribuzione della macchina è data dalle sue probabilità, dove la fonte le fornisce (modelli decisionali, k_sample, logprob), oppure dalla sua etichetta come vettore one-hot. Il contratto è soddisfatto quando l'estremo superiore dell'intervallo è al massimo max_distance oppure, senza max_distance, quando ci sono 20 item etichettati da 3 o più persone. Quando l'estremo inferiore dell'intervallo è sopra max_distance, il contratto è infeasible, perché altri item restringerebbero soltanto l'intervallo attorno a una distanza troppo grande.
Con groups_by, gli stessi numeri vengono riportati per gruppo di annotatori. La distribuzione di ogni gruppo su un item è costruita solo dalle persone di quel gruppo, ricavate dalle loro risposte alla domanda prestudy indicata, e se nessuno ha risposto alla domanda il contratto lo dice.
threshold_legacy
threshold_legacy accetta le etichette automatiche sopra una confidenza fissa e non esegue alcun test statistico:
- id: old-rule
kind: threshold_legacy
schema: sentiment
threshold: 0.8potato label migrate-config scrive questo contratto per icl_labeling, alla vecchia confidence_threshold, così una configurazione convertita si comporta come prima, e puoi anche scriverlo a mano. Il certificato segna queste etichette come non certificate e riporta il loro errore misurato sulle etichette di calibrazione, e l'export assegna loro lo stato accepted_uncertified.
Risultati degli studi di esempio
I tre studi di esempio in examples/labeling-engine/ sono stati eseguiti con le fonti LLM, giudice e visione puntate su Gemma 12B su un server vLLM, invece dei modelli Ollama usati dalle configurazioni presenti nel repository. Il README di ogni esempio mostra il blocco della fonte che è stato modificato, e con i default di Ollama i numeri saranno diversi.
- Sentiment del testo (481 recensioni, Gemma 12B con confidenza logprob come ultimo livello).
selective_riskal 10% e 0,9 è stato soddisfatto con 165 etichette umane, e sono state accettate 316 etichette automatiche. Il loro errore misurato rispetto alle etichette vere era del 7,6%, e gli intervalli PPI coprivano la prevalenza vera di tutte e tre le etichette. - Immagini (128 immagini COCO, YOLOv8n e Gemma 12B come modello di visione). Un'etichetta di presenza di persone è stata certificata al 10%. Il contratto sui box è rimasto
insufficient, perché i box di YOLOv8n erano sbagliati sul 32% delle immagini dev con IoU 0,5. - Tracce degli agenti (288 tracce, Gemma 12B come giudice). Il giudice aveva ragione sull'80% delle tracce, ma la sua confidenza era sempre 1,0, quindi
selective_riskè risultato infeasible. Il test dell'annotatore alternativo è risultato insufficiente, con la macchina a 0,82 contro lo 0,93 delle persone. PPI ha stimato il successo del task a 0,66 [0,57; 0,76], dove il valore vero era 0,60 e il solo giudice diceva 0,76, 16 punti troppo alto.
Approfondimenti
- Il motore di etichettatura
- Configurazione del motore di etichettatura, comprese le chiavi
humansche questi contratti leggono - Accordo tra annotatori e accordo sulla geometria, che usa le stesse loss per regioni, segmenti e oggetti 3D
Per i dettagli di implementazione, consulta la documentazione sorgente.
Riferimenti
- 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
- Angelopoulos, A. N., Bates, S., Fannjiang, C., et al. (2023). Prediction-powered inference. Science, 382(6671). https://doi.org/10.1126/science.adi6000
- Angelopoulos, A. N., Duchi, J. C., and Zrnic, T. (2023). PPI++: Efficient prediction-powered inference. arXiv. https://arxiv.org/abs/2311.01453
- 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/