Function calling et structured outputs
Donner à Gemini une fonction qu'il peut appeler le transforme d'un générateur de texte en quelque chose qui peut lire votre agenda, interroger votre APIAPIApplication Programming Interface : une interface standardisée qui permet aux applications de communiquer et d'échanger des données sans connaître leur fonctionnement interne respectif.Voir la définition complète → de pricing ou requêter votre base de données, et récupérer du JSON propre signifie que votre code peut réellement exploiter le résultat sans bricolage à coups de regex. Ces deux capacités sont la colonne vertébrale de toute intégration Gemini sérieuse, et elles fonctionnent très différemment sous le capot. Voyons les deux en profondeur.
Le function calling est une négociation, pas une exécution
Le changement de perspective le plus important : Gemini n'exécute jamais votre fonction. Il décide seulement *qu'une* fonction doit être appelée et *avec quels arguments*. C'est vous qui exécutez le code. Vous renvoyez le résultat. Gemini continue.
Cet aller-retour, c'est la boucle de tool calling :
- Vous envoyez un prompt plus une liste de *déclarations* de fonctions (nom, description, paramètres).
- Gemini répond soit par du texte normal, soit par une part
functionCallcontenant la fonction choisie et les arguments. - Votre code exécute réellement cette fonction.
- Vous renvoyez le résultat sous forme de
functionResponse. - Gemini utilise le résultat pour produire sa réponse finale (ou appeler une autre fonction).
Le modèle fait de la reconnaissance d'intention structurée. Votre travail consiste à câbler l'exécution réelle et à continuer de réinjecter l'état dans la conversation.
Déclarer une fonction
Une déclaration de fonction est un schémamaUtiliser un logiciel pour automatiser les tâches et campagnes marketing répétitives, afin de personnaliser à grande échelle sur des canaux comme l'email, le web et le social.Voir la définition complète →. Gemini lit les champs description pour décider quand et comment l'appeler, donc traitez-les comme du prompt engineering, pas comme de la documentation. Des descriptions vagues produisent des appels erronés.
from google import genai
from google.genai import types
client = genai.Client()
get_weather = types.FunctionDeclaration(
name="get_weather",
description="Get the current temperature for a city. Use only when the user asks about weather.",
parameters={
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name, e.g. 'Lisbon'"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["city"],
},
)
weather_tool = types.Tool(function_declarations=[get_weather])Ceci utilise le Google Gen AI SDK unifié, la bibliothèque Python actuellement recommandée. Le même SDK cible à la fois l'API Gemini (via les clés AI Studio) et Vertex AI en changeant la configuration du client, vous n'écrivez donc la boucle qu'une fois.
Exécuter la boucle
Voici l'aller-retour complet avec un modèle Flash. Notez que le *résultat de la fonction* revient dans la conversation comme une nouvelle content part, pas comme du texte brut.
def get_weather_impl(city, unit="celsius"):
return {"city": city, "temp": 19, "unit": unit} # l'appel API réel se place ici
config = types.GenerateContentConfig(tools=[weather_tool])
contents = ["What's the weather in Lisbon right now?"]
resp = client.models.generate_content(
model="gemini-2.5-flash", contents=contents, config=config
)
part = resp.candidates[0].content.parts[0]
if part.function_call:
call = part.function_call
result = get_weather_impl(**call.args)
contents.append(resp.candidates[0].content) # l'appel du modèle
contents.append(types.Content(role="user", parts=[
types.Part.from_function_response(name=call.name, response=result)
]))
final = client.models.generate_content(
model="gemini-2.5-flash", contents=contents, config=config
)
print(final.text) # "It's 19°C in Lisbon right now."Les lignes clés sont les deux appels contents.append. Vous rejouez l'appel de fonction du modèle dans l'historique, puis vous ajoutez le résultat. Sautez le premier append et Gemini perd la trace de ce qu'il a demandé.
Laisser Gemini appeler plusieurs fonctions
Donnez-lui plus d'une déclaration et Gemini choisit la bonne, ou en demande plusieurs. Le parallel function calling, c'est quand une seule réponse contient plusieurs parts functionCall (par exemple « compare la météo à Lisbonne et Madrid » produit deux appels d'un coup). Bouclez sur resp.candidates[0].content.parts, exécutez chacun, et ajoutez toutes les réponses ensemble avant le tour suivant.
Vous pouvez aussi contraindre le comportement avec tool_config. Régler le mode de function calling sur ANY force Gemini à appeler une fonction plutôt que de répondre en prose, ce qui est utile quand un appel d'outil est le seul résultat acceptable :
config = types.GenerateContentConfig(
tools=[weather_tool],
tool_config=types.ToolConfig(
function_calling_config=types.FunctionCallingConfig(mode="ANY")
),
)Les modes sont AUTO (par défaut, le modèle décide), ANY (doit appeler quelque chose) et NONE (n'appelle jamais). Utilisez `ANY` avec une liste `allowed_function_names` pour cantonner le modèle à un sous-ensemble précis.
Structured outputs : quand vous voulez des données, pas un outil
Le function calling sert à *agir*. Le structured output sert à *extraire*. Si vous voulez simplement que Gemini renvoie du JSON propre et parsable, ne le simulez pas avec un outil. Utilisez la fonctionnalité de response schema, qui contraint le décodage du modèle pour que la sortie corresponde à coup sûr à votre schéma.
C'est du constrained decoding : Gemini est restreint au moment de la génération à ne produire que des tokenstokensUn token est l'unité de base de texte que traitent les modèles de langage : le plus souvent un fragment de mot, un mot entier ou un signe de ponctuation, plutôt qu'un simple caractère.Voir la définition complète → qui maintiennent la sortie valide vis-à-vis de votre schéma. Vous n'espérez pas du JSON. Vous l'obtenez.
from pydantic import BaseModel
class Invoice(BaseModel):
vendor: str
total: float
currency: str
line_items: list[str]
resp = client.models.generate_content(
model="gemini-2.5-flash",
contents="Extract the invoice details from this email: ...",
config=types.GenerateContentConfig(
response_mime_type="application/json",
response_schema=Invoice,
),
)
invoice = Invoice.model_validate_json(resp.text)
print(invoice.total, invoice.currency)Passer un modèle Pydantic comme response_schema est la voie idiomatique : le SDK le convertit en schéma, Gemini le respecte, et vous validez directement en objets typés. Pas de prompt qui supplie « ne renvoie que du JSON ». Pas de blocs markdown parasites à nettoyer.
Quand le schéma est dynamique
Si votre structure est décidée à l'exécution, passez un dict de schéma brut plutôt qu'une classe Pydantic. Utilisez propertyOrdering pour figer l'ordre des champs, car l'ordre peut affecter la qualité sur des extractions complexes :
schema = {
"type": "object",
"properties": {
"sentiment": {"type": "string", "enum": ["positive", "neutral", "negative"]},
"topics": {"type": "array", "items": {"type": "string"}},
},
"required": ["sentiment", "topics"],
"propertyOrdering": ["sentiment", "topics"],
}Pour la classification en particulier, il existe aussi response_mime_type="text/x.enum" avec un schéma enum, qui force la réponse à être exactement l'un de vos labels et rien d'autre. C'est la manière la plus propre de faire de la classification mono-label.
Choisir entre les deux
Ils se recoupent, soyez donc délibéré :
- Structured output quand vous maîtrisez toute l'interaction et voulez juste des données parsées en retour d'un seul appel. Plus rapide, plus simple, forme garantie.
- Function calling quand Gemini doit aller chercher *à l'extérieur* de lui-même : données live, vos APIs, effets de bord, raisonnement multi-étapes où chaque étape dépend de résultats réels.
Un pattern courant combine les deux : un appel de fonction récupère des données réelles, puis une étape de génération finale les renvoie via un response schema pour que votre code en aval reste typé.
Ne réinventez pas ce que la plateforme fournit
Certaines « fonctions » existent déjà comme outils intégrés. Le grounding avec Google Search, le code execution et l'URL context sont des outils natifs que vous activez dans la config plutôt que d'implémenter vous-même. Si vous avez besoin de faits récents, activez le Search grounding au lieu d'écrire votre propre fonction de recherche :
config = types.GenerateContentConfig(
tools=[types.Tool(google_search=types.GoogleSearch())]
)Vous ne pouvez pas librement mélanger certains outils intégrés avec vos propres déclarations de fonctions dans un même appel, et les règles diffèrent entre l'API Gemini et Vertex AI : vérifiez l'outil dont vous avez besoin avant de combiner.
Function Calling with the Gemini API
Vérification des acquis
1. Quelle est la distinction conceptuelle la plus importante sur la façon dont Gemini gère le function calling ?
2. Pourquoi la leçon dit-elle que les champs `description` de la fonction doivent être traités comme du prompt engineering plutôt que comme de la documentation ?
3. Dans la boucle de tool calling, qu'est-ce que votre code renvoie à Gemini après avoir réellement exécuté la fonction choisie ?
4. Sélectionnez TOUTES les affirmations correctes sur la boucle de tool calling et les déclarations de fonctions.
Sélectionnez toutes les réponses correctes.
5. Sélectionnez TOUTES les affirmations correctes sur les bénéfices et la conception du function calling et des structured outputs décrits dans la leçon.
Sélectionnez toutes les réponses correctes.
Prototypez dans AI Studio, puis passez à l'échelle correctement
Avant d'écrire la moindre boucle, construisez la déclaration de fonction visuellement dans Google AI Studio. Vous pouvez définir des outils, voir Gemini émettre des parts functionCall, et copier du code fonctionnel dans votre langage. C'est le moyen le plus rapide d'ajuster ces fameuses chaînes description.
Quand vous passez en production, la décision porte sur *l'endroit* où tourne la boucle :
- API Gemini (ai.google.dev) pour des backends d'applications et des services rapides. Le code SDK ci-dessus suffit.
- Vertex AI quand vous avez besoin de contrôles entreprise : IAM, VPC, résidence des donnéesrésidence des donnéesL'exigence de stocker et traiter les données physiquement dans un pays ou une région précise, souvent pour des raisons légales ou contractuelles.Voir la définition complète → et déploiement managé. Même SDK, init du client différente.
- Agent Development Kit (ADK) quand un modèle avec une poignée d'outils devient un véritable agent doté de planification, de mémoire et de nombreux outils. ADK vous fournit la boucle, l'état et l'orchestration d'outils sous forme de framework, ce qui vous évite d'écrire à la main la tuyauterie d'ajout de réponses. Voir la documentation ADK pour l'approche agent-first.
Pour de l'automatisation Workspace interne, vous n'avez pas toujours besoin de tout cela. Apps Script peut appeler Gemini et agir directement sur Docs, Sheets ou Gmail, ce qui est souvent le chemin le plus court vers un outil fonctionnel dans Google Workspace.
Détails durement acquis qui vous feront gagner des heures
Les descriptions sont des prompts. La précision de Gemini pour choisir et remplir les fonctions suit presque entièrement la qualité de vos champs description et de la documentation des paramètres. Explicitez *quand* utiliser une fonction et *quand ne pas* l'utiliser.
Validez chaque argument. Gemini remplit les arguments à partir d'un schéma, mais il peut quand même halluciner une valeur plausible mais fausse, surtout pour des IDs ou des enums dont il se souvient à moitié. Traitez les arguments de fonction comme une entrée utilisateur non fiable. Validez avant d'exécuter quoi que ce soit ayant des effets de bord.
Utilisez `required` et `enum` de façon agressive. Chaque contrainte que vous placez dans le schéma est une contrainte que le modèle doit satisfaire. Les enums éliminent des classes entières de valeurs parasites. Les champs requis empêchent les appels à moitié remplis.
Choisissez le tier par tâche. Flash gère la grande majorité du routage d'outils et de l'extraction avec une latence et un coût faibles. Passez à Pro quand la décision sur *quel* outil appeler demande un vrai raisonnement sur un long contexte, ou quand l'extraction dépend d'une logique subtile multi-documents.
Renvoyez toujours les résultats de fonction. Le bug le plus fréquent est d'oublier d'ajouter l'appel de fonction du modèle avant la réponse. Sans cela, l'historique de conversation est incohérent et la réponse finale dérive.
Points clés à retenir
- Vous exécutez, Gemini décide. La boucle de tool calling, c'est : déclarer les fonctions, recevoir un
functionCall, l'exécuter vous-même, ajouter à la fois l'appel et lefunctionResponse, puis générer la réponse finale. - Utilisez `response_schema` avec un modèle Pydantic pour obtenir du JSON valide garanti via le constrained decoding. ArrArrL'Annual Recurring Revenue (ARR) est le revenu normalisé et prévisible qu'une entreprise par abonnement attend de ses contrats actifs sur une année.Voir la définition complète →êtez de demander du JSON par prompt et de nettoyer des blocs markdown.
- Agir vs extraire : le function calling va chercher hors du modèle des données live et des effets de bord ; le structured output parse des données à partir d'un seul appel. Combinez-les quand vous récupérez des données réelles, puis les renvoyez typées.
- Investissez dans les champs `description`, les enums et `required`. La précision des outils tient surtout à la qualité du schéma, et chaque contrainte en est une que le modèle doit satisfaire.
- Prototypez dans AI Studio, puis passez à l'API Gemini, Vertex AI ou ADK selon que vous avez besoin d'échelle, de contrôles entreprise ou d'une orchestration d'agent complète, et validez toujours les arguments de fonction avant d'agir dessus.