Zbudowanie prototypu opartego o model językowy (LLM) zajmuje dzisiaj jedno popołudnie: kilkadziesiąt linii kodu w Pythonie lub TypeScript, klucz API od OpenAI, Anthropic czy Google i mamy działający czat.
Prawdziwe problemy inżynieryjne zaczynają się w momencie wdrożenia na produkcję:
- Model sporadycznie zwraca niepoprawny JSON i wywraca parser w backendzie.
- Agent wykonujący zapytania SQL lub wywołujący API zapętla się, generując setki dolarów kosztu w kilka minut.
- Wyszukiwanie wektorowe gubi kluczowe numery seryjne i kody błędów, bo embeddingi traktują je jako szum.
- P99 czasu odpowiedzi rośnie do 12 sekund, a koszty tokenów rosną szybciej niż baza aktywnych użytkowników.
Przejście od „zabawy promptem” do dojrzałego systemu produkcyjnego wymaga traktowania LLM jako niedeterministycznego koprocesora, a nie wyroczni. Poniżej przedstawiamy wzorce architektoniczne, które sprawdzają się w rzeczywistych wdrożeniach enterprise.
1. Wymuszenie determinizmu: Strict Structured Outputs
Najczęstszy błąd początkujących zespołów to proszenie modelu w prompcie systemowym: “Zwróć odpowiedź wyłącznie w formacie JSON”, a następnie parsowanie wyniku za pomocą json.loads() lub wyrażeń regularnych. Prędzej czy później model doda komentarz przed nawiasem klamrowym albo urwie składnię w połowie odpowiedzi.
W systemach produkcyjnych stosuje się mechanizm Constrained Decoding / JSON Schema Enforcement na poziomie silnika generowania (np. Structured Outputs z flagą strict: true):
[ Zapytanie klienta ]
│
▼
[ LLM Execution Engine ] <── [ Ścisły schemat JSON Schema ]
│ (Wymuszenie gramatyki na tokenach)
▼
[ Gwarantowany poprawny JSON ]
│
▼
[ Parser z walidacją typów ] (np. Pydantic / Zod / Go struct)
│
▼
[ Baza danych / Logika biznesowa ]
Kiedy silnik modelu ogranicza przestrzeń próbkowania kolejnych tokenów (ang. logit biasing lub gramatyki CFG), model fizycznie nie może wygenerować tokena, który złamałby strukturę JSON-a. Dzięki temu warstwa aplikacji otrzymuje gwarancję poprawności typu jeszcze przed wykonaniem kodu biznesowego.
2. Bezpieczne pętle agentowe i Function Calling
Wzorce agentowe (ReAct – Reasoning + Acting) dają modelom możliwość podejmowania decyzji o wywołaniu zewnętrznych narzędzi (kalkulator, zapytanie do bazy danych, wysłanie e-maila). Pozostawienie agenta bez nadzoru to proszenie się o incydent produkcyjny.
Każdy produkcyjny runtime agenta musi implementować trzy zabezpieczenia:
// Szkic maszyny stanów agenta z bezpiecznymi ograniczeniami
type AgentExecutor struct {
MaxIterations int // Sztywne odcięcie (np. max 5 kroków)
Timeout time.Duration // Twardy deadline per żądanie
ToolAllowlist []string // Rygorystyczna lista dozwolonych funkcji
}
func (ae *AgentExecutor) Execute(ctx context.Context, plan *Plan) (*Result, error) {
ctx, cancel := context.WithTimeout(ctx, ae.Timeout)
defer cancel()
for step := 1; step <= ae.MaxIterations; step++ {
// 1. Ewaluacja stanu przez model
// 2. Jeśli model żąda 'tool_call':
// - weryfikacja uprawnień (RBAC)
// - weryfikacja idempotencji
// - wykonanie narzędzia w piaskownicy
// 3. Jeśli model zwrócił stan końcowy -> return
}
return nil, errors.New("agent_iteration_limit_exceeded")
}
- Idempotencja narzędzi: Każde narzędzie o charakterze mutującym (np.
create_order,cancel_subscription) musi przyjmować unikalnyidempotency_keygenerowany przez warstwę orkiestracji. Jeśli agent spróbuje wywołać to samo narzędzie dwukrotnie w jednej pętli, drugi call jest bezpiecznym no-opem. - Human-in-the-Loop dla akcji o wysokim ryzyku: Akcje niszczące (usunięcie danych, przelewy powyżej określonego progu) zatrzymują pętlę agenta, zapisują stan w kolejce i generują powiadomienie do operatora w panelu administracyjnym.
3. Retrieval: Dlaczego samo wyszukiwanie wektorowe nie wystarcza
Prosty RAG oparty o kalkulację cosine similarity na embeddingach doskonale radzi sobie z pytaniami ogólnymi (“Jaka jest polityka zwrotów?”), ale zupełnie zawodzi w systemach technicznych i enterprise:
- Zapytanie o kod błędu
ERR_TMF_620_404zostanie dopasowane do ogólnych artykułów o protokole HTTP zamiast do właściwego schematu TMF. - Zapytanie o numer faktury
FV/2026/09/112zostanie rozbite przez tokenizer na losowe pod-tokeny.
Rozwiązaniem produkcyjnym jest Hybrydowy Retrieval (Dense + Sparse) z Re-rankingiem:
[ Zapytanie użytkownika ]
│
┌──────────────┴──────────────┐
▼ ▼
[ Dense Search ] [ Sparse Search ]
(Wektory cosine/dot) (BM25 / Full-Text)
Top-50 wyników Top-50 wyników
└──────────────┬──────────────┘
│
▼
[ Reciprocal Rank ]
[ Fusion (RRF) ]
│ Top-30 kandydatów
▼
[ Cross-Encoder Re-ranker ]
(np. Cohere / BGE-Reranker)
│ Top-5 najbardziej trafnych
▼
[ Kontekst dla LLM ]
- Dense (wektorowe) znajduje powiązania semantyczne i synonimy.
- Sparse (BM25 w Postgresie lub Elasticsearch) bezbłędnie trafia w kody błędów, identyfikatory i precyzyjne nazwiska.
- Cross-Encoder Re-ranker analizuje pełne pary
(zapytanie, fragment)z uwzględnieniem uwagi na poziomie tokenów, redukując szum z 50 fragmentów do 3-5 precyzyjnych akapitów. Oszczędza to tokeny w oknie kontekstowym i drastycznie redukuje halucynacje.
4. Architektura kaskadowa (Model Routing)
Wysyłanie każdego zapytania użytkownika do największych i najdroższych modeli (takich jak GPT-4o czy Claude 3.5 Sonnet) to marnotrawstwo budżetu i gwarancja wysokiej latencji (często 2–4 sekundy na pierwsze tokeny).
W architekturze korporacyjnej stosuje się Model Router:
- Warstwa 1 (Triage & Classification): Lekki, szybki model (np. Gemini 1.5 Flash, GPT-4o-mini lub lokalny Llama-3-8B) klasyfikuje intencję użytkownika w 150 ms przy ułamkowym koszcie.
- Ścieżka prosta (FAQ, proste transformacje): Odpowiedź jest generowana bezpośrednio przez mały model lub pobierana z Semantic Cache (Redis / pgvector).
- Ścieżka złożona (Wielokrokowa analiza, synteza prawna, generowanie kodu): Ruch jest kierowany do dużego modelu reasoningowego.
W praktyce 60–80% ruchu w aplikacjach B2B może zostać bezstratnie obsłużone przez tańszą i szybszą ścieżkę, zmniejszając rachunek za API o ponad połowę.
5. Obserwowalność: Trzy metryki, które musisz monitorować
Jeśli nie logujesz każdego wywołania LLM z metrykami strukturalnymi, wdrażanie systemu na produkcję to lot na oślep. Narzędzia takie jak Langfuse czy standard OpenTelemetry Semantic Conventions for Generative AI pozwalają śledzić:
- Token Economics per Tenant: Dokładny koszt generowania w podziale na organizacje (kluczowe w aplikacjach Multi-Tenant SaaS, aby nie subsydiować stratnych klientów).
- TTFT (Time-to-First-Token) i Token-per-second: Separacja czasu potrzebnego na wyszukiwanie w bazie danych od czasu generowania tekstu przez model.
- Ewaluacja w locie (RAG Triad): Automatyczne próbkowanie odpowiedzi i weryfikacja:
- Context Relevance (czy retrieval wyciągnął właściwe fragmenty?),
- Groundedness (czy odpowiedź modelu ma pokrycie w faktach z kontekstu?),
- Answer Relevance (czy odpowiedź rzeczywiście odpowiada na pytanie klienta?).
Podsumowanie
W erze produkcyjnych systemów LLM wartość inżynierska nie leży w pisaniu wyszukanych promptów. Leży w architekturze odpornej na błędy: rygorystycznej walidacji schematów, hybrydowym wyszukiwaniu informacji, izolacji stanów maszyn agentowych i precyzyjnej kontroli kosztów. Traktuj LLM jak zewnętrzny serwis sieciowy, który może zwrócić błąd, opóźnić się lub skłamać – a Twój system będzie działał stabilnie.