Back to Linktree

functiongemma.fine-tuning.function.calling

September 17, 2026 13 min read

FunctionGemma 270M : comment tester, comprendre et dompter un SLM spécialisé dans le Function Calling

Les grands modèles de langage savent faire beaucoup de choses.

Mais pour certaines applications, beaucoup de choses est justement le problème.

Si mon besoin est simplement de transformer :

« Allume la lampe de mon téléphone »

en :

call:turn_on_flashlight{}

je n’ai peut-être pas besoin d’un modèle de plusieurs dizaines de milliards de paramètres.

C’est précisément là que les Small Language Models (SLM) deviennent intéressants.

Et un cas particulièrement intéressant est FunctionGemma 270M, le modèle de Google DeepMind spécialisé dans le function calling. Il est construit à partir de Gemma 3 270M et conçu pour transformer des instructions en appels de fonctions, notamment dans des environnements contraints ou on-device. Hugging Face

L’idée de cet article est donc simple :

ne pas seulement tester FunctionGemma… mais chercher à comprendre comment il fonctionne, où il échoue, quelles sont ses “astuces” et comment construire une véritable batterie de tests à partir des datasets disponibles sur Hugging Face.


1. FunctionGemma 270M : ce n’est pas un “petit ChatGPT”

C’est probablement le premier point à comprendre.

La fiche officielle du modèle indique explicitement que FunctionGemma n’est pas destiné à être utilisé comme modèle de dialogue généraliste.

Son objectif est plutôt de servir de base à des modèles spécialisés dans le function calling. Hugging Face

Son fonctionnement peut être résumé ainsi :

Utilisateur
    │
    ▼
"Réserve-moi un taxi pour 18h"
    │
    ▼
FunctionGemma
    │
    ├── choisir l'outil
    ├── identifier les paramètres
    └── générer l'appel
    │
    ▼
book_taxi(
    time="18:00"
)
    │
    ▼
Application

C’est donc moins :

“Que dois-je répondre ?”

que :

“Quelle action dois-je déclencher et avec quels paramètres ?”

Et cette nuance change complètement la manière de tester le modèle.


2. Ce que 270M paramètres peut réellement faire

Il serait tentant de demander à FunctionGemma :

“Explique-moi la théorie de la relativité.”

Ce n’est pas le meilleur test.

En revanche, on peut lui donner des outils comme :

[
  {
    "name": "get_weather",
    "description": "Get current weather",
    "parameters": {
      "location": "string"
    }
  },
  {
    "name": "send_email",
    "description": "Send an email",
    "parameters": {
      "to": "string",
      "subject": "string",
      "body": "string"
    }
  }
]

et tester :

"Quel temps fait-il à Rennes ?"

pour obtenir quelque chose du genre :

get_weather(location="Rennes")

La documentation officielle montre justement ce mécanisme avec un schéma JSON, un message developer indiquant que le modèle peut appeler des fonctions, puis une génération de l’appel correspondant. Hugging Face

Cela permet d’imaginer beaucoup de micro-agents :

  • assistant domotique ;
  • contrôle d’un smartphone ;
  • automatisation locale ;
  • recherche dans une base documentaire ;
  • API internes d’entreprise ;
  • commandes d’une application ;
  • agent embarqué dans un véhicule ;
  • assistants offline ;
  • automatisation industrielle ;
  • jeux et interfaces interactives.

Google présente notamment Mobile Actions, où le modèle traduit des instructions naturelles en appels à des fonctions Android, ainsi que Tiny Garden, où il pilote les actions d’un petit jeu. Hugging Face+1


3. Le vrai sujet : comment tester un SLM ?

Pour moi, il faut éviter le classique :

Prompt A → réponse
Prompt B → réponse
Prompt C → réponse

et passer à une logique de laboratoire expérimental.

Je proposerais 7 familles de tests.

Test 1 — Tool selection

Le modèle choisit-il le bon outil ?

"Quel est le temps à Paris ?"

avec :

get_weather()
search_web()
send_email()

On mesure :

✓ bon outil
✗ mauvais outil
✗ aucune fonction
✗ hallucination

Test 2 — Argument extraction

Le bon outil est-il sélectionné avec les bons paramètres ?

"Envoie un mail à paul@example.com
avec comme sujet 'Réunion'
et dis-lui que je serai en retard."

On vérifie :

{
  "to": "paul@example.com",
  "subject": "Réunion",
  "body": "Je serai en retard."
}

Ici, il faut séparer :

tool accuracy

et

argument accuracy.

Un modèle peut parfaitement choisir send_email tout en remplissant mal les arguments.


4. Le test qui devient vraiment intéressant : l’ambiguïté

C’est probablement l’une des meilleures façons de comprendre un SLM.

Imaginons :

search_internal_docs()
search_web()

Prompt :

“Quelle est notre politique de remboursement des repas ?”

Le modèle doit comprendre que la bonne source est probablement la documentation interne.

Mais :

“Quelle est la politique de remboursement des repas chez Air France ?”

change complètement le contexte.

C’est exactement le type de problème étudié dans le guide officiel de fine-tuning de FunctionGemma : apprendre au modèle à distinguer des outils proches selon le contexte métier. Google Developers Blog

On découvre alors quelque chose d’important :

un petit modèle peut être extrêmement efficace lorsqu’on réduit son espace de décision.


5. Le test le plus révélateur : “No Tool”

Il ne faut surtout pas tester uniquement les cas où une fonction doit être appelée.

Il faut également tester :

“Est-ce que le modèle sait ne rien appeler ?”

Exemple :

Tools:
- get_weather()
- send_email()
- create_calendar_event()

Prompt :

“Explique-moi ce qu’est Python.”

Le résultat attendu :

NO TOOL

et surtout pas :

search_web()

ou une fonction inventée.

C’est un excellent test de relevance / irrelevance.

Le benchmark publié avec FunctionGemma contient justement des catégories BFCL de relevance et d’irrelevance, en plus des scénarios de function calling simple, multiple et parallèle. Hugging Face


6. Tester les limites : les prompts “pièges”

C’est ici que l’on commence réellement à découvrir les caractéristiques du modèle.

Je créerais volontairement des prompts comme :

"Allume la lumière... enfin non, laisse tomber."

ou :

"Envoie un email à Paul si tu trouves son adresse."

ou :

"Réserve-moi quelque chose demain."

ou :

"Supprime le fichier rapport.pdf"

avec deux outils :

delete_file()
archive_file()

L’objectif n’est pas seulement de mesurer la réussite.

Il faut identifier les frontières comportementales du modèle.


7. Construire une matrice de tests

Une approche très efficace consiste à transformer chaque fonction en matrice.

Par exemple :

Catégorie Exemple Résultat attendu
Happy path “Allume la lumière” turn_on_light
Paramètre simple “Lumière du salon” room=salon
Paramètre absent “Allume la lumière” demander précision
Ambiguïté “Allume celle du salon” clarification
Négation “N’allume pas la lumière” aucun appel
Hors sujet “Quel temps fait-il ?” aucun appel
Outil similaire turn_on vs set_brightness bon outil
Valeur invalide luminosité 200% rejet/correction
Multi-tool lumière + chauffage deux appels
Séquence ouvrir → modifier → fermer ordre correct

On passe ainsi d’un simple test de LLM à un test fonctionnel d’agent.


8. Hugging Face devient alors notre laboratoire

Et c’est là que cela devient particulièrement intéressant.

Le dataset officiel Google Mobile Actions est disponible sur Hugging Face. Il contient environ 9 650 exemples, avec des conversations et des définitions d’outils, et est spécifiquement destiné à l’entraînement de modèles légers comme FunctionGemma pour le function calling on-device. Hugging Face

Dataset Google Mobile Actions sur Hugging Face

On peut donc commencer par :

from datasets import load_dataset

dataset = load_dataset(
    "google/mobile-actions",
    split="train"
)

print(dataset)
print(dataset[0])

Puis observer :

sample = dataset[0]

print(sample.keys())
print(sample["messages"])
print(sample["tools"])

Et surtout :

ne pas simplement utiliser le dataset pour entraîner.

Utilisons-le pour comprendre comment les données enseignent au modèle à agir.


9. Transformer un dataset en générateur de tests

C’est probablement l’une des idées les plus intéressantes de cette approche.

Prenons un exemple du dataset :

User:
"Turn on the flashlight"

Expected:
turn_on_flashlight()

On peut automatiquement générer plusieurs variantes :

"Allume la lampe torche"

"Tu peux activer le flash ?"

"Active la flashlight"

"J'ai besoin de lumière"

"Peux-tu allumer le flash du téléphone ?"

Puis comparer les résultats.

On passe alors de :

1 exemple → 1 test

à :

1 exemple
   ↓
20 variantes
   ↓
20 tests

Et là, on commence à construire un fuzzing sémantique pour LLM.


10. Encore mieux : créer des tests négatifs

Le dataset contient ce que le modèle doit faire.

Nous pouvons créer artificiellement ce qu’il ne doit pas faire.

Exemple :

TRAIN

"Turn on flashlight"
→ turn_on_flashlight()

Créer :

NEGATIVE TEST

"Do not turn on the flashlight"
→ NO TOOL

Puis :

"Is the flashlight currently on?"
→ get_flashlight_status()

Puis :

"Turn on the flashlight and set brightness to 50%"
→ turn_on_flashlight()
→ set_brightness(50)

Puis :

"Turn on the flashlight if the battery is above 30%"

On commence à tester :

  • négation ;
  • condition ;
  • dépendance ;
  • multi-tool ;
  • paramètres ;
  • ambiguïté ;
  • contexte.

11. Et maintenant : découvrir les “astuces” de FunctionGemma

C’est là que l’expérimentation devient vraiment intéressante.

Au lieu de demander :

“Quel prompt marche le mieux ?”

je construirais une Prompt Mutation Matrix.

Par exemple :

Variante A

You can call functions.

Variante B

You are an assistant capable of calling tools.

Variante C

Use the available functions whenever appropriate.

Variante D

Le format attendu est explicitement décrit.

Puis :

100 prompts
×
4 system prompts
×
5 températures

On obtient :

2 000 expériences

et on mesure :

tool_accuracy
argument_accuracy
no_tool_accuracy
format_accuracy
latency
tokens

On commence alors à construire une véritable carte comportementale du SLM.


12. Une métrique très importante : exact match vs semantic match

Attention ici.

Si le modèle produit :

{
  "location": "Rennes"
}

et que la vérité est :

{
  "location": "Rennes, France"
}

un simple exact_match dira :

FAIL

alors que fonctionnellement le résultat peut être acceptable.

Il faut donc plusieurs métriques :

Exact Match
   ↓
JSON validity
   ↓
Tool correctness
   ↓
Argument correctness
   ↓
Semantic correctness

Exemple :

def evaluate(prediction, expected):
    return {
        "tool_ok": ...,
        "arguments_ok": ...,
        "json_valid": ...,
        "semantic_ok": ...
    }

C’est beaucoup plus intéressant qu’un unique score.


13. Le dataset officiel donne aussi une piste essentielle

Le modèle de base obtient des résultats sensiblement différents selon le type de function calling évalué.

Dans les résultats publiés par Google, FunctionGemma 270M obtient notamment :

  • BFCL Simple : 61,6
  • BFCL Multiple : 63,5
  • BFCL Parallel : 39
  • BFCL Parallel Multiple : 29,5
  • BFCL Relevance : 61,1
  • BFCL Irrelevance : 73,7

Ces chiffres sont ceux rapportés par la model card et doivent être lus comme des résultats de benchmark, pas comme une garantie de performance sur votre propre application. Hugging Face

Cela donne une indication intéressante :

“faire un function call” et “orchestrer plusieurs function calls” sont deux problèmes très différents.


14. Le vrai potentiel apparaît avec le fine-tuning

Google montre justement l’intérêt de spécialiser FunctionGemma.

Sur son cas d’usage Mobile Actions, l’évaluation publiée passe de 58 % pour le modèle de base à 85 % après fine-tuning sur ce workflow spécifique. Hugging Face

Le message est important :

270M paramètres ne signifie pas nécessairement “faible capacité”.

Cela peut signifier :

capacité concentrée sur un problème bien défini.

C’est une philosophie très différente du :

“prenons le plus gros modèle possible.”


15. Et si on construisait notre propre dataset ?

Imaginons une entreprise qui possède :

create_ticket()
update_ticket()
close_ticket()
search_ticket()
assign_ticket()

On peut créer :

{
  "user": "Ferme le ticket 1234",
  "expected_tool": "close_ticket",
  "arguments": {
    "ticket_id": "1234"
  }
}

Puis générer :

"Tu peux clôturer le ticket 1234 ?"

"Ferme-moi le ticket numéro 1234"

"Le ticket 1234 peut être clôturé"

"Je veux clôturer 1234"

Mais surtout :

"Montre-moi le ticket 1234"

→ search_ticket

et :

"Ferme le ticket 1234"

→ close_ticket

Le dataset devient alors une spécification comportementale.


16. Attention au piège du train/test split

C’est un détail qui peut complètement fausser les résultats.

Le guide Google consacré au fine-tuning de FunctionGemma montre justement l’importance de la distribution des données lors du découpage train/test. Si les exemples sont organisés par catégorie et que l’on découpe sans mélanger, on peut finir avec une catégorie presque exclusivement dans le train et une autre dans le test. Google Developers Blog

Donc :

dataset.train_test_split(
    test_size=0.2,
    shuffle=True
)

est souvent préférable lorsque l’ordre initial du dataset n’est pas garanti comme étant correctement mélangé.

Mais surtout :

il faut penser au split en fonction du problème.

Pour un agent réel, je testerais également :

Train :
    formulations connues

Test :
    formulations inédites

et même :

Test OOD :
    nouveaux outils
    nouveaux paramètres
    nouvelles formulations

C’est beaucoup plus révélateur de la capacité de généralisation.


17. Une architecture de test que j’utiliserais

Je construirais un petit framework :

                 ┌─────────────────┐
                 │ Hugging Face    │
                 │ datasets        │
                 └────────┬────────┘
                          │
                          ▼
                 ┌─────────────────┐
                 │ Test Generator  │
                 └────────┬────────┘
                          │
             ┌────────────┼────────────┐
             ▼            ▼            ▼
          Normal       Ambiguous     Negative
             │            │            │
             └────────────┼────────────┘
                          ▼
                 ┌─────────────────┐
                 │ FunctionGemma   │
                 │      270M       │
                 └────────┬────────┘
                          │
                          ▼
                 ┌─────────────────┐
                 │ Evaluator       │
                 └────────┬────────┘
                          │
          ┌───────────────┼────────────────┐
          ▼               ▼                ▼
      Tool Acc.      Arg Acc.        No-Tool Acc.

Et conserver chaque expérience :

{
  "prompt": "...",
  "tools": [...],
  "expected": {...},
  "actual": {...},
  "tool_accuracy": true,
  "argument_accuracy": false,
  "latency_ms": 37,
  "tokens": 18
}

18. Le graal : tester le SLM comme du logiciel

C’est probablement la conclusion la plus importante.

On ne devrait plus traiter un SLM uniquement comme :

prompt → réponse

mais comme un composant logiciel :

INPUT
  ↓
MODEL
  ↓
STRUCTURED OUTPUT
  ↓
VALIDATOR
  ↓
ACTION

Avec des tests automatisés :

assert result.tool == "get_weather"

assert result.arguments["location"] == "Rennes"

assert result.is_valid_json

assert result.confidence_policy_ok

Et surtout :

CI/CD
 ↓
1000 prompts
 ↓
FunctionGemma
 ↓
Evaluation
 ↓
Regression detected

On peut alors détecter qu’un fine-tuning ou une modification du prompt a fait passer :

Tool accuracy
92% → 88%

avant de déployer le modèle.


19. Ce que je testerais en premier avec FunctionGemma 270M

Mon parcours expérimental serait :

Étape 1 — Baseline

Tester le modèle officiel sans modification.

Étape 2 — Single tool

1 prompt
1 tool

Étape 3 — Multiple tools

1 prompt
5 tools

Étape 4 — Similar tools

search_web()
search_docs()
search_database()

Étape 5 — No-tool

Tester explicitement les requêtes qui ne doivent déclencher aucune action.

Étape 6 — Ambiguity

Créer volontairement des cas ambigus.

Étape 7 — Multi-turn

User → demande
Model → clarification
User → précision
Model → function call

Étape 8 — Dataset Hugging Face

Utiliser google/mobile-actions comme matière première pour construire les tests. Hugging Face

Étape 9 — Mutation

Générer automatiquement des variantes linguistiques.

Étape 10 — Fine-tuning

Spécialiser le modèle sur son propre domaine.

Étape 11 — Regression suite

Conserver tous les cas qui ont déjà cassé le modèle.


20. Le changement de perspective

C’est finalement ce que je trouve le plus intéressant avec FunctionGemma.

Le sujet n’est pas seulement :

“Que peut faire un modèle de 270M ?”

La vraie question est :

“Que peut-on obtenir lorsqu’on transforme un petit modèle généraliste en composant extrêmement spécialisé, puis qu’on mesure précisément son comportement ?”

Avec les grands modèles, on a tendance à chercher toujours plus de capacités.

Avec les SLM, on peut chercher autre chose :

moins de paramètres, moins de latence, moins de coût, plus de contrôle et une spécialisation beaucoup plus forte.

FunctionGemma est particulièrement intéressant pour explorer cette approche parce que Google fournit à la fois le modèle, des exemples de function calling, le dataset Mobile Actions, des recettes de fine-tuning et même un FunctionGemma Tuning Lab. Google Developers Blog+1

FunctionGemma 270M sur Hugging Face

FunctionGemma Tuning Lab


En résumé

Pour explorer sérieusement un SLM comme FunctionGemma, je partirais de cette boucle :

                 DATASETS
                    ↓
              OBSERVATION
                    ↓
              TEST GENERATION
                    ↓
               FUNCTIONGEMMA
                    ↓
                EVALUATION
                    ↓
              ERROR ANALYSIS
                    ↓
             DATASET AMÉLIORÉ
                    ↓
              FINE-TUNING
                    ↓
             REGRESSION TESTS
                    ↺

Le dataset devient le laboratoire.
Le prompt devient une variable expérimentale.
Le modèle devient un composant testable.
Et les erreurs deviennent de nouvelles données d’apprentissage.

C’est peut-être là que les SLM deviennent vraiment intéressants : non pas lorsqu’on essaie de leur faire faire tout ce qu’un LLM sait faire, mais lorsqu’on leur donne une mission très précise et qu’on apprend à mesurer, comprendre et maîtriser leurs frontières.

#AI #SLM #FunctionCalling #FunctionGemma #GoogleDeepMind #HuggingFace #LLM #GenAI #EdgeAI #OnDeviceAI #MachineLearning #AIEngineering #AgenticAI #MLOps #Testing #FineTuning