Локальная модель не закрывает задачи: 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>
9.8 KiB
Задание 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.
Требования:
- Ничего не зашивать.
enable_thinking,reasoning_effortи прочее — это данные в конфигурации владельца, а не константы в коде. Завтра у llama.cpp появится другой ключ, и правка кода не должна понадобиться. - Сохраняется и переживает перезапуск, как остальные поля профиля.
- Вложенные структуры поддерживаются:
chat_template_kwargs— это словарь внутри словаря. - Явное поле запроса не перезаписывается молча. Если 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. Аудит вторым проходом
- Проверить на живом сервере владельца, а не только заглушкой: запрос с
enable_thinking: falseдолжен вернуть ответ за десяток секунд вместо ста. - Утечка в других провайдеров — проверить целенаправленно, что параметр уходит только в локальные.
- Неизвестный ключ не роняет вызов и показывается как ошибка провайдера.
- Зашитые значения — искать отдельно; в коде не должно быть ни
enable_thinking, ниreasoning_effort. - Побочные изменения объяснить.
- Пропущенный пункт назвать пропущенным.
Ограничения
- Зона:
adapters/local_adapter.py,router_config.py, карточка аккаунта в вебе, тесты. - Серверные юниты
qwen-coderиqwen-compressorне трогать: это машина владельца, он меняет их сам. - Правило честности без исключений.
- Тег
v0.1.1не создавать.
Критерии приёмки
- Ветка в
originотreview/a35-a37-verified,git statusчист. request_optionsесть в профиле, сохраняется, переживает перезапуск, поддерживает вложенные структуры.- Локальный адаптер отправляет их; проверено живым запросом к серверу владельца с приложенным замером времени до и после.
- Параметр не попадает в запросы к другим провайдерам; проверено.
- Неизвестный ключ даёт ошибку провайдера с текстом, а не отказ маршрутизатора.
- Поле настраивается из интерфейса, показывает отправляемое тело.
- Явные поля запроса Hermes не затираются.
- Ни
enable_thinking, ниreasoning_effortне зашиты в коде. ruff check .чисто; релизный гейт не ухудшен.- Отчёт:
START_HEAD,FINAL_HEAD,origin/main,git status,X passed / Y skipped / Z failed. На ветке ревьюера сейчас 508 passed, 2 skipped.
Главное
Локальная модель сейчас бесполезна: она не доходит до ответа за отведённое время, и Hermes от неё отказывается. Одна строка параметров превращает 111 секунд без результата в 11 секунд с ответом. Нужно, чтобы владелец задавал эту строку из хаба, а не пересобирал службу.
Порядок сдачи
Передать точный FINAL_COMMIT_SHA.