HOSTKEY написала пайп для бота: Gemma 4 отвечает за 5–7 секунд, Qwen 3 — за 30–40

Хостинг-провайдер HOSTKEY отказался от настроек кастомной модели в OpenWebUI и написал для бота техподдержки пайп — Python-плагин, который перехватывает запрос до модели. В режиме Legacy модель не вызывала MCP-инструмент и отвечала только по базе знаний (RAG), а в Native с Gemma 4 переставал работать и RAG. Gemma 4 с отключённым размышлением отвечает за 5–7 секунд на двух видеокартах A4000 по 16 ГБ, тогда как Qwen 3 думает 30–40 секунд. • Три эшелона проверки: ключевые слова, LLM-классификатор, повторная проверка • Первый эшелон на чистом Python закрывает типовые запросы без LLM • Статусы в чате вроде «Ищу документацию» заменяют «зависший» интерфейс

AI-обработка оригинала Habr AI; редакция Hamidun News
HOSTKEY написала пайп для бота: Gemma 4 отвечает за 5–7 секунд, Qwen 3 — за 30–40
Источник: Habr AI. Коллаж: Hamidun News.
Слушать статью
Паспорт материала и цифры
ПараметрДанные
ПервоисточникHabr AI ↗
Главный редактор
Три эшелона проверкиключевые слова, LLM-классификатор, повторная проверка
Ключевой факт #2Первый эшелон на чистом Python закрывает типовые запросы без LLM
Ключевой факт #3Статусы в чате вроде «Ищу документацию» заменяют «зависший» интерфейс

Хостинг-провайдер HOSTKEY рассказал, почему бот техподдержки Remote Hands Request (RHR, обращения по физическому обслуживанию серверов) не получилось собрать из штатных настроек OpenWebUI. Команда заменила настройки пайпом — Python-плагином, который перехватывает запрос до отправки в модель и ведёт его через фиксированную цепочку шагов. Выбор в пользу Gemma 4 объясняется временем ответа: с отключённым режимом размышления она отвечает за 5–7 секунд на связке из двух видеокарт A4000 по 16 ГБ. Qwen 3 на том же оборудовании думает 30–40 секунд, а по качеству Gemma 4 уступает ему совсем немного. Автор разбора — Александр Казанцев, руководитель отдела документации и контента HOSTKEY.

Почему настроек модели оказалось мало

Сначала в HOSTKEY рассчитывали, что для бота хватит кастомной модели на открытой основе с подключёнными инструментами и базой знаний. Для примера автор берёт модель hostkeyrurhr на основе gemma4:26b-a4b-it-qat. В её настройках включены Function Calling в режиме Legacy, temperature 0,2, размышление в Ollama выключено, подключена коллекция знаний hostkey_ru по клиентской документации. Инструменты — status_ru_mcp и docs_url_ru: проверка работы сайта, Invapi и дата-центров в России, а также MCP-запрос конфигураций VPS, выделенных серверов и сетевого трафика.

На вопрос про дешёвый VPS в Германии модель не пошла в инструмент get_vps_list, который возвращает список VPS с ценами по локации. Ответ получился правдоподобным, но это был пересказ инструкции из документации, а не данные из системы. Режим Native сделал картину хуже: переставал работать даже RAG. При запросе через API, например через CURL, приходит голый tool_call с пустым content, и вызывать инструмент и переспрашивать модель должен клиент. Гарантий, что инструмент вызовется, данные попадут в ответ, не смешаются с RAG и ответ будет на русском, нет.

В режиме Legacy данные инструментов подмешиваются в общий контекст, чаще всего в системный промпт. Способ работает с любой моделью, но модель может переусложнить вызов, выдать невалидный JSON или проигнорировать инструмент. В режиме Native модели передаётся только список инструментов через специальный API-параметр. Qwen3 хорошо работает в обоих режимах, а Gemma 4 даже в версии it (Instruction-Tuned) требует в Native специальной обработки. Её берёт на себя пайп.

К этому добавились структурные претензии:

  • Одна модель с одним большим системным промптом и одной температурой и выбирает действие, и отвечает.
  • Порядок вызовов не контролируется, а нужен был такой: поиск по ключевым словам, затем инструменты доступности сервера и MCP Invapi, затем ответ с RAG.
  • RAG нельзя отключить на время вызова инструментов, поэтому данные смешиваются.
  • Нет постобработки: проверки языка, обрезки служебных хвостов, отбрасывания заглушек и fallback.
  • Пользователь видит «зависший» интерфейс, пока идут несколько запросов к LLM и MCP.

Что такое пайп и как устроен hostkeyru_rhr_pipe

Пайп — это Python-класс с методом pipe. Он получает тело запроса и возвращает строку, JSON или поток, а внутри может сколько угодно раз обращаться к LLM, вызывать MCP-инструменты, менять промпт и включать или выключать RAG. В интерфейсе OpenWebUI пайп выглядит как отдельная модель: ему можно назначить права и вызывать его по API, а во внешних клиентах достаточно заменить имя кастомной модели на имя пайпа. Создаются пайпы в Admin Panel, раздел Function. Valves — настраиваемые параметры пайпа, которые хранятся в БД и видны в админ-панели, — в HOSTKEY не используют вовсе: промпты и значения проще переписывать в коде.

Пайп hostkeyru_rhr_pipe обслуживает русскоязычную поддержку. Финальная генерация идёт в кастомную модель hostkeyrurhr с включённым RAG, а всю подготовку пайп делает до этого. Он получает body (сообщения, модель, флаги, tool_ids, features), tools (словарь доступных MCP-инструментов) и __event_emitter__ — канал, по которому в чат уходят статусы. Вместо неподвижной полосы пользователь видит ленту: «Анализирую запрос», «Извлекаю ключевые слова», «Ищу документацию», «Использую инструмент», «Формирую финальный ответ». Без неё пользователи часто уходят из чата, не дождавшись результата.

Текст запроса извлекается из последнего сообщения пользователя кодом, без нейросетей, причём с учётом мультимодальных сообщений — списка блоков «текст + картинка».

Фаза −1: каскад из трёх эшелонов

В прежнем пайпе проверки «это RHR-запрос?» не было, поэтому на «выпишите мне счёт» и «ssh не работает» приходил одинаковый ответ, а нагрузка на отдел, обслуживающий серверы, росла. В новом пайпе появился каскад, где каждый следующий эшелон включается, только если предыдущий не дал однозначного ответа.

Эшелон 1 — keyword guard (_keyword_prefilter) на чистом Python. Он ищет два набора маркеров: RHR_KEYWORDS (ssh, перезагруз, raid, сеть, dns, не отвеч) и CLIENT_SOFTWARE_SIGNALS (код сайта, конфиг nginx, wordpress, laravel). Если найдены только RHR-ключи, результат — in_scope=True, edge, 0,9. Если только сигналы софта — in_scope=False, client_software, 0,9. Если оба набора или ни одного, возвращается None и запрос идёт дальше.

Эшелон 2 — LLM-классификатор (_classify_rhr_scope) на gemma4nothink, базовой модели с отключённым размышлением, при температуре 0. В промпт вшиты регламент RHR_REGULATION, пять критических правил, восемь few-shot примеров и строгий формат JSON-ответа. При любой неудаче возвращается in_scope=True, unknown, 0,0, то есть клиента не отсекают.

Эшелон 3 — recheck (_recheck_rhr_scope) страхует от ложного отсечения. Он запускается, только если первый проход вернул in_scope=False, категорию client_software или unknown, а confidence попал в диапазон [0,7; 0,85]. Для billing, client_area, legal, sales, abuse и для edge перепроверки нет.

Примеры из таблицы автора: «ssh не работает» решается на первом эшелоне, «хочу вернуть деньги» — на втором как billing с 0,95 и получает предупреждение, а «что-то странное с сервером» уходит в fail-open с обычным ответом.

Фаза 0: поиск по документации

Первый короткий запрос идёт к gemma4nothink и превращает вопрос пользователя в 2–3 ключевых слова для поиска по документации.

Сюжет

Вопросы и ответы по материалу

Что известно по теме: почему настроек модели оказалось мало?

Сначала в HOSTKEY рассчитывали, что для бота хватит кастомной модели на открытой основе с подключёнными инструментами и базой знаний. Для примера автор берёт модель hostkeyrurhr на основе gemma4:26b-a4b-it-qat. В её настройках включены Function Calling в режиме Legacy, temperature 0,2, размышление в Ollama выключено, подключена коллекция знаний hostkey_ru по клиентской документации. Инструменты — status_ru_mcp и docs_url_ru: проверка работы сайта, Invapi и дата-центров в России, а также MCP-запрос конфигураций VPS, выделенных серверов и сетевого трафика. На вопрос про дешёв

Что известно по теме: что такое пайп и как устроен hostkeyru_rhr_pipe?

Пайп — это Python-класс с методом pipe. Он получает тело запроса и возвращает строку, JSON или поток, а внутри может сколько угодно раз обращаться к LLM, вызывать MCP-инструменты, менять промпт и включать или выключать RAG. В интерфейсе OpenWebUI пайп выглядит как отдельная модель: ему можно назначить права и вызывать его по API, а во внешних клиентах достаточно заменить имя кастомной модели на имя пайпа. Создаются пайпы в Admin Panel, раздел Function. Valves — настраиваемые параметры пайпа, которые хранятся в БД и видны в админ-панели, — в HOSTKEY не используют вовсе: пром

Что известно по теме: фаза −1: каскад из трёх эшелонов?

В прежнем пайпе проверки «это RHR-запрос?» не было, поэтому на «выпишите мне счёт» и «ssh не работает» приходил одинаковый ответ, а нагрузка на отдел, обслуживающий серверы, росла. В новом пайпе появился каскад, где каждый следующий эшелон включается, только если предыдущий не дал однозначного ответа. Эшелон 1 — keyword guard (_keyword_prefilter) на чистом Python. Он ищет два набора маркеров: RHR_KEYWORDS (ssh, перезагруз, raid, сеть, dns, не отвеч) и CLIENT_SOFTWARE_SIGNALS (код сайта, конфиг nginx, wordpress, laravel). Если найдены только RHR-ключи, результат — in_scope=T

ЖХ
Жемал Хамидун — CPO Alpina Digital, продакт-менеджер AlpinaGPT. Делает AI-продукты с 2019 года. Hamidun News — pet project, который вырос в production-агрегатор с 6000+ читателей.
✦ Практика · Hamidun Academy

Соберите рабочего ИИ-агента или сервис своими руками без ручного кода

В Академии Жемала Хамидуна (academy.hamidun.com) открыт бесплатный 72-часовой тест-драйв: интерактивные скетч-уроки по Claude Code и Cursor, живой Tech Radar и готовые шаблоны агентов.

Открыть 72ч бесплатный доступ →Интенсив по Вайб-кодингу
Что вы думаете?
Загружаем комментарии…