Modele decyzyjne oparte na wpisywaniu tekstu a wywołania LLM: opóźnienie i stabilność na granicy
Eksperyment z 240 wywołaniami porównujący naturalne prawdopodobieństwa Jeva z tymi, które sam zgłasza model LLM, oraz sposoby przekształcenia tych danych w router modeli LangChain.
Źródła: **Does Every AI Decision Need an LLM? Testing Jev with LangChain**
Współczesny kod agenta jest pełen małych ocen typu „tak” lub „nie”: czy ten ticket jest pilny, czy wywołanie tego narzędzia odpowiada żądaniu, czy warto pobrać ten fragment danych. Standardowym podejściem jest odpowiadanie na każdą z tych pytań kolejnym wywołaniem modelu LLM i analizowanie uzyskanej, ustrukturyzowanej odpowiedzi – metoda ta działa, ale kosztuje sekundy na krok i generuje liczby o niejednoznacznym znaczeniu. W tym przewodniku ta sama decyzja jest realizowana 240 razy – raz za pomocą specjalnie stworzonego modelu decyzyjnego, a raz za pomocą ogólnego modelu LLM – a następnie uzyskana prawdopodobieństwo jest przekazywane do routera LangChain. Pod koniec dowiesz się, jak sprawiedliwie ocenić takie porównania, jak wyglądają różnice w opóźnieniach i stabilności oraz jak przechowywać zasady routingu w prostym kodzie, a nie w promptach.
Oceny ograniczone nie są zadaniami generatywnymi
Spójrz na decyzje występujące w typowej aplikacji opartej na LLM – wiele z nich tak naprawdę nie dotyczy tworzenia tekstu:
- Czy ten ticket obsługi klienta powinien być traktowany jako pilny?
- Czy proponowane narzędzie rzeczywiście odpowiada temu, o co prosił użytkownik?
- Czy dokument spełnia określone warunki?
- Czy odzyskany fragment jest na tyle istotny, by zostać włączony do kontekstu?
Zwykła implementacja przekazuje obecny stan modelowi LLM, prosi o strukturyzowaną odpowiedź i przekształca tę odpowiedź w gałąź w kodzie. W zasadzie nie ma z tym nic złego. Otwartym pytaniem pozostaje to, czy każdy z tych punktów rozgałęzienia zasługuje na pełny model autoregresyjny.
Jev jest pierwszym modelem TypeSafe AI w serii, którą firma nazywa „System One”, i przyjmuje zupełnie odwrotny podejście. Nigdy nie wytwarza tekstu wolnego – podaje się mu stan systemu oraz zestaw ograniczonych pytań, a on odpowiada poprzez zapisane decyzje i prawdopodobieństwa. Producent przedstawia go jako element budulcowy oprogramowania, a nie zamiennik modelu do rozmów czy rozumowania. LangChain opublikował integrację wykorzystującą Jev w narzędziach agentowych do zadań takich jak wybór modelu czy sprawdzanie wywołań narzędzi. Obie te produkty były nowe w momencie pisania tego tekstu, więc przed ich wykorzystaniem należy sprawdzić aktualne interfejsy API. Jeśli interesuje Cię głównie aspekt kosztowy tego rozwiązania, artykuł na temat określania ceny routera decyzji typowanych przed wywołaniami modeli frontier LLM omawia ten aspekt; tutaj natomiast skupiamy się na zachowaniu i opóźnieniach.
Projektowanie porównania
Oba systemy otrzymały dokładnie jedno pytanie do odpowiedzi, sformułowane w ten sposób: czy żądanie wymaga rzeczywistego wieloetapowego rozumowania, czy jest czymś prostszym, takim jak bezpośrednie wyszukiwanie, pobranie wartości, prosta kalkulacja, przepisanie lub niewielka lokalna edycja?
Zamierzenie przy tworzeniu zadań polegało na skupieniu się na przypadkach dwuznacznych. Oczywiste ekstremum niewiele mówią; interesujące zachowanie routera występuje w obszarze, gdzie „po prostu odpowiedz” przechodzi w „przemyśl to dokładnie”. Wykorzystano osiem żądań od programistów:
- Wyszukiwanie w słowniku: dlaczego wyszukiwanie klucza w słowniku Pythona jest zazwyczaj operacją O(1).
- Lista vs zbiór: która z tych dwóch struktur nadaje się do przechowywania unikalnych identyfikatorów użytkowników.
POST /users/{id}/delete oraz sprawdzenie, czy istnieje bardziej uporządkowana forma REST.Każde z zadań zostało wykonywane dziesięć razy w każdym z trzech scenariuszy:
- Jev, określany za pomocą
Noulktóry zwraca prawdopodobieństwo, że żądanie wymaga skomplikowanych obliczeń.
Budżet wywołań jest ustalany w następujący sposób.
8 prompts
× 10 repetitions
× 3 conditions
= 240 calls
Każde wywołanie rejestrowało swoją decyzję, istniejące prawdopodobieństwo (jeśli takie było), nazwę modelu oraz czas potrzebny na przesyłanie i odbieranie danych. Ważne jest, aby jasno określić, czego eksperyment nie próbuje osiągnąć: nie istnieje żadna prawdziwa wartość odniesienia określająca, ile rozumowania „naprawdę” wymaga dany zapytanie, więc kwestia poprawności jest niemożliwa do oceny. Zamiast tego eksperyment koncentruje się na trzech węższych pytaniach:
- Czy model decyzyjny i model generatywny dochodzą do podobnych wniosków dotyczących kierowania zapytaniem?
Najważniejsze wyniki pochodziły od promptów na granicy możliwości, a nie od tych wyraźnie złożonych.
Trzy implementacje jednej decyzji
Wszystkie trzy rozwiązania zostały napisane w Pythonie przy użyciu LangChain.
Jev z jednym Noul
Model Noul modeluje propozycję binarną, ale zamiast od razu podać wartość True lub False, zwraca prawdopodobieństwo. Jev otrzymuje żądanie programisty jako swój stan oraz jeden Noul zawierający pytanie. W przybliżeniu definicja pytania wygląda tak:
Noul(
instructions="""
Does this request require substantial multi-step reasoning
rather than a direct lookup, extraction, simple calculation,
rewriting task, or small localized edit?
"""
)
Odpowiedzią jest po prostu liczba, na przykład:
0.86
Ta wartość oznacza prawdopodobieństwo, że stwierdzenie jest prawdziwe:
P(requires substantial reasoning) = 0.86
Aby porównać Jev z konfiguracją binarnego LLM, prawdopodobieństwo wynoszące 0.5 lub więcej jest uznawane za True.
GPT-5.6 Sol raportuje własne prawdopodobieństwo
Jako bazę generatywną użyto ChatOpenAI poprzez LangChain, przy czym model Pydantic określał strukturę wyjściową. Ograniczenia Field(ge=0.0, le=1.0) gwarantują, że liczba mieści się w określonym zakresie; nie mówią one jednak nic o tym, czy ma ona jakiekolwiek znaczenie.
class ReasoningProbability(BaseModel):
requires_reasoning: bool
probability: float = Field(ge=0.0, le=1.0)
Tutaj model musiał dostarczyć zarówno werdykt, jak i ocenę prawdopodobieństwa odpowiedzi „tak”. Ta różnica zasługuje na uwagę. Wyjście Jev to dokładnie to, do czego został stworzony model. Liczba podana przez LLM to tekst, który generuje, ponieważ schemat wymaga wartości typu float, a nie ma gwarancji, że odzwierciedla ona jakiekolwiek wewnętrzne prawdopodobieństwo. Traktowanie tych dwóch liczb jako tego samego rodzaju wielkości jest założeniem, a nie faktem.
GPT-5.6 Sol zmuszony do pracy w formacie boolowskim
Trzecia konfiguracja wyeliminowała wszelkie odniesienia do prawdopodobieństwa i poprosiła ten sam model o jedno pole danych:
class ReasoningBinary(BaseModel):
requires_reasoning: bool
Pozostają wtedy trzy odrębne sygnały: jedno oparte na naturalnym prawdopodobieństwie oraz dwa warianty generatywne.
Jev
→ native probabilistic decision
GPT-5.6 Sol
→ generated probability + decisionGPT-5.6 Sol
→ forced binary decision
Co pokazały 240 wywołań
Wynikły trzy wzorce:
- Jev osiągnął decyzję w określonych granicach znacznie szybciej.
- W przypadkach, gdy wyraźnie potrzebne było rozumowanie, systemy w większości zgadzały się ze sobą; różnice pojawiły się blisko granicy.
- W przypadku jednego specyficznego zapytania, samodzielnie podane przez model prawdopodobieństwo znacznie się zmieniało pomiędzy identycznymi wywołaniami.
Latencja: dziesiątki milisekund kontra sekundy
Mierzony jako średni czas przejścia tam i z powrotem, Jev odpowiedział w 128,8 ms na każdą decyzję. GPT-5.6 Sol potrzebował 2 828,1 ms, aby podać prawdopodobieństwo, a w trybie wyłącznie binarnym – 4 072,1 ms. Oznacza to mniej więcej 22 razy wolniejszą pracę w wersji z prawdopodobieństwem i 32 razy wolniejszą w wersji logicznej.
Należy traktować te wartości jako chwilowy pomiar, a nie standard oceny wydajności. Opóźnienie API zależy od obciążenia dostawcy, wersji modelu, regionu oraz trasy sieciowej. Istotna jest skala tych wartości: gdy zadanie polega na jednej ograniczonej ocenie, uruchomienie ogólnego modelu generatywnego wymaga znacznie większych zasobów, niż jest to konieczne do rozwiązania zadania.
Wynik oparty wyłącznie na danych binarnych jest ciekawostką wartą odnotowania. Prośba o mniej pól wyjściowych nie przyspieszyła wykonywania zadania; wręcz przeciwnie, było to wolniejsze. Jeden mały test nie może wyjaśnić dlaczego, ale stanowi przypomnienie, że opóźnienia w działaniu modeli LLM są determinowane przez czynniki inne niż liczba widocznych tokenów wyjściowych, takie jak kolejki oczekiwania, wypełnianie danych z góry oraz wszelkie ukryte procesy rozumowania, które model przeprowadza przed udzieleniem odpowiedzi.
Zgodność w skrajnych przypadkach, różnice na granicy
W przypadku wyraźnie złożonych zapytań, przy zastąpieniu Redis i podziale na mikrosługi, oba systemy były zgodne i oceniły konieczność rozumowania jako wysoką. Różnica pojawiła się przy prostszych zapytaniach. W przypadku wyszukiwania w słowniku, porównywania list z zbiorem oraz pytań dotyczących projektu REST, GPT-5.6 Sol podał prawdopodobieństwa bliskie zeru, natomiast Jev umieścił je znacznie bliżej środka zakresu.
Najwyraźniejszym przykładem była ocena metodologii REST:
Zapytanie dotyczy krytyki POST /users/{id}/delete oraz lepszej alternatywy w stylu RESTful.
Srednia prawdopodobieństwo Jev wyniosła 0,551, co jest nieco powyżej progu 0,5. GPT-5.6 Sol osiągnął średnio 0,071. Nie była to przypadkowa wartość graniczna – we wszystkich dziesięciu próbach Jev sklasyfikował zapytanie jako wymagające intensywnego rozumowania, natomiast we wszystkich dziesięciu próbach obu systemów LLM Sol uznał je za takie, które nie wymagają intensywnego rozumowania.
To jednak nie oznacza, że Jev ma rację. Bez etykietowanych danych referencyjnych nie można stwierdzić, która ocena jest lepsza. Można natomiast stwierdzić, że te dwa sygnały nie są wzajemnie zamienialne i różnią się dokładnie w obszarze, w którym router jest najbardziej wrażliwy na sposób określenia swoich granic. Jeśli zastąpisz jeden źródło decyzji innym, oczekuj zmian w routowaniu dokładnie w tych zapytaniach, co do których jesteś najmniej pewien.
Dwa liczby od zera do jednego, które zachowują się inaczej
Powtórzenie każdego zapytania dziesięć razy pozwoliło dostrzec stabilność. Większość zapytań dała dość spójne wyniki zarówno w obu systemach. Wyjątkiem była prośba o wybór między kolejką a systemem pub/sub do powiadamiania o zamówieniach.
W ramach dziesięciu identycznych prób prawdopodobieństwo podane przez GPT-5.6 Sol wahało się mniej więcej od 0,28 do 0,90, podczas gdy wartości Jev pozostały ściśle skupione. Konfiguracja binarnego LLM odpowiedziała True w dziewięciu z dziesięciu prób, więc werdykty były dość stabilne, mimo że podane poziomy pewności nie były takie.
Wyjaśnienie ma charakter strukturalny. Obie systemy wytwarzają wartość, którą można zapisać jako liczbę z zakresu [0, 1], ale procesy leżące u ich podstaw się różnią. W przypadku Jev prawdopodobieństwo stanowi naturalny wynik modelu dla ograniczonej decyzji. W przypadku LLM jest to sekwencja tokenów wygenerowana, ponieważ prompt wymagał oszacowania, a proces próbkowania może przynieść zupełnie różne wartości przy kolejnych uruchomieniach. W tym zadaniu samodzielnie podawane przez LLM wartości prawdopodobieństwa nie zachowywały się spójnie jak wyniki modelu zaprojektowanego do podejmowania decyzji probabilistycznych. Jeśli planujesz użyć takiej wartości jako progu decyzyjnego, zmierz jej wariancję przy wielokrotnych wywołaniach przed zaufaniem jej wynikom.
Zmiana prawdopodobieństwa na router LangChain
To porównanie skłoniło do przeprowadzenia praktycznego testu: wykorzystanie prawdopodobieństwa z Jev do kierowania rzeczywistymi żądaniami pomiędzy dwoma modelami OpenAI.
- GPT-5.6 Luna obsługuje żądania, które według oceny nie wymagają złożonego rozumowania.
Jev nigdy nie wybiera modelu bezpośrednio. Odpowiada na to samo pytanie Noul z eksperymentu, czy żądanie wymaga skomplikowanego rozumowania wieloetapowego, i zwraca wartość prawdopodobieństwa, np. 0.54, co oznacza P(wymaga skomplikowanego rozumowania) = 0.54.
Kod aplikacji następnie porównuje tę wartość z progiem zdefiniowanym w standardowym Pythonie:
REASONING_THRESHOLD = 0.65
Sama gałąź jest równie prosta:
if reasoning_probability >= REASONING_THRESHOLD:
model = powerful_model
else:
model = fast_model
Kluczową kwestią jest podział zadań. Jev dostarcza prawdopodobieństwo; aplikacja decyduje, co z nim zrobić. Przy progu 0.65 wynik 0.54 kieruje dane do Luna, a wynik 0.86 – do Sol. Zasady są jasne, deterministyczne i można je przejrzeć w porównaniu kodu, natomiast ocena semantyczna pozostaje w gestii modelu.
Pełny proces wygląda następująco:
User request
↓
Jev
↓
P(requires substantial reasoning)
↓
Python threshold = 0.65
↙ ↘
Luna Sol
Uwaga dotycząca tego progu: 0.65 ma charakter ilustracyjny, a nie został dostosowany. Został wybrany jedynie po to, aby w małej demonstracji oczywiście proste żądania trafiły na jedną stronę, a pytania dotyczące projektu i architektury, które uzyskały wyższe wyniki, na drugą. W warunkach produkcyjnych należałoby go wybrać empirycznie na podstawie większego, oznaczonego zbioru danych, biorąc pod uwagę dwa różne rodzaje błędów: konieczność używania drogiego modelu do obsługi prostego żądania oraz wysyłanie naprawdę trudnego żądania do mniej wydajnego modelu. Te koszty rzadko są symetryczne, więc najlepszy próg rzadko wynosi 0.5.
Jak zachowywał się router
Sześć żądań przeszło przez router – od prostego obliczenia po problem związany z architekturą wielorégionalną. Większość wyników odpowiadała intuicji. Zadania związane z obliczeniami i przepisywaniem uzyskały bardzo niskie wyniki i trafiły do Luny; znacznie trudniejsze pytania dotyczące architektury uzyskały wysokie wyniki i trafiły do Sola.
Przypadki o średnim poziomie trudności znajdowały się pomiędzy nimi:
- wyjaśnienie związane z wyszukiwaniem w słowniku uzyskało ocenę 0,46
- przegląd REST API uzyskał ocenę 0,54
- pytanie dotyczące kolejek w porównaniu z pub/sub uzyskało ocenę 0,86
Ponieważ Jev zwraca ciągłą ocenę zamiast stałej etykiety easy lub hard, stopień agresywności routingu staje się odrębną, dostosowywalną decyzją. Przy wartości 0,65 przegląd REST API trafił do Luny, a pytanie o kolejki w porównaniu z pub/sub do Sol. Podniesienie progu spowodowałoby wysyłanie mniej zapytań do większego modelu i oszczędzenie kosztów; obniżenie go zmniejszyłoby ryzyko niewystarczającego obsłużenia trudnego zapytania. Ocena modelu nie zmienia się po dostosowaniu tego parametru, co oznacza, że można regulować zasady, nawet dynamicznie, bez konieczności ponownego zadawania pytań.
Ograniczenia tego eksperymentu
Zachowaj proporcję twierdzeń:
- Osiem zapytań nie może służyć do opisania obu modeli w ogólności, a sama kwestia etykietowania jest subiektywna.
- Dokładność i kalibracja nie zostały zmierzone. Test porównuje zachowanie, spójność i opóźnienie, a nie poprawność.
- Nie należy zakładać, że prawdopodobieństwa Jeva oraz wartości podawane przez sam model LLM mają to samo znaczenie statystyczne.
- Wartości opóźnienia zależą od dostawcy oraz warunków w momencie przeprowadzania testu.
Mocniejsze badanie wykorzystałoby większy zbiór danych z etykietami i oceniło funkcjonowanie routera od początku do końca: dokładność routingu, kalibrację, jakość odpowiedzi, koszt oraz wrażliwość na różne progi.
Kiedy warto użyć oddzielnego modelu decyzyjnego
Dla małej aplikacji często w zupełności wystarczy pozwolenie modelowi LLM na obsługę routingu – jeden dodatkowy wywołanie rzadko ma znaczenie. Sytuacja zmienia się, gdy agent musi wykonywać liczne kroki związane z routowaniem, wyszukiwaniem informacji, weryfikacją oraz sprawdzaniem narzędzi. Wiele z tych operacji polega na ocenach ograniczonych, a jeśli każda z nich staje się kolejnym wielosekundowym procesem generatywnym, pętla działania agenta staje się wolna i kosztowna z powodów niezwiązanych z samą pracą.
Czyste rozdzielenie obowiązków wygląda następująco:
- Model decyzyjny zajmuje się ocenami semantycznymi ograniczonymi i zwraca prawdopodobieństwo.
- Kod aplikacji odpowiada za progi, zasady działania oraz rozgałęzienia logiki.
- Model LLM zajmuje się myśleniem i pisaniem o otwartym zakończeniu.
Zdolny LLM mógłby obsłużyć wszystkie z tych zadań, ale to nie oznacza, że każda część systemu musi używać tego samego typu modelu, szczególnie gdy ma znaczenie opóźnienie. Szersze uzasadnienie dla doboru rozmiaru modeli do konkretnego zadania znajduje się w artykule o prawidłowym doborze rozmiaru LLMów w kontekście routingu, wyszukiwania i oceny.
Główne wnioski
- W tym teście model decyzyjny osiągał średnio około 129 ms na jedną ocenę, podczas gdy rozwiązania generatywne potrzebowały kilku sekund.
- Przy niemal dwuznacznych danych oba systemy konsekwentnie się nie zgadzały, a nie losowo, więc zastąpienie jednego sygnału drugim zmieni ścieżkę przekierowania w najbardziej wrażliwych punktach.
- Prawdopodobieństwo podane przez sam LLM może znacznie się różnić w identycznych wywołaniach (około 0,28 do 0,90 na jeden prompt); sprawdź jego wariancję przed ustawieniem progu.