From f8b6783641a06c439f75a95fd5a6f152c2817e53 Mon Sep 17 00:00:00 2001 From: Hermes Team Date: Sun, 30 Aug 2026 23:04:18 +0700 Subject: [PATCH] =?UTF-8?q?docs(agents):=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20A39=20=E2=80=94=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC?= =?UTF-8?q?=D0=B5=D1=82=D1=80=D1=8B=20=D0=B7=D0=B0=D0=BF=D1=80=D0=BE=D1=81?= =?UTF-8?q?=D0=B0=20=D0=B4=D0=BB=D1=8F=20=D0=BB=D0=BE=D0=BA=D0=B0=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=8B=D1=85=20=D0=BF=D1=80=D0=BE=D1=84=D0=B8=D0=BB?= =?UTF-8?q?=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Локальная модель не закрывает задачи: 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 --- .../2026-08-31-A39-local-request-options.md | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 agents/inbox/2026-08-31-A39-local-request-options.md diff --git a/agents/inbox/2026-08-31-A39-local-request-options.md b/agents/inbox/2026-08-31-A39-local-request-options.md new file mode 100644 index 0000000..507d7d9 --- /dev/null +++ b/agents/inbox/2026-08-31-A39-local-request-options.md @@ -0,0 +1,142 @@ +# Задание 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) поставить + +```json +{"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`.