Strona główna / Artykuły

Uruchamianie agentów AI AWS na dużą skalę: tokeny, wydatki, limity i autonomia

Liczenie tokenów, monitorowanie wydatków, przywracanie po przekroczeniu limitu kontekstu oraz trwałe autonomiczne procesy robocze dla agentów AWS, z których każdy jest wyjaśniony za pomocą wzorców znanych programistom JavaScript full-stack.

Wydawca: REACTAPP.TOP8 min czytania1929 słów

Źródła: 🏗️ Building Production-Ready Enterprise AI Agents on AWS — Part 3: Tokenization, Monitoring, Context Limits & Autonomous Workflows

Agent, który został dobrze zaprojektowany i wspierany przez mechanizmy walidacji oraz odzyskiwania danych, musi nadal przetrwać pierwszy miesiąc w środowisku produkcyjnym. To, co decyduje o jego sukcesie, jest przeważnie mało efektowne: sposób liczenia tokenów, monitorowanie wydatków, to, co się dzieje, gdy okno kontekstowe się wypełnia, oraz to, czy długo trwający autonomiczny cykl jest zbudowany jak prawdziwy silnik przepływu pracy. Jeśli pochodzisz z środowiska full-stack JavaScript na AWS, każdy z tych elementów odpowiada czemuś, co już znasz, a cały ten przewodnik wykorzystuje te podobieństwa na przestrzeni całego tekstu.

Tokenizacja to warstwa serializacji

Aplikacja internetowa serializuje dane przed ich przesłaniem, używając JSON.stringify lub protobuf. Model językowy robi coś podobnego z tekstem: zanim zobaczy cokolwiek, tekst jest dzielony na tokeny, które to fragmenty poniżej poziomu słów, a nie znaki czy całe słowa.

"Enterprise agents scale."
   → ["Enterprise", " agents", " scale", "."]   (≈4 tokens, illustrative)

Powód, dla którego jako inżynier powinienem się tym przejmować, sprowadza się do trzech kwestii.

  • Tokeny to jednostka, za którą jesteś opłacany, porównywalna z GB-sekundami w Lambda. Zarówno dane wejściowe, jak i wyjściowe kosztują pieniędzy, a ponieważ ceny Bedrock różnią się w zależności od modelu, liczba tokenów bezpośrednio wpływa na rachunek AWS.
  • Tokeny określają również górny limit treści, podobnie jak ograniczenie dla ciała żądania, np. express.json({ limit: '5mb' }). W tym przypadku takim limitem jest okno kontekstowe, które w obecnych modelach może zawierać setki tysięcy tokenów i stale rośnie, więc sprawdź dokładny limit dla swojego modelu, zamiast zgadywać.
  • Tokalizacja nie jest jednolita we wszystkich językach. Tekst w językach innych niż angielski często wymaga większej liczby tokenów na słowo, co ma znaczenie w przypadku produktów działających w kilku regionach.

W Node.js liczenie tokenów przed wysłaniem żądania przypomina pomiar objętości danych przed wykonaniem operacji fetch:

// Node.js: counting tokens before sending a request
// (conceptually like calculating payload size before a fetch call)
import { encoding_for_model } from "tiktoken";

const enc = encoding_for_model("gpt-4o");
const tokens = enc.encode(userPrompt);
console.log(`Payload size: ${tokens.length} tokens`); // like Content-Length
enc.free();

W Bedrock można pominąć tokenizer od third party. API CountTokens liczy tokeny po stronie serwera dla obsługiwanych modeli Claude, wykorzystuje tę samą strukturę wiadomości co API Converse i umożliwia wstępną weryfikację liczby tokenów w żądaniu bez konieczności płacenia za przetwarzanie:

# Python (boto3): pre-flight token count via Bedrock, no separate tokenizer library needed
response = bedrock_runtime.count_tokens(
    modelId="anthropic.claude-3-5-sonnet-20241022-v2:0",
    input={"converse": {"messages": [{"role": "user", "content": [{"text": userPrompt}]}]}}
)
print(f"Input tokens: {response['inputTokens']}")

Lekcja: mierz liczbę tokenów w taki sam sposób, jak mierzyłbyś rozmiar ładunku HTTP, przed wysłaniem wiadomości, a nie po naliczeniu opłaty lub odrzuceniu jej.

Nadzór nad zużyciem tokenów jak w CloudWatch dla rachunków LLM

W poprzednim rozdziale omówiono pojedynczą prośbę. Widok agregowany pokazuje, ile tokenów zużył każdy agent, dla każdego użytkownika i każdego dnia, a chcesz to sprawdzić przed działem finansowym. Nikt nie uruchomiłby API Express na AWS bez paneli kontrolnych i alarmów, a nadzór nad tokenami zasługuje na takie samo traktowanie.

Złote wskaźniki dla agenta:

  • Liczba tokenów na prośbę, podobnie jak rozmiar przychodzącego ładunku.
  • Liczba tokenów na zakończenie prośby, podobnie jak rozmiar odpowiedzi.
  • Kumulatywna liczba tokenów w sesji, która odpowiada zużyciu pamięci przez tę sesję.
  • Koszt na agenta, użytkownika lub tenanta – to ta sama metryka, którą stosuje się do pomiaru zużycia bazy danych w modelach SaaS wielotenantowych.
  • Opóźnienie p95 i p99 połączeń z agentem musi być zgodne z Twoimi standardowymi SLO. Musisz jasno określić te SLO i przechodzić na metodę wykorzystującą dane z pamięci podręcznej lub najlepszą dostępną ścieżkę, gdy istnieje ryzyko ich niespełnienia.
  • Tempo wydawania tokenów w minutę, porównywalne z ograniczeniami liczby żądań na sekundę.
  • Konkretne kroki w AWS:

    • Wysyłaj własne metryki CloudWatch dotyczące tokenów prompt, tokenów końcowych oraz kosztu w dolarach (prompt_tokens, completion_tokens, cost_usd), oznaczone nazwą agenta i użytkownikiem.
    • Włącz cacheowanie promptów. Bedrock może ponownie wykorzystywać długie, stabilne prefiksy, takie jak prompty systemowe, definicje narzędzi i przykłady typu few-shot, z dużą oszczędnością i niższym opóźnieniem. Umieść treści niezmienne na początku, w przeciwnym razie za identyczne tokeny przy każdym połączeniu będziesz płacić pełną cenę.
    • Stwórz alarmy CloudWatch, które powiadamiają przez SNS, gdy dzienny wydatek przekroczy określony próg, podobnie jak alarmy billingowe AWS.
    • Zapisuj każdą próbę połączenia z agentem do S3, za pośrednictwem Kinesis Firehose lub bezpośrednio, aby utrzymać ślad audytowy. SOC 2 oraz klienci korporacyjni będą tego wymagać.
    • Estymacja przybliżona działa tak samo jak w przypadku Lambda: dodaj tokeny prompt i completion, pomnóż przez cenę modelu, a następnie dodaj koszty pobierania danych i infrastruktury za sesję.

    Jeśli nie potrafisz podać, ile kosztował agent X w zeszły wtorek, rozdzielając koszty według klientów, oznacza to, że jesteś gotowy na demonstrację, ale nie na produkcję, a te dwa stanowiska są bardzo odległe od siebie.

    Błędy związane z ograniczeniami kontekstu: circuit breaker plus paginacja

    Każde okno kontekstowe ma swoją górną granicę. Długie rozmowy, ogromne wyniki generowane przez narzędzia oraz przeciążone fragmenty danych mogą ją przekroczyć. To odpowiednik błędu 413 Payload Too Large w świecie agentów, tylko gorszy, ponieważ może pojawić się w trakcie złożonego zadania składającego się z kilku kroków.

    Strategie naprawcze pochodzą bezpośrednio z inżynierii backendu:

    1. Streszczanie i kompresowanie. Okresowo kompresuj stare informacje, podobnie jak przy rotacji logów.
    2. Suwakowe okno lub obcinanie. Usuwaj najstarsze informacje, tak jak przeglądasz duży wynik zapytania i nie ładujesz go w całości.
    3. Przenoszenie obciążenia na mechanizm wyszukiwania. Przechowuj dane poza treścią promptu i ładuj je na żądanie, zgodnie z zasadą opóźnionego ładowania.
    4. Dzielenie na podagenty. Podziel jedno ogromne zadanie na mniejsze operacje z nowymi kontekstami, np. przekształcając monolityczne zadanie zbiorcze w kolejkę małych zadań.
  • Eleganckie radzenie sobie z awariami. Jeśli nie można przywrócić stanu przed wykonaniem zadania, należy zakończyć je z użyciem uporządkowanego punktu kontrolnego umożliwiającego kontynuację, a nigdy poprzez niekontrolowaną halucynację.
  • Oto wzorzec „catch-and-compact” w kodzie, podobny do radzenia sobie z przekroczeniem czasu oczekiwania w bazie danych:

    # Conceptual: catching a context-limit error, like catching a DB timeout
    try:
        result = agent.run(task, conversation_history)
    except AgentError as err:
        if err.code == "context_length_exceeded":
            # Keep the system prompt intact — compact the *conversation*, never the identity.
            # Summarizing everything (including system instructions) is how agents quietly
            # "forget" their role mid-task, the same way you'd never let a cache-eviction
            # policy drop your app's config alongside its session data.
            compacted = summarize(conversation_history, preserve="system_prompt")
            result = agent.run(task, compacted)
        else:
            raise  # don't swallow unrelated errors
    

    Błędy związane z ograniczeniami kontekstowymi są spodziewane i nie stanowią wyjątku. Traktuj je jak ograniczenia szybkości i czas oczekiwania: próby ponowne z opóźnieniem, przechowywanie punktów kontrolnych w DynamoDB oraz funkcja łagodnego spadku wydajności. Pusty blok catch, który pochłania błąd, jest nigdy nie do przyjęcia.

    Autonomiczne procesy jako maszyny stanowe

    Autonomiczny agent nie reaguje tylko raz. Planuje, działa, obserwuje i powtarza proces aż do osiągnięcia celu. Każdy, kto budował maszynę stanową XState, sekwencję Redux lub przepływ AWS Step Functions do wieloetapowej realizacji zamówienia, zna już tę strukturę. Jest to znajomy cykl w stylu ReAct – planowanie, działanie, obserwacja i ocena – z możliwością zakończenia procesu lub przekazania go do człowieka, i powinien być zaprojektowany jak wytrzymały silnik procesów.

    • Kroki idempotentne. Ponowne wykonanie kroku nie powinno dwa razy obciążać klienta ani wysyłać duplikatowego e-maila.
  • Jasne warunki zatrzymania. Ogranicz liczba iteracji, koszt i czas działania, albo unikaj tworzenia nieskończonego pętla while(true) związanej z kartą kredytową.
  • Eskalacja przez człowieka. Podobnie jak w transakcjach korygujących, gdy poziom pewności jest niski lub stawki wysokie, proces powinien trafić do osoby, a nie być wykonywany automatycznie.
  • Trwały stan. Zapisuj punkty kontrolne na każdym kroku w DynamoDB lub w stanie Step Functions, aby w przypadku awarii w trakcie przetwarzania można było kontynuować pracę bez utraty transakcji. Dodaj czas ważności TTL w DynamoDB do elementów sesji, aby przestarzałe rozmowy wygasły, zgodnie z tą samą zasadą co wygaszanie kluczy sesji w Redis.
  • Modele awaryjne. Jeśli główny model, na przykład Claude w Bedrock, przekroczy czas reakcji lub zostanie ograniczony, mechanizm circuit breaker powinien przełączyć się na model alternatywny, takiego jak Amazon Nova, i nie pokazywać użytkownikowi błędu. To ta sama zasada co w przypadku klienta HTTP, który przechodzi na region zapasowy.
  • Zarządzanie modelem. Zmianę modelu należy traktować jak każdą inny deployment w produkcji: wprowadzać ją stopniowo na części ruchu, uzyskiwać zatwierdzenie i mieć możliwość cofnięcia zmian. „Po prostu zmieniliśmy model” nie powinno oznaczać zmiany bez zatwierdzenia.
  • Przycisk wyłączający. Należy mieć możliwość, ręczną lub uruchamianą na podstawie określonych warunków, natychmiastowego wstrzymania całej floty agentów, podobnie jak przycisk wyłączający flagi funkcji w przypadku niekontrolowanego wypuszczenia aktualizacji.
  • Punkt kontrolny to po prostu kolejna запис w DynamoDB dotycząca zadania, które można wznowić – Step Functions odczytuje go przy ponownym uruchomieniu, aby kontynuować od ostatniego poprawnego kroku:

    {
      "pk": "session#8f2c1a",
      "sk": "checkpoint#2026-08-23T10:15:00Z",
      "step": "plan",
      "hop_count": 2,
      "cost_so_far_usd": 0.014,
      "state": { "goal": "resolve billing dispute", "last_action": "lookup_charge" },
      "ttl": 1788084900
    }
    

    Nie buduj autonomii jako pętli while otaczającej wywołanie LLM. Stwórz trwałą, obserwowalną maszynę stanów umożliwiającą wznowienie pracy – to właśnie nią jest w rzeczywistości. Step Functions doskonale spełnia to wymaganie, jeśli chcesz mieć gotowe rozwiązanie.

    Nad tym wszystkim znajduje się jeszcze jeden warstwa: oceny. Zasady bezpieczeństwa, jakość pozyskiwania danych oraz ich powiązanie z rzeczywistością wymagają testów regresji tak samo jak kod aplikacji. Zestaw narzędzi do oceny odtwarza ustalony zestaw danych wejściowych dla agenta i ocenia wyniki pod kątem oczekiwanego zachowania, dzięki czemu mała modyfikacja promptu lub zmiana modelu nie może potajemnie pogorszyć funkcjonowania systemu. Ragas ocenia wskaźniki specyficzne dla procesu pozyskiwania danych, takie jak wierność i trafność kontekstu, natomiast Promptfoo i Braintrust obejmują szersze testy promptów i wyników. Połącz wybrane narzędzie z procesem CI w taki sam sposób jak pytest, aby nieudana ocena blokowała wdrożenie i nikt nie musiał ręcznie sprawdzać wyników.

    Lista kontrolna gotowości do produkcji

    • Każdy agent ma jedną sprawdzalną odpowiedzialność oraz wąsko określone uprawnienia IAM.
    • Przekazy danych odbywają się za pośrednictwem ustrukturyzowanego kontekstu w trwałym systemie komunikacji (SQS lub EventBridge) i są zabezpieczone przed pętlami.
    • Zasady kontrolne dla danych wejściowych i wyjściowych są oddzielone, mogą być łączone ze sobą oraz mają własne wersje.
    • Jakość pobierania danych ma własne miary dokładności i trafności i nie jest łączona z stwierdzeniem „sztuczna inteligencja się myli”.
    • Wszystko o dużej wadze przechodzi testy na obecność halucynacji: weryfikacja faktów, ocena pewności lub kontrola przez człowieka.
    • Użycie tokenów jest mierzone przed wysłaniem żądania, a nie tylko po jego realizacji.
    • Paneli CloudWatch pokazują koszty rozłożone według poszczególnych użytkowników i agentów, z alertami dotyczącymi budżetu SNS.
    • Istnieje określony plan odzyskiwania po błędach związanych z ograniczeniami kontekstu: kompresja, obcięcie danych lub przeniesienie ich do innego systemu.
  • Pętle autonomiczne mają sztywne ograniczenia dotyczące liczby iteracji, upływu czasu oraz zużytego zasobu.
  • Działania nieodwracalne, takie jak zwroty pieniędzy, wysyłanie e-maili i usuwanie danych, wymagają kroku zatwierdzenia przez człowieka.
  • Decyzje agentów są w pełni rejestrowane w S3 lub CloudWatch w celu zapewnienia zgodności.
  • Autoryzowane testy odbywają się w środowisku CI przed wdrożeniem jakichkolwiek zmian w promptach lub modelach – jest to krok, którego nigdy by się nie pominęło przy kodzie aplikacji.
  • Środowisko testowe zostało poddane intensywnym testom chaosu z wykorzystaniem symulowanych przestojów modeli, uszkodzonych wyników wyszukiwania oraz pętli przenoszenia danych, dzięki czemu ścieżki odzyskiwania są sprawdzone przed tym, jak zostaną one wykorzystane w produkcji.
  • Jakie to daje efekty

    Każda koncepcja agenta ma swojego odpowiednika w świecie full-stack, który znamy. Agenci to mikrosługi posiadające zdolność do podejmowania decyzji, a przekazywanie zadań odbywa się poprzez trwałe, śledzone ścieżki routingu z ograniczeniem liczby przeskoków. Zasady bezpieczeństwa realizowane są za pomocą warstw middleware, a wyszukiwanie danych odbywa się poprzez bardziej zaawansowaną warstwę zapytań. Hallucynacje są wykrywane poprzez powiązanie z rzeczywistością i weryfikację, a nie poprzez uprzejme proszenie. Tokeny pełnią jednocześnie funkcję określania wielkości danych przekazywanych oraz jednostki płatności. Monitorowanie wydatków to odpowiednik CloudWatch w kontekście użytkowania modeli. Pełne okno kontekstowe stanowi przewidywalny problem, który wymaga planu odzyskiwania, natomiast autonomia to trwała maszyna stanowa – zupełnie inna od zwykłego pętla while.

    Agenty typu Enterprise rzadko zawodzą w środowisku produkcyjnym z powodu niewystarczającej inteligencji modelu. Poddają się, ponieważ zespoły pomijają podstawowe zasady systemów rozproszonych, których nigdy nie pomijałyby przy zwykłym API: walidację, możliwość obserwacji, próby ponowne, właściwości idempotentności, stabilność oraz łagodne przechodzenie na tryb awaryjny. Jeśli już uruchomiłeś odporny aplikację JavaScript na AWS, masz już te instynkty. Pozostaje tylko skierowanie tych instynktów na nieznaną, nieprzewidywalną zależność, która odpowiada zdawkami.