# Il prototipo LLM funziona. Quattro domande prima della produzione

> Stato, recovery, eval, costi: quattro domande da porsi prima di portare in produzione un prototipo LLM, con esempi reali e i limiti dichiarati.

Published: 2026-10-10
Canonical: https://gianlucamazza.it/it/blog/quattro-domande-produzione-llm
Tags: mklang, LLM, Production, Evals, Cost

Il prototipo risponde bene in demo. Il team è contento, il cliente interno anche. Poi arriva la domanda che nessuno ha messo in roadmap: cosa succede quando lo lasciamo girare da solo, con traffico vero, per tre mesi?

In quel passaggio i problemi raramente stanno nel modello. Stanno nel sistema attorno al modello. Io li riduco a quattro domande: dove si perde lo stato, come si recupera dai fallimenti, come si misura la qualità degli output e quanto costa ogni richiesta. Per ciascuna, qui sotto, c'è un esempio reale preso dal mio codice open source. Ogni esempio mostra come la risposta facile si è rivelata sbagliata, o almeno incompleta.

## 1. Dove si perde lo stato?

Un prototipo tiene lo stato in memoria: la conversazione, i risultati intermedi, il punto del flusso in cui si trova. Finché il processo non si riavvia, va tutto bene. In produzione il processo si riavvia: un deploy, un timeout, un budget esaurito a metà lavoro.

La prima risposta è «salviamo lo stato». È giusta, ma apre una seconda domanda: *cosa* stai salvando, e chi può leggerlo?

In mklang, il linguaggio per macchine a stati LLM che sviluppo in open source, le run si possono sospendere e riprendere da un checkpoint (ADR 0007, `docs/adr/0007-resumable-checkpoints.md`). Il progetto stesso scrive che quel checkpoint contiene **l'intera blackboard (lo stato condiviso della run) in JSON in chiaro**: testo dei clienti, dati personali, policy interne. E aggiunge che i casi che restano sospesi più a lungo, le escalation verso un umano, sono proprio i più sensibili (ADR 0032, `docs/adr/0032-pluggable-checkpoint-store.md`).

Nel tuo sistema la domanda pratica è doppia. Se il processo muore a metà, riparti dal punto giusto o ricominci da capo? E i file o le righe di database che rendono possibile la ripartenza sono trattati come dati sensibili, con cifratura e scadenza?

Lo stesso tema compare quando più componenti scrivono sullo stesso stato. L'ho raccontato per LangGraph in «Lo stato come API: LangGraph dopo tre riscritture» (gianlucamazza.it/it/blog/langgraph-workflow-orchestration): un flag scritto da un nodo e sovrascritto da quello dopo, perché il campo non dichiarava come andavano unite le scritture.

## 2. Come si recupera dai fallimenti?

Un LLM sbaglia in modi che il codice classico non conosce: un output troncato, un JSON non valido, una risposta che ignora un vincolo. La reazione naturale è riprovare, magari dicendo al modello cosa ha sbagliato.

Sembra ovvio che il secondo tentativo, con il feedback, vada meglio del primo. In mklang il costrutto `repair` fa esattamente questo, ma fino al 20 agosto 2026 non era mai stato misurato. Quel giorno (DeepSeek, 30 run) il tasso di successo è stato **0,57 al primo tentativo e 0,15 al secondo**. Fonte: `docs/experiments/repair-convergence.md` nel repo mklang.

Non è una confutazione. Al secondo tentativo arrivano solo i casi che il primo ha fallito, cioè i più difficili, e il campione è piccolo: 13 run su 30 sono arrivate al secondo tentativo. Ma basta a togliere la certezza. Oggi non posso dire che il feedback funzioni meglio di un semplice nuovo campione, che costerebbe uguale.

La domanda per il tuo sistema: i tuoi retry migliorano davvero il risultato, o pagano due volte la stessa probabilità? E quando i retry finiscono, dove va la richiesta: a un umano, a un errore esplicito, o a un «ok» che nasconde il fallimento?

## 3. Come si misura la qualità degli output?

Quasi ogni team ha qualche forma di valutazione: un set di esempi, un confronto tra modelli, a volte un secondo LLM che fa da giudice. Il rischio è avere un numero che sembra buono e non misura niente.

In mklang misuro se modelli diversi prendono la stessa decisione sugli stessi input. Il 27 luglio 2026 quel numero era **1,0 su quattro macchine a stati di test**, cioè accordo perfetto. Il progetto stesso, nella pagina dell'esperimento (`docs/experiments/gate-divergence.md`), scrive che quel numero «non aveva potere discriminante», per tre motivi. I casi erano facili. Due modelli possono essere d'accordo sulla risposta sbagliata. E il dato mescolava due domande diverse: un modello è coerente con sé stesso? Due modelli sono d'accordo tra loro?

La correzione è stata aggiungere casi di confine, dove la risposta giusta è difendibile ma non ovvia, e misurare l'accuratezza contro una risposta di riferimento, non solo l'accordo.

La domanda per il tuo sistema: i tuoi test possono fallire? Se un cambio di modello o di prompt peggiora le risposte, quale numero se ne accorge, e prima o dopo il rilascio?

## 4. Quanto costa ogni richiesta?

Il costo di un sistema LLM sembra semplice: token in entrata più token in uscita, per il prezzo del provider. Il problema sono le richieste che *non* finiscono bene.

Fino alla versione 1.3.7 di mklang (29 settembre 2026), una risposta troncata o un JSON non valido fermavano la run senza registrare i token di quella chiamata, che però il provider aveva già fatturato. Il conteggio dei costi della run sottostimava proprio i fallimenti, cioè la parte di costo che serve vedere. La correzione è nel CHANGELOG 1.3.7 ed è coperta da test di regressione (PR #111).

La domanda per il tuo sistema: il costo che misuri include le risposte scartate, i retry e le chiamate fallite? E conosci il costo per richiesta, non solo il totale del mese?

## Prima della produzione

Le quattro domande non richiedono un framework particolare. Servono risposte scritte, con un riferimento al codice o a un run per ciascuna. Dove la risposta è «non lo sappiamo», di solito lì sta il primo intervento.

Se hai un prototipo LLM funzionante e vuoi queste risposte sul tuo repository, è il lavoro della review di production readiness: una valutazione scritta per ciascuna delle quattro domande, senza modifiche al codice. I dettagli sono su [/it/servizi](https://gianlucamazza.it/it/servizi).
