Гайд · TNWS AI

Как обработать named tool call в vLLM без произвольного выполнения кода

4 мин—

Требуем вызов одной безопасной функции, валидируем аргументы и не отдаём модели право запускать произвольные команды.

Задача и применимость

Вопрос читателя: «как вызвать конкретную функцию через tool_choice vLLM». Для Chat API vLLM с моделями и шаблонами, поддерживающими tool-формат; официальная документация проверена 20 сентября 2026 года. Здесь рассматривается named function choice, а не auto-режим, требующий настройки parser для конкретной модели.

Для воспроизводимости запишите фактическую версию установленного vLLM, модельный checkpoint и параметры запуска. Путь /models/your-chat-checkpoint либо /models/your-embedding-checkpoint в команде ниже — заполнитель, а не реальный файл. Наличие GPU, объём памяти и условия лицензии весов проверяются до запуска. Демонстрация не утверждает, что ответ модели заранее известен по буквам.

Проверенные возможности

vLLM поддерживает named function через tool_choice={"type":"function","function":{"name":...}}. Разработчики говорят, что структурный механизм гарантирует разбираемый вызов функции, но не качество выбора аргументов. Реальное выполнение инструмента и валидация последствий остаются ответственностью приложения.

Пошаговая процедура

  1. Определите одну безвредную функцию с известными вариантами входа.
  2. Опишите JSON Schema параметров и передайте tools в Chat API.
  3. Задайте named tool_choice, чтобы не зависеть от решения модели вызвать функцию.
  4. Разберите tool_calls, убедитесь в ожидаемом имени и валидируйте аргументы.
  5. Выполните только локальную функцию из allowlist и сравните результат с эталоном.

Команда для тестового запуска на локальном адресе (подставьте законно полученный checkpoint):

vllm serve /models/your-tool-capable-checkpoint --host 127.0.0.1 --port 8000

Готовый запрос и контроль ответа

В приведённом фрагменте используется стандартная библиотека Python и простой общий помощник для отправки JSON. Подставьте при необходимости Bearer-токен через защищённую переменную окружения и проверьте, что ваш сервер его ожидает.

import json, urllib.request
BASE = "http://127.0.0.1:8000"
def call(path, payload):
    data = json.dumps(payload, ensure_ascii=False).encode("utf-8")
    request = urllib.request.Request(BASE + path, data=data,
        headers={"Content-Type": "application/json"}, method="POST")
    with urllib.request.urlopen(request, timeout=120) as reply:
        return json.load(reply)

model = json.load(urllib.request.urlopen(BASE + "/v1/models"))["data"][0]["id"]
tool = {"type": "function", "function": {"name": "weekday_delivery",
    "description": "Вернуть текст о доставке по будням",
    "parameters": {"type": "object", "properties": {},
                   "required": [], "additionalProperties": False}}}
payload = {"model": model, "messages": [{"role": "user",
    "content": "Когда бывает доставка? Вызови weekday_delivery без аргументов."}],
    "tools": [tool], "tool_choice": {"type": "function",
    "function": {"name": "weekday_delivery"}}}
reply = call("/v1/chat/completions", payload)
function = reply["choices"][0]["message"]["tool_calls"][0]["function"]
assert function["name"] == "weekday_delivery"
assert json.loads(function["arguments"]) == {}
print("Доставка бывает по будням")

Пример входа и ожидаемого результата

Вход — вопрос о доставке; функция без параметров возвращает заранее известную строку. Ожидаемая техническая структура — один tool call weekday_delivery с пустым объектом аргументов. Вывод приложения о буднях берётся из разрешённой локальной функции, а не из догадки модели.

Как интерпретировать результат

Названный инструмент безопаснее произвольного выполнения в том смысле, что приложение само решает, что позволено делать. Но название функции в ответе модели нельзя передавать в eval, subprocess или поисковый импорт: сравните со статическим allowlist. Если в схеме есть ID заказа, проверяйте принадлежность этого ID пользователю на сервере. Наличие структурно корректного JSON-аргумента не доказывает, что операция допустима. Для реальных изменяющих действий нужен отдельный шаг подтверждения и журнал операции.

Развёртывание без потери контекста

Документация предупреждает: первый вызов named tool может иметь дополнительную задержку на подготовку структурного механизма. Измеряйте задержку после прогрева и отдельно на холодном старте, чтобы не ошибиться с p95. Не смешивайте named и auto при настройке: auto требует --enable-auto-tool-choice и подходящий --tool-call-parser, а конкретная именованная функция использует ограниченную генерацию. Проверьте модельный chat template и поддержку сообщений role=tool до построения многошагового агента.

Проверки качества и границы метода

В тесте инструмент только читает константу; для сложной функции добавьте отрицательные примеры с несуществующим ID, лишним параметром и строкой вместо числа. Проверьте ответ приложения на отсутствие tool_calls: такое состояние не должно привести к выполнению подставленной функции по умолчанию. После реального вызова сообщите модели результат отдельным сообщением только при необходимости; не копируйте необработанный внешний текст в привилегированную системную инструкцию. Отделяйте валидность аргументов от правильности окончательного ответа.

Если приложение получает несколько tool_calls, заранее определите максимальное число и порядок исполнения. В этом уроке ожидается один именованный вызов, поэтому дополнительные вызовы служат поводом остановить сценарий и сохранить диагностический идентификатор запроса. Подмена ответа инструмента пользовательским текстом особенно опасна при дальнейших шагах; помечайте происхождение каждого сообщения. Факт, что пример ничего не меняет, делает его удобным безопасным тестом до подключения заказов, почты или платежей.

Критерии готовности

  1. Имя инструмента явно совпадает с allowlist.
  2. Аргументы разобраны и пусты согласно схеме.
  3. Сообщение о доставке сформировано локальным кодом.

Типичные ошибки и чего не делать

  • Не исполнять имя функции через eval.
  • Не доверять корректным аргументам без авторизации.
  • Не переносить auto parser на named-сценарий без проверки.

Частые вопросы

Исполняет ли vLLM инструмент сам?

Нет, вызов обрабатывает приложение.

Гарантирует ли named choice правильные аргументы?

Гарантируется разбираемая форма, качество проверяйте.

Нужен ли allowlist?

Да, для управления разрешёнными действиями.

Официальные источники

Частые вопросы

Исполняет ли vLLM инструмент сам?

Нет, вызов обрабатывает приложение.

Гарантирует ли named choice правильные аргументы?

Гарантируется разбираемая форма, качество проверяйте.

Нужен ли allowlist?

Да, для управления разрешёнными действиями.

Читайте также

Комментарии

Пока тихо. Скажите первое слово