← BlogBlog

Dlaczego wdrożenia AI się nie udają - post-mortem z realnymi liczbami

Większość nieudanych wdrożeń AI nigdy nie rzuca błędem. Model zwraca odpowiedź, która dobrze się czyta, brzmi pewnie i jest błędna - w tym jednym miejscu, w które demo nigdy nie zagląda. To jest uczciwy powód, dlaczego wdrożenia AI się nie udają: nie awaria, tylko płynny, pewny siebie, błędny wynik, który przeszedł każdą kontrolę zrobioną przez człowieka na oko. To post-mortem pięciu awarii, które widzieliśmy z bliska, każda z liczbą, która ją zdradziła, i poprawką, która się utrzymała. Żadna z poprawek nie jest egzotyczna. To ten sam ruch w różnych przebraniach: osadź odpowiedź w realnych danych, a potem sprawdź ją, zanim wyjdzie na produkcję.

Zapytaj, dlaczego wdrożenia AI się nie udają - odpowiedź rzadko jest głośna

Obraz nieudanego systemu AI, który wszyscy nosimy w głowie, jest dramatyczny: halucynuje coś absurdalnego, ktoś robi zrzut ekranu, projekt umiera. Prawdziwe awarie na produkcji są cichsze. Model produkuje coś wiarygodnego, człowiek przelatuje to wzrokiem, wynik idzie dalej, a szkoda wychodzi dwa tygodnie później w kolejce supportu albo na zepsutej stronie, której nikt nie powiązał ze startem.

Jest powód, dla którego silniejsze modele pogarszają to, a nie poprawiają. Jak ujmuje to Atlan w swoim tekście o tym samym problemie, słaby model produkuje oczywiste błędy, a silny produkuje przekonujące. Zły wynik, który widać, jest tani do wyłapania. Zły wynik przebrany za dobry to ten drogi rodzaj, bo przechodzi review na samej płynności.

Warto oddzielić to od drugiej warstwy przyczyn. Artur Jabłoński w zestawieniu dziesięciu błędów wdrożeń AI w firmie trafnie zauważa, że AI nie naprawia złych procesów i że przedwczesna automatyzacja to częsty błąd - to problemy organizacyjne. Ten artykuł jest o czymś innym: o awarii technicznej, która przeżywa nawet dobrze poprowadzone wdrożenie. Prawie każda awaria poniżej ma ten sam korzeń. Zespół zaufał wynikowi, bo dobrze się czytał, zamiast osadzić go w realnych danych i sprawdzić, zanim wyszedł. Poprawka nigdy nie jest sprytniejszym promptem. Jest osadzeniem plus bramką.

Wiarygodny kod, który przechodzi demo i wykłada się na review

Plik Figmy to nie specyfikacja. To zbiór wizualnych wskazówek: przyciski bez nazw semantycznych, design tokens w osobnej bibliotece, reguły auto-layoutu, które znaczą co innego w różnych klatkach. Skieruj na tę niejednoznaczność zwykły model, a wypełni luki zgadywaniem. W pipeline design-to-code, który prowadzimy, wersja generyczna halucynowała nazwy klas i wymyślała propy, których nie było - a wynik wyglądał na tyle wiarygodnie, że przechodził na pierwszy rzut oka.

I to jest pułapka. Kod, który wygląda dobrze i renderuje się źle przy pierwszym uruchomieniu, jest gorszy niż brak kodu, bo ktoś musi najpierw zauważyć, że jest zepsuty, zanim go naprawi - a wtedy siedzi już w gałęzi. Zagnieżdżone komponenty zaostrzały problem: gdy karta zawiera badge, który zawiera ikonę, okno kontekstu wypełnia się szumem komponentu-rodzica, a model zaczyna wymyślać nazwy propów, żeby połączyć to, czego już wyraźnie nie widzi.

Naprawiły to dwie bramki i żadna nie jest błyskotliwa. Pierwsza to kontrola strukturalna przez Pydantic: każda nazwa komponentu, prop i import muszą się resolvować, zanim powstanie choć jeden plik, więc strukturalnie zepsuty kod nigdy nie opuszcza pipeline'u. Druga jest wizualna: skrajne przypadki auto-layoutu rozjeżdżały mniej więcej 15% klatek, więc wygenerowany kod jest renderowany ponownie headlessowo i porównywany piksel po pikselu z oryginalną klatką. Niepowodzenia wracają do kolejki z dołączonym diffem, więc model poprawia się względem konkretnej rozbieżności, a nie zgaduje ponownie. Demo nie potrzebowało nic z tego. Produkcja potrzebowała wszystkiego.

Dane były prawdziwe minutę temu - i to jest problem

Część awarii nie dotyczy błędnych faktów, tylko starych. Zbudowaliśmy głosowego inżyniera wyścigowego do sesji iRacing na żywo, który musi odpowiedzieć kierowcy w niecałe dwie sekundy, czytając telemetrię na żywo przez 19 narzędzi. Oczywisty projekt trzyma cały łańcuch wywołań narzędzi w rozmowie, tak jak chatbot trzyma swój transkrypt. Ten projekt zatruwa kolejną odpowiedź.

Czas okrążenia zebrany 30 sekund temu jest już błędny, gdy nadchodzi kolejne pytanie, ale model nie odróżni nieaktualnej liczby od świeżej - dla niego to wszystko po prostu tekst w kontekście. Więc rozumuje, pewnie, na danych, które wygasły w połowie rozmowy. Nieaktualne dane niesione dalej są gorsze niż brak danych, bo brak danych przynajmniej wymusza świeży odczyt.

Rozwiązaniem było przestać traktować historię jak magazyn danych. Utrwalane są tylko pytanie kierowcy i finalna odpowiedź - okno czterech wiadomości - a każde pośrednie wywołanie narzędzia uruchamia się na świeżo w każdej turze i jest potem odrzucane. Stan na żywo żyje całkowicie poza modelem: worker odpytuje symulator co 100 ms i zapisuje ukończone okrążenia do bazy, którą agent odpytuje na żądanie. Reguła, która uogólnia się poza wyścigi: wszystko, co wrażliwe na czas, pobiera się w momencie pytania, nigdy nie pamięta z wcześniejszej tury.

Model zmyśla liczbę, a ona wygląda prawdziwie

Najgroźniejsza rzecz, jaką produkuje model językowy, to konkretny, pewny fakt wyciągnięty z pamięci zamiast z twoich danych. W asystencie RAG nad bazą wiedzy z 500 tys. rekordów awaria była dokładna: zapytaj o drop rate, a model podawał precyzyjny procent - pewnie i precyzyjnie błędny. Ogólnikowa odpowiedź zaprasza do sprawdzenia. Precyzyjna nie zaprasza, i to właśnie czyni ją gorszą.

Poprawką jest walidacja każdej deklaracji. Każda liczba w odpowiedzi - procent, licznik czasu, wymagany poziom - jest sprawdzana względem źródłowego chunku, z którego rzekomo pochodzi, zanim odpowiedź trafi do użytkownika. Deklaracja bez możliwego do pobrania źródła jest odrzucana albo oznaczana jako niezweryfikowana, nigdy wygładzana w płynną prozę. To nie problem gier. Każda firma siedząca na dużej, ustrukturyzowanej bazie - katalogu produktów, arkuszu specyfikacji, regulaminie - spotyka tę samą awarię w chwili, gdy postawi przed nią okienko czatu: płynne odpowiedzi subtelnie błędne dokładnie na tych liczbach, na których ludzie zadziałają. W kontekście RODO czy AI Act pewny siebie, błędny numer w dokumencie to nie tylko wstyd, to problem zgodności.

Ten sam odruch zmyśla odwołania, nie tylko liczby. W pipelinie treści, który publikuje artykuły SEO, model pisał wiarygodne linki wewnętrzne do stron, które nie istniały. Bez kontroli zapełnia to serwis martwymi linkami i po cichu podkopuje zarówno SEO, jak i zaufanie czytelnika - awaria niewidoczna przy sprawdzeniu trzech artykułów i oczywista przy trzystu. Bramka działa w dwóch miejscach: przed generowaniem pobierana jest żywa sitemapa i realne adresy są wstrzykiwane do promptu, więc model linkuje do stron, które istnieją, zamiast zgadywać; po generowaniu każdy link dostaje żywe zapytanie HTTP, a wszystko, co zwraca 404 albo wskazuje poza znaną sitemapę, zostaje rozpakowane - tekst zakotwiczenia zostaje, uszkodzony link znika. Wzorzec pod oboma przypadkami to jedno zdanie. Jeśli model może coś zadeklarować, każ mu to udowodnić względem źródła.

Działa przy średnim obciążeniu i składa się w szczycie

Ostatni tryb awarii jest najbardziej podstępny, bo to ten, którego demo strukturalnie nie pokaże. System może czuć się dobrze przy średnim obciążeniu i rozpaść się w szczycie, a szczyt to zwykle jedyny moment, który się liczy. Widzieliśmy to na backendzie platformy OTT: startuje mecz na żywo i dziesiątki tysięcy widzów naciska play w tej samej minucie. Tytuł VOD może zaciąć się na sekundę i nikt nie zauważy. Mecz piłki nożnej na żywo - nie.

Naiwne rozwiązanie wykłada się jako kaskada, a nie pojedynczy punkt. Autoryzacja przelatuje aż do bazy, baza się nasyca, timeouty cofają się do serwisów, a spowolnienie rozlewa się, aż cała ścieżka play degraduje się naraz - dokładnie w trakcie wydarzenia, dla którego wszyscy się włączyli. Poprawka jest architektoniczna: Go na ścieżkach krytycznych dla latencji, Redis przed najgorętszymi danymi, żeby autoryzacja nigdy nie trafiała do bazy pod obciążeniem, i strumienie zdarzeń zamiast blokujących wywołań, żeby jeden wolny konsument w dole nie zatrzymał żądania, które widz ma przed sobą.

Skala chowa się tak samo w mniejszych systemach. Bot feedowy na Telegramie, który prowadzimy, wygląda trywialnie - odpytaj kanał, prześlij nowe pozycje - dopóki jedno ogłoszenie nie pasuje do setek użytkowników naraz i jedno zadanie nie staje się setkami wiadomości, wszystkimi do wysłania w kilka sekund i wszystkimi pod limitem tempa. Odpowiedzią była kolejka, która pochłania skok, i workery, które drenują ją w kontrolowanym tempie, ponownie kolejkując przy 429 zamiast gubić wiadomość. Miliony wiadomości dziennie, i nic z tego nie widać w teście z trzema użytkownikami. Obciążenie istnieje tylko na produkcji, więc obciążenie trzeba przetestować przed produkcją.

Co ukrywa demo, zebrane w jednej tabeli

Pięć awarii, jeden kształt. Każda wyglądała dobrze w kontrolowanym demie i pękła w kontakcie z realnymi warunkami: prawdziwą niejednoznacznością, upływającym czasem, danymi na żywo i realnym skokiem obciążenia. Zestawione obok siebie, kolumna z bramką jest tą przydatną: nic w niej nie jest lepszym modelem, wszystko jest osadzeniem i bramkowaniem wokół modelu.

Pięć trybów awarii, od demo do produkcji
Tryb awariiCo pokazuje demoCo pęka na produkcjiBramka
Wiarygodny, ale błędny wynik (design-to-code)Czysto wyglądający kod na prostej klatceZmyślone propy; ~15% klatek rozjechanychBramka strukturalna + pętla pixel-diff
Nieaktualne dane w kontekście (telemetria)Szybkie odpowiedzi na statycznym snapshocieRozumowanie na czasie okrążenia sprzed 30 sSliding window; świeży pobór w każdej turze
Pewna, błędna liczba (RAG nad 500 tys. rekordów)Precyzyjna liczba do zacytowaniaLiczba z pamięci, nie ze źródłaWalidacja każdej deklaracji względem źródła
Zmyślone odwołania (pipeline treści)Ładnie zalinkowany artykułLinki wskazują na strony, które nie istniejąWstrzyknięcie sitemapy + sprawdzenie linków
Składa się w szczycie (streaming, bot feedowy)Żwawo przy średnim obciążeniuKaskadowa awaria w szczycie na żywoCache gorącej ścieżki; kolejka i drenaż skoku

Kolumna, która nigdy się nie zmienia, to ta środkowa. Produkcja to miejsce, gdzie niejednoznaczność, czas, realne dane i obciążenie przychodzą naraz, a demo usuwa całą czwórkę z założenia. To właśnie dlatego zaliczone demo tak mało przewiduje.

Checklista przed wdrożeniem, którą zrobisz w tydzień

Nie potrzebujesz nas ani frameworka, żeby przycisnąć wdrożenie przed startem, i nie ma znaczenia, czy zbudowałeś system, czy go kupiłeś - kupione narzędzie halucynuje tak samo jak własne. Przepuść je przez checklistę poniżej. Każdy wiersz to jedna z awarii wyżej, zamieniona w pytanie, na które odpowiesz małym eksperymentem, a nie opinią.

Zanim wyślesz: sześć kontroli i awaria, którą każda łapie
KontrolaJak ją zrobićAwaria, którą łapie
OsadzeniePoproś o fakt, który umiesz sprawdzić, potem zapytaj, skąd pochodzi. Brak cytowalnego źródła znaczy, że zgaduje.Pewne, błędne fakty
Walidacja każdej deklaracjiPodrzuć zapytanie o znanej ci odpowiedzi, z wiarygodną błędną wartością obok w danych. Zobacz, którą zwróci.Precyzyjnie błędne liczby, podane z pełną pewnością
Bramka strukturalna wynikuPodaj zniekształcone albo brzegowe wejście i potwierdź, że zepsuty wynik jest odrzucany, nie publikowany.Wiarygodnie zepsuty wynik idący dalej
Weryfikacja wynikuDla wszystkiego, na co system się powołuje - link, ID, plik - potwierdź, że cel istnieje po generacji.Zmyślone odwołania
Obsługa nieaktualnych danychZadaj dwa pytania z rzędu, gdzie odpowiedź zmienia się między nimi. Potwierdź, że drugie nie rozumuje z pierwszego.Stare dane niesione dalej
Test szczytu obciążeniaOdtwórz swoją realną najgorszą minutę, nie średnią - skok na starcie, wydarzenie na żywo, wsad na koniec miesiąca.Systemy, które składają się w szczycie

Zrób to przed startem, a większość awarii z tego tekstu nigdy nie dotrze do użytkownika. Pomiń, a dostajesz ten cichy rodzaj awarii, który wychodzi czysto i wypływa tygodnie później. (To robota, którą robimy na co dzień, tak swoją drogą - ale checklista broni się sama, kto by jej nie zrobił.)

Jeśli chcesz drugą parę oczu na to, gdzie konkretne wdrożenie najpewniej pęknie, krótki audyt to niskostawkowy sposób, żeby ją mieć: wychodzisz z dwoma czy trzema trybami awarii, które najpewniej ugryzą twój system, przypiętymi do kontroli wyżej.

FAQ

Dlaczego agenty AI przechodzą demo, a potem wykładają się na produkcji?

Demo działa na dobranych wejściach, statycznym snapshocie i jednym użytkowniku. Produkcja dokłada realną niejednoznaczność, dane na żywo, które się starzeją, fakty, które model woli zmyślić, i skok obciążenia - a żadnego z tego demo nie ćwiczy. Wynik, który na scenie wyglądał płynnie i poprawnie, to ten sam płynny wynik, który teraz jest pewny siebie i błędny, tylko nikt nie zbudował bramki, żeby go złapać.

Czy większy albo nowszy model to rozwiązanie?

Rzadko. Silniejszy model zwykle robi błędne odpowiedzi bardziej przekonującymi, a nie rzadszymi, więc łatwiej przechodzą przez review człowieka. Trwałe poprawki są architektoniczne: osadź odpowiedź w pobranych danych, zweryfikuj każdą deklarację względem źródła i odrzuć wynik, który się nie resolvuje. To trzyma się niezależnie od tego, jaki model stoi z tyłu.

Którą bramkę dodać jako pierwszą, jeśli mamy dodać jedną?

Osadzanie każdej deklaracji, jeśli twój system podaje fakty albo liczby. Zmuś każdą deklarację, żeby prowadziła do pobranego źródła, i odrzuć albo oznacz to, co nie prowadzi. Usuwa to najdroższą awarię - pewną, precyzyjną, błędną odpowiedź - i przy okazji jest twoim śladem audytowym, gdy ktoś zapyta, skąd wzięła się liczba.

Jak przetestować awarię szczytu obciążenia, zanim się wydarzy?

Odtwórz swoją realną najgorszą minutę, nie syntetyczną średnią. Weź zeszłomiesięczny skok na starcie, okno wydarzenia na żywo albo wsad na koniec miesiąca jako kształt testu. Awarie kaskadowe - autoryzacja przelatująca do bazy, cofające się timeouty - pojawiają się tylko blisko szczytu, więc test obciążenia zbudowany wokół średniego ruchu przejdzie, a produkcja i tak się złoży.

Historia zmian
  • 17 lipca 2026Publikacja.
Bezpłatny audyt procesów

Zobacz, jak wyglądałoby to w Twoich procesach.

Skontaktuj się

30 minut · wskazujemy 3 najlepsze obszary do automatyzacji · bez zobowiązań