Главная / Статьи

Модели принятия решений на основе ввода текста против вызовов LLM: задержка и стабильность на границе

Эксперимент с 240 вызовами, сравнивающий естественные вероятности, указанные Джефом, с теми, которые само сообщает большая языковая модель, а также способы преобразования этих данных в маршрутизатор моделей LangChain.

Издатель: REACTAPP.TOP12 мин чтения2657 слов

Источники: **Does Every AI Decision Need an LLM? Testing Jev with LangChain**

Современный код агентов полон небольших вопросов типа «да/нет»: является ли этот тикет срочным, соответствует ли используемый инструмент запросу, стоит ли загружать этот фрагмент данных. Обычно для ответа на каждый из этих вопросов делается ещё один вызов генеративной нейронной сети, а затем обрабатывается структурированный ответ; это сработает, но потребует нескольких секунд на каждый шаг и приведёт к получению чисел неоднозначного значения. В данном примере тот же ограниченный набор решений выполняется 240 раз с помощью специально созданной модели принятия решений и обычной нейронной сети, после чего полученные вероятности передаются в маршрутизатор LangChain. К концу вы узнаете, как справедливо оценивать такое сравнение, в чём заключаются различия в задержках и стабильности, а также как хранить правила маршрутизации в обычном коде, а не в промптах.

Ограниченные решения — это не задачи генерации

Посмотрите на решения, принимаемые в типичном приложении с ИИ-моделью, и многие из них на самом деле не связаны с генерацией текста:

  • Следует ли считать этот заявок на поддержку срочной?
  • Действительно ли предлагаемый инструмент соответствует тому, о чем просил пользователь?
  • Удовлетворяет ли документ определенному условию?
  • Является ли извлеченный отрывок достаточно релевантным, чтобы включить его в контекст?

Типичная реализация передает текущее состояние ИИ-модели, запрашивает структурированный ответ и преобразует этот ответ в отдельную ветку в коде. В принципе в этом нет ничего плохого. Оставшимся вопросом является то, заслуживает ли каждая из этих точек разветвления использования полной авторегрессивной модели.

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 — это текст, который она генерирует, поскольку схема требует значения типа float, и нет никаких гарантий, что оно отражает какую-либо внутреннюю вероятность. Считать эти два числа одним и тем же типом величины — это предположение, а не факт.

    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. При одном граничном запросе самооценка вероятности LLM сильно менялась при идентичных вызовах.

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

    При измерении среднего времени в пути туда-обратно 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. Средняя вероятность для 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(требуется сложное рассуждение) = 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. Повышение порога приведёт к отправке меньшего количества запросов к более мощной модели, тем самым снижая затраты; понижение порога увеличит вероятность правильного обработки сложных запросов. Оценка модели не меняется при изменении этого параметра, что позволяет настраивать правила, даже динамически, без необходимости повторного задавания вопросов.

    Ограничения этого эксперимента

    Сохраняйте соразмерность утверждений:

    • Восемь примеров недостаточно для общего описания любой из моделей, к тому же сам вопрос маркировки является субъективным.
    • Точность и калибровка не измерялись. В ходе тестирования сравниваются поведение, последовательность действий и задержка, а не правильность ответа.
    • Не следует предполагать, что вероятности, рассчитанные Джефом, и значения, самостоятельно указанные большой языковой моделью, имеют одинаковое статистическое значение.
    • Значения задержки зависят от поставщика и условий в момент тестирования.

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

    Когда стоит использовать отдельную модель принятия решений

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

    Четкое разделение обязанностей выглядит следующим образом:

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

    Способный LLM мог бы справиться со всеми этими задачами, но это не обязывает каждую часть системы использовать один и тот же тип модели, особенно когда важна задержка. Более подробное обоснование необходимости подбора размера модели в соответствии с задачей приводится в статье о правильном подборе размера LLM с учётом механизмов маршрутизации, поиска и оценки.

    Основные выводы

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