Il problema dei costi nascosto nella tua fattura
Guarda il parametro del modello nel tuo codice in produzione. Per la maggior parte dei team che eseguono un carico di lavoro LLM che ha superato il prototipo ed è arrivato a traffico reale, quel parametro viene impostato una volta (di solito sul modello più potente a cui il team aveva accesso quando ha rilasciato) e non viene mai più rivisto. Ogni query, indipendentemente dalla complessità, finisce sullo stesso modello. Ed è lì che si annida lo sforamento silenzioso dei costi.
In qualsiasi carico di lavoro di produzione non banale, le query non sono tutte ugualmente difficili. Un assistente di customer support potrebbe vedere l’80% di query che sono semplici ricerche, classificazioni o brevi follow-up, e il 20% che richiedono davvero ragionamento di frontiera. Un assistente di coding potrebbe gestire un flusso costante di piccoli refactor e una lunga coda di modifiche architetturali multi-file. Una pipeline di contenuti potrebbe elaborare centinaia di task di riassunto per ogni singola richiesta che necessita di scrittura creativa strutturata. La forma del lavoro è disomogenea, ma l’instradamento verso il modello non lo è.
Se oggi stai eseguendo 100M token al mese su GPT-5.5 e il 70% di quelle query verrebbe risposto altrettanto bene da un modello più economico, stai pagando circa $600 al mese per capacità che non stai usando. A volumi più alti lo stesso schema si amplifica linearmente: per ogni 1B token, il divario tra una configurazione senza routing e una con routing è di diverse migliaia di dollari al mese.
Il routing è la risposta ingegneristica a questa asimmetria. Il principio è semplice: invia ogni query al modello più economico in grado di gestirla, ed effettua l’escalation verso un modello più capace solo quando serve. Le implementazioni sono dove vivono i compromessi interessanti, e la maggior parte delle linee guida pubblicate li gestisce male. Questo pezzo copre i tre pattern che funzionano davvero in produzione, la matematica dei costi che rende evidente il caso, le modalità di guasto che ti faranno inciampare e un playbook di migrazione per passare da una configurazione a modello singolo a una instradata senza riscrivere l’applicazione.
I dati di prezzo su cui si basa questo articolo provengono dal pezzo companion (il confronto prezzi API LLM 2026), che stabilisce le tariffe per modello a cui si fa riferimento nel testo. Quando questa guida cita una cifra di costo, è ricavata da quei dati.
I tre pattern di routing che funzionano in produzione
Esistono tre pattern consolidati per instradare il traffico LLM. Differiscono per complessità di implementazione, overhead di latenza e tipi di risparmio sbloccati. La maggior parte dei sistemi in produzione finisce per usare una combinazione di tutti e tre; capire i punti di forza di ciascuno ti aiuta a sequenziare il lavoro.
Pattern 1: Regole statiche
Il pattern più semplice. Scrivi regole che instradano le query verso modelli diversi in base a proprietà osservabili della richiesta: lunghezza dell’input, tier dell’utente, tipo di query (se hai già un classificatore), endpoint API o logica di business. Le query brevi vanno a un modello economico; le query lunghe a uno più potente. Gli utenti free-tier ottengono un modello più economico rispetto a quelli a pagamento. Le richieste di generazione di codice vanno a un modello ottimizzato per il codice; tutto il resto a un modello general-purpose.
Il routing statico è prevedibile, debuggabile e aggiunge essenzialmente zero overhead di latenza: la decisione di routing sono poche righe di codice che girano localmente. Anche il “soffitto” è più basso: stai instradando in base a proprietà che puoi osservare prima che il modello venga eseguito, il che significa che non puoi instradare in base a “quanto la query è davvero difficile” perché non lo sai ancora. Per carichi di lavoro in cui le proprietà dell’input correlano bene con la difficoltà (documenti lunghi di solito sono più difficili; il codice di solito è diverso dalla prosa; gli utenti paganti hanno tipicamente query più esigenti), le regole statiche possono catturare il 30–50% dei risparmi disponibili con pochissimo sforzo ingegneristico.
Pattern 2: Cascata
Il pattern più applicabile in assoluto. Invi la query prima a un modello economico; se la risposta soddisfa una soglia di qualità, la restituisci; se non lo fa, effettui l’escalation a un modello più capace e usi invece quella risposta. Il risparmio deriva dal fatto che, per le query che il modello economico riesce a gestire, paghi solo il prezzo del modello economico.
La caratteristica distintiva della cascata è che la decisione di routing è informata dall’output del modello, non solo dall’input: lasci che il modello economico provi a svolgere il lavoro, poi giudichi se il tentativo è stato abbastanza buono. Il giudizio può essere implementato in vari modi: punteggi di confidenza dal modello stesso, validazione di output strutturato (la risposta si parsifica nello schema atteso?), prompt di auto-valutazione (chiedere a un modello piccolo se la risposta risponde alla domanda) o segnali comportamentali downstream (l’utente ha accettato la risposta oppure ha riformulato e riprovato?).
La cascata è il pattern che la maggior parte dei sistemi in produzione finisce per adottare perché cattura risparmi che le regole statiche non possono ottenere. Il compromesso è che, sulle query che fanno escalation, paghi sia la chiamata al modello economico sia la chiamata al flagship, quindi il risparmio dipende dalla frazione di query che “riescono” al tier economico. Questo è il pattern che analizziamo in dettaglio più avanti in questo articolo.
Pattern 3: Routing basato su classificatore
Il soffitto più alto e il maggiore investimento ingegneristico. Un modello piccolo e veloce (spesso una versione fine-tuned di un modello sub-frontier, o un classificatore dedicato) guarda ogni query in ingresso e predice quale modello downstream dovrebbe gestirla. Il classificatore può decidere in base al tipo di query (“sembra un task di generazione di codice; instrada al modello ottimizzato per il codice”), stima della difficoltà (“sembra una query di ragionamento difficile; instrada a GPT-5.5”), o una policy di routing appresa e addestrata su traffico storico e risultati.
Il routing basato su classificatore può superare la cascata perché la decisione di routing avviene prima che qualsiasi modello costoso venga eseguito, quindi non paghi la “tassa del modello economico” sulle query che avrebbero comunque richiesto il flagship. Il costo è il lavoro ingegneristico per costruire, addestrare e mantenere il classificatore, più il piccolo overhead di latenza della chiamata di routing. Per carichi di lavoro ad altissimo volume, questo compromesso si ripaga; per carichi più piccoli, di solito no.
Da quale pattern partire: prima regole statiche se il tuo carico di lavoro ha segnali di routing evidenti (lunghezza input, tier utente, endpoint). Cascata se non li ha, o una volta esaurite le regole statiche ovvie. Routing basato su classificatore solo dopo che statico e cascata sono in produzione e il volume giustifica l’investimento ingegneristico. Saltare direttamente al classificatore è una classica trappola di over-engineering di cui la maggior parte dei team si pente.
Cosa misurare prima di iniziare a fare routing
Non puoi ottimizzare ciò che non misuri. Prima di introdurre qualsiasi logica di routing in un sistema in produzione, strumenta l’attuale carico di lavoro a modello singolo così da avere una baseline con cui confrontarti. La strumentazione non deve essere elaborata: un log di base di ogni richiesta con un piccolo set di campi è sufficiente per iniziare.
La strumentazione minima utile:
- Per richiesta: modello usato, conteggio token in input, conteggio token in output, costo (calcolato dai conteggi token e dal rate card), latenza end-to-end, stato della risposta (success / error / partial) ed eventualmente un’etichetta di tipo query se ne hai una.
- Per conversazione o per utente: durata sessione, numero di retry (segnala che l’utente non ha accettato la prima risposta), tasso di follow-up (segnala che la risposta ha richiesto chiarimenti).
- Un set di valutazione held-out: 100–500 query rappresentative che puoi rilanciare su qualunque modello, con output di riferimento di cui ti fidi. È così che misuri se un possibile modello più economico produce qualità accettabile sul tuo carico di lavoro. Senza, ogni decisione di routing è un’ipotesi.
Il set di valutazione è dove la maggior parte dei team investe troppo poco, ed è il pezzo di infrastruttura a leva più alta per qualsiasi progetto di routing. Strumenti leggeri come Promptfoo o Helicone evals possono metterlo in piedi rapidamente; per carichi di lavoro in fase iniziale, un set curato a mano di 50 query con output valutati manualmente è più che sufficiente per iniziare.
Una volta strumentato, esegui il carico di lavoro così com’è per almeno una settimana per stabilire la baseline. La forma dei dati (quanto è asimmetrica la distribuzione delle lunghezze input, quale frazione di query è breve e semplice, quale frazione sembra difficile) ti dice con quale pattern di routing partire.
Il pattern a cascata in dettaglio, con matematica dei costi
Il pattern a cascata merita più spazio perché è il più ampiamente applicabile e quello che la maggior parte dei team implementerà per primo o per secondo. Anche la matematica è dove il caso per il routing diventa concreto.
Considera un carico di lavoro di produzione rappresentativo che gira oggi su Claude Sonnet 4.6: 100 milioni di token al mese, 80% input e 20% output, fattura mensile di $475 a list pricing. Supponiamo di introdurre una cascata davanti: le query colpiscono prima Claude Haiku 4.5, ed effettuano escalation a Sonnet 4.6 solo se la risposta di Haiku fallisce un controllo qualità. Haiku 4.5 è listato a $1.00 input e $5.00 output per milione di token, un terzo della tariffa di Sonnet.
La matematica dei costi dipende da due parametri: quale percentuale di query “riesce” al tier Haiku (chiamiamo questo valore success rate), e come il rapporto input/output differisce tra query riuscite ed escalate. Per semplicità, assumiamo che il rapporto input/output sia lo stesso per entrambe e che il success rate sia 70%, cioè la risposta di Haiku è sufficientemente buona sul 70% delle query e il 30% fa escalation a Sonnet.
| Scenario | Calcolo del costo | Fattura mensile | Risparmio |
|---|---|---|---|
| Modello singolo: 100% Sonnet 4.6 | 100M token × tariffe Sonnet | $475 | n/a |
| Cascata: 70% Haiku, 30% Haiku→Sonnet | 100M Haiku + 30M Sonnet | $237 | 50% |
| Cascata con success rate 80% | 100M Haiku + 20M Sonnet | $190 | 60% |
| Cascata con success rate 60% | 100M Haiku + 40M Sonnet | $285 | 40% |
Cosa ti dice questo. Anche con un success rate moderato del 70% (cioè Haiku ci azzecca 7 volte su 10), la cascata dimezza la fattura. Il motivo è che la chiamata al modello economico è così tanto più economica della chiamata al flagship che pagare entrambe sul 30% di query che fanno escalation è comunque molto meno che pagare il flagship su ogni query. Il punto di break-even (dove la cascata equivale al costo del modello singolo) è circa un success rate del 33%. Sotto quel valore, conviene andare diretto; sopra, la cascata vince.
L’implementazione minima viable della cascata
Qui sotto c’è la versione più semplice del pattern, espressa in Python con il client OpenAI-compatibile (che funziona con qualsiasi provider che espone un endpoint OpenAI-compatibile, incluso Claude tramite il layer di compatibilità di Anthropic, Gemini e l’endpoint unificato di CometAPI). La struttura è deliberatamente essenziale; le implementazioni in produzione aggiungono osservabilità, gestione errori e controlli qualità più sofisticati.
from openai import OpenAI
import json
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.cometapi.com/v1", # or your provider of choice
)
CHEAP_MODEL = "claude-haiku-4-5"
FLAGSHIP_MODEL = "claude-sonnet-4-6"
def cascade(messages, output_schema=None):
"""
Run a query through a cascade.
Returns (response, model_used, escalated).
"""
# Step 1: try the cheap model
cheap_response = client.chat.completions.create(
model=CHEAP_MODEL,
messages=messages,
response_format=output_schema,
)
cheap_text = cheap_response.choices[0].message.content
# Step 2: judge whether the cheap response is good enough
if is_acceptable(cheap_text, output_schema):
return cheap_text, CHEAP_MODEL, False
# Step 3: escalate to the flagship
flagship_response = client.chat.completions.create(
model=FLAGSHIP_MODEL,
messages=messages,
response_format=output_schema,
)
flagship_text = flagship_response.choices[0].message.content
return flagship_text, FLAGSHIP_MODEL, True
def is_acceptable(response_text, output_schema=None):
"""
Quality gate.
Returns True if the cheap model's output is good enough.
"""
if not response_text or len(response_text.strip()) < 10:
return False
if output_schema:
# Structured output: it has to parse against the schema
try:
parsed = json.loads(response_text)
return validate_schema(parsed, output_schema)
except (json.JSONDecodeError, ValueError):
return False
# For free-form responses, plug in your own quality signal:
# - confidence score from the model
# - self-evaluation prompt to a small model
# - rules-based checks (length, format, refusal patterns)
return True
Questo è un punto di partenza, non un’implementazione finita. Tre cose che aggiungeresti per la produzione:
- Un vero quality gate. La funzione is_acceptable sopra è intenzionalmente minimale. In pratica, il gate è il pezzo più importante della cascata: troppo permissivo e distribuisci risposte di bassa qualità; troppo severo e fai escalation troppo spesso e perdi i risparmi. La maggior parte delle cascate in produzione usa una combinazione di validazione dell’output strutturato, rilevamento dei rifiuti (il modello economico dice “non posso rispondere”), e auto-valutazione da parte di un modello piccolo con prompt che lo istruisce a valutare la risposta.
- Osservabilità per richiesta. Logga quale modello è stato usato, se la richiesta ha fatto escalation, la latenza a ciascun tier e il costo. È ciò che ti dice, dopo una settimana di esecuzione della cascata, se il success rate è quello che avevi ipotizzato.
- Un percorso canary per la valutazione. Invia una piccola percentuale di traffico (diciamo 5%) al flagship anche quando la cascata “riesce” al tier economico. Confronta le risposte su un task di grading held-out. È così che intercetti degradazioni silenziose di qualità; vedi la sezione successiva.
Dove il routing si rompe
La matematica del risparmio sopra è reale, ma è anche il caso ottimistico. Tre modalità di guasto fanno inciampare i team, e chiamarle per nome onestamente è ciò che separa un’implementazione di routing che accumula valore da una che degrada silenziosamente il prodotto.
Overhead di latenza sulle richieste che fanno escalation
Quando una query fa escalation, paghi la chiamata al modello economico prima che inizi la chiamata al flagship. Se il modello economico impiega 800ms e il flagship 1.5s, la query in escalation impiega 2.3s end-to-end. Per carichi di lavoro sensibili alla latenza, questo conta. Le mitigazioni sono scegliere un modello economico veloce (Haiku 4.5 e Gemini 3 Flash sono progettati per questo), impostare timeout aggressivi sulla chiamata al modello economico, e considerare chiamate in parallelo per le query che sospetti siano più propense a fare escalation. Alcuni team accettano il costo di latenza perché il risparmio in dollari è grande; altri usano regole statiche per evitare di mandare query ovviamente difficili nella cascata in assoluto.
Degradazione silenziosa della qualità
La modalità di guasto più insidiosa. Il modello economico produce risposte che passano il tuo quality gate ma sono sottilmente peggiori delle risposte del flagship: leggermente meno accurate, leggermente meno utili, leggermente più propense a mancare edge case. Gli utenti non si lamentano subito; le metriche che guardi (latenza risposta, error rate, gate pass rate) sembrano tutte ok; ma le metriche downstream (retention, conversion rate, escalation al supporto) deragliano. Quando te ne accorgi, hai già distribuito settimane di qualità degradata.
La difesa è il percorso canary menzionato sopra: una percentuale held-out di traffico che gira sul flagship in parallelo alla cascata, con entrambe le risposte valutate rispetto a una rubric di valutazione. La valutazione può essere fatta da un modello stesso (LLM-as-judge) o da review umane campionate. Il punto è mantenere un segnale continuo di qualità indipendente dal gate della cascata, così la degradazione emerge come drift in quel segnale invece che come sorpresa downstream.
Costo di complessità nel codice e nell’osservabilità
Ogni modello aggiuntivo nel grafo di routing è un altro modello da valutare, monitorare e aggiornare quando il provider rilascia una nuova versione. Una cascata a due tier è gestibile; un router basato su classificatore a cinque modelli con percorsi separati per code, RAG, chat, agenti ed edge case è significativamente più complesso del setup a modello singolo che ha sostituito. La complessità vale quando il volume del carico di lavoro lo giustifica; sotto quel volume, il tempo ingegneristico speso a mantenere lo strato di routing può superare i risparmi che produce. Sii onesto sul tuo volume soglia.
Come aiutano gli aggregator (e dove no)
Gli aggregator LLM (servizi che espongono più modelli dietro una singola API OpenAI-compatibile) interagiscono con il routing in due modi distinti. Entrambi vale la pena capirli perché la risposta a “voglio un aggregator nel mio stack di routing?” dipende da quale interazione ti interessa.
L’aiuto reale: rimuovere la integration tax
Costruire una cascata o un router basato su classificatore usando API dirette dei provider significa gestire più SDK, più credenziali di autenticazione, più superfici di billing e più set di particolarità provider-specifiche (comportamento dei timeout, formati errori, semantica rate-limit). Per un setup di routing multi-modello, questo overhead è reale. Un aggregator come CometAPI espone ogni modello dietro un unico endpoint OpenAI-compatibile, il che significa che il cambio di codice per il routing è solo modificare il parametro model, senza switching tra provider, senza chiavi separate, senza uno strato di osservabilità separato. Per i team il cui ostacolo principale al routing è il costo di integrazione piuttosto che il costo di valutazione qualità, questo è decisivo.
La cosa a cui fare attenzione: strati di routing “built-in”
Alcuni aggregator offrono una feature di “smart routing” o “model optimiser” che sceglie il modello per te in base alla query. Può essere utile per prototipare ma in genere è il default sbagliato per la produzione. Il motivo è che la decisione di routing è una delle cose più specifiche del carico di lavoro nel tuo stack: ciò che conta come “abbastanza difficile da fare escalation” dipende dai tuoi criteri di valutazione, dal budget di latenza, dalla soglia di qualità e dal tetto di costo. Uno strato di routing generico non può conoscere nulla di tutto questo. La maggior parte dei sistemi in produzione è servita meglio da un aggregator sottile e trasparente (uno che espone gli stessi modelli che useresti direttamente, con una credenziale e una fattura) più la propria logica di routing sopra, piuttosto che da uno strato di routing black-box che non possono tarare.
Il playbook di migrazione
Un percorso sicuro, step-by-step, per passare da un carico di lavoro in produzione a modello singolo a uno instradato. Il principio lungo tutto il percorso è fare cambiamenti individualmente reversibili e misurare l’impatto di ogni cambiamento prima di fare il successivo.
- Strumenta il carico di lavoro attuale. Logga ogni richiesta con modello, token input/output, costo, latenza e un’etichetta di tipo query. Esegui per almeno una settimana per stabilire una baseline. Senza questo, ogni step successivo è un’ipotesi.
- Costruisci il set di valutazione. Cura 100–500 query rappresentative con output di riferimento di cui ti fidi. È il set held-out che userai per confrontare la cascata con la baseline a modello singolo a ogni step.
- Identifica il tipo di query a volume più alto. Dai dati di strumentazione, trova la categoria di query che rappresenta più traffico. È qui che piloterai la cascata. Non deve essere la categoria più facile, solo la più volumetrica, perché è lì che si concentrano i risparmi.
- Costruisci un prototipo di cascata per quel solo tipo di query. Due tier: modello economico prima, flagship se fallisce il quality gate. Eseguilo prima sul set di valutazione. Confronta costo e qualità con la baseline a modello singolo. Se la qualità regge e il costo scende, procedi; se la qualità scende, rendi il gate più severo e riprova.
- Rilascia dietro una percentuale di traffico. Parti con il 5–10% del traffico di produzione per il tipo di query scelto. Esegui per almeno una settimana. Monitora escalation rate della cascata, costo per richiesta, latenza a ciascun tier e il confronto qualità del percorso canary. Se le metriche corrispondono alla previsione del prototipo, espandi al 25%, poi 50%, poi 100%.
- Ripeti per il tipo di query successivo. Una volta che il primo tipo di query è completamente migrato e il risparmio è realizzato, passa alla successiva categoria per volume. Ogni cascata è una decisione separata; non assumere che un pattern che ha funzionato per un tipo di query funzionerà per un altro.
- Aggiungi un canary di qualità continuo. Quando più tipi di query girano su cascate, imposta permanentemente il percorso canary held-out, con il 5% del traffico che gira sul flagship per il grading. È il tuo sistema di early-warning contro la degradazione silenziosa, ed è ciò che mantiene affidabile lo strato di routing mentre i modelli vengono aggiornati.
Quando il routing non vale la pena
Riconoscimento onesto. Esistono carichi di lavoro in cui l’investimento ingegneristico nel routing non si ripaga, e riconoscerli in anticipo fa risparmiare tempo:
- Carichi di lavoro a modello singolo in cui un modello è davvero la risposta giusta per tutto. Se il tuo set di valutazione mostra un calo di qualità significativo al tier del modello economico su tutto il carico di lavoro, la cascata non ha su cosa lavorare. Un carico di lavoro di generazione di codice vincolato dalla capacità di ragionamento è un esempio: Haiku fallirà il gate troppo spesso perché la cascata faccia risparmiare denaro.
- Carichi di lavoro a volume molto basso. Sotto circa $200/mese di spesa LLM, il tempo ingegneristico speso a costruire e mantenere lo strato di routing tipicamente supera i risparmi. La soglia dipende dal carico di lavoro, ma è reale. Sii onesto sul fatto che la tua spesa sia abbastanza alta da giustificare il lavoro.
- Ambienti regolamentati in cui conta il vendor-of-record. Se il tuo assetto di compliance richiede che tutto il traffico di produzione passi attraverso una relazione specifica con un provider, il routing multi-modello complica la conversazione. Possono comunque esistere opzioni di routing intra-provider (Sonnet → Opus su Anthropic; GPT-5 nano → GPT-5.5 su OpenAI), ma il routing cross-provider è più difficile da giustificare.
L’inquadramento onesto: il routing si ripaga quando il tuo carico di lavoro è ad alto volume, le query non sono uniformemente difficili e hai l’infrastruttura di valutazione per sapere quando la cascata produce qualità accettabile. La maggior parte dei carichi di lavoro in produzione a scala significativa corrisponde a questa descrizione; alcuni no, e rilasciano più velocemente restando su un modello singolo. Entrambe le scelte sono difendibili.
Dove andare dopo: Se non hai già esaminato il rate card per modello su cui questo articolo si basa, il pezzo companion, The 2026 LLM API Pricing Comparison: GPT-5.5, Claude Sonnet 4.6, Gemini 3.5 Flash and DeepSeek V4, è la base. I dati di prezzo lì sono ciò che rende concreta la matematica dei costi in questa guida sul tuo carico di lavoro specifico.
