Jev в ИИ-агентах: быстрые микрорешения вместо вызовов LLM

Обновлено

Агент на LLM тратит полный вызов модели на каждое мелкое решение — куда нажать, какой инструмент взять, закончена ли задача. Разбираем, какие из этих решений можно отдать Jev, как это сделали в браузерных и мобильных агентах и где такой подход не окупается.

Где агент теряет время

Классический агент тратит полный вызов LLM на каждое микрорешение: каким инструментом воспользоваться, безопасна ли команда, готов ли результат. Так описывает проблему обзор ai-stat.ru. Каждый такой вызов добавляет секунды ожидания и центы.

Но у большинства этих решений закрытый набор ответов. Элементы на странице известны, список инструментов известен, «готово» — это да или нет. Такие решения можно отдать Jev: она выбирает из заданных вариантов за 70–500 мс и не может вернуть вариант вне списка. Короткий обзор всех сценариев — в статье о применении Jev, здесь разберём агентов подробно.

Решение Кто принимает
Какую операцию выполнить и с каким элементом Jev, Choice
Какой инструмент или навык подключить Jev, Choice и Noul «ничего не подходит»
Зациклился ли агент, пора ли перепланировать Jev, Noul
Безопасно ли действие Jev и правила в коде
Текст для поля, план, ответ пользователю LLM

Браузерный агент: одно решение — один запрос

Показательный пример — jev-ultrafast от Browser Use. На каждом шаге агент снимает таблицу видимых элементов страницы с номерами. Jev одним запросом выбирает операцию — нажатие, ввод текста, выбор из списка, прокрутку, ожидание, DONE или BLOCKED — и сразу цель для каждой операции. Вопросы о целях спекулятивные: если выбрано нажатие, код берёт только ответ о цели нажатия, остальные отбрасывает. Так два решения укладываются в один сетевой запрос. Небольшая LLM подключается, только когда нужно написать текст для поля.

Результат: поиск рейсов из Цюриха в Лондон в Google Flights за 7,1 секунды, включая загрузку страниц и генерацию текста. Тот же агент открыл нужную статью Википедии за 2,8 секунды. Это отдельные демонстрационные прогоны, а не бенчмарк. Другой пример приводит ai-stat.ru: команда Cua показала computer-use агента, где решения о кликах принимает Jev, и он оказался в пять раз быстрее варианта на Astra и на три порядка дешевле. Схема «спросить всё сразу, а потом выбрать нужное» подробно описана в статье о fan-out.

from typesafe_sdk import TypeSafeClient, Choice

# elements — видимые элементы страницы, например {"e7": "button · Найти"}
# в каждый вопрос о цели попадают только подходящие элементы;
# если подходящих нет, такой вопрос не отправляйте
buttons = {k: v for k, v in elements.items() if v.startswith(("button", "link"))}
fields = {k: v for k, v in elements.items() if v.startswith(("textbox", "combobox"))}

with TypeSafeClient() as client:
    r = client.system_one(
        state={"goal": goal, "elements": elements, "last_steps": history[-3:]},
        questions={
            "operation": Choice(
                instructions="Какое действие сейчас приблизит выполнение цели?",
                criteria={
                    "CLICK": "Нажать на кнопку или ссылку",
                    "TYPE_TEXT": "Ввести текст в поле",
                    "SCROLL_DOWN": "Нужного элемента нет на экране",
                    "DONE": "Цель выполнена, результат виден на странице",
                    "BLOCKED": "Продолжить нельзя без человека",
                },
            ),
            "click_target": Choice(
                instructions="Если нажимать, то на какой элемент?", criteria=buttons
            ),
            "type_target": Choice(
                instructions="Если вводить текст, то в какое поле?", criteria=fields
            ),
        },
    )

op = r.choices["operation"]
if op.confidence < 0.6:
    action = ("ASK_PLANNER", None)  # решение неочевидно, зовём LLM
elif op.choice == "CLICK":
    action = ("CLICK", r.choices["click_target"].choice)
elif op.choice == "TYPE_TEXT":
    action = ("TYPE_TEXT", r.choices["type_target"].choice)
else:
    action = (op.choice, None)

Порог 0,6 — условный, подберите его на своих прогонах. Перед исполнением код проверяет, что элемент по-прежнему на странице и ничем не перекрыт. Авторы jev-ultrafast подчёркивают принцип: ответ модели никогда не превращается в селектор, координаты, команду оболочки или JavaScript. В рецепте jev-use от Cua правило то же: таблицу допустимых действий строит приложение, а неизвестный или устаревший идентификатор отклоняется.

Мобильный агент — даже без LLM

Проект mobile-jev от Droidrun управляет Android-телефоном через API Mobilerun. Jev выбирает операцию: открыть приложение, нажать, ввести текст, прокрутить, перейти по навигации, подождать, DONE или BLOCKED. Операция и подходящие цели снова уходят одним запросом.

Интересная деталь: текст для полей здесь не генерируется. Jev выбирает точный фрагмент из формулировки цели, а код копирует его в поле. Поэтому генеративная модель этому агенту не нужна. В демонстрации агент открыл Uber, ввёл маршрут от аэропорта Сан-Франциско до моста Золотые Ворота и дошёл до выбора оплаты — 9 действий примерно за 21 секунду. Само бронирование не показано.

Выбор инструмента и навыка

Когда у агента десятки инструментов, он то берёт не тот, то подключает лишний. В обзоре Refix предлагают безопасную последовательность: отфильтровать инструменты по правам пользователя, дать Jev выбрать из оставшихся, проверить уверенность и риск, проверить аргументы кодом, запросить подтверждение перед значимыми последствиями и только потом выполнить вызов.

В рецепте TypeSafe Jev выбирает не больше одного навыка из 182 в каталоге Hermes от Nous Research. Работа идёт в два этапа:

  1. Choice ранжирует все навыки по коротким описаниям, а три вопроса Noul проверяют, нужен ли навык вообще. Если их средняя оценка ниже 0,3, ничего не предлагается.
  2. Три лучших кандидата сравниваются по полным описаниям, и для каждого отдельный Noul спрашивает, делает ли навык именно то, что просят.

На 488 запросах к агенту на Claude Haiku 4.5 доля неверно подключённых навыков упала с 16,8% до 7,3%, лишних — с 9,8% до 4,0%. Этапы заняли около 0,31 и 0,1 секунды. Была и цена: семь запросов, которые агент раньше решал верно, сломались из-за уверенных неверных подсказок. Поэтому подсказка агенту сформулирована мягко — её можно проигнорировать.

«Подсознание агента»

По данным ai-stat.ru, в сообществе r/LLMDevs обсуждают паттерн «Jev как подсознание агента»: быстрая модель постоянно оценивает контекст и зовёт большую LLM, только когда действительно нужно думать. Диогу Алмейда, CEO TypeSafe, в разговоре с TechCrunch тоже называл слежение за трассами LLM-агентов и защиту от джейлбрейков одним из сценариев для Jev.

from typesafe_sdk import Noul

WATCH = {
    "stuck": Noul(instructions="Агент повторяет одну и ту же неудачную попытку без прогресса?"),
    "off_task": Noul(instructions="Последний шаг не относится к задаче пользователя?"),
    "premature_done": Noul(instructions="Агент объявил задачу выполненной, не проверив результат?"),
}

r = client.system_one(
    state={"task": task, "plan": plan, "recent_steps": steps[-5:]}, questions=WATCH
)
if max(r.nouls[name].noul for name in WATCH) >= 0.7:
    replan_with_llm()  # подключаем медленное мышление

Похожие проверки есть в pi-warden для кодового агента Pi. Среди его проверок — «застрял» (повторные неудачи одной и той же стратегией) и «проверка готовности» (заявления «готово» без тестов и сборки). Большинство замечаний возвращается агенту, чтобы он исправился сам, не отвлекая человека.

Ещё один пример — fast-jev-compaction: Jev ранжирует старые вызовы инструментов в истории Claude Code и оставляет полезные. По данным Хабра, контекст сократился с миллиона до 86 тысяч токенов примерно за секунду. Но автор обзора оговаривает, что это не доказывает сохранность важного среди отброшенных 914 тысяч токенов.

Готовые интеграции тоже появляются. LangChain выпустила экспериментальные middleware: ModelRouterMiddleware выбирает модель по последнему сообщению пользователя, а AutoModeMiddleware проверяет вызовы опасных инструментов, например bash, и блокирует рискованные до выполнения. Подробнее — в статье о Jev и LangChain.

Где подвох

  • Повторная отправка состояния. На каждом шаге агент заново отправляет страницу. В разборе на Хабре около 98% расходов на модели в семисекундном прогоне jev-ultrafast пришлось на Jev: повторная отправка состояния оказалась дороже двух коротких генераций текста. Отправляйте только видимые элементы и без скриншотов, как делают авторы jev-ultrafast.
  • Не всегда дешевле. На Хабре описан тест, где конфигурация с Jev была на 31% и 43% быстрее, но на 38% и 51% дороже: 39 из 50 обращений были Score, и предварительная фильтрация съела экономию. Прогонов было по одному на конфигурацию.
  • DONE — не доказательство. И jev-ultrafast, и mobile-jev проверяют итог отдельно, не полагаясь на ответ модели: например, мобильный агент заново читает экран и сверяет состояние с целью.
  • Враждебные страницы. Текст на сайте может содержать инструкции для агента, а Jev по умолчанию не считает state враждебным. Нужен отдельный защитный слой.
  • Воспроизводимость. Одинаковый запрос не гарантирует одинаковую трассу. Авторы mobile-jev советуют фиксировать версию модели при сравнении прогонов и сохранять её имя в трассе.

Выбор модели для каждого шага агента — отдельная задача, её мы разобрали в статье о маршрутизации моделей.

Частые вопросы

Может ли Jev управлять агентом без LLM?

В узких задачах с закрытым набором действий — да. Мобильный агент mobile-jev берёт текст для полей из формулировки цели и обходится без генеративной модели. Но планирование, свободный текст и объяснения остаются за LLM.

Какие фреймворки уже поддерживают Jev?

LangChain выпустила экспериментальные middleware для выбора модели и проверки вызовов инструментов, у Cua есть рецепт jev-use, у Browser Use — открытый агент jev-ultrafast. Для других инструментов есть проекты сообщества.

Сколько стоит шаг агента на Jev?

Зависит от размера состояния. В разборе на Хабре браузерный агент за семисекундный прогон отправил в Jev около 90 тысяч входных токенов — примерно $0,0038. Главная статья расходов — повторная отправка состояния страницы на каждом шаге.

Источники