Aller au contenu principal

Fine-tuning pour le function calling

Pourquoi fine-tuner le function calling

Le function calling (appel de fonctions) permet au modèle de décider quand et comment appeler des fonctions externes. Un modèle fine-tuné pour le function calling apprend à :

  • Choisir la bonne fonction parmi plusieurs disponibles
  • Extraire les bons paramètres de la requête utilisateur
  • Savoir quand ne PAS appeler de fonction
  • Chaîner plusieurs appels de fonctions de manière logique

Format des données pour le function calling

Les exemples d’entraînement incluent la définition des fonctions (tools) et les appels correspondants :

{
  "messages": [
    {
      "role": "system",
      "content": "Vous êtes un assistant qui aide à gérer les rendez-vous."
    },
    {
      "role": "user",
      "content": "Réserve-moi un créneau demain à 14h avec Dr. Martin."
    },
    {
      "role": "assistant",
      "tool_calls": [
        {
          "id": "call_001",
          "type": "function",
          "function": {
            "name": "creer_rendez_vous",
            "arguments": "{\"date\": \"2026-04-03\", \"heure\": \"14:00\", \"praticien\": \"Dr. Martin\"}"
          }
        }
      ]
    },
    {
      "role": "tool",
      "tool_call_id": "call_001",
      "content": "{\"status\": \"confirme\", \"id\": \"rdv_42\"}"
    },
    {
      "role": "assistant",
      "content": "Votre rendez-vous avec Dr. Martin est confirmé pour demain à 14h. Référence : RDV-42."
    }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "creer_rendez_vous",
        "description": "Crée un nouveau rendez-vous médical",
        "parameters": {
          "type": "object",
          "properties": {
            "date": {
              "type": "string",
              "description": "Date au format YYYY-MM-DD"
            },
            "heure": {
              "type": "string",
              "description": "Heure au format HH:MM"
            },
            "praticien": {
              "type": "string",
              "description": "Nom du praticien"
            }
          },
          "required": ["date", "heure", "praticien"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "lister_creneaux",
        "description": "Liste les créneaux disponibles pour un praticien",
        "parameters": {
          "type": "object",
          "properties": {
            "praticien": {"type": "string"},
            "date": {"type": "string"}
          },
          "required": ["praticien"]
        }
      }
    }
  ]
}

Cas d’usage courants

Sélection de la bonne fonction

Entraînez le modèle à distinguer quelle fonction appeler selon le contexte :

{
  "messages": [
    {"role": "user", "content": "Quels créneaux sont libres jeudi chez Dr. Martin ?"},
    {
      "role": "assistant",
      "tool_calls": [
        {
          "id": "call_002",
          "type": "function",
          "function": {
            "name": "lister_creneaux",
            "arguments": "{\"praticien\": \"Dr. Martin\", \"date\": \"2026-04-04\"}"
          }
        }
      ]
    }
  ],
  "tools": ["... mêmes tools que ci-dessus ..."]
}

Ne PAS appeler de fonction

Il est important d’inclure des exemples où le modèle ne doit pas utiliser de fonction :

{
  "messages": [
    {"role": "user", "content": "Bonjour, comment allez-vous ?"},
    {
      "role": "assistant",
      "content": "Bonjour ! Je vais bien, merci. Comment puis-je vous aider avec vos rendez-vous aujourd'hui ?"
    }
  ],
  "tools": ["... mêmes tools ..."]
}

Extraction de paramètres complexes

{
  "messages": [
    {"role": "user", "content": "Annule mon rendez-vous de lundi prochain matin avec le cardiologue"},
    {
      "role": "assistant",
      "tool_calls": [
        {
          "id": "call_003",
          "type": "function",
          "function": {
            "name": "annuler_rendez_vous",
            "arguments": "{\"date\": \"2026-04-06\", \"periode\": \"matin\", \"specialite\": \"cardiologie\"}"
          }
        }
      ]
    }
  ],
  "tools": ["..."]
}

Script de préparation des données

import json

def creer_exemple_function_calling(
    messages: list[dict],
    tools: list[dict]
) -> dict:
    """Crée un exemple d'entraînement pour le function calling."""
    return {
        "messages": messages,
        "tools": tools
    }

# Définition des outils
tools = [
    {
        "type": "function",
        "function": {
            "name": "rechercher_produit",
            "description": "Recherche un produit dans le catalogue",
            "parameters": {
                "type": "object",
                "properties": {
                    "requete": {"type": "string", "description": "Termes de recherche"},
                    "categorie": {"type": "string", "enum": ["electronique", "vetements", "maison"]},
                    "prix_max": {"type": "number", "description": "Prix maximum en euros"}
                },
                "required": ["requete"]
            }
        }
    }
]

# Exemples d'entraînement
exemples = [
    creer_exemple_function_calling(
        messages=[
            {"role": "user", "content": "Je cherche un casque audio à moins de 100 euros"},
            {
                "role": "assistant",
                "tool_calls": [{
                    "id": "call_1",
                    "type": "function",
                    "function": {
                        "name": "rechercher_produit",
                        "arguments": json.dumps({
                            "requete": "casque audio",
                            "categorie": "electronique",
                            "prix_max": 100
                        })
                    }
                }]
            }
        ],
        tools=tools
    )
]

# Sauvegarder
with open("function_calling_train.jsonl", "w", encoding="utf-8") as f:
    for ex in exemples:
        f.write(json.dumps(ex, ensure_ascii=False) + "\n")

Lancer le fine-tuning

from openai import OpenAI

client = OpenAI()

fichier = client.files.create(
    file=open("function_calling_train.jsonl", "rb"),
    purpose="fine-tune"
)

job = client.fine_tuning.jobs.create(
    training_file=fichier.id,
    model="gpt-5.4-mini",
    suffix="function-calling-v1"
)

Bonnes pratiques

Diversité des exemples

  • Incluez tous les cas de figure : chaque fonction doit apparaître plusieurs fois
  • Variez les formulations utilisateur pour la même intention
  • Incluez des cas ambigus avec la bonne résolution
  • Ajoutez des exemples sans appel de fonction (conversations normales)

Paramètres réalistes

  • Les arguments doivent correspondre exactement au schéma défini dans tools
  • Utilisez des valeurs réalistes, pas des placeholders comme “xxx”
  • Testez que chaque arguments est un JSON valide

Proportion recommandée

Pour un jeu de 100 exemples avec 3 fonctions :

  • 25-30 exemples par fonction
  • 10-15 exemples sans appel de fonction
  • 5-10 exemples avec appels chaînés (multi-step)

Points clés à retenir

  • Le format inclut les tools en plus des messages
  • Les appels de fonction utilisent tool_calls dans le message assistant
  • Incluez des exemples où le modèle ne doit PAS appeler de fonction
  • Variez les formulations pour une même intention
  • Vérifiez que tous les arguments sont des JSON valides conformes au schéma