functiongemma.un.slm.specialise.dans.le.function.calling
Oui. Là, on tient un cas d’usage beaucoup plus parlant pour des développeurs : au lieu de faire un énième assistant météo/domotique, on fine-tune FunctionGemma pour devenir un mini-agent de bibliothèque de snippets/templates de code.
L’idée : le développeur écrit naturellement ce qu’il cherche, et le SLM sélectionne une fonction structurée dans notre bibliothèque.
🎯 Projet : SnippetGemma
On construit une petite bibliothèque de templates :
snippetgemma/
├── templates/
│ ├── python/
│ │ ├── requests.py
│ │ ├── fastapi.py
│ │ └── pytest.py
│ ├── javascript/
│ │ ├── fetch.js
│ │ └── express.js
│ └── docker/
│ └── dockerfile
│
├── dataset/
│ ├── train.jsonl
│ └── test.jsonl
│
├── evaluate.py
└── app.py
Le développeur peut demander :
“Donne-moi un endpoint FastAPI avec validation Pydantic.”
Le modèle ne génère pas directement le code.
Il appelle :
{
"name": "find_snippet",
"arguments": {
"language": "python",
"framework": "fastapi",
"topic": "validation_pydantic"
}
}
Notre application récupère alors le template.
Pourquoi utiliser FunctionGemma ?
Parce qu’on réduit énormément le problème.
Un LLM classique doit potentiellement :
comprendre
+
chercher
+
générer
+
formater
Notre FunctionGemma fait essentiellement :
demande développeur
↓
FunctionGemma 270M
↓
TOOL CALL
↓
snippet registry
↓
template/code
Le modèle devient donc une interface NLP ultra-légère au-dessus d’une bibliothèque déterministe.
Et c’est exactement le genre de tâche où un SLM spécialisé devient intéressant.
🧩 Notre API de snippets
On pourrait définir seulement 5 fonctions au départ.
TOOLS = [
{
"name": "find_snippet",
"description": "Find a code snippet matching the developer request",
"parameters": {
"language": "string",
"topic": "string",
"framework": "string"
}
},
{
"name": "list_snippets",
"description": "List available snippets",
"parameters": {
"language": "string"
}
},
{
"name": "get_snippet",
"description": "Get a specific snippet by identifier",
"parameters": {
"id": "string"
}
},
{
"name": "search_snippets",
"description": "Search snippets by keywords",
"parameters": {
"query": "string"
}
},
{
"name": "explain_snippet",
"description": "Explain how a snippet works",
"parameters": {
"id": "string"
}
}
]
Et là, on obtient quelque chose de très intéressant :
FunctionGemma devient le routeur intelligent de notre CLI développeur.
💻 Exemple réel
Le développeur tape :
snippet "pytest mock une requête HTTP"
FunctionGemma produit :
{
"name": "find_snippet",
"arguments": {
"language": "python",
"topic": "mock_http_request",
"framework": "pytest"
}
}
Notre registry renvoie :
from unittest.mock import patch
@patch("requests.get")
def test_api(mock_get):
mock_get.return_value.status_code = 200
response = requests.get(
"https://api.example.com/users"
)
assert response.status_code == 200
Le SLM n’a pas besoin de connaître tout le code.
Il doit savoir trouver le bon template.
🔥 Et c’est là que le fine-tuning devient amusant
On crée notre propre dataset.
Par exemple :
{
"prompt": "Comment mocker requests.get avec pytest ?",
"tool": "find_snippet",
"arguments": {
"language": "python",
"framework": "pytest",
"topic": "mock_http_request"
}
}
Mais on génère plusieurs formulations :
"pytest mock requests"
"Comment tester une API sans faire réellement la requête ?"
"Mocker un GET HTTP dans un test Python"
"Je veux remplacer requests.get pendant mes tests"
"Comment faire un mock HTTP avec pytest ?"
Toutes doivent converger vers :
find_snippet(...)
🧪 Et on peut créer des catégories
Python
FastAPI
pytest
asyncio
requests
pandas
SQLAlchemy
logging
typing
JavaScript
fetch
Express
React
Node
Vitest
Jest
TypeScript
DevOps
Dockerfile
docker-compose
GitHub Actions
Kubernetes
Git
rebase
cherry-pick
reset
branch
bisect
🧠 Là où le dataset devient vraiment intéressant
On peut volontairement créer des exemples où plusieurs snippets sont proches.
Par exemple :
pytest_mock_http
pytest_mock_database
pytest_mock_function
Prompt :
“Je veux mocker une fonction.”
→
pytest_mock_function
Prompt :
“Je veux mocker une requête HTTP.”
→
pytest_mock_http
Prompt :
“Je veux éviter d’interroger ma DB pendant mon test.”
→
pytest_mock_database
On teste alors la capacité du modèle à faire la distinction entre des outils sémantiquement proches.
🧨 Et surtout : les tests négatifs
On pourrait mettre :
"Explique-moi comment fonctionne pytest."
Résultat attendu :
NO TOOL
ou :
"Écris-moi une application complète en React."
Résultat :
NO TOOL
Parce que notre outil est une bibliothèque de snippets, pas un générateur de logiciels complets.
🧪 Notre benchmark devient très concret
On pourrait fabriquer automatiquement 500 requêtes :
100 recherche Python
100 recherche JavaScript
100 recherche DevOps
100 requêtes ambiguës
100 requêtes hors domaine
Puis :
FunctionGemma base
│
├── 500 tests
│
▼
score
puis :
FunctionGemma fine-tuned
│
├── mêmes 500 tests
│
▼
score
Et comparer :
| Test | Base | Fine-tuned |
|---|---|---|
| Tool selection | — | — |
| Language detection | — | — |
| Framework detection | — | — |
| Topic extraction | — | — |
| No-tool | — | — |
| Ambiguous | — | — |
| JSON validity | — | — |
Les cellules restent volontairement vides jusqu’à ce qu’on fasse tourner le benchmark : on mesure, plutôt que d’inventer un gain.
🚀 Et on peut en faire une vraie CLI
Quelque chose comme :
$ snip "fastapi endpoint avec pydantic"
🔎 Searching snippets...
python / fastapi / pydantic
┌───────────────────────────────────┐
│ fastapi_pydantic_endpoint │
│ Python · FastAPI · Pydantic │
└───────────────────────────────────┘
@app.post("/users")
async def create_user(
user: User
):
return user
Ou :
$ snip "dockeriser une app python"
→
docker/python_basic
Ou :
$ snip "github action pour lancer pytest"
→
github_actions_pytest
💡 Et là, je pousserais le concept un cran plus loin
La bibliothèque pourrait avoir des metadata structurées :
id: fastapi_pydantic_endpoint
language: python
framework: fastapi
tags:
- api
- rest
- pydantic
- validation
difficulty: beginner
version:
python: "3.12"
fastapi: "0.115"
Le SLM ne sélectionne donc pas seulement :
"du code"
mais :
intent
+
language
+
framework
+
topic
+
constraints
🔬 Et ça nous donne un excellent sujet d’expérimentation
On peut faire 4 versions du dataset.
Dataset V1 — minimal
prompt → tool
Dataset V2 — paramètres
prompt → tool + arguments
Dataset V3 — variantes linguistiques
10 formulations → même tool
Dataset V4 — adversarial
ambiguïtés
négations
hors domaine
outils concurrents
paramètres manquants
Puis fine-tuner successivement :
FunctionGemma
│
├── V1
├── V2
├── V3
└── V4
Et regarder ce que chaque ajout au dataset change réellement.
🏗️ Architecture finale
┌──────────────────────┐
│ Developer / CLI │
└──────────┬───────────┘
│
"mock requests avec pytest"
│
▼
┌──────────────────────┐
│ FunctionGemma 270M │
│ fine-tuned │
└──────────┬───────────┘
│
▼
Function Call
│
▼
┌──────────────────────┐
│ Snippet Registry │
├──────────────────────┤
│ Python │
│ JavaScript │
│ Docker │
│ GitHub Actions │
│ Git │
└──────────┬───────────┘
│
▼
Code Template
Et le truc particulièrement sympa : la bibliothèque peut être open source, tandis que le modèle reste un composant minuscule que chacun peut faire tourner localement.
Pour le Colab, je partirais donc sur ce projet plutôt que Mobile Actions : FunctionGemma 270M → fine-tuning → Developer Snippet Router → benchmark automatique.
C’est beaucoup plus facile à comprendre pour un développeur, tout en permettant de démontrer concrètement dataset → fine-tuning → function calling → évaluation → découverte des limites du SLM.