Aller au contenu

Tool Calling

vllm-mlx prend en charge le tool calling compatible OpenAI (function calling) avec un parsing automatique pour de nombreuses familles de modèles populaires.

Démarrage rapide

Activez le tool calling en ajoutant le flag --enable-auto-tool-choice au démarrage du serveur :

vllm-mlx serve mlx-community/Devstral-Small-2507-4bit \
  --enable-auto-tool-choice \
  --tool-call-parser mistral

Utilisez ensuite les outils avec l'API OpenAI standard :

from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed")

response = client.chat.completions.create(
    model="default",
    messages=[{"role": "user", "content": "What's the weather in Paris?"}],
    tools=[{
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get weather for a city",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "City name"}
                },
                "required": ["city"]
            }
        }
    }]
)

# Check for tool calls
if response.choices[0].message.tool_calls:
    for tc in response.choices[0].message.tool_calls:
        print(f"Function: {tc.function.name}")
        print(f"Arguments: {tc.function.arguments}")

Parsers disponibles

Utilisez --tool-call-parser pour sélectionner un tool parser adapté à votre famille de modèles :

Parser Alias Modèles Format
auto N'importe quel modèle Détection automatique du format (essaie tous les parsers)
mistral Mistral, Devstral Tableau JSON [TOOL_CALLS]
qwen qwen3 Qwen, Qwen3 XML <tool_call> ou [Calling tool:]
llama llama3, llama4 Llama 3.x, 4.x Balises <function=name>
hermes nous Hermes, NousResearch JSON <tool_call> dans XML
deepseek deepseek_v3, deepseek_r1 DeepSeek V3, R1 Délimiteurs Unicode
kimi kimi_k2, moonshot Kimi K2, Moonshot Tokens <\|tool_call_begin\|>
granite granite3 IBM Granite 3.x, 4.x <\|tool_call\|> ou <tool_call>
nemotron nemotron3 NVIDIA Nemotron <tool_call><function=...><parameter=...>
xlam Salesforce xLAM JSON avec tableau tool_calls
functionary meetkai MeetKai Functionary Plusieurs blocs de fonctions
glm47 glm4 GLM-4.7, GLM-4.7-Flash <tool_call> avec XML <arg_key>/<arg_value>

Exemples par modèle

Mistral / Devstral

# Devstral Small (optimized for coding and tool use)
vllm-mlx serve mlx-community/Devstral-Small-2507-4bit \
  --enable-auto-tool-choice --tool-call-parser mistral

# Mistral Instruct
vllm-mlx serve mlx-community/Mistral-7B-Instruct-v0.3-4bit \
  --enable-auto-tool-choice --tool-call-parser mistral

Qwen

# Qwen3
vllm-mlx serve mlx-community/Qwen3-4B-4bit \
  --enable-auto-tool-choice --tool-call-parser qwen

Llama

# Llama 3.2
vllm-mlx serve mlx-community/Llama-3.2-3B-Instruct-4bit \
  --enable-auto-tool-choice --tool-call-parser llama

DeepSeek

# DeepSeek V3
vllm-mlx serve mlx-community/DeepSeek-V3-0324-4bit \
  --enable-auto-tool-choice --tool-call-parser deepseek

IBM Granite

# Granite 4.0
vllm-mlx serve mlx-community/granite-4.0-tiny-preview-4bit \
  --enable-auto-tool-choice --tool-call-parser granite

NVIDIA Nemotron

# Nemotron 3 Nano
vllm-mlx serve mlx-community/NVIDIA-Nemotron-3-Nano-30B-A3B-MLX-6Bit \
  --enable-auto-tool-choice --tool-call-parser nemotron

GLM-4.7

# GLM-4.7 Flash
vllm-mlx serve lmstudio-community/GLM-4.7-Flash-MLX-8bit \
  --enable-auto-tool-choice --tool-call-parser glm47

Kimi K2

# Kimi K2
vllm-mlx serve mlx-community/Kimi-K2-Instruct-4bit \
  --enable-auto-tool-choice --tool-call-parser kimi

Salesforce xLAM

# xLAM
vllm-mlx serve mlx-community/xLAM-2-fc-r-4bit \
  --enable-auto-tool-choice --tool-call-parser xlam

Parser automatique

Si vous n'êtes pas sûr du parser à utiliser, le parser auto tente de détecter le format automatiquement :

vllm-mlx serve mlx-community/Qwen3-4B-4bit \
  --enable-auto-tool-choice --tool-call-parser auto

Le parser automatique essaie les formats dans cet ordre : 1. Mistral ([TOOL_CALLS]) 2. Qwen bracket ([Calling tool:]) 3. Nemotron (<tool_call><function=...><parameter=...>) 4. Qwen/Hermes XML (<tool_call>{...}</tool_call>) 5. Llama (<function=name>{...}</function>) 6. JSON brut

Streaming tool calls

Le tool calling fonctionne avec le streaming. Les informations du tool call sont envoyées lorsque le modèle a terminé de générer :

stream = client.chat.completions.create(
    model="default",
    messages=[{"role": "user", "content": "What's 25 * 17?"}],
    tools=[{
        "type": "function",
        "function": {
            "name": "calculator",
            "description": "Calculate math expressions",
            "parameters": {
                "type": "object",
                "properties": {
                    "expression": {"type": "string"}
                },
                "required": ["expression"]
            }
        }
    }],
    stream=True
)

for chunk in stream:
    if chunk.choices[0].delta.tool_calls:
        for tc in chunk.choices[0].delta.tool_calls:
            print(f"Tool call: {tc.function.name}({tc.function.arguments})")

Gestion des résultats de tool calls

Après avoir reçu un tool call, exécutez la fonction et renvoyez le résultat :

import json

# First request - model decides to call a tool
response = client.chat.completions.create(
    model="default",
    messages=[{"role": "user", "content": "What's the weather in Tokyo?"}],
    tools=[weather_tool]
)

# Get the tool call
tool_call = response.choices[0].message.tool_calls[0]
tool_call_id = tool_call.id
function_name = tool_call.function.name
arguments = json.loads(tool_call.function.arguments)

# Execute the function (your implementation)
result = get_weather(**arguments)  # {"temperature": 22, "condition": "sunny"}

# Send result back to model
response = client.chat.completions.create(
    model="default",
    messages=[
        {"role": "user", "content": "What's the weather in Tokyo?"},
        {"role": "assistant", "tool_calls": [tool_call]},
        {"role": "tool", "tool_call_id": tool_call_id, "content": json.dumps(result)}
    ],
    tools=[weather_tool]
)

print(response.choices[0].message.content)
# "The weather in Tokyo is sunny with a temperature of 22C."

Gestion des balises think

Les modèles qui produisent des balises de reasoning <think>...</think> (comme DeepSeek-R1, Qwen3, GLM-4.7) sont gérés automatiquement. Le parser supprime le contenu de la réflexion avant d'extraire les tool calls, de sorte que les balises de reasoning n'interfèrent jamais avec le parsing des tool calls.

Cela fonctionne même lorsque <think> a été injecté dans le prompt (balises think implicites avec uniquement un </think> fermant).

Référence CLI

Option Description
--enable-auto-tool-choice Active le tool calling automatique
--tool-call-parser Sélectionne le parser (voir tableau ci-dessus)

Voir Référence CLI pour toutes les options.