Головна / Статті

Моделі рішень, створені шляхом набору тексту, проти викликів LLM: затримка та стабільність на межі

Експеримент із 240 викликами, який порівнює природні ймовірності Jevа з тими, які самостійно задає LLM, а також способи перетворення цього сигналу на маршрутизатор моделей LangChain.

Видавець: REACTAPP.TOP12 хв читання2657 слів

Джерела: **Does Every AI Decision Need an LLM? Testing Jev with LangChain**

Сучасний код агента сповнений дрібними судженнями типу «так» чи «ні»: чи є цей замовлення терміновим, чи підходить цей інструмент для виконання запиту, чи варто отримувати цей фрагмент даних. Зазвичай для кожного з цих питань використовується ще один запит до генеративного LLM та аналізується структурована відповідь, що працює, але займає кілька секунд на кожен крок та дає результати з неоднозначним значенням. У цьому посібнику однакове обмежене судження виконується 240 разів через спеціально створену модель прийняття рішень та через звичайний LLM, а отримані ймовірності передаються до маршрутизатора LangChain. До кінця ви дізнаєтесь, як справедливо оцінювати таке порівняння, як виглядають різниці у затримках та стабільності, а також як зберігати правила маршрутизації у звичайному коді, а не всередині запиту.

Обмежені судження — це не завдання на генерацію

Подивіться на рішення, які зустрічаються у типовому додатку на основі LLM, і багато з них насправді не стосуються створення мови:

  • Чи слід вважати цей заявку на підтримку терміновою?
  • Чи справді запропонований інструмент відповідає тому, про що просив користувач?
  • Чи відповідає документ певній умові?
  • Чи є отриманий уривок достатньо релевантним, щоб його включити до контексту?

Звичайна реалізація передає поточний стан LLM, просить структуровану відповідь та перетворює її на гілку в коді. У принципі з цим немає жодних проблем. Відкритим залишається питання, чи кожна з цих точок розгалуження справді потребує повноцінної авторегресивної моделі.

Jev є першою моделлю TypeSafe AI у тому, що компанія називає своєю лінійкою „System One“, і вона застосовує протилежний підхід. Вона ніколи не генерує вільного тексту. Ви надаєте їй певний стан та набір обмежених запитань, а вона відповідає у вигляді типових рішень та ймовірностей. Виробник представляє її як елемент для створення програмного забезпечення, а не як заміну моделі для чатування чи міркувань. LangChain опублікував інтеграцію, яка використовує Jev у механізмах агентів для завдань, таких як вибір моделі та перевірка викликів інструментів. Обидва продукти на момент написання статті були новими, тому переконайтеся у актуальності API перед їх використанням. Якщо вас переважно цікавить аспект витрат у цьому підході, стаття про ціноутворення для типового маршрутизатора рішень перед викликами Frontier LLM розглядає саме цей аспект; тут увага зосереджена на поведінці та затримках.

Проектування порівняння

Обом системам було поставлено рівно одне запитання, яке можна сформулювати так: чи вимагає запит справжнього багатокрокового міркування, чи це щось простіше — наприклад, прямий пошук, отримання значення, базові обчислення, переписування чи невелика локальна зміна?

Набір запитів був навмисно побудований з урахуванням неоднозначних випадків. Очевидні крайнощі мало що пояснюють; цікава поведінка маршрутизатора проявляється саме там, де варіант «просто відповісти» переходить у варіант «ретельно все обміркувати». Було використано вісім запитів від розробників:

  1. Пошук у словнику: чому пошук ключа в Python-словнику зазвичай є операцією O(1).
  2. Список проти множини: яка з цих двох структур підходить для зберігання унікальних ідентифікаторів користувачів.

  • Дизайн REST API: аналіз кінцевої точки POST /users/{id}/delete та можливість використання більш оптимізованої структури REST.
  • Redis проти PostgreSQL: чи варто замінити існуючу кеш-систему Redis на PostgreSQL.
  • Асинхронний Python: чи допоможе перехід веб-скрейпера на асинхронний режим.
  • Очікування проти моделі pub/sub: який з цих підходів краще використовувати для повідомлень про статус замовлень.
  • Індексування в SQL: аналіз запиту та оцінка можливості прискорення його виконання за допомогою індексу.
  • Мікросервіси проти моноліту: чи варто розділити Python-сервіс на мікросервіси чи залишити його цілим.
  • Кожне завдання виконувалося десять разів у кожній з трьох конфігурацій:

    • Jev — оцінка через модель Noul, яка визначає ймовірність того, що запит потребує складних обчислень.
  • GPT-5.6 Sol з ймовірністю — через LangChain формує структурований результат та зобов’язаний повернути булеве значення разом із самостійно вказаною ймовірністю.
  • GPT-5.6 Sol, лише у бінарному форматі — цей самий модель вимагає лише значень True або False, без жодної згадки про рівень впевненості.
  • Бюджет викликів розраховується наступним чином.

    8 prompts
    × 10 repetitions
    × 3 conditions
    = 240 calls
    

    Кожен виклик фіксував своє рішення, наявність ймовірності (у разі її наявності), назву моделі та час виконання. Важливо чітко зрозуміти, що експеримент не намагається зробити: не існує об’єктивної ознаки для визначення того, скільки „справді“ розумових зусиль потребує певний запит, тому питання коректності не стоїть. Натомість експеримент спрямований на відповідь на три більш конкретні запитання:

    1. Чи доходять модель прийняття рішень та генеративна модель до схожих висновків щодо маршрутизації?
  • Наскільки послідовними є кожен з них при повторенні ідентичного запиту?
  • Якою є вартість семантичного рішення з обмеженими можливостями з точки зору затримки, коли його приймає спеціалізована модель порівняно з генеративною?
  • Найважливіші результати були отримані від межових запитів, а не від явно складних.

    Три реалізації одного рішення

    Усі три конфігурації були написані на Python за допомогою LangChain.

    Jev з одним Noul

    Модель Noul моделює бінарну пропозицію, але замість того, щоб одразу визначити True чи False, вона повертає ймовірність. Jev отримує запит розробника як свій стан та один Noul, який містить запитання. У загальних рисах визначення запитання виглядає так:

    Noul(
        instructions="""
        Does this request require substantial multi-step reasoning
        rather than a direct lookup, extraction, simple calculation,
        rewriting task, or small localized edit?
        """
    )
    

    Відповідь — це просто число, наприклад:

    0.86
    

    Це значення є ймовірністю того, що твердження є правдивим:

    P(requires substantial reasoning) = 0.86
    

    Щоб порівняти Jev із бінарною конфігурацією LLM, ймовірність 0.5 або більше вважається значенням True.

    GPT-5.6 Sol повідомляє про власну ймовірність

    Як база для генерації використовувався ChatOpenAI через LangChain, причому модель Pydantic визначала формат вихідних даних. Параметри Field(ge=0.0, le=1.0) гарантують, що число знаходиться у встановлених межах; вони не вказують, чи є це число значущим.

    class ReasoningProbability(BaseModel):
        requires_reasoning: bool
        probability: float = Field(ge=0.0, le=1.0)
    

    Тут модель мусила надати як вердикт, так і оцінку ймовірності «так». Це розрізнення заслуговує уваги. Вихідний результат Jev — це саме те, що було створено моделлю для генерації. Число LLM — це текст, який вона генерує, оскільки схема вимагає числа з плаваючою комою, і немає гарантій, що воно відображає якусь внутрішню ймовірність. Вважати ці два числа однаковими є припущенням, а не фактом.

    GPT-5.6 Sol змушений працювати у форматі булевих значень

    У третій конфігурації було видалено всі посилання на ймовірність, і від того ж моделювання було запитано дані лише для одного поля:

    class ReasoningBinary(BaseModel):
        requires_reasoning: bool
    

    Це дає три різні сигнали: один, пов’язаний із первинною ймовірністю, та два генеративні варіанти.

    Jev
        → native probabilistic decision
    
    GPT-5.6 Sol
        → generated probability + decisionGPT-5.6 Sol
        → forced binary decision
    

    Що показали 240 викликів

    Було виявлено три закономірності:

    1. Jev досягав обмеженого рішення значно швидше.
    2. При запитах, які явно вимагали міркувань, системи здебільшого погоджувалися; вони розходились біля межі.
    3. При одному прикладі на межі ЛЛМ самостійно оцінював ймовірність дуже сильно змінював її під час ідентичних викликів.

    Затримка: десятки мілісекунд проти секунд

    Якщо вимірювати середній час поїздки та повернення, Jev відповів за 128,8 мс на кожне рішення. GPT-5.6 Sol зайняв 2 828,1 мс, коли повертав ймовірність, та 4 072,1 мс у режимі з використанням лише бінарних даних. Це приблизно у 22 рази повільніше для варіанту з ймовірностями та у 32 рази повільніше для булевого варіанту.

    Розглядайте ці коефіцієнти як моментальний зразок, а не стандарт оцінки. Затримка API залежить від навантаження провайдера, версії моделі, регіону та мережевого шляху. Важливою є порядкова величина: коли завдання полягає у одному обмеженому судженні, запуск загальної генеративної моделі вимагає значно більших ресурсів, ніж потрібно для вирішення запитання.

    Результат, отриманий лише у бінарному форматі, є цікавим фактом, який варто зазначити. Запит на меншу кількість полів виводу не прискорив обробку; навпаки, вона стала повільнішою. Одного невеликого тесту недостатньо, щоб пояснити це, але це нагадує про те, що затримка роботи LLM від початку до кінця зумовлена факторами, що не стосуються кількості видимих токенів виводу, такими як чергування запитів, попереднє заповнення та будь-які приховані процеси міркування, які модель виконує перед відповіддю.

    Узгодженість у крайніх випадках, розбіжності на межі

    Щодо досить складних запитів, коли використовувалося заміщення Redis та розподіл функцій між мікросервісами, обидві системи дійшли згоди та оцінили необхідність міркувань як високу. Розбіжності з’явилися при простіших запитах. Для завдань на пошук у словнику, порівняння списків та множин та питань щодо дизайну REST GPT-5.6 Sol повідомив про ймовірності майже нульові, тоді як Jev оцінив їх значно ближче до середнього рівня.

    Найяскравішим прикладом був аналіз REST-інтерфейсу:

    У запиті проситься критика POST /users/{id}/delete та краща RESTful альтернатива.

    Середня ймовірність Jev становила 0.551, що трохи перевищує поріг у 0.5. U середньою ймовірністю GPT-5.6 Sol була 0.071. Це не був шум, що знаходиться на межі порога: у всіх десяти спробах Jev класифікував запит як складний для обробки, тоді як у всіх десяти спробах обох моделей Sol класифікував його як простий.

    Це не означає, що Jev має рацію. Без позначеної істинної відповіді неможливо сказати, яке рішення краще. Однак це підтверджує, що ці два сигнали не є взаємозамінними, і вони відрізняються саме у тій зоні, де маршрутизатор найбільш чутливий до способу визначення своїх меж. Якщо ви заміните одне джерело рішень на інше, очікуйте змін у маршрутизації саме для тих запитів, щодо яких у вас найменше впевненості.

    Два числа від нуля до одиниці, які поводяться по-різному

    Повторення кожного запиту десять разів дозволило побачити стабільність. Більшість запитів давали досить послідовні результати від обох систем. Винятком була пропозиція вибрати між чергою та системою pub/sub для сповіщень про замовлення.

    Під час десяти ідентичних викликів самооцінка ймовірності GPT-5.6 Sol коливалася в межах приблизно від 0,28 до 0,90, тоді як значення Jev залишалися дуже близькими одне до одного. Система бінарних LLM відповідала True у дев’яти з десяти випробувань, тож вердикти були досить стабільними, навіть якщо заявлена впевненість не була такою.

    Пояснення є структурним. Обидві системи генерують значення, які можна записати у діапазоні [0, 1], але процеси, що стоять за ними, відрізняються. Для Jev ймовірність є вихідним даним моделі для прийняття обмежених рішень. Для LLM це послідовність токенів, яка створюється через запит на оцінку, причому процес вибору може призводити до досить різних чисел у різних виконаннях. У цьому завданні самооприлюднена ймовірність LLM не демонструвала стабільної поведінки, схожої на вихід дані моделі, розробленої для прийняття ймовірнісних рішень. Якщо ви плануєте використовувати таке число як поріг, виміряйте його дисперсію під час кількох повторних викликів, перш ніж довіряти йому.

    Перетворення ймовірності на маршрутизатор LangChain

    Це порівняння надихнуло на практичний тест: використати ймовірність Jev для маршрутизації реальних запитів між двома моделями OpenAI.

    • GPT-5.6 Luna обробляє запити, які, на думку системи, не вимагають складних міркувань.
  • GPT-5.6 Sol обробляє ті випадки, які, на думку системи, потребують цього.
  • Jev ніколи не обирає модель безпосередньо. Він відповідає на те саме запитання Noul з експерименту щодо того, чи потребує запит значного багатокрокового міркування, та повертає ймовірність, наприклад 0.54, що означає P(requires substantial reasoning) = 0.54.

    Код додатку потім порівнює це значення з пороговим рівнем, визначеним у звичайному Python:

    REASONING_THRESHOLD = 0.65
    

    Сама структура ветки також є досить простою:

    if reasoning_probability >= REASONING_THRESHOLD:
        model = powerful_model
    else:
        model = fast_model
    

    Суть у розподілі обов’язків. Jev надає ймовірність; додаток вирішує, що з нею робити. При пороговому значенні 0.65 оцінка 0.54 направляється до Luna, а оцінка 0.86 — до Sol. Політика є чіткою, детермінованою та може бути переглянута у відмінностях коду, тоді як семантичне судження залишається у моделі.

    Повний алгоритм виглядає так:

    User request
         ↓
        Jev
         ↓
    P(requires substantial reasoning)
         ↓
    Python threshold = 0.65
       ↙                  ↘
    Luna                  Sol
    

    Примітка щодо цього порогу: 0.65 є ілюстративним значенням, а не оптимізованим. Його обрали лише для того, щоб у невеликій демонстрації очевидно прості запити потрапляли в одну групу, а питання щодо дизайну та архітектури, які мали вищий бал, — у іншу. У реальних умовах його потрібно вибирати емпірично на основі більшого набору даних із позначками, враховуючи два різні види помилок: необхідність використання дорогого моделювального інструменту для простого запиту та надсилання справді складного запиту до менш потужного інструменту. Ці витрати рідко є симетричними, тому найкращий поріг рідко дорівнює 0.5.

    Як поводився маршрутизатор

    Через маршрутизатор пройшло шість запитів — від простих обчислень до проблем архітектури кількох регіонів. Більшість результатів відповідали інтуїції. Запити на обчислення та переписування отримали дуже низькі бали та потрапили до Luna; складні питання архітектури мали високі бали та потрапили до Sol.

    Інформативні випадки знаходились посередині:

    • оцінка пояснення з використанням словника становила 0.46
    • оцінка аналізу REST API становила 0.54
    • оцінка запитання про різницю між чергою та моделлю pub/sub становила 0.86

    Оскільки Jev повертає неперервну оцінку замість фіксованої мітки easy чи hard, рівень агресивності маршрутизації стає окремим параметром, який можна налаштовувати. При значенні 0.65 аналіз REST API було передано Luna, а запитання про різницю між чергою та моделлю pub/sub — Sol. Підвищення порогового значення призведе до надсилання меншої кількості запитів до більшої моделі та економії коштів; зниження його зменшить ризик недостатнього оброблення складних запитів. Оцінка моделі не змінюється при коригуванні цього параметра, що дозволяє налаштовувати політику, навіть динамічно, без необхідності повторного запиту.

    Обмеження цього експерименту

    Зберігайте претензії у пропорціях:

    • Вісім запитів не можуть характеризувати жодну з моделей в цілому, а саме питання маркування є суб’єктивним.
    • Точність та калібрування не вимірювалися. Тестування порівнює поведінку, послідовність та затримки, а не правильність.
    • Ймовірності Jev та самостійно задані значення LLM не слід вважати матеріально еквівалентними з точки зору статистики.
    • Значення затримок залежать від постачальника та умов під час тестування.

    Більш ретельне дослідження передбачало б використання більшого набору даних із маркуванням та оцінку роутера від початку до кінця: точність маршрутизації, калібрування, якість відповідей на кінцевому етапі, витрати та чутливість до різних порогових значень.

    Коли варто використовувати окрему модель прийняття рішень

    Для невеликого додатку часто цілком достатньо дозволити LLM виконувати маршрутизацію; один додатковий виклик рідко має значення. Ситуація змінюється, коли агент виконує кроки маршрутизації, пошуку інформації, її перевірки та контролю інструментів. Багато з цих кроків є обмеженими семантичними оцінками, і якщо кожен з них стає ще одним багатосекундним генеративним викликом, цикл роботи агента сповільнюється та стає дорожчим з причин, не пов’язаних із самою роботою.

    Чітке розділення обов’язків виглядає так:

    • Модель прийняття рішень обробляє обмежені семантичні оцінки та повертає ймовірність.
    • Код додатку визначає пороги, правила та шляхи розвитку подій.
    • LLM виконує відкритий процес мислення та написання тексту.

    Здатний LLM міг би впоратися з усіма цими завданнями, але це не означає, що кожна частина системи зобов’язана використовувати однаковий тип моделі, особливо коли важлива затримка. Більш детально аргументи на користь підбору розміру моделей під конкретне завдання розглядаються у правильному підборі розміру LLM з урахуванням маршрутизації, пошуку та оцінки.

    Ключові висновки

    • Під час цього тестування модель прийняття рішень в середньому витрачала близько 129 мс на кожне судження, тоді як у генеративних системах цей час становив кілька секунд.
    • При майже неоднозначних вхідних даних обидві системи послідовно, а не випадково, розходилися у своїх рішеннях, тому заміна одного сигналу на інший змінить маршрутизацію саме там, де вона найбільш чутлива.
    • Самооприлюднена ймовірність LLM може сильно варіюватися при ідентичних запитах (приблизно від 0,28 до 0,90 для одного запиту); перевірте її дисперсію перед встановленням порогу.
  • Зберігайте порогове значення в коді, обираючи його на основі позначених даних та асиметричної вартості кожної помилки, і розглядайте спеціалізовану модель прийняття рішень як доповнення до LLM, а не як її швидшу імітацію.