Chiudere il cerchio: rimandare alle persone gli errori dell'agente e i disaccordi del giudice
Il tempo di revisione umana è la risorsa più scarsa nella valutazione degli agenti. Potato 2.6 unisce una coda di triage basata su segnali all'allineamento giudice-umano, così le tracce peggiori arrivano prima alle persone e il tuo giudice LLM continua a migliorare.
Non appena valuti agenti a qualsiasi scala, il vincolo smette di essere «possiamo etichettare questo» e diventa «su chi spendiamo l'attenzione, e su cosa». Hai migliaia di tracce di produzione e una manciata di revisori. Un giudice LLM può preselezionare tutto, ma è imperfetto, e i casi in cui sbaglia sono esattamente quelli che valgono il tempo di una persona.
Due funzionalità di Potato 2.6 collaborano per gestire questa scarsità. Una coda di triage basata su segnali decide cosa vedono per primi gli umani. L'allineamento giudice-umano misura quanto puoi appoggiarti al giudice e lo migliora. Eseguile insieme e ottieni un ciclo di valutazione attivo: il giudice gestisce il volume facile, i casi sospetti saltano la coda verso gli umani e i disaccordi rifluiscono in un giudice migliore.
Questo articolo copre entrambe le metà e come si collegano.
Il badge della coda di triage in Potato
La metà del triage: il peggiore per primo, non primo arrivato primo servito
Per impostazione predefinita, una coda di annotazione è FIFO: gli elementi vengono serviti nell'ordine in cui sono stati caricati. È l'ordine sbagliato quando il tempo di revisione è scarso. Una traccia pulita e una traccia in cui l'agente ha sollevato un errore valgono quantità di attenzione umana molto diverse, e FIFO le tratta allo stesso modo.
La coda di triage riordina la coda in base a un segnale di qualità per ogni elemento. Il segnale può essere un errore dell'agente, un pollice verso il basso in produzione, un punteggio automatico basso o qualsiasi campo dei tuoi dati:
triage:
enabled: true
order: desc # high priority first (default)
show_badge: true # banner during annotation explaining the priority
rules: # evaluated in order; highest matching priority wins
- name: "Agent errored"
priority: 100
when:
field: status
equals: error
- name: "Negative feedback"
priority: 80
when:
field: feedback
in: [thumbs_down, negative]
- name: "Low quality score"
priority: 60
when:
field: score
lt: 0.5
assignment_strategy: priorityLe regole vengono valutate dall'alto verso il basso e vince la priorità corrispondente più alta, quindi una traccia in errore che ha anche un feedback negativo finisce comunque a 100. Se ometti del tutto rules, Potato ricade su un insieme predefinito sensato (stato di errore a 100, feedback negativo a 80, punteggio inferiore a 0.5 a 60), così il comportamento chiavi in mano è ragionevole prima di regolare qualsiasi cosa.
Gli operatori di condizione coprono i confronti di cui hai davvero bisogno:
| Operator | Significato |
|---|---|
equals | corrispondenza esatta (le stringhe non distinguono maiuscole/minuscole) |
in | il valore è uno di una lista |
contains | la lista contiene, oppure corrispondenza di sottostringa |
lt / lte / gt / gte | confronto numerico |
exists | il campo è presente o assente |
Quando il segnale è già un numero, puoi leggerlo direttamente dal campo invece di scrivere regole:
triage:
enabled: true
signal_field: quality_score
invert_signal: true # lower score => higher priorityFunziona anche sul traffico dal vivo
Il punteggio di priorità viene calcolato una sola volta quando un elemento viene caricato o acquisito, poi memorizzato sull'elemento, così l'assegnazione resta economica. Lo stesso design fa sì che l'acquisizione a runtime funzioni senza altro: una traccia inviata a metà sessione tramite l'endpoint webhook o un poller Langfuse viene valutata all'arrivo e si inserisce nell'ordine di priorità. Una traccia con punteggio basso o in errore che arriva alle 14 scavalca quelle pulite ancora in attesa da stamattina. Impostare assignment_strategy: priority è ciò che fa servire la coda davvero in quell'ordine; show_badge è indipendente, quindi il banner «perché è stato segnalato» appare anche se mantieni una strategia diversa.
La metà dell'allineamento: quanto fidarsi del giudice
Il triage decide cosa vedono gli umani. L'allineamento decide quanto del resto puoi affidare al giudice senza supervisione, e nel tempo restringe il giudice.
Judge Alignment esegue un giudice LLM configurabile su istanze che i tuoi annotatori hanno già etichettato, poi riporta il κ di Cohen (kappa di Cohen, una misura di accordo), una matrice di confusione e un elenco di disaccordi rispetto al gold umano. La pratica standard (allineare un giudice a circa 100–200 etichette gold, ispezionare dove diverge, riscrivere la rubric e rieseguire) è il ciclo attorno al quale è costruito tutto questo.
ai_support:
enabled: true
endpoint_type: "ollama"
ai_config:
model: "llama3.2"
temperature: 0.0
judge_alignment:
enabled: true
schemas:
correctness:
rubric: >
Label 'correct' only if the agent's answer is factually right and fully
satisfies the request; otherwise 'incorrect'.
inline:
enabled: true # show the judge verdict beside the human label
schemas: [correctness]Esegui il giudice dall'API di amministrazione, e le previsioni vengono memorizzate nella cache per versione di prompt, così le riesecuzioni sono economiche:
curl -X POST localhost:8000/admin/api/judge-alignment/run \
-H "X-API-Key: <admin-key>" \
-H "Content-Type: application/json" \
-d '{"max_per_schema": 200}'Quando vuoi calibrare, passa una rubric modificata. Questo crea una nuova versione di prompt, così puoi confrontare κ tra i cicli e vedere davvero se la tua riscrittura ha aiutato:
curl -X POST localhost:8000/admin/api/judge-alignment/run \
-H "X-API-Key: <admin-key>" -H "Content-Type: application/json" \
-d '{"rubrics": {"correctness": "Stricter rubric text..."}}'Il report, disponibile come JSON o come pagina renderizzata su /admin/judge-alignment, mostra κ con un'interpretazione Landis–Koch, la matrice di confusione, una tabella dei disaccordi con il ragionamento del giudice e una cronologia delle versioni di prompt, così che i progressi della calibrazione siano visibili tra i cicli.
La modalità inline lo mette davanti all'annotatore
Con inline.enabled, ogni pagina di annotazione mostra il verdetto in cache del giudice accanto all'etichetta umana (la sua scelta, la confidenza e un ragionamento espandibile) insieme a un κ in corso per il compito. «Accetta» compila la scelta corrispondente. Ogni salvataggio umano registra un confronto umano↔giudice che alimenta l'accordo in corso, così il κ verso cui stai calibrando si aggiorna man mano che le persone lavorano.
Mettere insieme le due cose
Le funzionalità sono progettate per comporsi in un unico ciclo:
Il ciclo di valutazione attivo: triage, revisione umana, allineamento del giudice, raffinamento della rubric
- Il triage spinge le tracce in errore e a bassa confidenza in cima alla coda umana.
- Gli umani revisionano quegli elementi di alto valore, producendo etichette gold fresche esattamente dove il sistema è meno sicuro.
- L'allineamento valuta il giudice rispetto a quel gold, e l'elenco dei disaccordi mostra con precisione dove giudice e umani si separano.
- Tu raffini la rubric, riesegui e osservi κ muoversi, poi lasci che il giudice meglio calibrato assorba più volume facile, così il tempo umano continua a fluire verso i casi difficili.
Ogni giro del ciclo spende l'attenzione umana dove vale di più e la converte in un giudice di cui puoi fidarti un po' di più. È proprio questo il punto: non rimuovere le persone dalla valutazione degli agenti, ma indirizzarle.
Entrambe le funzionalità sono incluse in Potato 2.6. Consulta la documentazione della coda di triage e la documentazione dell'allineamento del giudice per il riferimento completo, e la visualizzazione eval_trace per leggere rapidamente le tracce prioritizzate.