Lesson 1 — Comprendre le function calling

Le cycle du function calling et les déclarations

5 min read

This content is not translated yet. Showing the original version.

Le cycle du function calling et les déclarations

Le modèle n'exécute rien

Premier point, le plus important : le modèle n'appelle jamais votre API. Il renvoie une intention structurée (« j'aimerais appeler consulter_solde avec {"employe_id": "E001"} »). C'est votre code qui décide de l'exécuter, l'exécute, puis renvoie le résultat au modèle.

sequenceDiagram
  participant U as Utilisateur
  participant A as Votre code
  participant G as Gemini
  participant API as API RH
  U->>A: "Combien de congés me reste-t-il ?"
  A->>G: question + déclarations des outils
  G-->>A: function_call consulter_solde(employe_id="E001")
  A->>API: GET /employes/E001/soldes
  API-->>A: {"conges_payes": 18, "rtt": 4}
  A->>G: function_response (le résultat)
  G-->>A: "Il vous reste 18 jours de congés payés et 4 RTT."
  A-->>U: réponse finale

Deux allers-retours avec le modèle pour une seule question : c'est normal, et c'est ce qui coûte (en latence et en jetons). Un jeton (token) est un morceau de mot, l'unité de facturation des LLM.

Ce que voit le modèle : la déclaration

Le modèle ne lit pas votre code Python. Il lit une déclaration de fonction (FunctionDeclaration) : un nom, une description et un schéma JSON des paramètres. JSON Schema est un format standard pour décrire la forme d'un objet JSON (types, champs obligatoires, valeurs permises).

files/outils_rh.py (extrait)
from google.genai import types

types.FunctionDeclaration(
    name="consulter_solde",
    description="Donne le solde de congés payés et de RTT (en jours) d'un employé.",
    parameters_json_schema={
        "type": "object",
        "properties": {"employe_id": {"type": "string", "description": "Ex. E001"}},
        "required": ["employe_id"]}),

types.FunctionDeclaration(
    name="chercher_employe",
    description="Cherche un employé dans l'annuaire par son nom ou une partie du nom. "
                "Renvoie son identifiant (ex. E002). À appeler AVANT tout autre outil "
                "quand l'utilisateur donne un nom au lieu d'un identifiant.",
    parameters_json_schema={
        "type": "object",
        "properties": {"nom": {"type": "string", "description": "Ex. « Benali »"}},
        "required": ["nom"]}),

Les cinq déclarations complètes sont dans outils_rh.py.

ChampRôle pour le modèleBonne pratique
nameidentifiant renvoyé dans function_callverbe + objet en snake_case : consulter_solde
descriptionle prompt de l'outil : quand et pourquoi l'appelerdire l'ordre d'appel, donner un exemple de valeur
propertiesles paramètres et leur typeenum pour une liste fermée (["conges_payes", "rtt"])
requiredles paramètres sans lesquels l'appel n'a pas de senstout ce que la fonction exige

Deux façons d'écrire une déclaration

Le SDK google-genai peut aussi déduire la déclaration d'une fonction Python typée et documentée :

files/auto.py (extrait)
def consulter_solde(employe_id: str) -> dict:
    """Donne le solde de congés payés et de RTT (en jours) d'un employé, ex. E001."""
    return outils_rh.consulter_solde(UTILISATEUR, employe_id)

types.FunctionDeclaration.from_callable(client=client, callable=consulter_solde) produit alors la même chose que le schéma écrit à la main (sortie réelle plus bas). La signature donne les types, la docstring donne la description.

Schéma écrit à la mainDéduit d'une fonction Python
Contrôle fin (enum, descriptions par paramètre)ouilimité
Une seule source de vériténon : schéma et code à garder alignésoui
Lisible dans une revue de codetrèsoui
Utilisé dans ce lab pourla boucle manuellele mode automatique

Lors d'un function calling, qui envoie la requête HTTP à l'API RH ?

Quel champ de la déclaration influence le plus le moment où le modèle choisit un outil ?

Exercice : déclarer lister_demandes

Écrivez la déclaration de l'outil lister_demandes, qui liste les demandes de congés d'un employé avec leur statut. Ajoutez une indication qui évite au modèle de l'appeler avec un nom de personne.

Voir la solution
types.FunctionDeclaration(
    name="lister_demandes",
    description="Liste les demandes de congés d'un employé, avec leur statut "
                "(en_attente, annulee). Si l'utilisateur donne un nom, "
                "appelle d'abord chercher_employe pour obtenir l'identifiant.",
    parameters_json_schema={
        "type": "object",
        "properties": {"employe_id": {"type": "string",
                                      "description": "Identifiant, ex. E001"}},
        "required": ["employe_id"]})

La description renvoie vers chercher_employe et l'exemple E001 fixe le format attendu. La version du lab est plus courte car l'instruction système répète déjà la règle « nom → chercher_employe ».

Résultat obtenu

Déclaration déduite par le SDK à partir de auto.consulter_solde (exécuté le 2026-10-15, sans appel réseau) :

{
 "description": "Donne le solde de congés payés et de RTT (en jours) d'un employé, ex. E001.",
 "name": "consulter_solde",
 "parameters": {
  "properties": {"employe_id": {"type": "STRING"}},
  "required": ["employe_id"],
  "type": "OBJECT"
 }
}

Et le cycle complet avec le vrai modèle (python e2e.py, scénario 1, gemini-3.5-flash) :

[E001] Combien de jours de congés me reste-t-il ?   (mode AUTO)
  [tour 1] 1 appel(s) : consulter_solde({"employe_id": "E001"})
  → Il vous reste **18 jours** de congés payés et **4 jours** de RTT.

Le modèle a deviné seul que « me » désignait E001, parce que l'instruction système lui donne l'identifiant de la session.

Je sais faire

  • Expliquer pourquoi le modèle n'exécute jamais lui-même une fonction
  • Écrire une FunctionDeclaration avec parameters_json_schema
  • Rédiger une description qui dit quand appeler l'outil
  • Choisir entre schéma écrit à la main et schéma déduit d'une fonction Python
Next