Как я перевёл aux-задачи Hermes на локальные модели
У меня на домашнем сервере живёт агент Hermes — он ведёт блог, следит за сертификатами, ходит в мессенджеры и выполняет кучу мелких, но важных задач. Основную модель он берёт в облаке (провайдер polza.ai, 131K контекст), а для вспомогательных задач — генерации заголовков, извлечения текста из веб-страниц, описания картинок (vision) и сжатия контекста — у него есть отдельный механизм auxiliary. По умолчанию все aux-задачи тоже резолвятся в облако, а значит — тратят токены и деньги.
На сервере стоит видеокарта RTX 5060 Ti 16 GB (да, та самая, про которую я писал в статье про зависание Ubuntu при загрузке). Раз есть GPU — почему бы не увести aux-задачи на локальные модели? Приватность, скорость, ноль затрат на API. Рассказываю, как выбирал модель, как настраивал и какой грабли встретил при отключении режима размышлений (thinking) у Qwen3.
Что такое auxiliary-задачи в Hermes
Hermes — агент с модульной архитектурой. Кроме основной модели (которая думает и пишет ответы), он вызывает вспомогательные (auxiliary) задачи через отдельный клиент — auxiliary_client.py. В моей версии их несколько:
| Задача | Что делает | Порог контекста |
|---|---|---|
vision | Описывает картинки, читает скриншоты | нет |
title_generation | Генерирует заголовки диалогов | нет |
web_extract | Извлекает текст из веб-страниц | нет |
compression | Сжимает историю диалога (context compaction) | 64K жёсткий минимум |
skills_hub, approval, mcp и др. | Служебные | нет |
Ключевой момент: только compression требует большого контекста (64K). Это жёсткое требование самого Hermes — для сжатия истории ему нужна модель, которая видит весь диалог. Локальные GGUF-модели до 64K не дотягивают (проверил: qwen3-8b упирается в 40960 токенов контекста, qwen2.5-coder-14b — в 32768; теги «64k/65k» в названиях моделей — маркетинг, реальный контекст меньше). Поэтому compression я оставил в облаке, а вот все остальные aux-задачи — кандидаты на локализацию.
Выбор модели
Критерии были простые:
- Модель должна уметь vision (для
vision-задачи). - Должна влезать в 16 GB VRAM вместе с эмбеддинг-моделью
bge-m3и основной текст-моделью. - Должна быстро отвечать — aux-задачи вызываются часто, ждать минуту утомительно.
- Желательно уметь закрыть и текстовые задачи (генерация заголовков, извлечение текста) — чтобы не гонять облако вообще.
Я поставил qwen3-vl:8b — мультимодальную модель Qwen 8B с поддержкой vision. Она весит ~6.1 GB, контекст 262K (но KV cache на полный контекст — ~309 GB, так что реально держу num_ctx=8192). Проверил через /api/show — у неё есть capability vision, значит Hermes её увидит как vision-модель.
Важный нюанс про qwen3-vl: она великолепно описывает картинки (проверено E2E — отвечает «red»/«blue» на цветные картинки за 1-10 секунд), но для текстовых задач она… слишком умная. На простой вопрос «какой сегодня день недели» она генерирует 3778 токенов рассуждений и отвечает через 64 секунды! Это потому, что qwen3-модели по умолчанию включён режим reasoning/thinking. Для заголовков и извлечения текста это неприемлемо.
Поэтому я взял две модели:
qwen3-vl:8b— для vision (картинки);qwen3:8b— для текстовых aux (title_generation, web_extract), с принудительно отключённым thinking.
Настройка
Hermes поддерживает per-task конфигурацию auxiliary-задач в config.yaml. Формат:
| |
Настройка через CLI:
| |
Пара важных граблей:
api_keyобязан быть непустым. В коде Hermes пустойapi_keyозначает «унаследовать ключ основного провайдера» — и тогда он попытается сходить в polza.ai с локальной моделью. Я поставил заглушкуollama(Ollama её не проверяет).- Ollama надо форматировать через OpenAI-совместимый эндпоинт
/v1/chat/completions— именно так Hermes ходит в локальные модели. - Для qwen3-vl держать
num_ctxнебольшим (я использую 8192), иначе Ollama пытается зарезервировать KV cache под весь 262K контекст — это ~309 GB, runner падает с EOF.
Допиливание отключения режима размышлений (thinking)
Самая интересная часть. Qwen3-модели (и qwen3, и qwen3-vl) по умолчанию генерируют скрытый поток рассуждений (thinking/reasoning) перед ответом. Для aux-задач это означает:
- Заголовок генерируется 64 секунды вместо 3-5.
- При ограниченном
max_tokensответ вообще пустой — весь бюджет съедает thinking, доcontentдело не доходит.
Я перепробовал несколько способов отключить thinking, и вот что выяснилось:
Что НЕ работает (в Ollama)
| Способ | Результат |
|---|---|
/no_think в начале сообщения | Не работает — модель всё равно думает |
enable_thinking: false в extra_body | Не работает |
thinking: {type: disabled} (как в OpenAI API Qwen) | Не работает — content пустой, reasoning продолжается |
system: "Не думай" | Не работает |
Я проверил chat template модели — там есть команды /think и /no_think, но они не активируются в Ollama (флаг IsThinkSet не выставляется).
Что работает
Единственный рабочий способ — корневой параметр think: false в теле запроса:
| |
Ответ приходит через 0.7 секунды (вместо 64!), reasoning=false, content заполнен. Именно эту опцию я и прописал в extra_body конфига Hermes:
| |
В коде Hermes 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: после текстового вызова в памяти остаются обе модели.
Итог
- Vision полностью локальный — картинки описываются на сервере, в облако не уходят.
- Текстовые aux (заголовки, извлечение текста) — локальные, быстрые, бесплатные.
- Compression остался в облаке — ему нужен контекст 64K, который локально не влезает.
- Облачные токены тратятся только на основную модель и сжатие контекста — экономия существенная.
Самое ценное знание, которым делюсь: если вы используете Qwen3 в Ollama для вспомогательных задач — не забудьте think: false. Это превращает задумчивую модель, которая час думает над заголовком, в мгновенного исполнителя. И помните: /no_think, enable_thinking и thinking: disabled — в Ollama не работают, работает только корневой think: false.
Полезные ссылки: Hermes Agent · Ollama qwen3-vl · Ollama qwen3