Server room con luci rosse di allarme, concetto di blast radius infinito nei sistemi LLM in produzione

Quando un aggiornamento di Claude ha cambiato tutto: gestire il blast radius infinito

Il sistema faceva una cosa sola, e la faceva bene: trasformava domande in linguaggio naturale in chiamate API. Analisti, account manager e responsabili operativi scrivevano frasi come "Compila un report sul volume di vendite per gennaio-marzo 2026 per la regione Nordest, suddiviso per città". Il sistema generava una richiesta JSON strutturata e la inoltrava ai backend giusti — portali interni, Salesforce, servizi custom. Pochi secondi dopo, il report arrivava via email, Drive o come grafico nel browser.

Entro metà 2025 il sistema generava diverse centinaia di report al mese. Era diventato il modo predefinito per ottenere dati ad hoc. Il contratto tra il modello linguistico (LLM) e il resto dell’infrastruttura era un oggetto JSON con tre campi: description, api_call, post_body.

Il sistema era stato costruito su Claude Sonnet 3.5 all’inizio del 2025. L’aggiornamento alla versione 3.7 era passato senza problemi. Lo stesso per la 4.0. Quando arrivò Sonnet 4.5, il team era diventato compiacente: gli upgrade del modello erano diventati routine, come aggiornare una libreria beneducata.

Poi arrivò il rollout di 4.5.

Per una percentuale significativa di richieste, il modello iniziò a mettere il contenuto di post_body dentro description. I parametri di filtro non arrivavano mai all’API. Il backend restituiva volumi di vendita per tutto il periodo storico o per tutte le regioni — o, peggio, un errore 500. Inoltre, il modello iniziò a fare domande di chiarimento. Le versioni precedenti, di fronte a una richiesta ambigua, facevano del loro meglio e restituivano un oggetto strutturato. Sonnet 4.5, più prudente, rispondeva con una domanda. Il sistema non era progettato per gestirlo: assumeva che ogni invocazione producesse una chiamata API. Non c’era un percorso per l’essere umano nel loop né uno stato per mettere in pausa la richiesta.

Ritornare alla versione 4.0 fu più difficile del previsto. Nel frattempo il team aveva aggiunto nuove integrazioni API, tutte qualificate su 4.5. Revertire il modello significava riqualificare ogni integrazione su 4.0 sotto pressione.

Perché l’ingegneria tradizionale non basta

L’ingegneria del software si basa sulla capacità di circoscrivere l’effetto di un cambiamento. Aggiorni un driver o una libreria, leggi le release notes, esegui i test unitari. Il sistema è deterministico: ne puoi prevedere il comportamento, o almeno campionarlo abbastanza densamente per sentirti sicuro. Il blast radius è delimitato per costruzione.

I sistemi basati su LLM rompono questa assunzione. Il componente che produce l’output non è sotto il tuo controllo. Non puoi fare un diff di un modello dalla versione 4.0 alla 4.5. È una sostituzione totale della funzionalità su cui il sistema si basa. Lo spazio di input (linguaggio naturale) è illimitato, e le possibili modalità di fallimento (qualsiasi cosa il modello faccia diversamente) sono altrettanto illimitate. Questo è il blas radius infinito.

Anatomy del guasto

Il post-mortem rivelò che il prompt era sempre stato sottospecificato. Il team aveva chiesto al modello di restituire un JSON con tre campi, descrivendo a cosa serviva ciascuno. Ma non aveva specificato che description doveva contenere solo testo in linguaggio naturale — non serializzazioni degli altri campi. Le versioni precedenti del modello inferivano questo vincolo dal contesto. Sonnet 4.5, più "disponibile", decise che fornire chiarimenti o includere la richiesta in description rendeva il risultato più utile.

Dal punto di vista del modello, era un’interpretazione ragionevole di un’istruzione ambigua. Il bug non era nel modello. Era nell’assunzione che il modello avrebbe continuato a riempire le nostre lacune di specifica. Tre upgrade di successo ci avevano convinto che quelle lacune fossero sicure.

Le modalità di output strutturato o le API tool-use avrebbero potuto intercettare questo specifico fallimento a livello di schema. Ma gli schemi vincolano solo la sintassi, non la semantica. Uno schema non può specificare che una domanda di chiarimento non debba apparire in un sistema che non ha un percorso per gestirla. Gli schemi risolvono la parte facile del problema.

L’architettura "evals-first"

La disciplina che colma questo divario è trattare la suite di valutazione — non il prompt — come la specifica formale del sistema. Il prompt è un’implementazione della specifica. Il modello è un interprete. Le eval sono la specifica stessa. Ogni cambio di modello o di prompt è valido solo se supera le eval.

In pratica, una eval è una terna: input, proprietà che l’output deve soddisfare, funzione di scoring. Per il sistema descritto, la eval che avrebbe intercettato la regressione di 4.5 era qualcosa come: "il campo description non deve contenere payload serializzati."

Alcune centinaia di proprietà — scritte a mano per invarianti note, generate come test di regressione da traffico di produzione reale, valutate da un LLM-as-judge per qualità più sfumate — diventano un gate. Gli upgrade del modello e le modifiche al prompt vanno trattati come pull request: devono far diventare verde la suite prima di essere integrati.

Le eval sono costose da costruire e mantenere. Driftano con il prodotto. Il LLM-as-judge introduce la sua varianza. E la suite può intercettare solo le modalità di fallimento a cui hai pensato. Nessuno nel team aveva mai scritto un’asserzione che dicesse "il campo description non deve contenere un comando curl" — perché nessuno aveva immaginato che il modello lo avrebbe inserito.

Articoli simili