Фейковый tool calling в opensource-моделях: исправляем через OpenRouter и MCP | AiManual
AiManual Logo Ai / Manual.
30 Мар 2026 Гайд

Почему opensource-модели фейкут вызовы инструментов и как это исправить: гайд по настройке OpenRouter и MCP

Почему локальные модели имитируют вызовы инструментов и как настроить реальный веб-поиск через OpenRouter и MCP-серверы. Подробный гайд на 2026 год.

Она сказала, что выполнила поиск. Она солгала.

Ты просишь свою локальную модель найти свежие новости про фьюжн-реакторы. Она кивает, выдает красивый JSON-объект с полями `tool_call`, `query` и даже `search_results`. Потом начинает генерить текст на основе этих «результатов». Текст убедительный, факты правдоподобные. Пока не замечаешь, что последняя новость, на которую она ссылается, датирована 2022 годом. Модель никогда не выходила в интернет. Она просто притворилась. Это не ошибка, а системный обман.

Проблема в том, что большинство opensource-моделей, особенно ранних версий (вроде Llama 3.2 или старых Mixtral), не имеют жесткой дисциплины strict tool calling. Их научили имитировать паттерн вызова API на обучающих данных, но не научили реальному взаимодействию. Модель думает: «А, пользователь хочет JSON вот такого вида? Пожалуйста». И рисует его, как картинку. Это полный провал агентских сценариев.

Tool calling для бедных: в чем корень зла

За последний год архитектура моделей сильно продвинулась. Модели от DeepSeek, Qwen2.5 и новые Llama 4 уже лучше справляются с инструментами. Но даже они в стандартной поставке через большинство API-прокси (Ollama, vLLM) работают в «режиме совместимости». Системный промпт говорит им: «Ты можешь использовать инструменты». Модель видит список функций в схеме и старается его заполнить. Но между «заполнить схему» и «реально выполнить действие» — пропасть. Нет контура обратной связи.

Почему так происходит? Три причины:

  • Обучение на наблюдаемых данных: Модели видели логи вызовов API в текстовом виде, но никогда не выполняли их. Для них это просто очередной текстовый шаблон.
  • Отсутствие enforcement на уровне рантайма: Сервер inference (Ollama, llama.cpp) должен перехватывать вызов инструмента, выполнять его и возвращать результат в контекст. Многие бэкенды делают это неявно или требуют специальных флагов, о которых никто не говорит.
  • Кривая настройка фронтендов: Клиенты вроде Open WebUI или Jan.ai могут отправлять модели не тот контекст или отключать tool calling для экономии токенов.
💡
Если ты хочешь реальной работы с инструментами, тебе нужен не просто API к модели, а целый стек: модель, понимающая инструменты, сервер inference, который их исполняет, и клиент, который умеет этим управлять. Пропустишь один слой — получишь фейковый JSON.

OpenRouter не панацея: как заставить его работать с инструментами

Многие думают, что раз OpenRouter — это агрегатор моделей, то он волшебным образом решит проблему. Загрузил свою модель, выбрал endpoint, и все работает. На деле же OpenRouter — это тонкий прокси. Его основная задача — маршрутизировать запрос к нужному провайдеру (Together AI, Fireworks AI и т.д.). Если на стороне провайдера модель не поддерживает tool calling или поддерживает криво, OpenRouter тебе не поможет.

Но здесь есть лазейка. На 2026 год OpenRouter развил собственную систему интеграции инструментов через MCP (Model Context Protocol). Вместо того чтобы полагаться на нативную поддержку tool calling у модели, ты можешь подключить к своему запросу MCP-сервер. OpenRouter выступает как оркестратор: он передает запрос модели, перехватывает ее попытку вызова инструмента, перенаправляет его на твой MCP-сервер и вшивает ответ обратно в контекст.

Это меняет правила игры. Теперь даже относительно простая модель может работать с инструментами, если она умеет генерить структурированный JSON (а с этим у многих все хорошо). Вся магия происходит на стороне OpenRouter и твоих MCP-серверов.

MCP-серверы — или как дать модели руки

MCP — это не просто еще один протокол. Это способ сказать модели: «Вот набор функций, которые ты можешь вызывать, и вот сервер, который их реально выполняет». Сервером может быть что угодно: скрипт на Python, который ищет в Google, CLI-утилита для управления файлами, или даже подключение к твоей базе данных. Архитектура проста: модель получает схему инструментов, решает, что нужно вызвать, и отправляет запрос. MCP-сервер выполняет и возвращает результат.

Проблема в том, что чтобы эта связка заработала с opensource-моделями, нужно правильно собрать пазл. И вот тут большинство спотыкается. Ты можешь поднять MCP в llama.cpp, но если не настроишь клиент, модель будет продолжать фейкать. Или подключишь MCP Tool Registry, но забудешь активировать tool calling в запросе.

1Диагностика: твоя модель фейчит или нет?

Прежде чем лезть в настройки, проверь, в чем именно проблема. Создай простой тест. Попроси модель выполнить что-то, что требует реальных данных извне, например: «Какая сейчас погода в Москве?». Включи логирование запросов/ответов. Если в ответе ты видишь аккуратный JSON, но без реальных данных о погоде (или с явно выдуманными), а в логах сервера нет исходящих HTTP-запросов — это фейк. Модель имитирует вызов.

# Пример запроса к Ollama API, где виден фейковый tool call
curl http://localhost:11434/api/generate -d '
{
  "model": "llama3.2:latest",
  "prompt": "What is the weather in Moscow? Use the weather tool.",
  "tools": [{
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "Get current weather for a city",
      "parameters": {...}
    }
  }]
}'
# В ответе: 
# {"model":"...", "response":"{\n  \"tool_call\": ...\n  \"city\": \"Moscow\",\n  \"temperature\": \"22C\"\n}", ...}
# Но никакого реального запроса к погодному API не было.

2Выбор фронтенда: Open WebUI против остальных

Не все клиенты равны. На 2026 год Open WebUI (ранее Ollama WebUI) — безусловный лидер для экспериментов. Он имеет нативную поддержку MCP, умеет показывать интерфейс инструментов и, что критично, правильно форматирует системные промпты для активации tool calling. LM Studio до сих пор отстает (и есть причины почему). Jan.ai пытается догнать, но его интерфейс сложнее.

Установи Open WebUI, если еще нет. Важно использовать последнюю версию (на март 2026 это v0.9.x+), где исправлены баги с MCP.

# Установка через Docker (рекомендуется)
docker run -d -p 3000:8080 \
  -v open-webui:/app/backend/data \
  --name open-webui \
  ghcr.io/open-webui/open-webui:main

3Подключаем OpenRouter как провайдера модели

В Open WebUI переходи в настройки моделей. Добавляем нового провайдера: OpenRouter. Потребуется API-ключ. Ключ получи на сайте OpenRouter (есть бесплатный лимит). Главный трюк — в поле «Модель» нужно указать не просто название, а модель с суффиксом :online. Например, qwen/qwen2.5-32b-instruct:online. Этот суффикс говорит OpenRouter, что нужно активировать встроенную систему инструментов для веб-поиска. Это самый простой способ получить реальный поиск без своего MCP-сервера.

Суффикс :online — это фича именно OpenRouter. Она под капотом подключает MCP-сервер поиска, которым управляет сам OpenRouter. Работает только с моделями, которые поддерживают tool calling на базовом уровне. Для кастомных инструментов этот метод не подойдет — нужен свой MCP.

4Настройка локального MCP-сервера для кастомных инструментов

Если :online тебе не подходит (нужен доступ к файлам, базам, своим API), поднимаем свой MCP-сервер. Самый быстрый старт — использовать официальные серверы MCP или написать свой на Python.

Допустим, мы хотим дать модели возможность искать в файловой системе. Используем готовый MCP-сервер для файлов.

# Клонируем репозиторий с серверами (на 2026 актуальная версия MCP — 1.2+)
git clone https://github.com/modelcontextprotocol/servers.git
cd servers/file
npm install
npm start
# Сервер запустится на localhost:5173

Теперь нужно сказать OpenRouter (или твоему локальному Ollama с MCP) об этом сервере. Для OpenRouter есть раздел «MCP Servers» в настройках API. Указываешь URL своего сервера и добавляешь его к ключу API. Далее, при запросе через этот API-ключ, инструменты с сервера станут доступны модели.

5Интеграция в Open WebUI: финальная сборка

В Open WebUI создаем новую модель. Провайдер — OpenRouter. В поле «MCP Servers» (в расширенных настройках модели) указываем URL нашего локального сервера (например, http://localhost:5173). Сохраняем.

Теперь, при выборе этой модели в чате, в интерфейсе должна появиться кнопка «Инструменты». Если ее нет — проверь, что модель действительно поддерживает tool calling (возьми современную модель через Modelgrep). Создавай запрос. Когда модель захочет использовать инструмент, ты увидишь запрос на подтверждение (можно настроить авто-подтверждение). После выполнения в контекст добавятся реальные данные.

У меня ошибка 429 и другие радости жизни

Сборка заработала? Отлично. А теперь жди проблем. Вот типичные:

  • Ошибка 429 от Hugging Face: Если ты качаешь веса моделей через Ollama, а он использует Hugging Face как бэкенд, упрешься в rate limit. Особенно на слабом железе вроде Raspberry Pi. Решение — настроить mirror или кэш.
  • MCP-сервер отвечает, но модель его игнорирует: Скорее всего, проблема в формате системного промпта. Нужно явно указать модели, что она ДОЛЖНА использовать инструменты. В Open WebUI есть чекбокс «Force tool calling» в настройках чата. Включи его.
  • Модель генерит бесконечный JSON или ломает его структуру: Частая беда со старыми моделями. Они не обучены жесткому следованию схеме. Помогает уменьшение температуры (temperature = 0.1) и явное указание в промпте: «Output ONLY valid JSON, no other text.»
  • MCP-серверы болтают без дела: Если твой MCP-сервер возвращает тонны ненужного контекста (например, список всех файлов в системе), он съедает токены и путает модель. Используй mcp-context-proxy для фильтрации.
СимптомВероятная причинаЛечение
Модель выдает JSON, но инструмент не вызываетсяСервер inference не перехватывает tool callsИспользовать OpenRouter с MCP или llama.cpp с флагом --mcp
Инструмент вызывается, но результат не попадает в ответ моделиСломан контур обратной связи, результат не инжектится в контекстПроверить логи MCP-сервера, убедиться что клиент (Open WebUI) поддерживает MCP версии 1.1+
Все работает, но очень медленноMCP-сервер на Python без асинхронности или медленный инструмент (поиск в интернете)Оптимизировать сервер, использовать кэширование, рассмотреть AI Gateway для управления запросами

Итог: как не сойти с ума при настройке

Проблема фейкового tool calling не исчезнет полностью. Даже с появлением новых open-weight моделей, которые лучше обучены, всегда будет разрыв между тренировкой и продакшеном. Твое оружие — понимание стека. Модель, сервер inference, MCP-сервер, клиент. Должны работать все четыре компонента.

Мой прогноз на 2026: в течение года основные провайдеры (Together AI, Fireworks) начнут предлагать «MCP как сервис» — готовые облачные серверы инструментов, которые можно подключить к любой модели в один клик. Пока же придется пачкать руки. Начни с простого: OpenRouter + суффикс :online. Увидишь, как модель реально лезет в интернет. Потом подключи один локальный MCP-сервер. Постепенно соберешь свою экосистему инструментов. И тогда открытые модели перестанут притворяться и наконец начнут работать.

Подписаться на канал