Progettare la sostituibilità del modello AI: abstraction layer, eval di portabilità, fallback self-hosted

Progettare la sostituibilità del modello AI: abstraction layer, eval di portabilità, fallback self-hosted

Il 12 giugno 2026, alle 17:21 ora della costa est, Anthropic ha ricevuto una direttiva di export control dal governo degli Stati Uniti e ha disabilitato Claude Fable 5 e Mythos 5 per tutti i clienti del mondo, come documentato nel suo statement ufficiale. Chi aveva costruito un processo critico su quel modello si è trovato davanti a una scelta secca: avere un'alternativa già pronta, oppure restare fermo a tempo indeterminato. Ho raccontato altrove perché quell'evento sia un punto di non ritorno, nel pezzo su come hanno spento il modello AI più potente del mondo in tre giorni; qui parlo solo di ingegneria. Perché la lezione, una volta tolta la cronaca, è banale e antica: un componente da cui dipende il tuo business va trattato come sostituibile fin dal primo giorno. Lavoro con i modelli di frontiera in produzione ogni giorno e continuo a usarli; proprio per questo li isolo dietro un'architettura che mi permette di cambiarli senza riscrivere nulla.

Il modello non è una fondazione, è un driver. Il codice di business non deve sapere quale modello sta parlando, esattamente come un controller non sa se sotto c'è MySQL o PostgreSQL. Se lo sa, hai già perso la sostituibilità.

Questa non è teoria difensiva astratta: è lo stesso principio di disaccoppiamento con cui da vent'anni isolo un'applicazione dal database concreto, dal provider di hosting o dal sistema di code. La novità del 2026 è che il layer più pericoloso da accoppiare rigidamente è proprio quello che sembrava più stabile e intoccabile, il modello. Vediamo come si costruisce la sostituibilità, strato per strato, in modo che spegnere un modello sia un cambio di configurazione e non un progetto di migrazione.

Da dove si comincia a rendere sostituibile un modello?

Si comincia da un punto di contatto unico. Nella stragrande maggioranza delle codebase che vedo, le chiamate al modello sono sparse: una qui nel controller, una là in un job, una nascosta in un service, ognuna con il nome del provider hardcoded e i suoi parametri specifici. È l'equivalente di avere query SQL native sparse in tutta l'applicazione invece di un layer di accesso ai dati. Il primo passo è incanalare ogni interazione con l'AI attraverso una sola interfaccia, dove la scelta del modello vive in configurazione e non nel codice. In ecosistema PHP questo si fa con un layer come il Laravel AI SDK o pacchetti dedicati come Prism; nel mondo Python, con un gateway provider-agnostic come LiteLLM, che normalizza decine di provider dietro un'interfaccia unica compatibile con il formato OpenAI.

La configurazione del modello, e soprattutto la sua catena di fallback, deve essere un dato, non una costante sparsa nel codice:

# Il primo provider disponibile vince. Se un modello sparisce
# (kill-switch, deprecation, repricing), si riordina questa lista.
# Nessuna riga di codice applicativo viene toccata.
AI_PROVIDER_PRIMARY=anthropic:claude-opus-4-8
AI_PROVIDER_FALLBACK=openai:gpt-5.5
AI_PROVIDER_SOVEREIGN=selfhosted:mistral-large-3
AI_FALLBACK_ON=timeout,http_5xx,model_unavailable
AI_TIMEOUT_SECONDS=60

Dietro a questa configurazione c'è un'astrazione minima: un contratto che il resto dell'applicazione conosce, e degli adapter intercambiabili che lo implementano per ciascun provider. In pseudocodice PHP, senza dipendere da alcun framework:

interface ModelGateway
{
    // input strutturato in, output strutturato out: nessun dettaglio del provider trapela.
    public function complete(Prompt $prompt, array $options = []): Completion;
}

final class FallbackGateway implements ModelGateway
{
    public function __construct(private array $chain) {} // adapter ordinati per priorità

    public function complete(Prompt $prompt, array $options = []): Completion
    {
        foreach ($this->chain as $gateway) {
            try {
                return $gateway->complete($prompt, $options);
            } catch (ModelUnavailable | TimeoutException) {
                continue; // prova il prossimo provider della catena
            }
        }
        throw new AllProvidersExhausted();
    }
}

Il valore di questo strato non è la sua complessità, che è minima, ma il fatto che concentra in un solo punto la decisione su quale modello usare e cosa fare quando non risponde. Il giorno del kill-switch, riordinare la catena è un cambio di una riga.

Se stai integrando modelli AI in un sistema di produzione e vuoi vedere come imposto questo tipo di architettura, dalla scelta del modello alla governance dei costi, nel mio hub dedicato all'AI per lo sviluppo raccolgo gli articoli con la metodologia che applico sul campo.

Perché un fallback non testato non è un fallback

Qui sta l'errore che vedo più spesso, ed è grave perché dà una falsa sicurezza. Avere la catena di fallback in configurazione non basta: un'alternativa che non hai mai mandato in produzione non la tiri su nel giorno dell'emergenza. Le migrazioni a freddo falliscono perché ogni provider ha le sue idiosincrasie, e queste idiosincrasie non sono nell'API, sono nel comportamento del modello: il tono, il modo di seguire le istruzioni, i formati di output, i casi in cui sbaglia. Il lock-in di un modello, lo dico sempre, non è tecnico, è comportamentale, e si stringe più diventi agentico, perché ogni guardrail e ogni prompt che aggiungi è tarato su quel modello specifico.

La pratica solida è il warm standby: far passare già da subito una quota di traffico reale, indicativamente tra il quindici e il venti per cento, sul provider secondario o sul modello self-hosted. Serve a far emergere i difetti di integrazione, le differenze di prompt e i divari di latenza mentre l'incumbent regge ancora, non sotto pressione. E serve una eval di portabilità: un set di test sul tuo workload reale che misura quanto si degrada la qualità passando da un modello all'altro. Senza quel numero, il piano B è una scommessa.

Costruire una eval di portabilità è più semplice di quanto sembri, e non richiede strumenti esotici. Si parte da un golden set: un insieme di casi reali tratti dal tuo traffico di produzione, dalle poche decine alle poche centinaia, ciascuno con l'input e l'output atteso o un criterio di accettazione. Si fa girare lo stesso golden set sul modello primario e su ogni alternativa della catena, e si confrontano i risultati con una metrica adatta al task: corrispondenza esatta per la classificazione e l'estrazione strutturata, una rubrica con un modello giudice per i task generativi, la validità sintattica per il codice o l'output JSON. Il numero che esce, la percentuale di degrado passando dal modello A al modello B sul tuo workload reale, è l'informazione che ti manca quando decidi sotto pressione. La regola operativa che applico è semplice: se un'alternativa fa scendere la qualità oltre una soglia che hai deciso a freddo, non è un fallback, è un downgrade da dichiarare esplicitamente, con i processi che possono tollerarlo e quelli che no. E questa eval va nel continuous integration: ogni volta che cambi prompt, aggiorni una libreria o un provider rilascia una nuova versione, la rilanci, così la portabilità non degrada in silenzio mentre tutti guardano altrove.

C'è poi un prerequisito che quasi nessuno mette in pratica e che vale quanto tutto il resto: l'osservabilità del layer di modello. Ogni chiamata deve loggare quale provider l'ha servita, con quale latenza, a quale costo e con quale esito (successo, fallback, errore). Senza questo, non sai quanta parte del tuo traffico sta già finendo sul secondo provider, non ti accorgi che il primario sta degradando finché non crolla, e non hai i dati per dimensionare l'alternativa. È la stessa disciplina del distributed tracing applicata al layer AI: se non lo misuri, non lo governi. Un effetto collaterale prezioso è che il tasso di fallback diventa un indicatore di salute in tempo reale, e l'esercizio della prova d'uscita smette di essere un evento e diventa una metrica continua.

Livello di difesaCosa garantisceCosto
Abstraction layer in configCambio modello = una rigaBasso, da fare subito
Eval di portabilitàSai quanto perdi cambiandoMedio, è codice di test
Warm standby (15-20% traffico)L'alternativa è già provataMedio, doppio provider
Exit plan documentatoSai chi fa cosa nell'emergenzaBasso, è organizzazione

Su come costruire l'alternativa sovrana ho scritto sia il lato infrastrutturale, con un LLM self-hosted su VPS Hetzner con Ollama per la produzione, sia il confronto tra un modello a pesi aperti ospitato in Europa e l'API di frontiera in Mistral 3 MoE on-premise contro l'API Claude sul piano della sovranità.

Serve davvero un modello di frontiera per tutto?

No, ed è la leva che rende la sostituibilità economicamente sostenibile invece che un costo puro. L'entusiasmo sul "modello più grande" nasconde un fatto operativo: la maggior parte dei task aziendali ad alto valore non ha bisogno della frontiera. Classificazione, estrazione di entità, smistamento e triage di documenti, instradamento, sintesi, redazione strutturata: tutto questo sta comodamente alla portata di modelli compatti a pesi aperti, eseguibili su hardware che possiedi davvero. Il milione di token di contesto e la capability di frontiera servono per le codebase intere e gli agenti long-horizon, non per il novanta per cento del lavoro di produzione.

Questo abilita un'architettura a livelli, il model tiering, che è anche la migliore difesa contro il lock-in: un modello piccolo e sostituibile per l'instradamento e i task semplici, un modello di frontiera invocato solo per i casi difficili, dietro lo stesso abstraction layer. Il risultato è duplice. Da un lato i costi crollano, perché paghi la frontiera solo dove serve. Dall'altro la tua esposizione sovrana si riduce alla sola quota di lavoro che richiede davvero il modello di frontiera: se quel modello sparisce, a fermarsi è una fetta del processo, non tutto. Spostare i task commodity su un modello self-hosted non è rinunciare alla qualità, è togliere una dipendenza da dove non serviva.

Un esempio concreto, dal tipo di pipeline che costruisco. Un flusso documentale aziendale che riceve fatture, contratti e ordini deve fare cinque cose: riconoscere il tipo di documento, estrarne i campi, validarli, instradare il documento al processo giusto e, solo in pochi casi ambigui, ragionare su un'eccezione. Le prime quattro sono task deterministici a basso giudizio: un modello compatto a pesi aperti, ospitato in casa, le gestisce con qualità piena e a costo marginale quasi nullo. Solo l'ultima, l'eccezione ambigua che richiede un ragionamento contestuale, viene inoltrata dietro lo stesso abstraction layer a un modello di frontiera. Il risultato è che il novanta per cento del traffico non tocca mai un'API esterna, i costi sono prevedibili e l'esposizione sovrana è confinata a quella fetta minoritaria di casi difficili. Se domani il modello di frontiera sparisce, il flusso documentale continua a funzionare in modalità degradata, con le eccezioni messe in coda per revisione umana invece di bloccare tutto. Questa è la differenza tra un'architettura che subisce il kill-switch e una che lo assorbe.

L'exit plan e la prova d'uscita

L'ultimo strato non è codice, è organizzazione, ed è quello che separa chi il 12 giugno ha ripuntato la pipeline su un altro modello in un quarto d'ora da chi ha scoperto quel giorno di non avere un piano. L'exit plan è la procedura scritta che dice, nero su bianco, cosa succede nelle prime ore in cui un modello diventa indisponibile: quali processi si fermano, quali degradano a un modello inferiore, quali possono attendere il ripristino, e chi prende la decisione. Non è burocrazia, è la differenza tra subire l'evento e governarlo.

Un piano che non hai mai provato è una speranza, non un piano. La resilienza si esercita a cadenza fissa, non si dichiara.

Il modello da copiare esiste già, e viene dal settore finanziario, che su questo è anni avanti: le prove di resilienza operativa periodiche. Una prova d'uscita trimestrale in cui si simula la perdita del modello primario e si verifica che il sistema regga, con la catena di fallback che entra, le eval di portabilità che confermano la qualità accettabile e l'exit plan che viene eseguito da chi di dovere. La prima volta che la fai scopri sempre qualcosa di rotto: ed è esattamente il punto, scoprirlo durante l'esercitazione e non durante l'emergenza.

Messo tutto insieme, progettare la sostituibilità non chiede di rinunciare ai modelli migliori, chiede di trattarli per quello che sono: componenti potenti e sostituibili, isolati dietro un layer di astrazione, con un fallback caldo già provato, una eval che misura cosa perdi cambiando, un model tiering che limita l'esposizione e un piano d'uscita esercitato. È lavoro ingegneristico ordinario, lo stesso disaccoppiamento che applichiamo da sempre al database e all'infrastruttura, spostato sul layer che il 2026 ha scoperto essere il più fragile di tutti. Se stai costruendo o rivedendo un sistema che dipende da un modello di frontiera e vuoi capire dove sei esposto e da dove cominciare a renderlo resiliente, puoi usare il modulo di preventivo gratuito: sette domande, due minuti, e ti dico se il tuo caso rientra nel mio perimetro o se ti conviene un'altra figura.

Ultima modifica: