From 2bf62c99443113af06658368ac24e55603e8426a Mon Sep 17 00:00:00 2001 From: Storozhenko Evgeny Date: Sun, 30 Aug 2026 13:11:10 +0000 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D0=B4=D0=BE=D0=BA=D1=83=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BB=20=D0=BE?= =?UTF-8?q?=D0=BF=D1=8B=D1=82=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=BB=D0=BE=D0=BA=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B?= =?UTF-8?q?=D1=85=20aux-=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B5=D0=B9=20Herme?= =?UTF-8?q?s=20(docs/local-aux-models.md)=20=D0=B8=20=D0=BE=D0=B1=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D0=B8=D0=BB=20=D0=B8=D1=81=D1=82=D0=BE=D1=80=D0=B8?= =?UTF-8?q?=D1=8E=20=D0=B2=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 ++ docs/local-aux-models.md | 142 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 docs/local-aux-models.md diff --git a/README.md b/README.md index 63c12c9..5417ad1 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,13 @@ ## История изменений +### 30 августа 2026 года + +- Написана и опубликована статья «Как я перевёл aux-задачи Hermes на локальные модели» (пост `20260830 - local aux models hermes`, slug `local-aux-models-hermes-qwen3`) +- Исправлена сборка с современными версиями Hugo: добавлен `defaultContentLanguage = 'ru'` в hugo.toml (Hugo 0.123+ требует, чтобы defaultContentLanguage совпадал с одним из `[languages]`, иначе ошибка `config value "en" does not match any language definition`) +- Установлен локальный git identity в репозитории: Storozhenko Evgeny +- Подробный опыт настройки локальных aux-моделей Hermes задокументирован в [docs/local-aux-models.md](docs/local-aux-models.md) + ### 31 января 2026 года - Установлена Hugo расширенная версия 0.155.1 diff --git a/docs/local-aux-models.md b/docs/local-aux-models.md new file mode 100644 index 0000000..3f8d526 --- /dev/null +++ b/docs/local-aux-models.md @@ -0,0 +1,142 @@ +# Опыт: локальные auxiliary-модели для Hermes (RTX 5060 Ti 16 GB) + +> Дата: 2026-08-30 · Автор: Стороженко Евгений (kpa39l) · Среда: bigbox, RTX 5060 Ti 16 GB, Ubuntu +> Связанная статья: [`content/posts/20260830 - local aux models hermes/index.md`](../content/posts/20260830%20-%20local%20aux%20models%20hermes/index.md) + +Этот документ — техническая копия опыта, описанного в статье блога. Здесь — точные конфиги, команды, замеры и грабли, чтобы можно было повторить настройку без повторного исследования. + +## Проблема + +Агент Hermes (`/opt/hermes/.hermes/hermes-agent/`) помимо основной модели вызывает вспомогательные (auxiliary) задачи через `auxiliary_client.py`: + +- `vision` — описание картинок/скриншотов +- `title_generation` — генерация заголовков диалогов +- `web_extract` — извлечение текста из веб-страниц +- `compression` — сжатие истории диалога (context compaction), **жёсткий минимум контекста 64K токенов** +- `skills_hub`, `approval`, `mcp`, `triage_specifier`, `kanban_decomposer`, `profile_describer`, `curator` — служебные + +По умолчанию все они резолвятся в облачного провайдера (polza.ai) — тратят токены и деньги. Цель: увести на локальную Ollama то, что не требует 64K контекста. + +## Выбор модели + +Критерии: уметь vision, влезать в 16 GB VRAM вместе с `bge-m3` (эмбеддинги), быстро отвечать (aux-задачи вызываются часто), желательно закрыть и текстовые задачи. + +- **qwen3-vl:8b** (~6.1 GB, контекст 262K, умеет vision) — для `vision`. Проверено: отвечает «red»/«blue» на цветные картинки 256x256 за 1–10 сек. +- **qwen3:8b** (~5.2 GB, чисто текстовая) — для текстовых aux (`title_generation`, `web_extract`). На простой вопрос qwen3-vl генерит 3778 токенов reasoning и отвечает 64 сек — для текста непригодна. + +**compression осталась на polza.ai**: ей нужен контекст 64K+, а локальные GGUF не дотягивают: +- qwen3-8b: реальный контекст 40960 (тег «64k» в названии — маркетинг) +- qwen2.5-coder-14b: реально 32768 (тег «32k» честный) + +## Настройка + +Рабочий конфиг в `/opt/hermes/.hermes/config.yaml`: + +```yaml +auxiliary: + vision: + provider: custom + model: qwen3-vl:8b + base_url: http://localhost:11434/v1 + api_key: ollama + title_generation: + provider: custom + model: qwen3:8b + base_url: http://localhost:11434/v1 + api_key: ollama + extra_body: + think: false + web_extract: + provider: custom + model: qwen3:8b + base_url: http://localhost:11434/v1 + api_key: ollama + extra_body: + think: false +``` + +Команды CLI: + +```bash +hermes config set auxiliary.vision.provider custom +hermes config set auxiliary.vision.model qwen3-vl:8b +hermes config set auxiliary.vision.base_url http://localhost:11434/v1 +hermes config set auxiliary.vision.api_key ollama +# ...аналогично для title_generation и web_extract (model qwen3:8b + extra_body think:false) +``` + +### Грабли + +1. **`api_key` обязан быть непустым.** Пустой `api_key` = «унаследовать ключ основного провайдера» → попытка сходить в polza.ai с локальной моделью. Заглушка `ollama` подходит (Ollama её не проверяет). +2. **Ollama подключается через OpenAI-совместимый эндпоинт** `/v1/chat/completions` (именно так Hermes ходит в локальные модели). +3. **qwen3-vl:8b: держать `num_ctx` небольшим (8192).** Полный контекст 262K → KV cache ~309 GB, runner падает с EOF (`EOF on 127.0.0.1:45579`). +4. **`session_search` — НЕ auxiliary-задача** (это tool). Переопределение `auxiliary.session_search.*` из конфига нужно удалить. + +## Допиливание: отключение режима размышлений (thinking) у Qwen3 + +Qwen3-модели по умолчанию генерируют скрытый поток reasoning перед ответом. Для aux это катастрофа: 64 сек на заголовок, пустой `content` при ограниченном `max_tokens` (весь бюджет съедает thinking). + +### Что НЕ работает (проверено на Ollama) + +| Способ | Результат | +|---|---| +| `/no_think` в начале сообщения | Модель всё равно думает | +| `enable_thinking: false` в extra_body | Не работает | +| `thinking: {type: disabled}` (как в OpenAI API Qwen) | Не работает — reasoning продолжается | +| System prompt «не думай» | Не работает | + +В chat template qwen3 есть команды `/think` и `/no_think`, но в Ollama они не активируются (флаг `IsThinkSet` не выставляется). + +### Что работает + +**Единственный способ — корневой параметр `think: false` в теле запроса** (HTTP-уровень): + +```bash +curl http://localhost:11434/api/chat -d '{ + "model": "qwen3:8b", + "messages": [{"role": "user", "content": "Привет!"}], + "think": false +}' +``` + +Результат: ответ через **0.7 сек** (вместо 64), `reasoning=false`, `content` заполнен. + +В Hermes это передаётся через `extra_body: {think: false}` в конфиге — в коде `auxiliary_client.py` `effective_extra_body` уходит в корень JSON-тела запроса, ровно туда, куда Ollama ждёт `think`. + +### E2E-замеры (реальные вызовы через Hermes `call_llm`) + +| Задача | Время | Результат | +|---|---|---| +| `title_generation` | 11.3 сек | «Настройка Ollama: локальные модели» | +| `web_extract` | 7.5 сек | Извлёк главную мысль | +| `vision` (картинка 256x256) | 7.6 сек | «blue» | + +## VRAM / память + +RTX 5060 Ti 16 GB, держатся одновременно: + +- `qwen3-vl:8b` — ~7.2 GB (vision) +- `qwen3:8b` — ~6.1 GB (текст) +- `bge-m3` — ~1.2 GB (эмбеддинги) + +Итого ~14.5 GB — влезает, переключение vision↔текст без выгрузки (проверено через `/api/ps`). + +## Откат + +```bash +hermes config set auxiliary..provider auto +hermes config set auxiliary..model "" +docker exec ollama ollama stop qwen3-vl:8b +docker exec ollama ollama stop qwen3:8b +``` + +## Сопутствующий фикс Hugo + +При сборке репозитория современным Hugo (0.145+) возникала ошибка: +`config value "en" for defaultContentLanguage does not match any language definition`. + +Решение (коммит `1bda9e2`): добавить в `hugo.toml`: +```toml +defaultContentLanguage = 'ru' +``` +Потому что в `[languages]` объявлен только `ru`, а Hugo по умолчанию считает язык `en`. \ No newline at end of file