hermes-hub/agents/inbox/2026-08-31-A39-local-request-options.md
Hermes Team f8b6783641 docs(agents): задание A39 — параметры запроса для локальных профилей
Локальная модель не закрывает задачи: Hermes сообщает о таймауте 180 секунд
после четырёх вызовов и переключается на другого провайдера.

Причина измерена, а не предположена. Служба запущена с --reasoning on и
--reasoning-budget 4096, а модель выдаёт 13,4 токена в секунду. На простой
задаче рефакторинга с лимитом 1500 токенов получено:

    сгенерировано  1500 токенов за 111,6 с
    рассуждений    5483 символа
    ответа         0 символов

Весь лимит уходит на размышления, до ответа модель не доходит. За 180 секунд
она успевает около 2400 токенов — и это тоже одни рассуждения.

Отключение рассуждений на уровне запроса проверено и работает:

    reasoning_effort: none                        ответ за 19,5 с
    chat_template_kwargs: enable_thinking=false   ответ за 11,4 с

Одиннадцать секунд вместо ста одиннадцати. Серверный флаг --reasoning off
решил бы это грубо, лишив рассуждений насовсем, поэтому владелец выбрал
гибкий путь: параметры задаёт хаб, по профилю.

Задание требует не зашивать ни enable_thinking, ни reasoning_effort: набор
ключей зависит от версии llama.cpp, и это данные конфигурации, а не
константы кода. Отдельным критерием — проверка живым запросом к серверу
владельца с замером времени до и после.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 23:04:18 +07:00

9.8 KiB
Raw Permalink Blame History

Задание A39: параметры запроса для локальных профилей

Дата поступления

2026-08-31

База

Ветка ревьюера review/a35-a37-verified (88d579a) — там уже слиты A35, A36, A37 и правки ревьюера.

git fetch origin --prune
git checkout -b antigravity/a39-local-request-options origin/review/a35-a37-verified

В main напрямую не пушить.

Порядок исполнения

Два прохода: Flash реализует, Pro проводит аудит. Пункт P0-5 написан для аудитора.

Задание небольшое и независимое: зона — только локальный адаптер и конфигурация профиля.


Задача

Локальная модель не закрывает задачи: Hermes сообщает «Локальный 27B не закрыл задачу: таймаут 180s, 4 вызова» и переключается на другого провайдера.

Причина найдена и измерена, гадать не нужно.

Что измерено ревьюером — заново не выяснять

Сервер владельца, 127.0.0.1:8081, Qwen3.8-27B на Tesla V100. Служба запущена с --reasoning on --reasoning-budget 4096.

Задача рефакторинга простой функции, лимит 1500 токенов:

сгенерировано:      1500 токенов за 111,6 с (13,4 ток/с)
рассуждений:        5483 символа
самого ответа:      0 символов

Модель израсходовала весь лимит на размышления и до ответа не дошла. За отведённые Hermes 180 секунд она успевает около 2400 токенов — и это по-прежнему одни рассуждения. Отсюда таймаут и четыре безрезультатных вызова.

Отключение рассуждений на уровне запроса — проверено, работает:

reasoning_effort: "none"                          540 симв. рассуждений, ответ 302, 19,5 с
chat_template_kwargs: {"enable_thinking": false}    0 рассуждений,       ответ 449, 11,4 с

11 секунд вместо 111, и ответ появляется. Проблема не в скорости модели, а в том, что она не доходит до ответа.

Серверный флаг --reasoning off решил бы это грубо, но лишил бы рассуждений насовсем. Владелец выбрал гибкий путь: параметры задаёт хаб, по профилю.

Что уже есть

adapters/local_adapter.py:164   payload собирается здесь; сейчас проходят
                                tools, tool_choice, response_format,
                                max_tokens, stream, stop
router_config.py:13             RouterProfileConfig — места под произвольные
                                параметры запроса нет

P0-1. Параметры запроса в профиле

Добавить в RouterProfileConfig поле для произвольных параметров, которые адаптер подмешивает в тело запроса. Например request_options: dict.

Требования:

  1. Ничего не зашивать. enable_thinking, reasoning_effort и прочее — это данные в конфигурации владельца, а не константы в коде. Завтра у llama.cpp появится другой ключ, и правка кода не должна понадобиться.
  2. Сохраняется и переживает перезапуск, как остальные поля профиля.
  3. Вложенные структуры поддерживаются: chat_template_kwargs — это словарь внутри словаря.
  4. Явное поле запроса не перезаписывается молча. Если Hermes прислал max_tokens, параметры профиля его не затирают; при конфликте выигрывает запрос, а факт расхождения пишется в журнал.

P0-2. Локальный адаптер их отправляет

local_adapter.invoke подмешивает request_options в тело перед отправкой.

Осторожно с двумя вещами:

  • Неизвестный параметр не должен ронять вызов. Сервер вернёт ошибку — её надо показать как ошибку провайдера с текстом, а не как отказ маршрутизатора. Механизм разбора ошибок уже есть в base_adapter.extract_api_error_message.
  • Другие провайдеры не затрагиваются. Поле относится к локальным профилям; попадание chat_template_kwargs в запрос к Antigravity или Codex — дефект.

P0-3. Настройка из интерфейса

Владелец должен задавать это без правки YAML вручную.

В карточке локального аккаунта — поле параметров запроса. Достаточно текстового поля с JSON и проверкой разбора: набор ключей зависит от версии llama.cpp, и выпадающий список из зашитых вариантов быстро устареет.

Показать, что именно уйдёт на сервер. И честно сказать, если параметр отклонён сервером, — с его текстом ошибки.

P0-4. Умолчание для профилей владельца

Предложить в отчёте, но не применять молча: для local-1 (27B, порт 8081) поставить

{"chat_template_kwargs": {"enable_thinking": false}}

Обосновать измерением выше. Решение принимает владелец.

Для local-2 (4B, порт 8082) этого не нужно: она запущена с --reasoning off.

P0-5. Аудит вторым проходом

  1. Проверить на живом сервере владельца, а не только заглушкой: запрос с enable_thinking: false должен вернуть ответ за десяток секунд вместо ста.
  2. Утечка в других провайдеров — проверить целенаправленно, что параметр уходит только в локальные.
  3. Неизвестный ключ не роняет вызов и показывается как ошибка провайдера.
  4. Зашитые значения — искать отдельно; в коде не должно быть ни enable_thinking, ни reasoning_effort.
  5. Побочные изменения объяснить.
  6. Пропущенный пункт назвать пропущенным.

Ограничения

  • Зона: adapters/local_adapter.py, router_config.py, карточка аккаунта в вебе, тесты.
  • Серверные юниты qwen-coder и qwen-compressor не трогать: это машина владельца, он меняет их сам.
  • Правило честности без исключений.
  • Тег v0.1.1 не создавать.

Критерии приёмки

  1. Ветка в origin от review/a35-a37-verified, git status чист.
  2. request_options есть в профиле, сохраняется, переживает перезапуск, поддерживает вложенные структуры.
  3. Локальный адаптер отправляет их; проверено живым запросом к серверу владельца с приложенным замером времени до и после.
  4. Параметр не попадает в запросы к другим провайдерам; проверено.
  5. Неизвестный ключ даёт ошибку провайдера с текстом, а не отказ маршрутизатора.
  6. Поле настраивается из интерфейса, показывает отправляемое тело.
  7. Явные поля запроса Hermes не затираются.
  8. Ни enable_thinking, ни reasoning_effort не зашиты в коде.
  9. ruff check . чисто; релизный гейт не ухудшен.
  10. Отчёт: START_HEAD, FINAL_HEAD, origin/main, git status, X passed / Y skipped / Z failed. На ветке ревьюера сейчас 508 passed, 2 skipped.

Главное

Локальная модель сейчас бесполезна: она не доходит до ответа за отведённое время, и Hermes от неё отказывается. Одна строка параметров превращает 111 секунд без результата в 11 секунд с ответом. Нужно, чтобы владелец задавал эту строку из хаба, а не пересобирал службу.

Порядок сдачи

Передать точный FINAL_COMMIT_SHA.