Niezawodny routing API LLM: przekroczenia limitu czasu, ponowne podjęcie próby i awaria modelu bez regresji semantycznej
Praktyczna architektura do klasyfikowania błędów API LLM, egzekwowania jednego budżetu opóźnień, wybierania zgodnych modeli awaryjnych, ochrony skutków ubocznych i sprawdzania poprawności każdej zaakceptowanej odpowiedzi.
Żądanie zastępcze nie powiedzie się tylko dlatego, że inny model zwrócił HTTP 200. Zastąpienie może przekroczyć pierwotny budżet opóźnień, pominąć wymagane pola JSON, wywołać inne narzędzie lub dać odpowiedź o zasadniczo odmiennej semantyce. Niezawodny routing LLM API wymaga zatem czegoś więcej niż uporządkowanej listy modeli: wymaga kontraktu, klasyfikatora niepowodzeń, zasad ograniczonych prób i walidacji przed akceptacją.
Główna zasada jest prosta: ponów próbę tylko wtedy, gdy awaria jest prawdopodobnie przejściowa, a wycofaj się tylko wtedy, gdy następna trasa nadal może spełnić pierwotny kontrakt żądania.
Określ umowę routingu przed wybraniem modeli
Zacznij od opisania, co musi zapewnić skuteczna odpowiedź. Ta umowa routingu powinna nadawać się do odczytu maszynowego i być dołączona do każdego obciążenia lub klasy żądania.
{
"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
}
Umowa powinna obejmować wymagane modalności, pojemność kontekstu, wsparcie narzędzi, zachowanie ustrukturyzowanego wyniku, akceptowalne klasy modeli, maksymalny koszt i kompleksowy termin realizacji. W razie potrzeby dodaj ograniczenia specyficzne dla aplikacji, takie jak dozwolone regiony, minimalna długość wyjściowa lub wymagany powód zakończenia.
Zalecenie: utrzymuj oddzielne, przetestowane grupy tras dla zwykłego tekstu, danych wyjściowych ograniczonych schematem, użycia narzędzi, wizji i żądań o długim kontekście. Model będący akceptowalnym zastępczym tekstem nie jest automatycznie akceptowalnym zastępczym narzędziem do wywoływania narzędzi lub wprowadzania obrazu.
Sklasyfikuj awarię przed podjęciem działania
Błędy uwierzytelniania, źle sformułowane żądania, limity szybkości i awarie serwera wymagają różnych reakcji. Traktowanie każdej nieudanej odpowiedzi jako odpowiedzi, która może zostać ponowiona, marnuje pojemność i może ukryć defekty.
| Klasa awarii | Przykłady | Działanie domyślne |
|---|---|---|
| Trwały błąd żądania | Nieprawidłowe dane uwierzytelniające, zniekształcone parametry, nieobsługiwana funkcja | Zatrzymaj i zwróć wyraźny błąd |
| Niekompatybilność tras | Kontekst zbyt duży, nieobsługiwane wejście obrazu, niedostępny tryb schematu | Wypróbuj tylko zgodną trasę |
| Przejściowa awaria transportu | Reset połączenia, awaria DNS, wybrany limit czasu | Ponów próbę w ramach pozostałego budżetu |
| Awaria przepustowości lub szybkości | HTTP 429, przeciążona usługa, wybrane odpowiedzi 5xx | Zastosuj wskazówki dotyczące ponownej próby lub użyj zdrowego rozwiązania zastępczego |
| Nieprawidłowa odpowiedź | Zniekształcony JSON, nieznane narzędzie, brak wymaganego pola | Odrzuć, a następnie spróbuj ponownie lub wycofaj się, jeśli pozwalają na to zasady |
| Niejednoznaczne wykonanie | Połączenie utracone po tym, jak dostawca mógł zaakceptować żądanie | Deduplikacja przed ponownym odtworzeniem |
Fakt: nieudane żądania z ograniczoną szybkością nadal mogą wliczać się do limitów dostawcy. Agresywne, natychmiastowe ponowne próby mogą zatem pogłębić ograniczanie przepustowości zamiast go rozwiązać. Ponowne próby zużywają także dodatkową pojemność podczas awarii, a zasady ponawiania prób w kilku warstwach aplikacji mogą zwielokrotnić wynikowe obciążenie.
Zalecenie: pozwól, aby jedna warstwa była właścicielem ponownych prób generowania modelu. W typowej architekturze brama AI API jest właściwym właścicielem, ponieważ widzi stan trasy, historię prób, opóźnienia i koszt. Jeśli to możliwe, wyłącz automatyczne ponawianie prób u klientów niższego poziomu lub policz je jawnie w ramach tego samego budżetu prób.
Wydaj jeden kompleksowy budżet na opóźnienia
Limity limitów czasu na każdą próbę są niewystarczające. Trzy próby z pięciosekundowym limitem czasu mogą zamienić zamierzoną pięciosekundową operację w piętnastosekundową reakcję, zanim zostaną uwzględnione wycofywanie i sprawdzanie poprawności.
Zapisz bezwzględny termin, w którym żądanie wpływa do bramy. Przed każdą próbą oblicz pozostały czas:
remaining = deadline - current_time
required = connect_allowance + generation_allowance + validation_allowance
if remaining < required:
stop_without_launching_another_attempt
W przypadku terminu ośmiosekundowego rozsądny przydział początkowy może zarezerwować 300 ms na pracę bramy i końcową weryfikację, maksymalnie 4,5 sekundy na trasę główną i zachować około 3,2 sekundy na jedno rozwiązanie awaryjne. Wartości te stanowią przykład, a nie punkt odniesienia. Muszą one pochodzić ze zmierzonych rozkładów opóźnień dla rzeczywistych dostawców, modeli, regionów i rozmiarów wyjściowych.
Użyj ograniczonego wykładniczego wycofywania z jitterem w przypadku przejściowych ponownych prób:
delay = random(0, min(cap, base * 2^retry_index))
Wskazówki dostawcy dotyczące ponownej próby, takie jak wartość ponownej próby, powinny mieć pierwszeństwo, jeśli mieszczą się w pozostałym terminie. Zatrzymaj się po niewielkiej liczbie prób. Typową zasadą jest jedna próba podstawowa i jedna próba awaryjna, z opcjonalnym ponowieniem tej samej trasy tylko w przypadku wcześniejszej awarii połączenia, która nie mogła wygenerować płatnych wyników.
Kompromis: sekwencyjne przełączanie awaryjne poprawia dostępność, ale zwiększa opóźnienie końcowe. Żądania równoległe lub zabezpieczone mogą zmniejszyć opóźnienia podczas spowolnień, ale zużywają więcej pojemności i mogą wiązać się z opłatami za wiele pomyślnych generacji. Zabezpieczanie powinno być ograniczone do obciążeń krytycznych z powodu opóźnień i wolnych od skutków ubocznych, z możliwością anulowania i kontrolą kosztów.
Wybierz rezerwy według możliwości, a nie rangi
Tabela rezerwowa powinna kodować zgodność, a nie globalną kolejność preferencji. Filtruj potencjalne trasy według umowy, zanim weźmiesz pod uwagę stan, opóźnienie lub cenę.
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)
Obsługa wyników strukturalnych zasługuje na jawne przetestowanie. Nawet jeśli dwie trasy ogłaszają generowanie ograniczone schematem, mogą obsługiwać różne podzbiory schematu JSON lub inaczej interpretować przypadki brzegowe. Modele obsługujące narzędzia mogą również różnić się wyborem narzędzi, konstrukcją argumentów i zachowaniem wywołań równoległych.
Fakt: zmiana rodzin modeli może zachować dostępność transportu przy jednoczesnej zmianie stylu, jakości rozumowania, zachowań związanych z bezpieczeństwem, tokenizacji i wyboru narzędzi. HTTP sukces nie jest dowodem równoważności semantycznej.
Przewidywanie: w miarę rozszerzania się katalogów modeli zasady routingu produkcji będą w coraz większym stopniu wykorzystywać wersjonowane profile możliwości i testy akceptacyjne specyficzne dla obciążenia zamiast statycznych list modeli. Traktuj to jako kierunek projektowania, a nie gwarancję zachowania dostawcy.
Zatwierdź odpowiedź przed jej zaakceptowaniem
Uruchom każdą odpowiedź, łącznie z odpowiedzią główną, tym samym potokiem akceptacji. Walidacja powinna nastąpić, zanim wynik zostanie zapisany w pamięci podręcznej, wewnętrznie rozliczony jako pomyślny lub przekazany do wykonawcy narzędzia.
- Potwierdź zakończenie transportu i możliwość przeanalizowania koperty odpowiedzi.
- Sprawdź przyczynę zakończenia i odrzuć obcięcie, jeśli wymagane jest pełne wyjście.
- Sprawdź uporządkowane dane wyjściowe pod kątem oryginalnego schematu.
- Sprawdź wymagane pola, wartości wyliczeniowe i niezmienniki aplikacji.
- Zezwalaj tylko na zarejestrowane nazwy narzędzi i sprawdzaj argumenty w odniesieniu do każdego schematu narzędzia.
- Zastosuj kontrole semantyczne specyficzne dla obciążenia tam, gdzie fałszywa akceptacja byłaby kosztowna.
W przypadku wyodrębniania faktur kontrole semantyczne mogą wymagać nieujemnej sumy, obsługiwanego kodu waluty i sum pozycji w ramach wyraźnie określonej tolerancji. Do klasyfikacji wymagana jest etykieta z dozwolonego zestawu. Do generowania kodu odpowiednie może być parsowanie lub kompilacja. Kontrole te nie potwierdzają jakości, ale zapobiegają traktowaniu przewidywalnych naruszeń umowy jako sukcesów.
Nie naprawiaj po cichu każdej źle sformułowanej odpowiedzi. Dopuszczalna może być normalizacja deterministyczna, taka jak usuwanie nieszkodliwych otaczających białych znaków. Odgadnięcie brakujących pól finansowych lub przepisanie argumentów narzędzia zmienia znaczenie modelu i powinno spowodować odrzucenie lub weryfikację manualną.
Oddzielne próby generowania od skutków ubocznych
Żądania LLM często wykorzystują HTTP POST, który nie jest z natury idempotentny. Co ważniejsze, odpowiedź modelowa może zainicjować akcję zewnętrzną, taką jak obciążenie metody płatności, wysłanie wiadomości, utworzenie biletu lub modyfikacja infrastruktury. Ponowna próba wygenerowania i odtworzenie tej akcji to osobne decyzje.
Przypisz identyfikator operacji na granicy aplikacji i identyfikator próby do każdego wywołania modelu. Utrwalaj stan wykonania narzędzia względem deterministycznego klucza, takiego jak:
execution_key = operation_id + tool_name + canonical_arguments_hash
Przed wykonaniem narzędzia sprawdź, czy dany klucz oczekuje na realizację, został ukończony czy też nie powiódł się. Zwróć zapisany wynik, aby zakończyć wykonanie, zamiast uruchamiać je ponownie. W przypadku operacji, których argumenty mogą zgodnie z prawem ulec zmianie, wymagaj zatwierdzenia na poziomie aplikacji lub nowego identyfikatora operacji.
Niejednoznaczny limit czasu wymaga specjalnego postępowania. Jeśli połączenie nie powiedzie się po przesłaniu żądania, brama może nie wiedzieć, czy doszło do generowania. Klucz idempotencji obsługiwany przez dostawcę może pomóc, jeśli jest dostępny. W przeciwnym razie zarejestruj wynik jako nieznany i zastosuj zasady odtwarzania specyficzne dla obciążenia, zamiast zakładać, że nic się nie wydarzyło.
Pomijaj nieprawidłowe trasy i ujawniaj każdą próbę
Wyłącznik automatyczny lub tymczasowa przerwa w działaniu uniemożliwiają każdemu nowemu żądaniu ponowne odnalezienie tej samej uszkodzonej trasy. Otwórz obwód po osiągnięciu określonego progu błędu lub kolejnych uszkodzeń, a następnie dopuść ograniczone sondy w stanie półotwartym. Dostosuj progi według trasy i klasy awarii, aby zniekształcone żądanie klienta nie mogło sprawić, że zdrowy model będzie wyglądał na niedostępny.
Nagraj jedno zdarzenie na poziomie żądania i jedno zdarzenie na próbę. Przydatne pola obejmują identyfikator operacji, identyfikator próby, wybranego dostawcę i model, klasę awarii, kod stanu, opóźnienie, liczbę tokenów, szacowany koszt, przyczynę awarii, wynik walidacji, stan obwodu i wynik końcowy. Redaguj lub mieszaj podpowiedzi, dane wyjściowe i argumenty narzędzi zgodnie z ich czułością i wymaganiami dotyczącymi przechowywania.
Przydatne wskaźniki operacyjne obejmują współczynnik awaryjności, liczbę prób na zrealizowane żądanie, wskaźnik wyczerpania terminu, współczynnik odrzuceń podczas walidacji, niejednoznaczne wyniki, koszt zaakceptowanej odpowiedzi i opóźnienie według ostatecznej trasy. Rosnący HTTP wskaźnik powodzenia wraz ze wzrostem współczynnika odmów weryfikacji jest ostrzeżeniem, że dostępność transportu maskuje niepowodzenie umów.
Lista kontrolna wdrożenia produkcyjnego
- Zdefiniuj umowę routingu z wersjami dla każdej klasy obciążenia.
- Mapuj błędy dostawcy na kategorie trwałe, przejściowe, niezgodne, z nieprawidłową odpowiedzią i niejednoznaczne.
- Wybierz jednego właściciela ponownych prób i ogranicz liczbę prób.
- Propaguj bezwzględny termin przez bramę, klienta dostawcy, weryfikację i wykonanie narzędzia.
- Tworzyj sprawdzone pod kątem możliwości grupy rezerwowe zamiast jednego globalnego łańcucha modeli.
- Sprawdź schematy, wywołania narzędzi, przyczyny zakończenia i niezmienniki domeny.
- Deduplikacja efektów ubocznych za pomocą kluczy operacyjnych i wykonawczych.
- Dodaj pomijanie tras z ograniczonymi sondami półotwartymi.
- Rejestruj opóźnienia na poziomie próby, tokeny, koszt, niepowodzenia i wyniki akceptacji.
- Przekroczenia limitu czasu wstrzykiwania, 429 s, wybrane błędy 5xx, zniekształcony JSON, przepełnienie kontekstu i powolne pomyślne uruchamianie.
Zacznij od trasy głównej i jednej zgodnej trasy zastępczej dla pojedynczego obciążenia niskiego ryzyka. Przed rozszerzeniem zasad porównaj jakość, opóźnienia i koszty zaakceptowanej odpowiedzi. Celem nie jest najwyższy możliwy wskaźnik rezerw. Jest to system ograniczony, który albo zwraca odpowiedź zgodną z pierwotną umową, albo wyraźnie zawodzi, zanim spowoduje zdublowanie pracy lub uszkodzenie semantyczne.