Instradamento

Come funziona un router per LLM?

Un router trasforma una richiesta che non nomina alcuna macchina nella risposta di un endpoint. Una funzione pura filtra i candidati in base a policy e residenza, valuta ciò che sopravvive e prende il punteggio più alto.

Un endpoint in ingresso, un endpoint scelto

Un router di modelli prende una richiesta che non nomina alcuna macchina e restituisce la risposta di quella che una regola ha selezionato. Qui è volutamente piccolo: una richiesta compatibile con OpenAI arriva a un unico URL di base, e una funzione pura — nessun database, nessun orologio, nessuna rete — decide quale endpoint le risponde. Gli ingressi della funzione sono gli endpoint candidati caricati da chi chiama e l'ora corrente, ed è questo che rende ogni regola verificabile senza uno stack in esecuzione.

Il campo model decide quanta scelta ha il router. Inviando llmeu-auto (o llmeu/auto, auto, llmeu:auto) gli si consegna l'intero insieme. Nominare un modello fissa quel modello: il router sceglie allora tra gli endpoint di quell'unico modello e non ne sostituisce mai un altro, perché una sostituzione silenziosa renderebbe il campo model della risposta un'ipotesi. Gli id dei modelli vengono prima normalizzati, quindi un id con prefisso di fornitore o suffisso di data si risolve nello slug che il catalogo conosce.

Il filtro gira prima del punteggio, in un ordine fisso

Ogni endpoint candidato viene verificato contro la policy e contro la richiesta, e ogni rifiuto viene registrato con una stringa di motivo letterale. L'ordine fa parte del contratto, perché il primo motivo per cui un endpoint viene rifiutato è quello che spiega la rotta.

Un endpoint di tipo solo catalogo viene per primo: nulla su questa installazione risponde con esso, quindi viene rimosso prima che qualsiasi altra regola sia considerata. Poi quelli il cui stato non è né attivo né degradato. Poi la classe di sovranità, verificata sia contro la policy dell'organizzazione sia contro la residenza nominata dalla richiesta. Poi la regione, quando la residenza o la policy ne fissano una. Poi un modello che non sa generare testo — un modello di riconoscimento vocale, di embedding o un reranker viene rifiutato qui invece che interrogato per un completamento che non può produrre. Poi la lista di esclusione dei fornitori, la lista di ammissione dei fornitori, la lista di esclusione dei modelli e la lista di ammissione dei modelli, in quest'ordine. Poi gli endpoint partner finché il flag partner è spento. Poi un modello senza la modalità vision se la richiesta porta un'immagine. Poi la finestra di contesto, se la finestra documentata è più piccola dell'input più l'output richiesto. E infine il prezzo, contro il tetto nella policy o nella richiesta.

Nulla sopravvive a quel filtro quando la regola è davvero insoddisfacibile, e allora la risposta è 409 no_endpoint_for_policy. Il messaggio è la frase del motore stesso sulla residenza richiesta, seguita da «Residency is never relaxed silently.» Non è un guasto transitorio: la stessa richiesta fallisce di nuovo allo stesso modo, e la via d'uscita è nominare una residenza che la policy consente o allargare deliberatamente la policy nella console.

Il punteggio, e perché non è un concorso di popolarità

Ciò che sopravvive viene valutato, non ordinato per dimensione o per tabella di benchmark. L'aderenza al compito pesa cinque, l'aderenza linguistica tre, la completezza della documentazione uno, e una classe di sovranità documentata fino a due. Prezzo, latenza registrata e tasso di errore registrato sottraggono: due, due e tre rispettivamente. Prezzo e latenza sono normalizzati sull'insieme dei superstiti, così i candidati vengono confrontati tra loro invece che contro una scala fissa, e un candidato senza latenza registrata viene valutato a 500 millisecondi.

Poiché l'aderenza al compito domina, lo stesso insieme di richieste instrada diversamente per compito. Il compito economico preferisce modelli da 9B parametri o meno e fa scendere un modello da 753B a 0.15. Il recupero è deciso dalla finestra di contesto registrata, quindi un modello che porta il tag rag ma non può contenere i blocchi non vince. Una richiesta di codice preferisce uno slug specializzato nel codice, una richiesta in tedesco guadagna punti per un modello la cui lista di lingue forti contiene il tedesco, e una richiesta multilingue guadagna punti quando un modello dichiara sei o più lingue forti. I pareggi si sciolgono sul prezzo più basso, poi sulla latenza registrata più bassa, poi su un identificatore stabile — così la stessa richiesta instrada allo stesso modo due volte.

I campi di policy che lo decidono

Sei campi di policy raggiungono il filtro: quali classi di residenza e regioni sono ammesse, le liste di ammissione e di esclusione dei fornitori, le liste di ammissione e di esclusione dei modelli, se gli endpoint partner sono ammissibili o no, e un tetto di prezzo per milione di token. La richiesta può solo restringerli. Chiedere eu-owned dentro una policy che ammette eu-hosted restringe l'insieme; non può mai allargarlo. Il tetto di prezzo della richiesta può solo abbassare quello della policy.

Tre ulteriori colonne di policy sono applicate uno strato sopra il motore, intorno alla stessa decisione: la conservazione, le classi di dati ammesse e un budget giornaliero. Un budget già esaurito fa fallire la richiesta prima che qualsiasi endpoint venga valutato, con budget_exceeded. Una richiesta che non nomina alcuna residenza riceve l'insieme della policy stessa: eu-hosted finché ogni classe che la policy ammette è ospitata nell'UE, e any quando ne ammette altre.

Il failover resta dentro la decisione

Su un 5xx o su un backend irraggiungibile viene provato il candidato successivo per punteggio, fino a tre tentativi, e ogni tentativo viene registrato. Un errore che il backend contrassegna come definitivo non viene ritentato affatto. La lista dei tentativi è costruita dalla decisione già filtrata, quindi un nuovo tentativo può passare a un endpoint diverso dentro la vostra policy e mai fuori di essa: un failover che uscisse dal filtro di residenza sarebbe un bug di residenza, ed è la classe di difetto che questo disegno esiste per prevenire.

Che cosa vi dice la risposta

La risposta aggiunge un blocco accanto ai campi standard di OpenAI: l'id della trace, il modello usato, la sua versione, il fornitore, l'id dell'endpoint, la regione di inferenza, la classe di sovranità, l'id della policy, la conservazione applicata, una stima dei costi e un motivo di instradamento. Quel motivo è una frase e non un codice, e nomina la regione e la classe: instradamento automatico per un compito di codifica con residenza eu-hosted, lo slug e la regione scelti, la classe a parole, quanti endpoint sono stati esclusi e se gli endpoint partner erano ammessi. La stessa frase è mostrata alla lettera nella console, e la trace memorizzata è recuperabile tramite il suo id.

Una nota sui nomi, perché le parole si sovrappongono nei risultati di ricerca: routing è usato per diverse cose in questo campo. Quello descritto qui è il router di questo repository, e ogni regola sopra è letta dal codice che la applica — i motivi di rifiuto sono le sue stringhe letterali, i pesi sono la sua funzione di punteggio e i valori predefiniti sono i valori predefiniti delle colonne dello schema del database.

Domande frequenti

Che cosa succede se invio llmeu-auto come model?

Il router conserva ogni endpoint che passa il filtro e li valuta. La risposta riporta quale ha vinto: modello usato, regione di inferenza, classe di sovranità, id della policy e la frase di instradamento. Un pareggio si scioglie sul più economico, poi sul più veloce, poi su un id stabile.

Il router può inviare la mia richiesta fuori dalla regione che ho chiesto?

No. La residenza è applicata come filtro prima della valutazione, e la lista dei tentativi per un backend in errore è costruita dalla decisione già filtrata, fino a tre tentativi. Un endpoint fuori dall'insieme ammesso non entra mai nel confronto.

Perché nominare un modello specifico è fallito invece di instradare altrove?

Un modello nominato è fissato. Se nessuno dei suoi endpoint sopravvive, il router nomina il motivo: model_not_found, hosted_unavailable per un modello presente solo in catalogo, model_denied per una lista di policy, not_a_text_model per un modello vocale o di embedding.