Strona główna / Rozdział 7 · Model na produkcji
Ostatnia zmiana · 9 min czytania
LLM na produkcji
Wywołanie modelu to zdalna zależność, która bywa przeciążona, wolna i droga, a czasem zwraca nie to, o co prosisz. System produkcyjny to kod wokół tego wywołania: ponowienia i fallbacki, kontrola czasu i kosztu, trace’y, walidacja i bezpieczne wdrażanie zmian.
Po ludzkuRestauracja z jednym świetnym, ale kapryśnym kucharzem: czasem jest zawalony zamówieniami, czasem gotuje wolno, czasem poda nie to danie. Kierownik sali nie poprawi kucharza, ale może powtórzyć zamówienie za chwilę, trzymać drugiego kucharza na zastępstwo, sprawdzić talerz przed wyniesieniem i notować, co poszło nie tak.
Wybierz awarię i włączaj zabezpieczenia. Zobacz, co dostanie użytkownik, po jakim czasie i za ile
Awaria
Zabezpieczenia
Symulacja poglądowa, liczby dobrane ręcznie. Bez awarii: pierwszy token po 0,8 s, całość po 6,8 s, koszt 1×. Model zapasowy u innego dostawcy ma zimny cache, więc kosztuje 1,4×. Polityka: timeout 20 s na próbę (przy streamingu 10 s ciszy między fragmentami), najwyżej 2 ponowienia w łącznym limicie 45 s, fallback po wyczerpaniu ponowień. Przerwana próba kosztuje proporcjonalnie do tego, co zdążyła wygenerować.
Awarie: co ponawiać i jak
- Ponawiaj tylko błędy przejściowe: 429 (limit), przeciążenie (529 u Anthropic, 503 u OpenAI), inne 5xx, zerwane połączenie i timeout. Błąd 400, 401 albo 403 za drugim razem wyjdzie tak samo. Podobnie 429 z miesięcznego limitu wydatków twojego poziomu konta: u Anthropic przychodzi bez nagłówka
retry-after, aerror.details.error_codema wartośćenforced_spend_limit_reached. - Odstępy między próbami wydłużaj wykładniczo, z losowym rozrzutem (jitter): ok. 1, 2, 4 s plus losowy dodatek, a gdy serwer poda
Retry-After, czekaj co najmniej tyle. Bez rozrzutu wszyscy klienci wracają w tej samej sekundzie i dobijają przeciążony serwis. Ogranicz liczbę prób i łączny czas. Ponawiaj w jednej warstwie: oficjalne SDK same ponawiają (u Anthropic domyślnie 2 razy), więc własna pętla trzech prób nad SDK robi z jednego kliknięcia do 9 requestów. - Ponowienie jest bezpieczne tylko wtedy, gdy powtórka niczego nie psuje. Samo wywołanie modelu niczego nie zmienia, ale narzędzie agenta już tak. Każda akcja z efektem ubocznym dostaje klucz idempotencji (np. id zadania i numer kroku), a narzędzie odrzuca duplikaty, więc ponowiony krok nie wyśle drugiego maila. Odpowiedzi, którą już zacząłeś streamować użytkownikowi, nie powtarzaj automatycznie.
- Limity liczy się w requestach i tokenach na minutę (RPM i TPM, u Anthropic osobno wejście i wyjście). Anthropic odnawia je na bieżąco metodą wiadra tokenów (token bucket), a limit 60 RPM może działać jak 1 request na sekundę, więc przy nagłym skoku ruchu dostajesz 429 mimo zapasu w skali minuty. OpenAI wlicza do limitu
max_tokens, jeśli przekracza szacowaną liczbę tokenów w requeście. Anthropic liczy faktycznie wygenerowane tokeny, a odczytów z cache’u dla większości modeli nie wlicza wcale. Limit jest wspólny dla całej organizacji, więc potrzebujesz własnej kolejki i limitów na użytkownika, żeby jeden klient nie zablokował reszty. - Najbliższy fallback to ten sam model na platformie, którą obsługuje ktoś inny: Claude na Bedrock albo Google Cloud, GPT na Azure albo Bedrock (stan na wrzesień 2026). To osobne konto z własnymi limitami i identyfikatorami modeli, część funkcji trafia tam później, a cache jest zimny. Fallback na inny model też ratuje dostępność, ale prompt strojony pod główny działa na nim inaczej, a format narzędzi bywa inny. W obu przypadkach ścieżka zapasowa potrzebuje własnych evali, bo rzadko używana psuje się po cichu. Circuit breaker po serii błędów na chwilę przestaje wołać chorego dostawcę i od razu kieruje ruch do fallbacku, a co jakiś czas wpuszcza próbny request. Gdy nic nie działa, zadbaj o łagodną degradację: wynik z cache’u, prostsza odpowiedź albo jasny komunikat zamiast wiszącego spinnera.
Czas odpowiedzi
- Liczą się dwie liczby: czas do pierwszego tokena (TTFT, czyli kolejka plus przetworzenie promptu) i czas całkowity (TTFT plus liczba tokenów wyjścia razy czas na token). Streaming skraca tylko odczuwane czekanie: użytkownik czyta od pierwszego tokena, a całość trwa tyle samo. Przy streamingu ustaw timeout na ciszę między fragmentami, nie na całą odpowiedź, a zdarzenie błędu w środku strumienia (może przyjść po 200 OK) traktuj jak awarię, nie koniec odpowiedzi. Przy długiej odpowiedzi bez streamingu bezczynne połączenie może zostać zerwane. Ceną streamingu jest walidacja: JSON sprawdzisz dopiero w całości.
- Czas rośnie głównie z długością wyjścia, bo każdy token to osobny krok dekodowania (temat „Czemu GPU się nudzi”). Według heurystyki OpenAI skrócenie odpowiedzi o połowę skraca czas mniej więcej o połowę, a skrócenie promptu o połowę tylko o 1–5%. Tokeny rozumowania też są wyjściem. Pomaga zwięzły format, krótkie nazwy pól i niższy poziom rozumowania tam, gdzie wysoki nie jest potrzebny.
- Niezależne wywołania puszczaj równolegle, na przykład klasyfikację pytania i wyszukiwanie. Proste kroki, takie jak routing, klasyfikacja czy ekstrakcja, dawaj mniejszemu i szybszemu modelowi. To, co załatwia reguła albo zwykły kod, rób bez modelu.
Koszt
- Stały prefiks (system prompt, narzędzia, dokumenty) idzie na początek, bo odczyt z cache’u kosztuje ułamek ceny wejścia, u Anthropic zwykle 10% (temat „Prompt caching”). Zadania offline, jak nocna klasyfikacja, wzbogacanie danych czy przebiegi evali, puszczaj przez batch API: u OpenAI i Anthropic 50% taniej, z wynikiem w ciągu 24 h (stan na wrzesień 2026).
- Kaskada: najpierw tani model, a drogi tylko wtedy, gdy walidator odrzuci wynik albo pewność jest niska. Opłaca się, gdy większość ruchu jest prosta i gdy umiesz tanio sprawdzić, czy tani model sobie poradził. Bez takiego sprawdzenia to zwykłe obniżenie jakości.
- Twarde limity:
max_tokensna każde wywołanie (to też limit czasu), maksymalna liczba kroków agenta, dzienny budżet na użytkownika lub klienta i alarm kosztowy. Wyniki powtarzalnych zadań trzymaj w zwykłym cache’u z kluczem z wejścia, wersji promptu i wersji modelu. Cache semantyczny, który dopasowuje podobne pytania, potrafi oddać odpowiedź na inne pytanie.
Obserwowalność
- Każde zadanie to trace, a każde wywołanie modelu i każdy krok narzędzia to jego span: wejście, wyjście, tokeny (także z cache’u), TTFT i czas całkowity, koszt, dokładna wersja modelu z odpowiedzi, wersja promptu i request-id dostawcy. OpenTelemetry ma na to konwencje GenAI (atrybuty
gen_ai.*, wciąż w fazie rozwoju). - Metryki: p50 i p95 czasu (średnia ukrywa ogon), odsetek błędów według typu (429, 5xx, timeout, walidacja), udział fallbacku, koszt na ukończone zadanie, a nie na wywołanie, oraz wyniki evali online: sędzia-LLM na próbce ruchu i oceny użytkowników.
- Prompty i odpowiedzi zawierają dane osobowe i tajemnice firmy. Maskuj PII przed zapisem, ogranicz dostęp i czas przechowywania logów. W konwencjach OpenTelemetry zapis treści wiadomości jest domyślnie wyłączony. Trace’y, w których system zawiódł, zamieniaj w przypadki testowe (temat „Ewaluacje”), żeby każdy incydent stał się testem regresyjnym.
Guardrails i wdrażanie zmian
- Wyjście sprawdzaj w kodzie: schemat, typy i reguły biznesowe (kwota nie większa od salda, identyfikator istnieje). Przy błędzie odeślij modelowi konkretny komunikat i ponów raz lub dwa razy, potem fallback albo błąd. Tryb ścisły usuwa błędy składni, nie złe wartości (temat „Wymuszanie formatu”). Tam, gdzie wymaga tego domena, dodaj limit długości wejścia, moderację i maskowanie PII. Ryzykowne akcje, takie jak płatność, usunięcie czy wysyłka na zewnątrz, zatwierdza człowiek, a wymusza to kod, nie prompt.
- Prompt wersjonuj jak kod i przypinaj dokładną wersję modelu, nie alias, który może się przesunąć. Każda zmiana promptu, modelu albo parametrów przechodzi najpierw evale offline, potem canary na kilku procentach ruchu z porównaniem metryk i szybkim rollbackiem. Dostawcy wycofują stare wersje, więc migracja i tak przyjdzie, a własne evale są jedynym dowodem, że nowa wersja nie jest gorsza (temat „Czy model głupieje?”).
- Sprawdź, dokąd trafiają dane. U OpenAI i Anthropic treść wysłana przez API jest domyślnie przechowywana do 30 dni (monitoring nadużyć), krócej tylko przy umowie o zerowej retencji (ZDR). U Anthropic modele Claude Fable i Mythos 5.x wymagają 30-dniowej retencji, a ZDR dostają tylko za wyraźną zgodą Anthropic (od września 2026 przejściowo uprawnieni klienci na Fable 5 i 5.1), więc wybór modelu to też decyzja o danych. Funkcje ze stanem, takie jak pliki, wyniki batchy czy zapisane odpowiedzi, trzymają dane dłużej (stan na wrzesień 2026). Twoje logi i narzędzie do trace’ów to druga kopia tych samych danych.
- AI Act (stan na wrzesień 2026): od 2 sierpnia 2026 chatbot musi informować, że rozmówca ma do czynienia z AI, a generowane treści muszą mieć oznaczenie czytelne maszynowo (systemy już obecne na rynku mają czas do 2 grudnia 2026). Zastosowania wysokiego ryzyka, takie jak selekcja CV, ocena zdolności kredytowej czy ocenianie egzaminów, dostają swoje obowiązki od 2 grudnia 2027.
Co widzi użytkownik
- Pokazuj postęp i pozwól przerwać pracę: przy rozumowaniu i krokach agenta pokazuj, który krok trwa (wyszukiwanie, czytanie pliku), obok przycisku stop. Spinner kręcący się przez minutę wygląda jak zawieszenie, a złą ścieżkę najtaniej przerwać wcześnie.
- Pokazuj, skąd jest odpowiedź: źródła z linkiem do fragmentu, który potwierdzają, i zwykłe „nic nie znaleziono” zamiast odpowiedzi z pamięci. Niepewność sygnalizuj tym, co da się sprawdzić (brak źródeł, odrzucenie przez walidator, rozbieżne próbki), a nie pewnością, którą model deklaruje sam o sobie (temat „Halucynacje”).
- Akcje agenta mają podgląd przed i cofnięcie po: szkic zamiast wysłanego maila, miękkie usuwanie, dziennik zmian z przywracaniem. Akceptacji człowieka, opisanej wyżej, wymaga tylko to, czego cofnąć się nie da.
Sprawdź się
Wdrażasz funkcję opartą na LLM-ie na produkcję. Co budujesz wokół samego wywołania modelu?
Model traktuje się jak zawodną, wolną i drogą zależność zewnętrzną. Każde wywołanie ma timeout, a błędy przejściowe, czyli 429, przeciążenie i 5xx, ponawia się z wykładniczym backoffem i jitterem, w jednej warstwie. Akcje narzędzi mają klucze idempotencji. Fallback, najlepiej ten sam model na innej platformie, ma własne evale i circuit breaker. Czas i koszt obniżają streaming, krótsze wyjście, prompt caching, tańszy model do prostych kroków i batch offline. Każde wywołanie trafia do trace’a z tokenami, kosztem i wersją. Wyjście waliduje się w kodzie, a zmiany promptu i modelu wypuszcza się przez evale i canary.
In English
Treat the model as an unreliable, slow and expensive external dependency. Every call has a timeout, and transient errors (429, overload, 5xx) are retried with exponential backoff and jitter, in one layer only. Tool actions carry idempotency keys. The fallback, ideally the same model on another platform, gets its own evals and a circuit breaker. Streaming, shorter outputs, prompt caching, a cheaper model for simple steps and offline batch jobs cut latency and cost. Every call lands in a trace with tokens, cost and version. Outputs are validated in code, and prompt and model changes ship through evals and a canary.
Pytania pogłębiające (5)
- Dostawca zwraca 529 od dziesięciu minut. Co widzi użytkownik?
- Po serii błędów circuit breaker przestaje wołać dostawcę i ruch idzie od razu do fallbacku, więc użytkownik dostaje odpowiedź modelu zapasowego bez czekania na kolejne ponowienia. Bez fallbacku: szybki, jasny komunikat, a zadania, które mogą poczekać, trafiają do kolejki. Gdy próbne requesty przechodzą, breaker stopniowo przywraca ruch.
- Czemu nie ponawiać każdego błędu?
- Błąd 400 czy 401 za drugim razem wyjdzie tak samo, a 429 z wyczerpanego limitu wydatków nie minie sam. Ślepe ponawianie mnoży ruch w najgorszym momencie: przy przeciążeniu każdy klient z trzema próbami potraja obciążenie. Stąd jitter, limit łącznego czasu i ponawianie w jednej warstwie.
- Jak obniżysz rachunek o połowę bez utraty jakości?
- Najpierw pomiar: koszt na ukończone zadanie z podziałem na wejście, wyjście i cache. Potem stały prefiks pod prompt caching, batch dla wszystkiego, co nie jest interaktywne, krótsze wyjście, tańszy model tam, gdzie evale nie pokazują różnicy, i cache wyników powtarzalnych zadań. Każdą zmianę sprawdź na evalach, bo tańszy model potrafi po cichu obniżyć jakość.
- Jak pogodzić streaming z walidacją JSON-a?
- Pełną walidację zrobisz dopiero po ostatnim tokenie. W interfejsie streamuj tekst albo parsuj strukturę przyrostowo i pokazuj pola, które są już kompletne. Tam, gdzie błąd jest kosztowny, na przykład przed zapisem albo akcją, buforuj i waliduj całość.
- Jak bezpiecznie przejść na nowszy model?
- Evale offline na zestawie z prawdziwych przypadków, porównanie kosztu i czasu, potem canary na kilku procentach ruchu z tymi samymi metrykami i gotowym rollbackiem. Prompt zwykle trzeba dostroić, bo nowy model inaczej rozumie te same instrukcje. Fallback na inny model testuj tak samo, bo to też zmiana modelu.