# LM Studio tool calling: проверить вызов функции через локальный API

Источник: https://modelium.tech/zhurnal/lm-studio-tool-calling/

В обычном LM Studio передайте описание функции в `tools` запроса к локальному `/v1/chat/completions`. Совместимая модель может вернуть `choices[0].message.tool_calls` с именем и аргументами; она не выполняет функцию сама. На тестовом товаре проверьте структуру ответа, строго разрешите только один вызов и отдельно запустите безвредную функцию в клиенте. Нужны уже загруженная модель и компьютер, на котором она помещается в память; редакция этот запуск не воспроизводила.

**Инженерная проверка по документации на 8 октября 2026 года, не домашний рецепт.** Ни LM Studio, ни модель на компьютере Modelium не запускались. Путь ниже — macOS 14+ на Apple Silicon, Terminal с Python 3 и `curl`, обычное приложение LM Studio и конкретный `lmstudio-community/Qwen2.5-7B-Instruct-GGUF`, файл Q4_K_M (сжатый вариант весов модели в формате GGUF). Интернет нужен для скачивания приложения, runtime и весов; локальный сервер и уже загруженная модель могут работать без сети. Для LM Studio на Mac рекомендованы 16 ГБ RAM (оперативной памяти), но минимальная память именно для этой модели здесь не установлена: заранее оцените её на своём устройстве. [s1](#src-s1) [s2](#src-s2) [s3](#src-s3) [s4](#src-s4) [s6](#src-s6) [s9](#src-s9)

## Что будет результатом?

Представьте тестовый магазин: нужно узнать остаток товара `A-42`. В нашем *вымышленном* справочнике ему соответствует число 7; модель не должна угадывать остаток. **Tool calling** — это предложенный моделью вызов функции с аргументами, а не уже совершённое действие. Обычный LM Studio может вернуть такое предложение в `tool_calls` локального HTTP API; отдельно запущенная программа решает, можно ли его исполнять. Это другой сценарий, чем [MCP-сервер в интерфейсе LM Studio](/zhurnal/lm-studio-mcp-instrumenty/). [s1](#src-s1)

## Что подготовить на Mac?

- Проверьте Apple Silicon и macOS 14 или новее. 16 ГБ RAM — рекомендация LM Studio, а **не** гарантия размещения Qwen2.5-7B с выбранными настройками. Если установлен CLI `lms`, команда `lms load --estimate-only <model_key>` предварительно оценивает память для *вашей* конфигурации, но не загружает модель и не доказывает успешный запуск. Не выводите объём RAM/VRAM из размера GGUF-файла. [s2](#src-s2) [s4](#src-s4)

- Установите обычный LM Studio с официального сайта; во вкладке **Discover** найдите репозиторий `lmstudio-community/Qwen2.5-7B-Instruct-GGUF`, скачайте вариант `Q4_K_M` и загрузите его через **Chat**. Дождитесь обычного ответа на короткое приветствие, прежде чем добавлять инструменты. Карточка автора этого репозитория закреплена на ревизии `a8bb390`; установив через каталог, отдельно проверьте фактическую ревизию скачанного файла. LM Studio относит Qwen2.5-Instruct к примерам моделей с родной поддержкой tool use, но это не гарантия на каждом запуске. [s1](#src-s1) [s3](#src-s3) [s9](#src-s9)

- На вкладке **Developer** включите локальный сервер, выбрав порт `1234` и адрес только `127.0.0.1`. Другой вариант при доступном CLI: `lms server start --bind 127.0.0.1 --port 1234`. В Terminal выполните `curl -sS http://127.0.0.1:1234/v1/models` и скопируйте точное `id` своей загруженной модели в следующий запрос вместо указанного ниже примера. Если в настройках включено **Require Authentication**, добавьте к запросам свой API-токен по инструкции LM Studio, не публикуя его. [s1](#src-s1) [s5](#src-s5) [s7](#src-s7) [s8](#src-s8)

## Как получить предложение вызвать функцию?

В Terminal выполните одну команду (если `id` отличается, замените поле `model`): `curl -sS -X POST 'http://127.0.0.1:1234/v1/chat/completions' -H 'Content-Type: application/json' -d '{"model":"lmstudio-community/qwen2.5-7b-instruct","stream":false,"messages":[{"role":"user","content":"Каков остаток тестового товара A-42? Для получения числа запроси lookup_stock, не угадывай."}],"tools":[{"type":"function","function":{"name":"lookup_stock","description":"Вернуть фиктивный остаток тестового товара","parameters":{"type":"object","properties":{"sku":{"type":"string"}},"required":["sku"],"additionalProperties":false}}}]}' > lm-tools-first.json`. Файл появляется в текущей папке Terminal; это ответ сервера, **не** запись в магазин или доказательство вызова функции. [s1](#src-s1)

Посмотрите структуру без запуска полученных от модели строк: `python3 -c 'import json; r=json.load(open("lm-tools-first.json")); print(json.dumps(r["choices"][0]["message"].get("tool_calls", []), ensure_ascii=False, indent=2))'`. В `choices[0].message.tool_calls` ищите ровно один `function.name=lookup_stock`, а `function.arguments` сначала разбирайте как JSON, затем сравнивайте с `{"sku":"A-42"}`. `finish_reason=tool_calls` — дополнительный сигнал; связный ответ модели в `content` без `tool_calls` **не считается** вызовом. Если сервер вернул ошибку или пустой массив, остановитесь: попробуйте совместимую модель и проверьте её шаблон чата, а не объявляйте успех по тексту ответа. [s1](#src-s1)

## Как безопасно исполнить тест и проверить границу?

**Не используйте **`**eval**`** для **`**function.arguments**`, даже если встретили такой приём в чужом примере: аргументы создаёт модель. Эта команда разрешает лишь *один* вызов с точным именем и точным SKU, разбирает аргументы через `json.loads`, после чего читает локальную фиктивную запись, не обращаясь к файлам пользователя, сети магазина или реальной базе: `python3 -c 'import json,sys; r=json.load(open("lm-tools-first.json")); c=r["choices"][0]["message"].get("tool_calls") or []; ok=len(c)==1 and c[0].get("function",{}).get("name")=="lookup_stock" and json.loads(c[0]["function"]["arguments"])=={"sku":"A-42"}; sys.exit("Отклонено: нет единственного разрешённого вызова") if not ok else print("executed: lookup_stock(A-42) ->", {"A-42":7}["A-42"])'`. Напечатанное `executed: ... -> 7` подтверждает только работу **вашего тестового клиента** после проверки входа. Оно не означает, что Modelium наблюдал запуск или что модель уже получила результат. [s1](#src-s1)

Для полного цикла приложение затем должно сохранить исходное сообщение assistant с `tool_calls` и отправить **отдельное** сообщение `role: tool` с результатом `7` и соответствующим `tool_call_id`, после чего отдельно проверить финальный ответ модели. Официальная схема LM Studio описывает эту передачу; однострочный тест выше намеренно останавливается раньше, чтобы не скрыть границу «модель предложила → клиент разрешил → функция исполнилась → модель получила результат». Если нужен готовый пример клиента с этими этапами, откройте [гайд по tool calling локальных моделей](/zhurnal/tool-calling-lokalnyh-modeley/) (там используется Ollama, поэтому формат сообщений другой). [s1](#src-s1)

## Если инструмент не появился

Проверьте загруженную модель в `/v1/models`, доступность `127.0.0.1:1234` и совпадение `model` с её `id`; LM Studio может показать текст вместо `tool_calls`, если модель выдала неверный формат. Модель с отметкой native tool use обычно лучше подходит, но вызов зависит от конкретного ответа. Пустой или неверный `arguments` — **отказ в исполнении**, а не повод исполнить «похожую» команду. На macOS 8 ГБ иногда хватает для меньших моделей, но это не доказательство, что данная 7B-модель поместится; вернитесь к оценке памяти или выберите другую конфигурацию. [s1](#src-s1) [s2](#src-s2) [s4](#src-s4)

После проверки остановите сервер в интерфейсе или командой `lms server stop`, если включали его CLI, и удалите только свой `lm-tools-first.json`. Не включайте внешний bind или CORS для этого теста. Локальный адрес уменьшает поверхность доступа, но не доказывает офлайн-изоляцию всей машины; при рабочем размещении отдельно настройте аутентификацию и права клиента. [s5](#src-s5) [s6](#src-s6) [s7](#src-s7)

## Источники

1. [LM Studio — Tool Use via OpenAI-compatible Chat Completions](https://lmstudio.ai/docs/developer/openai-compat/tools) — получено 2026-10-08
2. [LM Studio — System Requirements](https://lmstudio.ai/docs/app/system-requirements) — получено 2026-10-08
3. [LM Studio — Get started with LM Studio](https://lmstudio.ai/docs/app/basics) — получено 2026-10-08
4. [LM Studio — lms load and estimate-only](https://lmstudio.ai/docs/cli/local-models/load) — получено 2026-10-08
5. [LM Studio — lms server start and localhost bind](https://lmstudio.ai/docs/cli/serve/server-start) — получено 2026-10-08
6. [LM Studio — Offline Operation](https://lmstudio.ai/docs/app/offline) — получено 2026-10-08
7. [LM Studio — API Authentication](https://lmstudio.ai/docs/developer/core/authentication) — получено 2026-10-08
8. [LM Studio — List Models via OpenAI-compatible API](https://lmstudio.ai/docs/developer/openai-compat/models) — получено 2026-10-08
9. [lmstudio-community/Qwen2.5-7B-Instruct-GGUF — model card](https://huggingface.co/lmstudio-community/Qwen2.5-7B-Instruct-GGUF/blob/a8bb3906b78b3009770d7ae7d116be2ea892802d/README.md) — получено 2026-10-08
