Rutare API LLM fiabilă: timeout-uri, reîncercări și modele de rezervă fără regresii semantice
O arhitectură practică pentru clasificarea eșecurilor API-ului LLM, aplicarea unui buget de latență, selectarea modelelor de rezervă compatibile, protejarea efectelor secundare și validarea fiecărui răspuns acceptat.
O solicitare de rezervă nu reușește doar pentru că un alt model a returnat HTTP 200. Înlocuirea poate depăși bugetul inițial de latență, poate omite câmpurile JSON obligatorii, poate apela un alt instrument sau poate produce un răspuns cu o semantică semnificativ diferită. Prin urmare, rutarea fiabilă API LLM necesită mai mult decât o listă ordonată de modele: necesită un contract, un clasificator de eșec, o politică de încercare limitată și validare înainte de acceptare.
Regula centrală este simplă: reîncercați numai atunci când eșecul este plauzibil temporar și reveniți numai atunci când următoarea rută poate încă îndeplini contractul de solicitare inițial.
Definiți contractul de rutare înainte de a alege modelele
Începeți prin a descrie ce trebuie să ofere un răspuns de succes. Acest contract de rutare trebuie să poată fi citit de mașină și să fie atașat fiecărei sarcini de lucru sau clase de solicitare.
{
"workload": "invoice_extraction",
„modalities”: [„text”, „imagine”],
„max_input_tokens”: 50000,
„requires_tools”: fals,
„structured_output”: {
„necesar”: adevărat,
"schema_id": "invoice-v3",
„strict”: adevărat
},
"allowed_model_classes": ["extracția documentului"],
„max_cost_usd”: 0,08,
„deadline_ms”: 8000
}
Contractul ar trebui să acopere modalitățile necesare, capacitatea contextului, suportul pentru instrumente, comportamentul de ieșire structurată, clasele de model acceptabile, costul maxim și termenul limită de la capăt la capăt. Adăugați constrângeri specifice aplicației acolo unde este necesar, cum ar fi regiuni permise, lungime minimă de ieșire sau un motiv de finisare necesar.
Recomandare: mențineți grupuri de rute separate și testate pentru text simplu, rezultate limitate de schemă, utilizarea instrumentelor, viziune și solicitări de context lung. Un model care este un text alternativ acceptabil nu este în mod automat o alternativă acceptabilă pentru apelarea instrumentelor sau introducerea imaginii.
Clasificați eșecul înainte de a lua măsuri
Erorile de autentificare, solicitările incorecte, limitele de viteză și defecțiunile serverului necesită răspunsuri diferite. Tratarea fiecărui răspuns nereușit ca pe o capacitate care poate fi reîncercată pierde și poate ascunde defecte.
Realitate: solicitările nereușite cu limitarea ratei pot fi luate în considerare în continuare pentru limitele furnizorilor. Prin urmare, reîncercările imediate agresive pot aprofunda accelerarea în loc să o rezolve. Reîncercările consumă, de asemenea, capacitate suplimentară în timpul unei întreruperi, iar politicile de reîncercare la mai multe straturi de aplicație pot multiplica încărcarea rezultată.
Recomandare: permiteți unui strat propriul reîncercări de generare a modelului. Într-o arhitectură tipică, poarta AI API este proprietarul potrivit, deoarece vede starea rutei, istoricul încercărilor, latența și costul. Dezactivați reîncercările automate la clienții de nivel inferior, acolo unde este posibil, sau numărați-le în mod explicit în același buget de încercare.
Cheltuiți un buget de latență de la capăt la capăt
Timpurile de expirare per încercare sunt insuficiente. Trei încercări cu un timeout de cinci secunde pot transforma o operațiune intenționată de cinci secunde într-un răspuns de cincisprezece secunde, înainte de a include backoff-ul și validarea.
Înregistrați un termen limită absolut atunci când solicitarea intră pe gateway. Înainte de fiecare încercare, calculați timpul rămas:
remaining = deadline - current_time
necesar = connect_allowance + generation_allowance + validation_allowance
dacă rămâne < necesar:
opriți_fără_lansarea_o altă_încercare
Pentru un termen limită de opt secunde, o alocare inițială rezonabilă poate rezerva 300 ms pentru lucrul la gateway și validarea finală, poate permite până la 4,5 secunde pentru ruta principală și poate păstra aproximativ 3,2 secunde pentru o rezervă. Aceste valori sunt un exemplu, nu un reper. Acestea trebuie să fie derivate din distribuțiile de latență măsurate pentru furnizorii, modelele, regiunile și dimensiunile de ieșire efective.
Utilizați retragerea exponențială limitată cu fluctuații pentru reîncercări tranzitorii:
întârziere = aleatoriu(0, min(cap, bază * 2^retry_index))
Sugestiile de reîncercare ale furnizorului, cum ar fi valoarea de reîncercare după, ar trebui să aibă prioritate atunci când se încadrează în termenul limită rămas. Opriți-vă după un număr mic de încercări. O politică comună este o încercare primară plus o alternativă, cu o reîncercare opțională pe aceeași rută numai pentru o eroare de conexiune timpurie care nu ar fi putut genera rezultate facturabile.
Compartiment: alternativă secvențială îmbunătățește disponibilitatea, dar crește latența finală. Solicitările paralele sau acoperite pot reduce latența în timpul încetinirilor, dar consumă mai multă capacitate și pot suporta taxe pentru mai multe generații de succes. Acoperirea ar trebui să fie limitată la sarcini de lucru critice pentru latență, fără efecte secundare, cu anulare și control al costurilor.
Selectați alternative în funcție de capacitate, nu de rang
Un tabel alternativ ar trebui să codifice compatibilitatea mai degrabă decât o ordine globală de preferințe. Filtrați rutele candidate în raport cu contractul înainte de a lua în considerare starea de sănătate, latența sau prețul.
candidați = rute
.filter(supports_required_modalities)
.filter(limită_context >= mărime_intrare_estimată)
.filter(supports_required_tools)
.filter(supports_requested_schema_mode)
.filter(clasa_model în clasele_model permise)
.filter(cost_estimat <= buget_cost_remanat)
.filter(nu_temporar_suppressed)
selectat = rang(candidați, sănătate, latență, cost)
Suportul pentru ieșiri structurate merită testare explicită. Chiar și atunci când două rute promovează generarea constrânsă de schemă, ele pot accepta diferite subseturi de schemă JSON sau pot interpreta cazurile marginale în mod diferit. Modelele capabile de instrumente pot diferi, de asemenea, în ceea ce privește selecția uneltelor, construcția argumentelor și comportamentul apelului în paralel.
Realitate: schimbarea familiilor de modele poate păstra disponibilitatea transportului în același timp schimbând stilul, calitatea raționamentului, comportamentul de siguranță, tokenizarea și selecția instrumentelor. Succesul HTTP nu este o dovadă a echivalenței semantice.
Predicție: pe măsură ce cataloagele de modele se extind, politicile de rutare a producției vor folosi din ce în ce mai mult profiluri de capabilități versionate și teste de acceptare specifice sarcinii de lucru în loc de liste de modele statice. Tratați acest lucru ca pe o direcție de proiectare, nu ca pe o garanție privind comportamentul furnizorului.
Validați răspunsul înainte de a-l accepta
Rulați fiecare răspuns, inclusiv răspunsul principal, prin același canal de acceptare. Validarea ar trebui să aibă loc înainte ca rezultatul să fie stocat în cache, facturat intern ca reușit sau transmis unui executant de instrumente.
- Confirmați că transportul a fost finalizat și plicul de răspuns poate fi analizat.
- Verificați motivul finalizării și respingeți trunchierea când este necesară o ieșire completă.
- Validați rezultatul structurat față de schema originală.
- Verificați câmpurile obligatorii, valorile de enumerare și invarianții aplicației.
- Permiteți numai nume de instrumente înregistrate și validați argumentele pentru fiecare schemă de instrumente.
- Aplicați verificări semantice specifice sarcinii de lucru acolo unde acceptarea falsă ar fi costisitoare.
Pentru extragerea facturii, verificările semantice pot necesita un total nenegativ, un cod valutar acceptat și totaluri ale elementelor rând într-o toleranță definită în mod explicit. Pentru clasificare, solicitați o etichetă din setul permis. Pentru generarea codului, analizarea sau compilarea poate fi adecvată. Aceste verificări nu dovedesc calitatea, dar împiedică ca încălcările previzibile ale contractului să fie tratate drept succese.
Nu reparați în tăcere fiecare răspuns defectuos. Normalizarea deterministă, cum ar fi eliminarea spațiului alb inofensiv din jur, poate fi acceptabilă. Ghicirea câmpurilor financiare lipsă sau rescrierea argumentelor instrumentului schimbă semnificația modelului și ar trebui să declanșeze respingerea sau revizuirea umană.
Separați încercările de generație de efectele secundare
Solicitările LLM folosesc de obicei HTTP POST, care nu este în mod inerent idempotent. Mai important, un răspuns model poate iniția o acțiune externă, cum ar fi taxarea unei metode de plată, trimiterea unui mesaj, crearea unui bilet sau modificarea infrastructurii. Reîncercarea de generare și reluarea acelei acțiuni sunt decizii separate.
Atribuiți un ID de operație la limita aplicației și un ID de încercare fiecărui apel de model. Persistați starea de execuție a instrumentului față de o cheie deterministă, cum ar fi:
execution_key = operation_id + tool_name + canonical_arguments_hash
Înainte de a executa un instrument, verificați dacă acea cheie este în așteptare, finalizată sau eșuată. Returnează rezultatul stocat pentru o execuție finalizată, în loc să-l ruleze din nou. Pentru operațiunile ale căror argumente se pot schimba în mod legitim, necesită aprobare la nivel de aplicație sau un nou ID de operație.
O expirare ambiguă necesită o gestionare specială. Dacă conexiunea eșuează după ce a fost transmisă o solicitare, este posibil ca gateway-ul să nu știe dacă a avut loc generarea. O cheie de idempotenta susținută de furnizor poate ajuta atunci când este disponibilă. În caz contrar, înregistrați rezultatul ca necunoscut și aplicați o politică de reluare specifică sarcinii de lucru în loc să presupuneți că nu s-a întâmplat nimic.
Suprimați rutele nesănătoase și expuneți orice încercare
Un întrerupător de circuit sau o suprimare temporară a sănătății împiedică fiecare nouă solicitare să redescopere aceeași rută eșuată. Deschideți circuitul după o rată de eroare definită sau un prag de eșec consecutiv, apoi admiteți sonde limitate într-o stare pe jumătate deschisă. Ajustați pragurile în funcție de rută și clasa de eșec, astfel încât o solicitare de client incorect să nu facă ca un model sănătos să pară indisponibil.
Înregistrați un eveniment la nivel de solicitare și un eveniment per încercare. Câmpurile utile includ ID-ul operațiunii, ID-ul încercării, furnizorul și modelul selectat, clasa de eșec, codul de stare, latența, numărul de simboluri, costul estimat, motivul alternativ, rezultatul validării, starea circuitului și rezultatul final. Redactați sau hash prompturile, ieșirile și argumentele instrumentului în funcție de sensibilitatea și cerințele lor de păstrare.
Valoriile operaționale utile includ rata de rezervă, încercările pentru fiecare solicitare finalizată, rata de epuizare a termenului limită, rata de respingere a validării, rezultatele ambigue, costul pe răspuns acceptat și latența după ruta finală. O rată de succes HTTP în creștere, alături de o rată în creștere de respingere a validării, este un avertisment că disponibilitatea transportului maschează eșecurile contractului.
Lista de verificare a lansării producției
- Definiți un contract de rutare cu versiuni pentru fiecare clasă de sarcină de lucru.
- Cartați erorile furnizorului în categorii permanente, tranzitorii, incompatibile, cu răspuns invalid și ambigue.
- Alegeți un proprietar de reîncercare și limitați numărul total de încercări.
- Propagați un termen limită absolut prin gateway, client furnizor, validare și execuție a instrumentului.
- Construiți grupuri alternative testate în funcție de capabilități, mai degrabă decât un lanț global de modele.
- Validați schemele, apelurile de instrumente, motivele de finalizare și invarianții de domeniu.
- Deduplicați efectele secundare cu tastele de operare și execuție.
- Adăugați suprimarea rutei cu sonde întredeschise delimitate.
- Înregistrați latența la nivel de încercare, indicativele, costul, eșecurile și rezultatele acceptării.
- Timp de injectare, 429 s, erori selectate 5xx, JSON incorect, depășire de context și succese lente în montare.
Începeți cu o rută principală și o alternativă compatibilă pentru un singur volum de lucru cu risc scăzut. Comparați calitatea răspunsului acceptat, latența și costul înainte de a extinde politica. Obiectivul nu este cea mai mare rată posibilă de rezervă. Este un sistem limitat, care fie returnează un răspuns care satisface contractul inițial, fie eșuează clar înainte de a provoca lucrări duplicate sau daune semantice.