Новая статья про перевод aux-задач Hermes на локальные модели и отключение thinking у Qwen3
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
---
|
||||
date: '2026-08-30T12:00:00+03:00'
|
||||
lastmod: '2026-08-30T12:00:00+03:00'
|
||||
draft: false
|
||||
title: 'Как я перевёл aux-задачи Hermes на локальные модели: экономия токенов и отключение режима размышлений у Qwen3'
|
||||
slug: 'local-aux-models-hermes-qwen3'
|
||||
description: 'Рассказываю, как выбрал модель для вспомогательных (auxiliary) задач агента Hermes, перевёл vision и текстовые задачи на локальную Ollama, сэкономил токены облачного провайдера и допилил отключение режима размышлений (thinking) у Qwen3.'
|
||||
|
||||
categories:
|
||||
- 'AI'
|
||||
- 'DevOps'
|
||||
|
||||
tags:
|
||||
- 'hermes'
|
||||
- 'ollama'
|
||||
- 'qwen3'
|
||||
- 'llm'
|
||||
- 'aux'
|
||||
- 'vision'
|
||||
- 'локальные-модели'
|
||||
- 'экономия-токенов'
|
||||
|
||||
keywords:
|
||||
- 'hermes'
|
||||
- 'ollama'
|
||||
- 'qwen3'
|
||||
- 'qwen3-vl'
|
||||
- 'auxiliary'
|
||||
- 'thinking'
|
||||
- 'reasoning'
|
||||
- 'локальная модель'
|
||||
- 'экономия токенов'
|
||||
|
||||
cover:
|
||||
image: "hero.svg"
|
||||
alt: "Локальные aux-модели Hermes: qwen3-vl и qwen3"
|
||||
---
|
||||
|
||||
# Как я перевёл aux-задачи Hermes на локальные модели
|
||||
|
||||
У меня на домашнем сервере живёт агент [Hermes](https://hermes-agent.nousresearch.com) — он ведёт блог, следит за сертификатами, ходит в мессенджеры и выполняет кучу мелких, но важных задач. Основную модель он берёт в облаке (провайдер 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-задачи — кандидаты на локализацию.
|
||||
|
||||
## Выбор модели
|
||||
|
||||
Критерии были простые:
|
||||
|
||||
1. Модель должна уметь **vision** (для `vision`-задачи).
|
||||
2. Должна влезать в 16 GB VRAM вместе с эмбеддинг-моделью `bge-m3` и основной текст-моделью.
|
||||
3. Должна быстро отвечать — aux-задачи вызываются часто, ждать минуту утомительно.
|
||||
4. Желательно уметь закрыть и текстовые задачи (генерация заголовков, извлечение текста) — чтобы не гонять облако вообще.
|
||||
|
||||
Я поставил [qwen3-vl:8b](https://ollama.com/library/qwen3-vl) — мультимодальную модель 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`. Формат:
|
||||
|
||||
```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
|
||||
# и так для каждой задачи
|
||||
```
|
||||
|
||||
Пара важных граблей:
|
||||
|
||||
- **`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` в теле запроса:**
|
||||
|
||||
```bash
|
||||
curl http://localhost:11434/api/chat -d '{
|
||||
"model": "qwen3:8b",
|
||||
"messages": [{"role": "user", "content": "Привет!"}],
|
||||
"think": false
|
||||
}'
|
||||
```
|
||||
|
||||
Ответ приходит через **0.7 секунды** (вместо 64!), `reasoning=false`, `content` заполнен. Именно эту опцию я и прописал в `extra_body` конфига Hermes:
|
||||
|
||||
```yaml
|
||||
extra_body:
|
||||
think: false
|
||||
```
|
||||
|
||||
В коде 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](https://hermes-agent.nousresearch.com) · [Ollama qwen3-vl](https://ollama.com/library/qwen3-vl) · [Ollama qwen3](https://ollama.com/library/qwen3)*
|
||||
Reference in New Issue
Block a user