Routing API LLM affidabile: timeout, nuovi tentativi e fallback del modello senza regressioni semantiche
Un'architettura pratica per classificare gli errori dell'API LLM, applicare un budget di latenza, selezionare modelli di fallback compatibili, proteggere gli effetti collaterali e convalidare ogni risposta accettata.
Una richiesta di fallback non ha esito positivo semplicemente perché un altro modello ha restituito HTTP 200. La sostituzione potrebbe superare il budget di latenza originale, omettere JSON campi obbligatori, richiamare uno strumento diverso o produrre una risposta con semantica sostanzialmente diversa. L'instradamento LLM API affidabile richiede quindi più di un elenco ordinato di modelli: richiede un contratto, un classificatore di errori, una policy di tentativo limitato e una convalida prima dell'accettazione.
La regola centrale è semplice: riprovare solo quando l'errore è plausibilmente temporaneo e ricorrere solo quando il percorso successivo può ancora soddisfare il contratto di richiesta originale.
Definisci il contratto di instradamento prima di scegliere i modelli
Inizia descrivendo cosa deve fornire una risposta efficace. Questo contratto di routing deve essere leggibile dalla macchina e allegato a ciascun carico di lavoro o classe di richiesta.
{
"workload": "invoice_extraction",
"modalities": ["text", "image"],
"max_input_tokens": 50000,
"requires_tools": false,
"structured_output": {
"required": true,
"schema_id": "invoice-v3",
"strict": true
},
"allowed_model_classes": ["document-extraction"],
"max_cost_usd": 0.08,
"deadline_ms": 8000
}
Il contratto deve coprire le modalità richieste, la capacità del contesto, il supporto degli strumenti, il comportamento dell'output strutturato, le classi di modelli accettabili, il costo massimo e la scadenza end-to-end. Aggiungi vincoli specifici dell'applicazione dove necessario, come regioni consentite, lunghezza minima dell'output o un motivo di fine richiesto.
Raccomandazione: mantieni gruppi di percorsi testati e separati per testo semplice, output vincolato dallo schema, utilizzo degli strumenti, visione e richieste a contesto lungo. Un modello che rappresenta un testo di riserva accettabile non è automaticamente un fallback accettabile per la chiamata di strumenti o l'input di immagini.
Classificare l'errore prima di agire
Errori di autenticazione, richieste non valide, limiti di velocità ed errori del server richiedono risposte diverse. Trattare ogni risposta non riuscita come riprovabile spreca capacità e può nascondere difetti.
| Classe di errore | Esempi | Azione predefinita |
|---|---|---|
| Richiesta non riuscita permanente | Credenziali non valide, parametri non validi, funzionalità non supportata | Interrompi e restituisci un errore cancellabile |
| Incompatibilità del percorso | Contesto troppo grande, input immagine non supportato, modalità schema non disponibile | Prova solo un percorso compatibile |
| Errore di trasporto temporaneo | Reimpostazione della connessione, errore DNS, timeout selezionato | Riprova entro il budget rimanente |
| Capacità o velocità di errore | HTTP 429, servizio sovraccarico, risposte 5xx selezionate | Rispetta i suggerimenti per nuovi tentativi o utilizza un fallback sano |
| Risposta riuscita non valida | Formato non valido JSON, strumento sconosciuto, campo obbligatorio mancante | Rifiuta, quindi riprova o fallback se i criteri lo consentono |
| Esecuzione ambigua | Connessione persa dopo che il provider potrebbe aver accettato la richiesta | Deduplica prima della riproduzione |
Fatto: le richieste con velocità limitata non riuscite possono comunque essere conteggiate ai fini dei limiti del fornitore. Tentativi immediati aggressivi potrebbero quindi accentuare la limitazione invece di risolverla. Inoltre, i nuovi tentativi consumano capacità aggiuntiva durante un'interruzione e le policy dei nuovi tentativi a diversi livelli dell'applicazione possono moltiplicare il carico risultante.
Raccomandazione: lascia che sia un livello a effettuare i tentativi di generazione del modello. In un'architettura tipica, il gateway AI API è il proprietario giusto perché rileva l'integrità del percorso, la cronologia dei tentativi, la latenza e i costi. Disattiva i tentativi automatici nei client di livello inferiore, ove possibile, oppure conteggiali esplicitamente nello stesso budget di tentativi.
Spendi un budget per la latenza end-to-end
I timeout per tentativo non sono sufficienti. Tre tentativi con un timeout di cinque secondi possono trasformare un'operazione prevista di cinque secondi in una risposta di quindici secondi, prima che vengano inclusi il backoff e la convalida.
Registra una scadenza assoluta quando la richiesta entra nel gateway. Prima di ogni tentativo, calcola il tempo rimanente:
remaining = deadline - current_time
required = connect_allowance + generation_allowance + validation_allowance
if remaining < required:
stop_without_launching_another_attempt
Per una scadenza di otto secondi, un'allocazione iniziale ragionevole potrebbe riservare 300 ms per il lavoro del gateway e la convalida finale, consentire fino a 4,5 secondi per il percorso principale e conservare circa 3,2 secondi per un fallback. Questi valori sono un esempio, non un punto di riferimento. Devono derivare dalle distribuzioni di latenza misurate per i fornitori, i modelli, le regioni e le dimensioni di output effettivi.
Utilizza backoff esponenziale limitato con jitter per tentativi temporanei:
delay = random(0, min(cap, base * 2^retry_index))
I suggerimenti per i nuovi tentativi del fornitore, ad esempio il valore riprova dopo, dovrebbero avere la precedenza quando rientrano nella scadenza rimanente. Arrestarsi dopo un numero limitato di tentativi. Una policy comune prevede un tentativo principale più un fallback, con un tentativo facoltativo sullo stesso percorso solo in caso di errore di connessione anticipato che non avrebbe potuto generare output fatturabile.
Compromesso: il fallback sequenziale migliora la disponibilità ma aumenta la latenza della coda. Le richieste parallele o coperte possono ridurre la latenza durante i rallentamenti, ma consumano più capacità e possono comportare addebiti per più generazioni riuscite. La copertura dovrebbe essere limitata ai carichi di lavoro critici in termini di latenza e privi di effetti collaterali, con cancellazione e controllo dei costi.
Seleziona i fallback in base alla capacità, non al ranking
Una tabella di fallback dovrebbe codificare la compatibilità anziché un ordine di preferenza globale. Filtra i percorsi candidati in base al contratto prima di considerare integrità, latenza o prezzo.
candidates = routes
.filter(supports_required_modalities)
.filter(context_limit >= estimated_input_size)
.filter(supports_required_tools)
.filter(supports_requested_schema_mode)
.filter(model_class in allowed_model_classes)
.filter(estimated_cost <= remaining_cost_budget)
.filter(not_temporarily_suppressed)
selected = rank(candidates, health, latency, cost)
Il supporto dell'output strutturato merita un test esplicito. Anche quando due percorsi pubblicizzano la generazione vincolata dallo schema, potrebbero supportare diversi sottoinsiemi di schemi JSON o interpretare i casi limite in modo diverso. Allo stesso modo, i modelli compatibili con gli strumenti possono differire nella selezione dello strumento, nella costruzione degli argomenti e nel comportamento delle chiamate parallele.
Fatto: cambiare famiglia di modelli può preservare la disponibilità del trasporto cambiando stile, qualità del ragionamento, comportamento di sicurezza, tokenizzazione e selezione degli strumenti. HTTP il successo non è prova di equivalenza semantica.
Previsione: con l'espansione dei cataloghi di modelli, le policy di routing di produzione utilizzeranno sempre più profili di capacità con versione e test di accettazione specifici del carico di lavoro invece di elenchi di modelli statici. Considera questo come un'indicazione di progettazione, non una garanzia sul comportamento del fornitore.
Convalida la risposta prima di accettarla
Esegui ogni risposta, inclusa la risposta primaria, attraverso la stessa pipeline di accettazione. La convalida dovrebbe avvenire prima che il risultato venga memorizzato nella cache, fatturato internamente come riuscito o passato a un esecutore dello strumento.
- Conferma che il trasporto è stato completato e che la busta di risposta può essere analizzata.
- Controlla il motivo della fine e rifiuta il troncamento quando è richiesto l'output completo.
- Convalida l'output strutturato rispetto allo schema originale.
- Verifica i campi obbligatori, i valori enum e le invarianti dell'applicazione.
- Consenti solo nomi di strumenti registrati e convalida gli argomenti rispetto a ciascuno schema di strumenti.
- Applica controlli semantici specifici del carico di lavoro laddove la falsa accettazione sarebbe costosa.
Per l'estrazione delle fatture, i controlli semantici potrebbero richiedere un totale non negativo, un codice valuta supportato e totali delle voci entro una tolleranza definita esplicitamente. Per la classificazione, richiedere un'etichetta dal set consentito. Per la generazione del codice, l'analisi o la compilazione potrebbero essere appropriate. Questi controlli non dimostrano la qualità, ma impediscono che le prevedibili violazioni contrattuali vengano trattate come successi.
Non riparare silenziosamente ogni risposta non valida. La normalizzazione deterministica, come la rimozione degli spazi bianchi circostanti innocui, può essere accettabile. Indovinare campi finanziari mancanti o riscrivere gli argomenti dello strumento cambia il significato del modello e dovrebbe innescare il rifiuto o la revisione umana.
Separare i tentativi di generazione dagli effetti collaterali
Le richieste LLM utilizzano comunemente HTTP POST, che non è intrinsecamente idempotente. Ancora più importante, una risposta del modello può avviare un’azione esterna come l’addebito di un metodo di pagamento, l’invio di un messaggio, la creazione di un ticket o la modifica dell’infrastruttura. Riprovare a generare e riprodurre l'azione sono decisioni separate.
Assegna un ID operazione al limite dell'applicazione e un ID tentativo a ogni chiamata del modello. Mantieni lo stato di esecuzione dello strumento rispetto a una chiave deterministica, ad esempio:
execution_key = operation_id + tool_name + canonical_arguments_hash
Prima di eseguire uno strumento, controlla se la chiave è in sospeso, completata o non riuscita. Restituisce il risultato memorizzato per un'esecuzione completata anziché eseguirla nuovamente. Per le operazioni i cui argomenti possono cambiare legittimamente, è necessaria l'approvazione a livello di applicazione o un nuovo ID operazione.
Un timeout ambiguo richiede una gestione speciale. Se la connessione fallisce dopo la trasmissione di una richiesta, il gateway potrebbe non sapere se è avvenuta la generazione. Una chiave di idempotenza supportata dal provider può essere utile, se disponibile. In caso contrario, registra il risultato come sconosciuto e applica una policy di riproduzione specifica del carico di lavoro invece di dare per scontato che non sia successo nulla.
Elimina i percorsi non integri ed esponi ogni tentativo
Un interruttore di circuito o una soppressione temporanea dell'integrità impedisce a ogni nuova richiesta di ritrovare lo stesso percorso con errori. Aprire il circuito dopo un tasso di errore definito o una soglia di guasto consecutivo, quindi ammettere sonde limitate in uno stato semiaperto. Ottimizza le soglie in base al percorso e alla classe di errore in modo che una richiesta del client in formato errato non possa far apparire non disponibile un modello integro.
Registra un evento a livello di richiesta e un evento per tentativo. I campi utili includono ID operazione, ID tentativo, provider e modello selezionati, classe di errore, codice di stato, latenza, conteggi di token, costo stimato, motivo del fallback, risultato della convalida, stato del circuito e risultato finale. Oscura o esegui l'hashing di prompt, output e argomenti dello strumento in base ai requisiti di sensibilità e conservazione.
I parametri operativi utili includono tasso di fallback, tentativi per richiesta completata, tasso di esaurimento della scadenza, tasso di rifiuto della convalida, risultati ambigui, costo per risposta accettata e latenza per percorso finale. Un tasso di successo in aumento HTTP insieme a un tasso di rifiuto di convalida in aumento è un avvertimento che la disponibilità del trasporto sta mascherando i fallimenti dei contratti.
Elenco di controllo per l'implementazione della produzione
- Definisci un contratto di routing con versione per ogni classe di carico di lavoro.
- Mappa gli errori del fornitore in categorie permanenti, temporanee, incompatibili, con risposte non valide e ambigue.
- Scegli un proprietario per i nuovi tentativi e limita il numero totale di tentativi.
- Propagare una scadenza assoluta tramite gateway, client del fornitore, convalida ed esecuzione dello strumento.
- Crea gruppi di fallback con funzionalità testate anziché una catena di modelli globale.
- Convalida schemi, chiamate agli strumenti, motivi di finitura e invarianti di dominio.
- Deduplica gli effetti collaterali con le chiavi di operazione ed esecuzione.
- Aggiungi la soppressione del percorso con sonde semiaperte delimitate.
- Registra latenza a livello di tentativo, token, costi, errori e risultati di accettazione.
- Timeout di iniezione, 429, errori 5xx selezionati, formato non valido JSON, overflow del contesto e operazioni lente nella gestione temporanea.
Inizia con un percorso principale e un percorso di riserva compatibile per un singolo carico di lavoro a basso rischio. Confronta la qualità, la latenza e i costi delle risposte accettate prima di espandere la policy. L’obiettivo non è il tasso di fallback più alto possibile. È un sistema limitato che restituisce una risposta che soddisfa il contratto originale o fallisce chiaramente prima di causare lavoro duplicato o danni semantici.