Articolo · AI e automazione

Un modello che decide senza scrivere una parola

Dentro un'automazione quasi tutte le decisioni sono piccole, e col modello che scrive ognuna diventa un JSON da riparare. Ho scritto uno strumento che gira dall'altra parte: la risposta si legge dai numeri interni del modello, arriva già del tipo giusto e resta sul mio computer.

Federico BoggiaFederico Boggia ·AI e automazione ·Settembre 2026 ·11 min di lettura

Questa mail è urgente? Di chi è competenza? Questa clausola la deve leggere un legale? Questo scontrino in che voce va? Sono le domande che tengono in piedi un'automazione, e le paghiamo come se fossero temi: un prompt che implora un JSON, una risposta da controllare, un ramo di riserva per quando il JSON arriva storto. Bivio fa la stessa cosa leggendo la risposta invece di farla scrivere. È libero, gira in locale, e qui ti racconto come funziona e quanto vale.

01Il punto in cui le catene si rompono

Chi ha messo in produzione un'automazione con dentro un modello linguistico riconosce questo pezzo di codice, perché ce l'ha scritto almeno dieci volte.

risposta = chiedi_al_modello('Rispondi solo con {"reparto": "..."} e nient\'altro')
try:
    reparto = json.loads(risposta)["reparto"]
except (ValueError, KeyError):
    reparto = "da_smistare_a_mano"     # e vai a capire perché

Il giro è sempre lo stesso. Scrivi un prompt che chiede per favore un JSON, speri che il JSON sia valido, lo leggi, gestisci il caso in cui arriva con tre righe di preambolo davanti, e paghi dei token in uscita per farti restituire una parola che avevi già scritto tu nel prompt. Quando ne fai una al giorno regge. Quando ne fai quindicimila, il ramo da_smistare_a_mano diventa una cartella che nessuno apre.

La cosa che mi ha fatto scrivere Bivio è questa sproporzione. La decisione che stai chiedendo vale un bit: urgente o no. Per averla stai accendendo una macchina che compone testo parola per parola, e poi controlli che il testo abbia la forma di un dato.

02La risposta si legge dalle lettere

L'idea di partenza è di TypeSafe AI, che a settembre 2026 ha presentato Jev e l'ha chiamato System One model.

Un modello che scrive costruisce la risposta un token alla volta: gliela chiedi in JSON, lui te la produce carattere per carattere, e tu poi la controlli. Un modello che decide fa un'altra cosa. Gli dai lo stato, cioè il testo su cui si deve decidere, e delle domande chiuse: sì o no, oppure scegli fra queste opzioni, oppure dai un voto su questa scala. Torna indietro una risposta del tipo che hai dichiarato, con la sua probabilità attaccata. Niente da riparare, niente da validare.

Arriva un messaggio all'assistenza:

Il pacco è arrivato rotto, vorrei fare un reso.

Da quelle otto parole servono tre decisioni, e sono tutte chiuse: che tono ha (negativo), in che lingua è (italiano), cosa vuole chi scrive (un reso). Con quelle tre il software manda il ticket al gruppo che gestisce i resi. E se la probabilità su una delle tre è bassa, invece di tirare a indovinare lo mette nella fila di quelli che guarda una persona. È un esempio banale di proposito. Quelle tre domande tornano identiche su diecimila ticket, e allora quanto costano e quanto durano decidono se l'automazione si può fare o no.

I numeri di Jev li mette il suo venditore, e vanno letti sapendolo: TypeSafe dichiara da 40 a 200 volte più veloce e 444 volte meno caro di un modello che scrive, e nella stessa pagina scrive che quei guadagni stanno «sul lato alto». Quello che invece si controlla da fuori è il listino: dal 18 settembre 2026 Jev sta su OpenRouter, dove Jev 1.13 costa 0,042 dollari per milione di token in ingresso e zero in uscita, con 32.000 token di contesto. Zero in uscita perché di token in uscita non ce ne sono, ed è la parte dell'idea che conta.

Il limite è che Jev è chiuso: gira sui server di TypeSafe, il modello non te lo danno, e per l'API dell'azienda c'è ancora una lista d'attesa. Se il tuo stato è una cartella clinica, una busta paga o il messaggio di un tuo cliente, quel testo esce di casa a ogni decisione. Bivio fa lo stesso lavoro con un modello aperto sul tuo disco, parla la stessa API, e non apre nessuna connessione.

Il meccanismo sta in tre passaggi, e la parte bella è che sono semplici. Ogni risposta possibile prende una lettera maiuscola. Al caricamento si controlla sul tokenizzatore che quella lettera, nel punto esatto in cui verrà letta, valga un token solo: se il conto torna diverso il modello viene rifiutato, invece di darti numeri sbagliati in silenzio. Poi un passaggio in avanti, e si guardano i logit di quelle lettere. Il modello di decodifica resta spento: output_tokens: 0 è vero alla lettera.

r = b.decidi(
    "Provo da tre giorni a collegare il conto Stripe e continua a fallire.",
    {"urgente": {"tipo": "si_no", "istruzioni": "Il messaggio esprime urgenza"},
     "reparto": {"tipo": "scelta", "istruzioni": "Chi prende in carico",
                 "opzioni": {"pagamenti": "Incassi, fatture, rimborsi",
                             "tecnico":   "Errori e malfunzionamenti"}}})

r["reparto"].valore         # 'tecnico'
r["reparto"].probabilita    # 0.9999

I tipi di domanda sono quattro: si_no, scelta fra opzioni che dichiari tu, voto su una scala ordinata, numero con delle ancore. Gli ultimi due tornano una media pesata, e per me sono la parte più utile. Una partita che sta fra «in bilico» e «persa» esce 1,5, con la sua dispersione accanto a dire se il modello era combattuto oppure stava davvero in mezzo. Un'etichetta secca quell'informazione la butta via.

Dove si vede il guadagno

Su un contratto da 1.559 token, otto domande fatte insieme costano 3,2 secondi; le stesse otto una per volta ne costano 18,4, cioè 5,75 volte tanto. Lo stato si legge una volta e resta in cache, poi cambia solo la coda della domanda. Su uno stato di due righe questa differenza sparisce: il vantaggio vive tutto nei documenti lunghi con tante domande sopra.

Sul mio MacBook con M5 una decisione su uno stato corto costa 187 millisecondi, e circa 95 se lo stato è già stato letto. A quel prezzo la domanda la puoi mettere davanti a ogni chiamata di un agente, che è uno degli esempi nel repository: prima che l'agente esegua uno strumento, gli chiedi se quella roba tocca dati già scritti e se manda qualcosa fuori. Un controllo che costa un decimo di secondo lo accendi sempre; un controllo che costa una chiamata a pagamento lo accendi quando te ne ricordi.

03L'italiano, e il modello italiano che perde

Implementazioni aperte di questa idea ce n'erano già due, e buone: SemIf di TheoLeeCJ e Rizzo Flow di Simone Rizzo, che ha misurato il suo contro il primo. Bivio l'ho scritto perché me ne servivano tre cose che lì mancano, e sono tutte e tre italiane.

La prima sono le domande già scritte. La libreria è la parte facile: il lavoro vero sta nel decidere quali domande fare e con che opzioni. Nel pacchetto ci sono quattro griglie pronte, e sono i mestieri che si fanno qui.

GrigliaChe cosa chiedePer chi
assistenzareparto, urgenza, quanto è scontento, se serve una personachi risponde ai clienti
spesevoce di spesa, inerenza, ordine di grandezzachi tiene la prima nota
contrattorinnovo tacito, termini, penali, foro, chi deve leggerlochi firma senza un legale in casa
moderazioneoffese, spam, dati personali, che farnechi tiene una pagina o dei commenti

La seconda sono i casi di prova. I 37 su cui l'ho misurato parlano di ticket, clausole di pagamento a sessanta giorni, documenti di trasporto e voci di spesa, in italiano. Le fixture di SemIf, che sono il metro del settore, stanno in inglese, e un modello che va bene lì qui va verificato lo stesso.

La terza è che i dati restano a casa. Studi, ambulatori, scuole e uffici, per mandare i testi dei loro utenti a un servizio estero, si mettono in una fila di adempimenti. Bivio gira senza rete: stacchi il wifi e continua a rispondere.

Poi c'è la parte che pensavo sarebbe andata in un altro modo. Il modello italiano per eccellenza è Minerva-7B della Sapienza, addestrato da zero sull'italiano, Apache-2.0, col suo GGUF ufficiale. L'ho messo nel catalogo e l'ho misurato sugli stessi casi.

Qwen3-4B Q4Minerva-7B Q4
31 casi etichettati30 giuste13 giuste
6 casi senza risposta, riconosciuti50
Per decisione188 ms334 ms
Il file da scaricare2,5 GB4,5 GB

Il confronto è onesto su una cosa sola, lo stesso prompt, e quel prompt l'ho scelto guardando come rispondeva Qwen. Minerva-7B-instruct v1.0 è un modello del 2024 che nessuno ha messo a punto per seguire una scelta multipla, quindi con un prompt scritto per lui i numeri cambierebbero. Il caveat sta nel README e resta lì.

Con quel caveat in mano, la conclusione che regge è questa: per questo mestiere conta più l'obbedienza alle istruzioni della lingua di addestramento. Una buona notizia per chi deve scegliere un modello, e scomoda per chi dava per scontato il contrario.

04La grotta, e un guadagno venuto da una sottrazione

Per la lezione di un corso mi serviva un esempio in cui si vedesse cosa succede quando deleghi una decisione. Ho scritto un gioco a turni: un eroe, un mostro, quattro mosse, il bottino. Un gioco ha tre cose che un processo di lavoro all'inizio si sogna: le regole sono scritte, lo stato sta in una riga, e una mossa sbagliata fa danni a nessuno.

A giocare ho messo tre giocatori: uno a caso, quattro righe di if scritte da me, e Bivio che a ogni turno guarda lo stato e sceglie.

GiocatorePartiteVinteFuggiteMorte
A caso1000%94%6%
Quattro righe di if10063%35%2%
Bivio, tutte le mosse sempre offerte400%0%100%
Bivio, solo le mosse legali4075%2%22%
Bivio legali, più una regola sul pericolo400%75%25%

Guarda la terza riga contro la quarta, che è il motivo per cui questo laboratorio esiste. Offrendogli sempre tutte e quattro le mosse, il modello muore in ogni partita: sceglie il colpo forte anche mentre è in ricarica, cioè butta il turno, perché nella descrizione c'è scritto che toglie da 18 a 24 ed è il numero più grosso della lista. Sei righe di Python che guardano eroe.ricarica e eroe.pozioni gli tolgono dalle opzioni le mosse impossibili, e passa a vincere tre volte su quattro.

Quale mossa sia possibile è meccanico, e lo fa il codice. Quale mossa sia conveniente è giudizio, e resta al modello.

Il guadagno è venuto da quello che al modello ho tolto. Questa è la frase che mi porto dietro in aula quando qualcuno vuole dare a un agente tutti gli strumenti dell'azienda e vedere che succede.

L'ultima riga è un esperimento andato male

Ci ho messo sopra una regola scritta a mano: se il modello dice che sono in pericolo, bevo o scappo. Il risultato crolla a zero vittorie, perché quel sì o no risponde sì quasi sempre. Una risposta non tarata, usata come se fosse tarata, fa più danni dell'averla ignorata. L'ho lasciata nella tabella apposta.

05Duecento strumenti, e la stessa sottrazione

Quella frase l'ho messa alla prova sul caso vero. Un agente con dieci server MCP addosso si porta dietro centomila token di soli schemi prima che qualcuno abbia scritto una parola, e più strumenti ha meno ci azzecca a sceglierli. Ho scritto una portineria che sta in mezzo: tiene i server dietro di sé, in contesto ne espone tre, e quando serve chiede a Bivio quali dei duecento servono a questa richiesta.

Le prime due versioni le ho buttate, e le ho buttate misurando. La prima faceva una domanda sì o no per strumento: duecento domande su una lettura sola, che è esattamente quello che Bivio fa bene. Ventinove secondi, e chiedendo «devo aprire una issue su GitHub» tornava cerca_contatto. Il secondo difetto conta più del primo: a «questo strumento serve?» il modello dice sì a qualunque cosa sia vagamente in tema, le probabilità si accalcano vicino a 1 e l'ordine che ne esce è rumore. Una scelta costringe al confronto, un sì o no no.

La seconda spezzava il catalogo in gironi da venticinque: nove domande invece di duecento. Le scelte sono migliorate, il tempo no, ventisei secondi. Non erano le domande a costare, erano gli undicimila token di descrizioni che il modello doveva leggere comunque.

Quello che funziona è la riga della grotta. Quali strumenti siano plausibili è meccanico: le parole della richiesta e quelle del nome si sovrappongono oppure no, e un set lo dice gratis. Quale sia giusto è giudizio, e resta al modello. Il filtro porta duecento a venticinque, il modello sceglie fra venticinque.

Su 200 strumenti, 10 richiestePrimo giustoFra i primi 5Mediana
Solo il modello, legge tutto10/1010/1018,7 s
Filtro meccanico, poi il modello10/1010/102,6 s

Stessa accuratezza, sette volte più veloce. È il terzo posto in cui finisco sulla stessa frase partendo da un problema diverso, e a questo punto ho smesso di considerarla una coincidenza.

Il cancello non è una misura di sicurezza

La portineria guarda anche le chiamate prima di passarle: è irreversibile? porta fuori dati personali? lo strumento fa quello che dichiara? Ma è un classificatore, cioè legge del testo e dice un numero, e chi controlla quel testo può provare a parlargli intorno. Prende le sviste e gli incidenti, che sono la maggioranza, non un avversario. Le cose che devono valere sempre stanno in un elenco di nomi vietati, che è meccanico e non si discute.

06Quanto ti puoi fidare

Poco, e lo dico io che l'ho scritto. Sono 37 casi che ho scritto io, misurati su una macchina sola. Ti dicono che gira e che risponde sensato. Per sapere se regge il confronto con Jev o con SemIf servirebbero le loro fixture e il loro valutatore, e quel lavoro qui manca.

Dei 31 casi etichettati ne sbaglia uno: un refuso nella pagina contatti, classificato come «fastidioso» invece che «trascurabile», con probabilità 1,000. Sicuro e sbagliato insieme. Tengo quel caso in prima fila perché spiega in tre righe che la confidenza di un modello è un numero, con tutti i difetti dei numeri che escono da una macchina non tarata.

Le tre cose da sapere prima di metterlo in produzione

  • Appena acceso è sicurissimo di tutto. Dove la documentazione di Jev mostra 0,88, qui esce 0,9999. Finché ti prendi l'opzione più probabile funziona lo stesso; il giorno che ci metti una soglia, quella soglia va tarata sui tuoi dati con bivio taratura.
  • La taratura è legata a un'impronta che tiene dentro i pesi, la versione del prompt e la taratura stessa. Cambi modello e il file si rifiuta di caricarsi, con un messaggio, al posto di darti numeri scollegati.
  • L'astensione è spenta di serie. Accesa riconosce 5 casi su 6 in cui la risposta nello stato manca davvero, e insieme si tira indietro 6 volte su 31 con la risposta sotto gli occhi. Accendila se hai un ramo dove far finire i dubbi.

C'è poi il difetto che questo metodo si porta dietro per costruzione: un modello a scelta multipla pesa un'opzione anche per dove sta, e chi legge i logit delle lettere lo eredita intero. Era la cosa più imbarazzante da lasciare a occhio, quindi l'ho misurata facendo la stessa domanda con le opzioni girate in tutti i modi.

Su 22 casiQwen3-4BMinerva-7B
Di quanto si muove il logit di un'opzione spostandola2,431,35
Margine più stretto fra prima e seconda7,880,01
Risposte che cambiano solo girando le opzioni0 su 2219 su 22

Le prime due righe vanno lette insieme. Il difetto c'è anche su Qwen, e vale due punti e mezzo; solo che lì la prima classificata stacca la seconda di quasi otto, quindi due e mezzo non ribaltano niente. Su Minerva il margine è un centesimo, e allora quel difetto decide da solo la risposta diciannove volte su ventidue. Si spiega così anche la sconfitta del modello italiano: in buona parte non sta leggendo male lo stato, sta scegliendo per posizione. Adesso si rimescola con --giri 3, che costa poco perché lo stato resta in cache e si ripaga solo la seconda metà del prompt, e su Minerva recupera tre casi su ventidue.

Restano fuori le opzioni per domanda, che si fermano a 26 perché tante sono le lettere, e il fatto che l'ho provato su un Mac con Apple Silicon e basta.

La misura che conta davvero è un'altra, e vale per qualunque strumento di questo tipo, compreso quello che stai valutando adesso: prendi cento decisioni che qualcuno in azienda ha già preso a mano, dagliele in pasto, e conta quante ne azzecca. Un'ora di lavoro, e ti risparmia sei mesi di automazione che smista male.

Dove sta e da dove viene

Bivio è su github.com/TheRealF/bivio, licenza Apache-2.0: pip install git+https://github.com/TheRealF/bivio, poi bivio scarica per il modello e bivio serve per il campo di prova. Dentro a un agente ci entra con bivio mcp, e bivio portineria è quella della sezione 05. Gira su llama.cpp con Qwen3-4B-Instruct-2507.

L'idea è di TypeSafe AI, che l'ha presentata in Introducing System One models and Jev. In aperto ci sono arrivati prima SemIf e Rizzo Flow, da cui ho preso il controllo sulle lettere e l'abitudine di pubblicare i numeri con tutti i loro se e ma.

Il laboratorio della grotta sta nella Lezione 6 del corso gratuito Gen AI per l'automazione dei processi, con il codice in pagina e il piano B per chi lascia stare i 2,5 GB del modello.

Federico BoggiaRispondo io, in giornata

Ciao! Dimmi che ti serve: un corso online, un workshop di AI in aula a Livorno o la formazione per la tua azienda.

Scrivimi su WhatsApp