# 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 :

```bash
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 :

```python
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

```bash
# 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

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

### Llama

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

### DeepSeek

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

### IBM Granite

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

### NVIDIA Nemotron

```bash
# 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

```bash
# 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

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

### Salesforce xLAM

```bash
# 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 :

```bash
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 :

```python
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 :

```python
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](../reference/cli.md) pour toutes les options.
