# Tool calling et sortie JSON avec des modèles open-weight

> Function calling avec des modèles open-weight au format OpenAI : tools, tool_choice, la boucle appel-et-réponse, et response_format pour une sortie JSON valide.

- URL: https://llmwithcrypto.com/fr/docs/tool-calling/
- Dernière mise à jour: 2026-10-23
- Éditeur: LLMwithCrypto (https://llmwithcrypto.com)

Le modèle peut demander à votre code d'exécuter une fonction, puis utiliser le résultat dans sa réponse ; ou il peut répondre par un objet JSON que votre programme lit directement. Les deux utilisent le format de requête OpenAI, et les deux dépendent du modèle que vous choisissez.

**Réponse rapide — Comment fonctionne le tool calling sur LLMwithCrypto ?**

Envoyez vos fonctions dans `tools`, au format OpenAI. Quand le modèle en veut une, **LLMwithCrypto** renvoie `finish_reason: "tool_calls"` avec le nom de la fonction et les arguments JSON ; votre code l'exécute et renvoie le résultat dans un message `tool`. Pour des réponses structurées, `response_format: {"type": "json_object"}` demande un JSON valide. Les deux fonctionnent sur les modèles qui les prennent en charge, comme documenté le 23 octobre 2026.

## Quels modèles prennent en charge les tools et le JSON ?

Le streaming fonctionne sur tous les modèles ; le tool calling et la sortie JSON suivent ce que chaque modèle prend lui-même en charge.

Testez votre propre schéma sur le modèle que vous comptez utiliser avant d'en dépendre. Un modèle qui ne prend pas en charge les tools répond en texte brut au lieu d'appeler la fonction ; un modèle qui ne prend pas en charge le mode JSON renvoie une erreur `400` pour `response_format`.

## Qu'est-ce que la boucle ?

1. **Décrire les fonctions** — Chaque tool a un name, une description que le modèle lit pour décider quand l'utiliser, et des parameters sous forme de JSON Schema.
2. **Envoyer la conversation avec les tools** — Le modèle répond soit en texte, soit s'arrête avec finish_reason: "tool_calls" et un ou plusieurs appels dans message.tool_calls.
3. **Exécuter chaque appel** — Parsez function.arguments (une chaîne JSON), exécutez votre fonction, et ne faites jamais confiance aveuglément aux arguments : validez-les comme n'importe quelle entrée utilisateur.
4. **Renvoyer les résultats** — Ajoutez le message de l'assistant, puis un message tool par appel avec son tool_call_id et le résultat en texte. Appelez à nouveau l'API ; répétez jusqu'à ce que le modèle réponde en texte.

*Python : une boucle de tools complète avec gpt-oss-120b*

```python
import json
import os

from openai import OpenAI

client = OpenAI(
    base_url="https://llmwithcrypto.com/api/v1",
    api_key=os.environ["LLMWITHCRYPTO_API_KEY"],
)

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_order_status",
            "description": "Return the delivery status of an order.",
            "parameters": {
                "type": "object",
                "properties": {"order_id": {"type": "string"}},
                "required": ["order_id"],
            },
        },
    }
]


def get_order_status(order_id):
    return {"order_id": order_id, "status": "shipped", "eta": "2026-10-25"}


messages = [{"role": "user", "content": "Where is my order A-1042?"}]
while True:
    resp = client.chat.completions.create(model="gpt-oss-120b", messages=messages, tools=tools, max_tokens=300)
    msg = resp.choices[0].message
    if not msg.tool_calls:
        print(msg.content)
        break
    messages.append(msg)
    for call in msg.tool_calls:
        args = json.loads(call.function.arguments)
        result = get_order_status(**args)
        messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})

```

## À quoi ressemble un appel de tool dans la réponse ?

Le message de l'assistant n'a pas de texte, un tableau `tool_calls`, et le choix se termine par `finish_reason: "tool_calls"`. Les arguments arrivent sous forme de chaîne JSON, pas d'objet. Les ids et les décomptes ci-dessous sont illustratifs.

*Réponse demandant un appel de fonction (illustratif)*

```json
{
  "id": "chatcmpl-3c9d27e1",
  "object": "chat.completion",
  "created": 1792742400,
  "model": "gpt-oss-120b",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": null,
        "tool_calls": [
          {
            "id": "call_7f31",
            "type": "function",
            "function": {
              "name": "get_order_status",
              "arguments": "{\"order_id\": \"A-1042\"}"
            }
          }
        ]
      },
      "finish_reason": "tool_calls"
    }
  ],
  "usage": {
    "prompt_tokens": 118,
    "completion_tokens": 22,
    "total_tokens": 140
  }
}

```

## Comment contrôler l'utilisation des tools ?

- **`"tool_choice": "auto"`** (la valeur par défaut quand `tools` est défini) : le modèle décide.
- **`"tool_choice": "none"`** : le modèle répond en texte même si des tools sont listés.
- **`"tool_choice": "required"`** : le modèle doit appeler au moins un tool.
- **`{"type": "function", "function": {"name": "get_order_status"}}`** : le modèle doit appeler celui-là.

Chaque définition de tool est envoyée en entrée à chaque appel, donc les descriptions longues et les tools nombreux augmentent les tokens d'entrée. Gardez les descriptions courtes et n'envoyez que les tools dont une étape a besoin.

## Comment obtenir un JSON valide en retour ?

Définissez `response_format` sur `{"type": "json_object"}` et décrivez les clés attendues dans le message système : le mode JSON garantit que la réponse se parse, pas qu'elle contient les clés que vous voulez. Gardez `temperature` bas pour une sortie stable et vérifiez l'objet parsé dans votre code avant de l'utiliser.

*Node.js : une réponse JSON avec response_format*

```javascript
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://llmwithcrypto.com/api/v1',
  apiKey: process.env.LLMWITHCRYPTO_API_KEY,
});

const resp = await client.chat.completions.create({
  model: 'gpt-oss-120b',
  messages: [
    { role: 'system', content: 'Reply with a JSON object {"sentiment": "positive" | "negative" | "neutral", "reason": string}.' },
    { role: 'user', content: 'The delivery was late but support fixed it in an hour.' },
  ],
  response_format: { type: 'json_object' },
  temperature: 0.2,
  max_tokens: 150,
});
const result = JSON.parse(resp.choices[0].message.content);
console.log(result.sentiment, '-', result.reason);

```

## Tools et JSON : questions fréquentes

### Les appels de tools coûtent-ils plus cher ?

Aucun frais propre. Les définitions de tools, l'appel et les résultats que vous renvoyez sont tous des tokens, facturés comme les autres. Vous payez au token depuis votre solde : les tokens d'entrée et de sortie sont comptés par le tokenizer du modèle lui-même et facturés au prix de ce modèle par 1M de tokens. Un appel qui se termine par une erreur ne coûte rien.

### Le modèle peut-il appeler plusieurs tools à la fois ?

Certains modèles renvoient plus d'un appel dans `tool_calls`. Exécutez-les tous et envoyez un message `tool` par appel avant la requête suivante.

### L'API exécute-t-elle mes fonctions ?

Non. Le modèle indique seulement quelle fonction appeler et avec quels arguments ; c'est votre code qui l'exécute. Rien n'est exécuté de notre côté, et rien de l'échange n'est stocké : Nous ne stockons ni vos prompts ni les réponses du modèle : une fois une réponse envoyée, son texte a disparu. Chaque appel laisse une ligne de log avec l'heure, le compte, le modèle et le nombre de tokens, supprimée après 30 jours.

---

LLMwithCrypto: LLMwithCrypto est une API LLM compatible OpenAI pour les modèles open-weight — DeepSeek V4 Pro, DeepSeek V4.1 Flash, DeepSeek R1, Qwen3.5 397B A17B, Qwen3 235B A22B Instruct, gpt-oss-120b, gpt-oss-20b, GLM-4.7, Llama 3.3 70B Instruct, Gemma 4 31B, Mistral Large 3, Mistral Small 4 — facturés au token depuis un solde crypto prépayé, à 5 % en dessous du prix médian des hébergeurs publics. Sans KYC : pas de pièce d'identité, pas de selfie, pas de documents. Les prompts et les sorties ne sont pas stockés.
