Introduction au Function Calling

10 min Debutant

Objectifs

  • Comprendre le concept de Function Calling (Tool Use)
  • Maitriser le flux model -> function_call -> function_result -> model
  • Connaitre les modes AUTO, ANY, NONE
  • Definir des fonctions avec JSON Schema

Qu'est-ce que le Function Calling ?

Le Function Calling permet a Gemini de generer des appels de fonctions structures plutot que du texte. Le modele ne execute PAS les fonctions lui-meme - il produit un JSON decrivant quelle fonction appeler et avec quels arguments. C'est votre code qui execute la fonction et renvoie le resultat.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ FLUX FUNCTION CALLING ────────────────────┐
β”‚                                                                β”‚
β”‚  1. REQUETE                    2. REPONSE MODEL                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚
β”‚  β”‚ User: "Quel β”‚   ──────►   β”‚ function_call:   β”‚            β”‚
β”‚  β”‚ temps fait-ilβ”‚              β”‚  name: get_meteo β”‚            β”‚
β”‚  β”‚ a Paris ?"  β”‚              β”‚  args: {         β”‚            β”‚
β”‚  β”‚             β”‚              β”‚   city: "Paris"  β”‚            β”‚
β”‚  β”‚ + tools:    β”‚              β”‚  }               β”‚            β”‚
β”‚  β”‚  [get_meteo]β”‚              β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜            β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                       β”‚                       β”‚
β”‚                                        β–Ό                       β”‚
β”‚  4. REPONSE FINALE             3. VOTRE CODE EXECUTE          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚
β”‚  β”‚ "Il fait 12Β°C   β”‚  ◄────  β”‚ function_response:β”‚            β”‚
β”‚  β”‚  a Paris avec   β”‚          β”‚  result: {       β”‚            β”‚
β”‚  β”‚  un ciel couvertβ”‚          β”‚   temp: 12,      β”‚            β”‚
β”‚  β”‚  et du vent."   β”‚          β”‚   cond: "nuageux"β”‚            β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚  }               β”‚            β”‚
β”‚                                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Definir une fonction

Python
from google import genai
from google.genai import types

# Definir la fonction avec JSON Schema
get_weather = types.FunctionDeclaration(
    name="get_current_weather",
    description="Obtient la meteo actuelle d'une ville donnee",
    parameters=types.Schema(
        type="OBJECT",
        properties={
            "location": types.Schema(
                type="STRING",
                description="Nom de la ville, ex: 'Paris, France'"
            ),
            "unit": types.Schema(
                type="STRING",
                enum=["celsius", "fahrenheit"],
                description="Unite de temperature"
            )
        },
        required=["location"]
    )
)

# Creer l'outil
weather_tool = types.Tool(function_declarations=[get_weather])

Les 3 modes de function calling

ModeComportementCas d'usage
AUTO (defaut)Le modele decide s'il appelle une fonction ou repond en texteUsage general, conversations mixtes
ANYLe modele est FORCE d'appeler une des fonctionsPipelines structures, routing obligatoire
NONEFunction calling desactive, reponse texte uniquementDesactiver temporairement les outils
Python
# Configurer le mode
config = types.GenerateContentConfig(
    tools=[weather_tool],
    tool_config=types.ToolConfig(
        function_calling_config=types.FunctionCallingConfig(
            mode="ANY",  # Force l'appel de fonction
            allowed_function_names=["get_current_weather"]
        )
    )
)

Le function calling est le pont entre l'IA et le monde reel. C'est la capacite la plus importante pour construire des applications utiles. Sans function calling, Gemini est un cerveau sans bras. Avec, il peut interroger des APIs, lire des bases de donnees, envoyer des emails - tout ce que votre code peut faire.

Function Calling en pratique

12 min Intermediaire

Objectifs

  • Implementer un flux function calling complet
  • Gerer le parallel function calling
  • Implementer le compositional calling (chaine)
  • Gerer les erreurs de function calling

Flux complet avec le SDK

Python
from google import genai
from google.genai import types
import json

client = genai.Client(api_key="VOTRE_CLE_API")

# 1. Definir les fonctions
get_weather = types.FunctionDeclaration(
    name="get_weather",
    description="Obtient la meteo d'une ville",
    parameters=types.Schema(
        type="OBJECT",
        properties={
            "city": types.Schema(type="STRING", description="Nom de la ville")
        },
        required=["city"]
    )
)

get_time = types.FunctionDeclaration(
    name="get_time",
    description="Obtient l'heure actuelle dans un fuseau horaire",
    parameters=types.Schema(
        type="OBJECT",
        properties={
            "timezone": types.Schema(type="STRING", description="ex: Europe/Paris")
        },
        required=["timezone"]
    )
)

tools = types.Tool(function_declarations=[get_weather, get_time])

# 2. Fonctions reelles
def execute_function(name, args):
    if name == "get_weather":
        # Simuler un appel API meteo
        return {"temp": 14, "condition": "ensoleille", "wind": "12 km/h"}
    elif name == "get_time":
        from datetime import datetime
        return {"time": datetime.now().strftime("%H:%M"), "timezone": args["timezone"]}

# 3. Boucle function calling
def chat_with_tools(user_message):
    messages = [types.Content(role="user", parts=[types.Part(text=user_message)])]

    while True:
        response = client.models.generate_content(
            model="gemini-2.5-flash",
            contents=messages,
            config=types.GenerateContentConfig(tools=[tools])
        )

        # Verifier s'il y a des function calls
        candidate = response.candidates[0]
        has_function_calls = any(
            part.function_call for part in candidate.content.parts
        )

        if not has_function_calls:
            return response.text  # Reponse finale texte

        # Executer toutes les fonctions (parallel calling)
        messages.append(candidate.content)
        function_responses = []
        for part in candidate.content.parts:
            if part.function_call:
                result = execute_function(
                    part.function_call.name,
                    dict(part.function_call.args)
                )
                function_responses.append(
                    types.Part(function_response=types.FunctionResponse(
                        name=part.function_call.name,
                        response=result
                    ))
                )

        messages.append(types.Content(parts=function_responses))

# 4. Test
print(chat_with_tools("Quelle meteo et quelle heure a Paris ?"))
# -> Gemini appelle get_weather ET get_time en parallele !

Parallel Function Calling

Gemini peut retourner plusieurs function_call dans une seule reponse. Par exemple, "Quelle meteo a Paris et a Londres ?" genere 2 appels get_weather simultanement. Votre code doit gerer ce cas en iterant sur toutes les parts.

Compositional Calling (chaine)

Avec Gemini 2.5+ et 3, le modele peut enchainer les fonctions automatiquement. Par exemple : "Quelle meteo dans ma ville ?" -> appelle d'abord get_location(), puis get_weather(city=result).

La boucle while True avec verification des function calls est le pattern fondamental. Memorisez-le. 90% des applications agents suivent ce pattern : envoyer -> verifier si function call -> executer -> renvoyer le resultat -> repeter jusqu'a reponse texte finale.

Code Execution Tool

10 min Intermediaire

Objectifs

  • Activer le Code Execution Tool
  • Comprendre l'environnement sandbox
  • Combiner code execution avec du texte
  • Connaitre les limites et libraries disponibles

Activer le Code Execution

Python
from google import genai
from google.genai import types

client = genai.Client(api_key="VOTRE_CLE_API")

response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="Calcule les 20 premiers nombres de Fibonacci "
             "et trace un graphique de leur croissance.",
    config=types.GenerateContentConfig(
        tools=[types.Tool(code_execution=types.CodeExecution())]
    )
)

# La reponse contient le code execute ET le resultat
for part in response.candidates[0].content.parts:
    if part.executable_code:
        print(f"CODE:\n{part.executable_code.code}")
    if part.code_execution_result:
        print(f"RESULTAT:\n{part.code_execution_result.output}")
    if part.text:
        print(f"TEXTE:\n{part.text}")

Libraries disponibles dans le sandbox

LibraryUsage
NumPyCalcul numerique, matrices, algebre lineaire
pandasManipulation de donnees, DataFrames
matplotlibVisualisation, graphiques
math, statisticsFonctions mathematiques standard
datetime, json, reUtilitaires Python standard
Limites du sandbox

Pas d'acces reseau (pas de requests, urllib). Pas de pip install. Pas d'acces au systeme de fichiers. Pas de libraries custom. Le code est execute dans un environnement isole et securise cote Google.

Le Code Execution est ideal pour : calculs mathematiques precis, generation de graphiques, transformation de donnees, validation d'hypotheses. Ne l'utilisez pas pour des taches qui necessitent des APIs externes - utilisez le function calling pour ca.

Google Search Tool (API)

10 min Intermediaire

Objectifs

  • Utiliser le grounding Google Search programmatiquement
  • Exploiter les groundingMetadata et citations
  • Comprendre le Dynamic Retrieval
  • Evaluer le cout ($35/1K requetes)

Activation via API

Python
from google import genai
from google.genai import types

client = genai.Client(api_key="VOTRE_CLE_API")

response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="Quels sont les derniers modeles Gemini sortis en 2026 "
             "et leurs performances sur les benchmarks ?",
    config=types.GenerateContentConfig(
        tools=[types.Tool(google_search=types.GoogleSearch())]
    )
)

print(response.text)

# Acceder aux sources et citations
grounding = response.candidates[0].grounding_metadata
if grounding:
    print("\n--- SOURCES ---")
    if grounding.grounding_chunks:
        for chunk in grounding.grounding_chunks:
            if chunk.web:
                print(f"  [{chunk.web.title}]({chunk.web.uri})")

    # Requetes de recherche utilisees par le modele
    if grounding.web_search_queries:
        print("\n--- REQUETES ---")
        for query in grounding.web_search_queries:
            print(f"  - {query}")

Quand utiliser le Search Grounding

Utiliser SearchNe PAS utiliser Search
Questions factuelles sur l'actualiteRaisonnement logique/math
Verification de faitsGeneration creative
Donnees en temps reel (prix, cours, meteo)Analyse de documents internes
Recherche technique a jourConversations generales
Pricing

Google Search Grounding : $35 par 1 000 requetes via API. Gratuit dans AI Studio pour les tests. En production, filtrez les requetes qui necessitent vraiment le grounding pour maitriser les couts.

URL Context Tool

8 min Intermediaire

Objectifs

  • Extraire du contenu depuis des URLs avec Gemini
  • Combiner URL Context avec Structured Output
  • Cas d'usage : scraping intelligent, analyse de pages

URL Context en action

Python
from google import genai
from google.genai import types

client = genai.Client(api_key="VOTRE_CLE_API")

# Gemini 3 supporte l'URL Context comme outil integre
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="Analyse la page https://ai.google.dev/gemini-api/docs/pricing "
             "et extrais un tableau comparatif des prix par modele.",
    config=types.GenerateContentConfig(
        tools=[types.Tool(url_context=types.UrlContext())],
        response_mime_type="application/json",
        response_schema={
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "model": {"type": "string"},
                    "input_price": {"type": "string"},
                    "output_price": {"type": "string"},
                    "context_window": {"type": "string"}
                }
            }
        }
    )
)

import json
data = json.loads(response.text)
for model in data:
    print(f"{model['model']}: {model['input_price']} / {model['output_price']}")

L'URL Context combine le meilleur du scraping web et de l'extraction IA. Avec le structured output, vous obtenez des donnees propres et structurees depuis n'importe quelle page web. C'est un outil puissant pour le competitive intelligence, la veille technologique et l'enrichissement de donnees.

Combinaison multi-outils

10 min Avance

Objectifs

  • Combiner Search + Code Execution + Function Calling
  • Comprendre les priorites et l'orchestration
  • Patterns multi-outils avances

Combiner tous les outils

Python
from google import genai
from google.genai import types

client = genai.Client(api_key="VOTRE_CLE_API")

# Fonction custom
save_report = types.FunctionDeclaration(
    name="save_report",
    description="Sauvegarde un rapport d'analyse dans le systeme",
    parameters=types.Schema(
        type="OBJECT",
        properties={
            "title": types.Schema(type="STRING"),
            "content": types.Schema(type="STRING"),
            "format": types.Schema(type="STRING", enum=["pdf", "html", "md"])
        },
        required=["title", "content"]
    )
)

# Combiner : Search + Code Execution + Custom Function
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="Recherche les dernieres stats d'adoption de Kubernetes en 2026, "
             "calcule les tendances de croissance avec un graphique, "
             "puis sauvegarde le rapport en PDF.",
    config=types.GenerateContentConfig(
        tools=[
            types.Tool(google_search=types.GoogleSearch()),
            types.Tool(code_execution=types.CodeExecution()),
            types.Tool(function_declarations=[save_report])
        ]
    )
)
# Gemini orchestre automatiquement :
# 1. Google Search -> donnees actuelles
# 2. Code Execution -> calcul + graphique
# 3. save_report() -> sauvegarde du resultat
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ ORCHESTRATION MULTI-OUTILS ───────────┐
β”‚                                                    β”‚
β”‚  User: "Analyse + Calcule + Sauvegarde"           β”‚
β”‚              β”‚                                     β”‚
β”‚              β–Ό                                     β”‚
β”‚  β”Œβ”€β”€β”€ Gemini decide l'ordre ───┐                  β”‚
β”‚  β”‚                              β”‚                  β”‚
β”‚  β”‚  1. Google Search           β”‚                  β”‚
β”‚  β”‚     -> donnees fraiches      β”‚                  β”‚
β”‚  β”‚                              β”‚                  β”‚
β”‚  β”‚  2. Code Execution          β”‚                  β”‚
β”‚  β”‚     -> calcul + graphique    β”‚                  β”‚
β”‚  β”‚                              β”‚                  β”‚
β”‚  β”‚  3. Function Call           β”‚                  β”‚
β”‚  β”‚     -> save_report(...)      β”‚                  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                  β”‚
β”‚              β”‚                                     β”‚
β”‚              β–Ό                                     β”‚
β”‚  Reponse finale avec resume                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Gemini 3 : Structured Output + Tools

Nouveaute Gemini 3 : vous pouvez combiner Structured Output (response_schema) avec les outils integres. Le modele utilise Search/Code Execution et formate le resultat en JSON conforme a votre schema.

Lab : Agent meteo & actualites

20 min Pratique

Objectif : Agent conversationnel avec function calling + Google Search

Etape 1 : Definir les outils

Python
import os, json, requests
from google import genai
from google.genai import types

client = genai.Client(api_key=os.environ["GOOGLE_API_KEY"])

# Outil meteo (simule)
get_weather_fn = types.FunctionDeclaration(
    name="get_weather",
    description="Obtient la meteo actuelle pour une ville",
    parameters=types.Schema(
        type="OBJECT",
        properties={
            "city": types.Schema(type="STRING"),
            "country": types.Schema(type="STRING", description="Code pays ISO")
        },
        required=["city"]
    )
)

# Outil conversion
convert_unit_fn = types.FunctionDeclaration(
    name="convert_temperature",
    description="Convertit une temperature entre Celsius et Fahrenheit",
    parameters=types.Schema(
        type="OBJECT",
        properties={
            "value": types.Schema(type="NUMBER"),
            "from_unit": types.Schema(type="STRING", enum=["celsius", "fahrenheit"]),
            "to_unit": types.Schema(type="STRING", enum=["celsius", "fahrenheit"])
        },
        required=["value", "from_unit", "to_unit"]
    )
)

custom_tools = types.Tool(function_declarations=[get_weather_fn, convert_unit_fn])

Etape 2 : Implementer les fonctions

Python
def execute(name, args):
    if name == "get_weather":
        # Simuler une API meteo
        meteo_db = {
            "paris": {"temp": 14, "condition": "Nuageux", "humidity": 72, "wind": "15 km/h"},
            "london": {"temp": 9, "condition": "Pluvieux", "humidity": 85, "wind": "22 km/h"},
            "tokyo": {"temp": 18, "condition": "Ensoleille", "humidity": 55, "wind": "8 km/h"},
        }
        city = args["city"].lower()
        return meteo_db.get(city, {"error": f"Ville '{args['city']}' non trouvee"})

    elif name == "convert_temperature":
        v = args["value"]
        if args["from_unit"] == "celsius" and args["to_unit"] == "fahrenheit":
            return {"result": round(v * 9/5 + 32, 1), "unit": "fahrenheit"}
        elif args["from_unit"] == "fahrenheit" and args["to_unit"] == "celsius":
            return {"result": round((v - 32) * 5/9, 1), "unit": "celsius"}
        return {"result": v, "unit": args["to_unit"]}

Etape 3 : Boucle agent conversationnel

Python
SYSTEM = """Tu es un assistant meteo et actualites. Tu utilises tes outils pour:
- get_weather: obtenir la meteo d'une ville
- convert_temperature: convertir des temperatures
- Google Search: rechercher des actualites
Tu reponds toujours en francais de maniere claire et concise."""

def agent_loop(user_msg, history):
    history.append(types.Content(role="user", parts=[types.Part(text=user_msg)]))

    while True:
        response = client.models.generate_content(
            model="gemini-2.5-flash",
            contents=history,
            config=types.GenerateContentConfig(
                system_instruction=SYSTEM,
                tools=[
                    custom_tools,
                    types.Tool(google_search=types.GoogleSearch())
                ]
            )
        )
        candidate = response.candidates[0]
        history.append(candidate.content)

        fn_calls = [p for p in candidate.content.parts if p.function_call]
        if not fn_calls:
            return response.text

        responses = []
        for part in fn_calls:
            result = execute(part.function_call.name, dict(part.function_call.args))
            responses.append(types.Part(function_response=types.FunctionResponse(
                name=part.function_call.name, response=result
            )))
        history.append(types.Content(parts=responses))

# Test
history = []
print(agent_loop("Quel temps fait-il a Paris et Tokyo ?", history))
print(agent_loop("Convertis la temperature de Tokyo en Fahrenheit", history))
print(agent_loop("Quelles sont les actualites tech du jour ?", history))

Quiz - Module 2.1 : Function Calling & Tools

10 min Evaluation

Testez vos connaissances

1. En mode ANY, que fait le modele ?

2. Qui execute reellement les fonctions dans le function calling ?

3. Quelles libraries sont disponibles dans le Code Execution sandbox ?

4. Combien coute le Google Search Grounding via API ?

5. Que permet le compositional function calling de Gemini 2.5+ ?

Introduction aux agents IA Google

10 min Intermediaire

Objectifs

  • Comprendre le paradigme agent : perceive-reason-act
  • Decouvrir l'ecosysteme Google pour les agents
  • Differencier chatbot, agent et systeme multi-agents
  • Connaitre Agent Builder, ADK et Agent Engine

Qu'est-ce qu'un Agent IA ?

Un agent IA est un systeme autonome qui percoit son environnement, raisonne sur les actions a entreprendre, et agit en utilisant des outils pour atteindre un objectif. Contrairement a un chatbot qui se contente de repondre a des questions, un agent peut planifier, executer des actions, et s'adapter en fonction des resultats.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ BOUCLE AGENT ──────────────────┐
β”‚                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚   β”‚ PERCEVOIR │───►│ RAISONNER │───►│   AGIR   β”‚  β”‚
β”‚   β”‚           β”‚    β”‚           β”‚    β”‚          β”‚  β”‚
β”‚   β”‚ - Input   β”‚    β”‚ - Gemini  β”‚    β”‚ - Tools  β”‚  β”‚
β”‚   β”‚ - Context β”‚    β”‚ - Planningβ”‚    β”‚ - APIs   β”‚  β”‚
β”‚   β”‚ - Memory  β”‚    β”‚ - Decisionβ”‚    β”‚ - Search β”‚  β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β”‚
β”‚        β–²                                  β”‚        β”‚
β”‚        β”‚         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚        β”‚
β”‚        └─────────│ OBSERVER  β”‚β—„β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                  β”‚ le result β”‚                     β”‚
β”‚                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

L'ecosysteme Google pour les Agents

Google propose une stack complete pour construire des agents, du framework open-source jusqu'au deploiement enterprise :

ComposantDescriptionUsage
ADKAgent Development Kit - Framework open-source PythonDeveloppement local d'agents
Agent BuilderInterface visuelle dans Vertex AICreation no-code/low-code
Agent EngineRuntime manage pour deployer des agentsProduction et scaling
AgentspaceHub enterprise pour les agentsPartage et decouverte d'agents

Chatbot vs Agent vs Multi-Agent

CaracteristiqueChatbotAgentMulti-Agent
OutilsAucunFunction calling, search, codeOutils specialises par agent
MemoireContexte de sessionSessions + Memory BankMemoire partagee entre agents
AutonomieRepond aux questionsPlanifie et executeDelegation et collaboration
ComplexiteFaibleMoyenneElevee

En 2026, la tendance est claire : on passe du chatbot a l'agent. Google a investi massivement dans ADK et Agent Builder. Mon conseil ? Commencez par un agent simple avec ADK, puis evoluez vers le multi-agents quand le besoin se presente. Ne sur-architecturez pas des le depart.

Vertex AI Agent Builder
Agent Builder = Agent Designer (interface visuelle) + ADK (framework code) + Agent Engine (runtime de deploiement). C'est la solution complete de Google pour l'enterprise.

Agent Development Kit (ADK)

15 min Intermediaire

Objectifs

  • Installer et configurer ADK
  • Creer un agent avec LlmAgent
  • Definir des outils custom (FunctionTool)
  • Tester un agent avec adk web

Installation et Setup

ADK (Agent Development Kit) est le framework open-source de Google pour construire des agents IA. Il fournit une structure claire pour definir des agents, leurs outils, leur memoire et leur orchestration.

Bash
# Installation
pip install google-adk

# Structure de projet recommandee
my_agent/
β”œβ”€β”€ __init__.py
β”œβ”€β”€ agent.py          # Definition de l'agent
β”œβ”€β”€ tools.py          # Outils custom
└── .env              # GOOGLE_API_KEY=...

Premier Agent avec LlmAgent

Python
from google.adk.agents import LlmAgent
from google.adk.tools import FunctionTool, google_search

# Definir un outil custom
def get_current_time(timezone: str = "UTC") -> dict:
    """Retourne l'heure actuelle dans le fuseau horaire donne."""
    from datetime import datetime
    import pytz
    tz = pytz.timezone(timezone)
    now = datetime.now(tz)
    return {"time": now.strftime("%H:%M:%S"), "timezone": timezone}

# Creer l'agent
agent = LlmAgent(
    name="assistant_agent",
    model="gemini-2.5-flash",
    instruction="""Tu es un assistant intelligent.
    Utilise tes outils pour repondre aux questions.
    Sois precis et concis dans tes reponses.""",
    tools=[
        FunctionTool(get_current_time),
        google_search,  # Outil built-in
    ],
)

Lancer l'agent en local

Bash
# Lancer l'interface de test web
adk web

# Ou executer directement en Python
adk run my_agent
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ ARCHITECTURE ADK ──────────────┐
β”‚                                              β”‚
β”‚  LlmAgent                                   β”‚
β”‚  β”œβ”€β”€ name: "assistant_agent"                β”‚
β”‚  β”œβ”€β”€ model: "gemini-2.5-flash"              β”‚
β”‚  β”œβ”€β”€ instruction: "Tu es un..."             β”‚
β”‚  β”œβ”€β”€ tools:                                  β”‚
β”‚  β”‚   β”œβ”€β”€ FunctionTool(get_current_time)     β”‚
β”‚  β”‚   β”œβ”€β”€ google_search                       β”‚
β”‚  β”‚   └── code_execution                     β”‚
β”‚  β”œβ”€β”€ sub_agents: []                          β”‚
β”‚  └── callbacks:                              β”‚
β”‚      β”œβ”€β”€ before_tool_callback                β”‚
β”‚      └── after_model_callback                β”‚
β”‚                                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Types d'outils ADK

TypeImportUsage
FunctionToolfrom google.adk.tools import FunctionToolWrapper pour vos fonctions Python
google_searchfrom google.adk.tools import google_searchRecherche Google integree
code_executionfrom google.adk.tools import code_executionSandbox Python du modele
AgentToolfrom google.adk.tools import AgentToolEncapsule un agent comme outil

ADK est le futur du developpement d'agents chez Google. La commande adk web lance une interface de test locale tres pratique pour debugger vos agents. Utilisez-la systematiquement pendant le developpement avant de deployer sur Agent Engine.

Sessions & Memory Bank

12 min Intermediaire

Objectifs

  • Gerer la memoire court terme avec les Sessions
  • Utiliser InMemorySessionService et DatabaseSessionService
  • Implementer la memoire long terme avec Memory Bank
  • Persister le contexte entre les interactions

Sessions : Memoire Court Terme

Les Sessions dans ADK gerent la memoire d'une conversation en cours. Chaque session contient l'historique des messages et un state (dictionnaire) pour stocker des variables persistantes pendant la conversation.

Python
from google.adk.sessions import InMemorySessionService

# Service de sessions en memoire (dev/test)
session_service = InMemorySessionService()

# Creer une session
session = await session_service.create_session(
    app_name="my_agent",
    user_id="user_123",
)

# Acceder au state de la session
session.state["user_preferences"] = {"language": "fr", "theme": "dark"}
session.state["interaction_count"] = 0

print(f"Session ID: {session.id}")
print(f"State: {session.state}")

Persistence avec DatabaseSessionService

Python
from google.adk.sessions import DatabaseSessionService

# Session persistante en base de donnees
session_service = DatabaseSessionService(
    db_url="sqlite:///sessions.db"
    # Ou PostgreSQL: "postgresql://user:pass@host/db"
)

# Les sessions survivent aux redemarrages
session = await session_service.get_session(
    app_name="my_agent",
    user_id="user_123",
    session_id="existing_session_id"
)

Memory Bank : Memoire Long Terme

Le Memory Bank (GA en 2026) va au-dela des sessions. Il stocke des informations a long terme entre les sessions, permettant a l'agent de "se souvenir" d'interactions passees.

Python
from google.adk.memory import InMemoryMemoryService

# Service de memoire long terme
memory_service = InMemoryMemoryService()

# L'agent avec memoire
agent = LlmAgent(
    name="memory_agent",
    model="gemini-2.5-flash",
    instruction="Tu te souviens des preferences de l'utilisateur.",
    tools=[google_search],
)

# Executer avec session + memoire
from google.adk.runners import Runner

runner = Runner(
    agent=agent,
    app_name="my_agent",
    session_service=session_service,
    memory_service=memory_service,
)

# Le runner gere automatiquement la memoire
response = await runner.run(
    user_id="user_123",
    session_id=session.id,
    new_message="Rappelle-toi que j'aime le Python"
)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ MEMOIRE ADK ────────────────┐
β”‚                                           β”‚
β”‚  SESSION (court terme)                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚  β”‚ Messages: [user, model, ...]    β”‚     β”‚
β”‚  β”‚ State: {prefs: {}, count: 3}    β”‚     β”‚
β”‚  β”‚ TTL: duree de la conversation   β”‚     β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β”‚                                           β”‚
β”‚  MEMORY BANK (long terme)                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚  β”‚ Faits: "Aime Python et FastAPI" β”‚     β”‚
β”‚  β”‚ Preferences: "Theme dark, FR"   β”‚     β”‚
β”‚  β”‚ Historique: resume interactions  β”‚     β”‚
β”‚  β”‚ TTL: indefini                   β”‚     β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β”‚                                           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Conseil pratique
Utilisez InMemorySessionService pour le developpement et les tests, puis passez a DatabaseSessionService (SQLite ou PostgreSQL) pour la production. Le Memory Bank est ideal pour les assistants personnalises qui doivent retenir les preferences utilisateur.

Multi-Agent Systems avec ADK

15 min Avance

Objectifs

  • Comprendre les patterns d'orchestration multi-agents
  • Utiliser SequentialAgent, ParallelAgent et LoopAgent
  • Deleguer des taches entre agents avec sub_agents
  • Communiquer entre agents via le session state

Patterns d'Orchestration

ADK propose trois types d'agents orchestrateurs pour combiner plusieurs agents specialises :

PatternClasseComportementCas d'usage
SequentielSequentialAgentExecute les agents un par un, dans l'ordrePipeline ETL, workflow lineaire
ParalleleParallelAgentExecute tous les agents simultanementRecherche multi-sources, analyses independantes
BoucleLoopAgentRepete un agent jusqu'a condition de sortieRaffinement iteratif, validation
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ MULTI-AGENT HIERARCHY ──────────────┐
β”‚                                                    β”‚
β”‚              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                     β”‚
β”‚              β”‚ Orchestrator β”‚                     β”‚
β”‚              β”‚ (Sequential) β”‚                     β”‚
β”‚              β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜                     β”‚
β”‚                     β”‚                              β”‚
β”‚         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                 β”‚
β”‚         β–Ό           β–Ό           β–Ό                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚  β”‚ Researcher β”‚ β”‚ Analyst β”‚ β”‚ Writer   β”‚        β”‚
β”‚  β”‚            β”‚ β”‚         β”‚ β”‚          β”‚        β”‚
β”‚  β”‚ Tools:     β”‚ β”‚ Tools:  β”‚ β”‚ Tools:   β”‚        β”‚
β”‚  β”‚ - search   β”‚ β”‚ - code  β”‚ β”‚ - none   β”‚        β”‚
β”‚  β”‚ - url_ctx  β”‚ β”‚   exec  β”‚ β”‚          β”‚        β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                                                    β”‚
β”‚  Communication via session.state :                β”‚
β”‚  researcher -> state["research_data"]             β”‚
β”‚  analyst    -> state["analysis_results"]          β”‚
β”‚  writer     -> state["final_report"]              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Exemple : Systeme 3 agents

Python
from google.adk.agents import LlmAgent, SequentialAgent, ParallelAgent
from google.adk.tools import FunctionTool, google_search

# Agent 1 : Chercheur
researcher = LlmAgent(
    name="researcher",
    model="gemini-2.5-flash",
    instruction="""Recherche des informations sur le sujet demande.
    Stocke tes resultats dans state['research_data'].""",
    tools=[google_search],
    output_key="research_data",  # Auto-save dans state
)

# Agent 2 : Analyste
analyst = LlmAgent(
    name="analyst",
    model="gemini-2.5-flash",
    instruction="""Analyse les donnees de recherche dans state['research_data'].
    Produis une analyse structuree avec points cles et tendances.""",
    output_key="analysis_results",
)

# Agent 3 : Redacteur
writer = LlmAgent(
    name="writer",
    model="gemini-2.5-flash",
    instruction="""A partir de state['analysis_results'],
    redige un rapport professionnel en francais.
    Structure : resume, points cles, recommandations.""",
    output_key="final_report",
)

# Orchestrateur sequentiel
pipeline = SequentialAgent(
    name="research_pipeline",
    sub_agents=[researcher, analyst, writer],
)

AgentTool : Agent comme outil

Python
from google.adk.tools import AgentTool

# Wrapper un agent specialise comme outil
expert_tool = AgentTool(agent=analyst)

# L'agent principal peut appeler l'expert
supervisor = LlmAgent(
    name="supervisor",
    model="gemini-2.5-pro",
    instruction="Tu supervises et delegues aux experts.",
    tools=[expert_tool, google_search],
    sub_agents=[researcher, writer],  # Delegation directe
)

Le pattern le plus courant en production est le SequentialAgent avec 2-3 agents specialises. N'abusez pas du multi-agent : chaque agent ajoute de la latence et des couts. Utilisez ParallelAgent uniquement quand les taches sont vraiment independantes (ex: recherche sur 3 sources differentes).

Interactions API & MCP

12 min Avance

Objectifs

  • Comprendre l'Interactions API pour les agents
  • Maitriser le Model Context Protocol (MCP)
  • Connecter un agent ADK a un serveur MCP
  • Configurer des outils externes via MCP

Interactions API

L'Interactions API est le mecanisme natif de Google pour permettre aux agents d'utiliser des outils externes de maniere standardisee. Elle fournit un framework pour definir, decouvrir et invoquer des outils a travers des services.

Model Context Protocol (MCP)

Le MCP (Model Context Protocol) est un standard ouvert (propose par Anthropic, adopte par Google) qui permet a n'importe quel agent de se connecter a des serveurs d'outils distants. C'est le "USB-C des agents IA" : un connecteur universel.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ MCP ARCHITECTURE ──────────────────┐
β”‚                                                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚
β”‚  β”‚  Agent  │◄──MCP──►│  MCP Server  β”‚             β”‚
β”‚  β”‚  (ADK)  β”‚         β”‚              β”‚             β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚  Tools:      β”‚             β”‚
β”‚                       β”‚  - database  β”‚             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚  - file_ops  β”‚             β”‚
β”‚  β”‚  Agent  │◄──MCP──►│  - api_calls β”‚             β”‚
β”‚  β”‚ (autre) β”‚         β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜             β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                β”‚                      β”‚
β”‚                       β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”               β”‚
β”‚                       β”‚ External   β”‚               β”‚
β”‚                       β”‚ Services   β”‚               β”‚
β”‚                       β”‚ - DB       β”‚               β”‚
β”‚                       β”‚ - APIs     β”‚               β”‚
β”‚                       β”‚ - Files    β”‚               β”‚
β”‚                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Connecter un agent ADK a MCP

Python
from google.adk.agents import LlmAgent
from google.adk.tools.mcp_tool import MCPToolset
from google.adk.tools.mcp_tool import SseServerParams, StdioServerParams

# Option 1 : Serveur MCP distant (SSE)
mcp_tools_remote = MCPToolset(
    connection_params=SseServerParams(
        url="https://my-mcp-server.example.com/sse",
        headers={"Authorization": "Bearer TOKEN"}
    )
)

# Option 2 : Serveur MCP local (stdio)
mcp_tools_local = MCPToolset(
    connection_params=StdioServerParams(
        command="npx",
        args=["-y", "@modelcontextprotocol/server-filesystem", "/data"]
    )
)

# Agent avec outils MCP
agent = LlmAgent(
    name="mcp_agent",
    model="gemini-2.5-flash",
    instruction="Utilise les outils MCP pour acceder aux donnees.",
    tools=[mcp_tools_remote],  # Ou mcp_tools_local
)

Serveurs MCP populaires

Serveur MCPOutils fournisTransport
filesystemLecture/ecriture de fichiers, navigation dossiersstdio
githubIssues, PRs, repos, fichiersSSE
postgresRequetes SQL, schema, tablesstdio
slackMessages, channels, usersSSE
google-driveDocuments, partage, rechercheSSE
MCP dans Google Cloud
Google a integre le support MCP natif dans Vertex AI Agent Builder et ADK. Vous pouvez aussi deployer vos propres serveurs MCP sur Cloud Run pour un acces securise.

Gemini CLI & Firebase Studio

10 min Intermediaire

Objectifs

  • Utiliser Gemini CLI comme assistant en terminal
  • Configurer MCP dans Gemini CLI
  • Decouvrir Firebase Studio pour le prototypage
  • Deployer rapidement depuis Firebase Studio

Gemini CLI

Gemini CLI est un outil en ligne de commande qui apporte la puissance de Gemini directement dans votre terminal. Il supporte MCP, le contexte de fichiers locaux, et l'execution de commandes.

Bash
# Installation
npm install -g @anthropic-ai/gemini-cli
# Ou via Google
npm install -g @google/gemini-cli

# Utilisation basique
gemini "Explique ce fichier" --file main.py

# Mode interactif
gemini chat

# Avec contexte de projet
gemini "Corrige les bugs" --dir ./src

Configuration MCP dans Gemini CLI

JSON - .gemini/settings.json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "ghp_xxxx"
      }
    }
  }
}

Firebase Studio

Firebase Studio (anciennement Project IDX) est un IDE cloud de Google avec IA integree. Son atout majeur : l'App Prototyping agent qui genere des applications completes a partir d'une description en langage naturel.

FonctionnaliteDescription
App PrototypingGenere une app complete (frontend + backend) depuis un prompt
Gemini IntegrationGemini 2.5 Pro integre dans l'editeur pour code assist
Nix TemplatesEnvironnements preconfigures (Next.js, Flutter, Python, Go...)
PreviewPrevisualisation web en temps reel dans l'IDE
DeployDeploiement one-click vers Firebase Hosting ou Cloud Run
Prompt - Firebase Studio App Prototyping
# Exemple de prompt pour App Prototyping :
"Cree une application web de gestion de taches avec :
- Interface React avec Material UI
- Backend Firebase avec Firestore
- Authentification Google
- CRUD complet sur les taches
- Filtres par statut et priorite"

# Firebase Studio genere automatiquement :
# - Code frontend React complet
# - Configuration Firebase
# - Rules Firestore
# - Deploiement configure

Firebase Studio est un outil formidable pour le prototypage rapide. En 5 minutes, vous pouvez avoir une app fonctionnelle deployee. Mais pour la production enterprise, preferez un workflow CI/CD classique. Gemini CLI, en revanche, est un outil quotidien indispensable - configurez-le avec MCP pour booster votre productivite.

Lab : Systeme multi-agents

20 min Avance

Objectifs

  • Construire un systeme multi-agents complet avec ADK
  • Implementer recherche, analyse et redaction automatisees
  • Orchestrer avec SequentialAgent et session state
  • Tester et valider le pipeline complet

Projet : Pipeline Recherche-Analyse-Rapport

Construisez un systeme de 3 agents qui recherche un sujet, analyse les resultats et produit un rapport structure.

Etape 1 : Setup du projet

Bash
# Creer la structure
mkdir research_system && cd research_system
pip install google-adk

# Structure
research_system/
β”œβ”€β”€ __init__.py
β”œβ”€β”€ agent.py
└── .env    # GOOGLE_API_KEY=votre_cle

Etape 2 : Definir le ResearchAgent

Python - agent.py
from google.adk.agents import LlmAgent, SequentialAgent
from google.adk.tools import google_search, code_execution

# Agent 1 : Recherche
research_agent = LlmAgent(
    name="researcher",
    model="gemini-2.5-flash",
    instruction="""Tu es un chercheur expert.
    Pour chaque sujet demande :
    1. Effectue 3-5 recherches Google pertinentes
    2. Synthetise les informations cles
    3. Identifie les sources fiables
    4. Stocke les resultats structures dans ta reponse.
    Format: points cles avec sources.""",
    tools=[google_search],
    output_key="research_data",
)

Etape 3 : Definir l'AnalysisAgent

Python
# Agent 2 : Analyse avec code execution
analysis_agent = LlmAgent(
    name="analyst",
    model="gemini-2.5-flash",
    instruction="""Tu es un analyste de donnees.
    A partir des donnees de recherche dans state['research_data'] :
    1. Identifie les tendances principales
    2. Classe les informations par importance
    3. Utilise code_execution pour creer des stats si pertinent
    4. Produis une analyse structuree.""",
    tools=[code_execution],
    output_key="analysis_results",
)

Etape 4 : Definir le ReportAgent

Python
# Agent 3 : Redaction du rapport
report_agent = LlmAgent(
    name="writer",
    model="gemini-2.5-flash",
    instruction="""Tu es un redacteur professionnel.
    A partir de state['analysis_results'] :
    1. Redige un rapport structure en francais
    2. Sections : Resume executif, Analyse, Recommandations
    3. Utilise un ton professionnel et factuel
    4. Limite : 500 mots maximum.""",
    output_key="final_report",
)

Etape 5 : Orchestrateur SequentialAgent

Python
# Pipeline sequentiel
root_agent = SequentialAgent(
    name="research_pipeline",
    sub_agents=[research_agent, analysis_agent, report_agent],
)

Etape 6 : Executer le systeme

Python
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
import asyncio

async def main():
    session_service = InMemorySessionService()
    runner = Runner(
        agent=root_agent,
        app_name="research_system",
        session_service=session_service,
    )

    session = await session_service.create_session(
        app_name="research_system",
        user_id="demo_user",
    )

    response = await runner.run(
        user_id="demo_user",
        session_id=session.id,
        new_message="Analyse les tendances de l'IA generative en 2026"
    )

    # Afficher le rapport final
    print("=== RAPPORT ===")
    print(session.state.get("final_report", "Pas de rapport"))

asyncio.run(main())

Etape 7 : Tester avec adk web

Bash
# Lancer l'interface de test
adk web

# Ouvrir http://localhost:8000
# Selectionner "research_pipeline"
# Tester avec differents sujets
# Observer l'execution sequentielle des 3 agents

Quiz Module 2.2 - Agents & ADK

10 min Intermediaire

Testez vos connaissances sur les Agents & ADK

1. Quelle est la difference principale entre un chatbot et un agent IA ?

2. Quelle commande lance l'interface de test locale d'ADK ?

3. Quel service fournit la memoire long terme dans ADK ?

4. Quel agent orchestrateur execute les sous-agents un par un dans l'ordre ?

5. Quel protocole standardise l'integration d'outils externes pour les agents ?

6. Quelle fonctionnalite de Firebase Studio genere des apps depuis un prompt ?

7. Comment les agents communiquent-ils dans un systeme multi-agents ADK ?

Live API : Streaming temps reel

12 min Avance

Objectifs

  • Comprendre l'architecture WebSocket de la Live API
  • Implementer un streaming bidirectionnel audio/video
  • Gerer les sessions et la reconnexion
  • Comparer REST API vs Live API

Qu'est-ce que la Live API ?

La Live API de Gemini est une API basee sur WebSocket qui permet des interactions bidirectionnelles en temps reel avec une latence inferieure a la seconde. Contrairement a l'API REST classique (requete/reponse), la Live API maintient une connexion persistante pour envoyer et recevoir de l'audio, de la video et du texte simultanement.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ LIVE API ARCHITECTURE ──────────────┐
β”‚                                                    β”‚
β”‚  CLIENT                        SERVEUR GEMINI     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   WebSocket     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚          │◄═══════════════►│              β”‚   β”‚
β”‚  β”‚  Audio   β”‚   bidirectionnelβ”‚  Gemini      β”‚   β”‚
β”‚  β”‚  input   │────────────────►│  2.5 Flash   β”‚   β”‚
β”‚  β”‚  (micro) β”‚                 β”‚              β”‚   β”‚
β”‚  β”‚          │◄────────────────│  Processing  β”‚   β”‚
β”‚  β”‚  Audio   β”‚   audio chunks  β”‚  + Tools     β”‚   β”‚
β”‚  β”‚  output  β”‚                 β”‚  + Grounding β”‚   β”‚
β”‚  β”‚  (HP)    β”‚                 β”‚              β”‚   β”‚
β”‚  β”‚          │────────────────►│              β”‚   β”‚
β”‚  β”‚  Video   β”‚   video frames  β”‚              β”‚   β”‚
β”‚  β”‚  input   β”‚                 β”‚              β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                    β”‚
β”‚  Latence : < 500ms (TTFT)                        β”‚
β”‚  Modeles : gemini-2.5-flash, gemini-2.0-flash     β”‚
β”‚  Duree max session : 15 minutes                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Connexion WebSocket

Python
from google import genai
from google.genai import types

client = genai.Client(api_key="VOTRE_CLE")

# Configuration Live API
config = types.LiveConnectConfig(
    response_modalities=["AUDIO"],  # ou ["TEXT"], ["AUDIO", "TEXT"]
    speech_config=types.SpeechConfig(
        voice_config=types.VoiceConfig(
            prebuilt_voice_config=types.PrebuiltVoiceConfig(
                voice_name="Puck"  # Voix disponible
            )
        )
    ),
    tools=[
        types.Tool(google_search_retrieval=
            types.GoogleSearchRetrieval()),
    ],
)

# Connexion live
async with client.aio.live.connect(
    model="gemini-2.5-flash",
    config=config
) as session:
    # Envoyer du texte
    await session.send_client_content(
        turns=types.Content(
            role="user",
            parts=[types.Part(text="Bonjour, quel temps fait-il ?")]
        )
    )

    # Recevoir la reponse en streaming
    async for response in session.receive():
        if response.text:
            print(response.text, end="", flush=True)
        if response.data:
            # Audio bytes a jouer
            play_audio(response.data)

REST API vs Live API

CritereREST APILive API
ProtocoleHTTP/HTTPSWebSocket
DirectionRequete β†’ ReponseBidirectionnel continu
Latence1-5 secondes< 500ms
InputTexte, images, fichiersAudio, video, texte en temps reel
DureePar requeteSession jusqu'a 15 min
Cas d'usageTraitement batch, chatbot texteVoix, video, assistant temps reel
Limites de la Live API
Les sessions Live API ont une duree maximale de 15 minutes. Apres ce delai, la connexion est fermee et une nouvelle session doit etre creee. Gerez la reconnexion automatique dans votre code de production.

Native Audio & Voice

12 min Avance

Objectifs

  • Utiliser le modele native audio pour la parole
  • Configurer les voix disponibles (Puck, Kore, Charon...)
  • Implementer text-to-speech et speech-to-text
  • Construire des conversations audio bidirectionnelles

Native Audio : Comprehension naturelle

Le modele gemini-2.5-flash-native-audio-preview comprend nativement la parole humaine - intonation, emotion, pauses, hesitations. Ce n'est pas une simple transcription : le modele traite l'audio comme une modalite de premiere classe.

Voix disponibles

VoixGenreStyleLangues
PuckMasculinEnergique, jeuneMulti-langue
CharonMasculinGrave, professionnelMulti-langue
KoreFemininClair, articuleMulti-langue
FenrirMasculinChaleureux, narratifMulti-langue
AoedeFemininDoux, melodiqueMulti-langue
LedaFemininNeutre, informatifMulti-langue
OrusMasculinAutoritaire, expertMulti-langue
ZephyrNon-binaireLeger, amicalMulti-langue

Text-to-Speech avec Gemini

Python
from google import genai
from google.genai import types
import wave, struct

client = genai.Client(api_key="VOTRE_CLE")

# Generation audio depuis du texte
response = client.models.generate_content(
    model="gemini-2.5-flash-native-audio-preview",
    contents="Bonjour ! Je suis votre assistant vocal Gemini.",
    config=types.GenerateContentConfig(
        response_modalities=["AUDIO"],
        speech_config=types.SpeechConfig(
            voice_config=types.VoiceConfig(
                prebuilt_voice_config=types.PrebuiltVoiceConfig(
                    voice_name="Kore"
                )
            )
        ),
    ),
)

# Sauvegarder l'audio en WAV
audio_data = response.candidates[0].content.parts[0].inline_data.data
with wave.open("output.wav", "wb") as wf:
    wf.setnchannels(1)
    wf.setsampwidth(2)   # 16-bit PCM
    wf.setframerate(24000)  # 24kHz
    wf.writeframes(audio_data)

Conversation audio bidirectionnelle

Python
# Via Live API pour le bidirectionnel
config = types.LiveConnectConfig(
    response_modalities=["AUDIO"],
    speech_config=types.SpeechConfig(
        voice_config=types.VoiceConfig(
            prebuilt_voice_config=types.PrebuiltVoiceConfig(
                voice_name="Charon"
            )
        )
    ),
)

async with client.aio.live.connect(
    model="gemini-2.5-flash",
    config=config
) as session:
    # Envoyer de l'audio du microphone
    while True:
        audio_chunk = capture_microphone(duration_ms=200)
        await session.send_realtime_input(
            media=types.Blob(
                data=audio_chunk,
                mime_type="audio/pcm;rate=16000"
            )
        )

        # Recevoir et jouer la reponse
        async for msg in session.receive():
            if msg.data:
                play_speaker(msg.data)

Les voix Gemini sont impressionnantes en qualite. Pour une application francophone, je recommande Kore ou Charon qui offrent une excellente prononciation francaise. Testez toujours avec votre audience cible - la perception des voix IA varie selon les cultures.

Embeddings API

10 min Intermediaire

Objectifs

  • Generer des embeddings avec gemini-embedding-001
  • Comprendre Matryoshka Representation Learning (MRL)
  • Choisir les dimensions (768, 1536, 3072)
  • Utiliser les task types pour optimiser la qualite

Qu'est-ce qu'un Embedding ?

Un embedding est une representation vectorielle d'un texte - un tableau de nombres qui capture le sens semantique. Deux textes similaires auront des vecteurs proches. C'est la brique fondamentale du RAG (Retrieval-Augmented Generation) et de la recherche semantique.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ WORKFLOW EMBEDDINGS ───────────────┐
β”‚                                                  β”‚
β”‚  INDEXATION                   RECHERCHE          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚  β”‚ Document β”‚               β”‚  Query   β”‚       β”‚
β”‚  β”‚ "Gemini  β”‚               β”‚ "modele  β”‚       β”‚
β”‚  β”‚  est un  β”‚               β”‚  Google" β”‚       β”‚
β”‚  β”‚  modele" β”‚               β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜       β”‚
β”‚  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜                    β”‚              β”‚
β”‚       β”‚                          β”‚              β”‚
β”‚       β–Ό                          β–Ό              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚  β”‚ Embed    β”‚               β”‚ Embed    β”‚       β”‚
β”‚  β”‚ [0.12,   β”‚               β”‚ [0.11,   β”‚       β”‚
β”‚  β”‚  0.85,   β”‚               β”‚  0.83,   β”‚       β”‚
β”‚  β”‚  ...]    β”‚               β”‚  ...]    β”‚       β”‚
β”‚  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜               β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜       β”‚
β”‚       β”‚                          β”‚              β”‚
β”‚       β–Ό                          β–Ό              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚  β”‚ Vector   │◄───cosine──│ Similarite β”‚        β”‚
β”‚  β”‚ Database β”‚  similarity β”‚ = 0.95     β”‚        β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Generer des Embeddings

Python
from google import genai
from google.genai import types

client = genai.Client(api_key="VOTRE_CLE")

# Embedding simple
result = client.models.embed_content(
    model="gemini-embedding-001",
    contents="Gemini est le modele IA de Google",
    config=types.EmbedContentConfig(
        task_type="RETRIEVAL_DOCUMENT",
        output_dimensionality=768,  # MRL : 768, 1536 ou 3072
    ),
)

vector = result.embeddings[0].values
print(f"Dimensions: {len(vector)}")  # 768
print(f"Premiers: {vector[:5]}")     # [0.012, -0.034, ...]

Batch Embeddings

Python
# Embeddings par lot (plus efficace)
texts = [
    "Gemini 2.5 Flash est rapide et economique",
    "Le RAG combine retrieval et generation",
    "Les agents utilisent des outils pour agir",
    "Le context caching reduit les couts de 90%",
]

result = client.models.embed_content(
    model="gemini-embedding-001",
    contents=texts,
    config=types.EmbedContentConfig(
        task_type="RETRIEVAL_DOCUMENT",
        output_dimensionality=1536,
    ),
)

for i, emb in enumerate(result.embeddings):
    print(f"Text {i}: {len(emb.values)} dimensions")

Task Types & Dimensions

Task TypeUsage
RETRIEVAL_DOCUMENTIndexer des documents pour la recherche
RETRIEVAL_QUERYEncoder les requetes de recherche
SEMANTIC_SIMILARITYComparer la similarite entre textes
CLASSIFICATIONClassifier des textes par categories
CLUSTERINGRegrouper des textes similaires
CODE_RETRIEVALRecherche semantique dans du code
QUESTION_ANSWERINGTrouver des reponses dans une base
DimensionsStockagePerformanceRecommandation
768MinimalBonnePrototypage, gros volumes
1536MoyenTres bonneProduction standard
3072MaximumExcellentePrecision maximale requise
Matryoshka (MRL)
Grace au Matryoshka Representation Learning, vous pouvez choisir la dimension apres l'entrainement. Un embedding de 3072 dimensions tronque a 768 reste de haute qualite. Commencez avec 768 pour le prototypage, puis augmentez si necessaire.

Batch API

10 min Intermediaire

Objectifs

  • Comprendre le traitement batch asynchrone
  • Economiser 50% sur les couts API
  • Creer et monitorer des batch jobs
  • Utiliser le format JSONL pour les lots

Pourquoi utiliser le Batch API ?

Le Batch API permet de soumettre des lots de requetes a traiter de maniere asynchrone, avec une reduction de 50% sur les couts. Ideal pour le traitement en masse ou les taches non urgentes qui n'ont pas besoin de reponse immediate.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ BATCH API WORKFLOW ─────────────────┐
β”‚                                                    β”‚
β”‚  1. PREPARATION        2. SOUMISSION              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”‚
β”‚  β”‚ Fichier  │────────►│ batches.createβ”‚           β”‚
β”‚  β”‚ JSONL    β”‚         β”‚               β”‚           β”‚
β”‚  β”‚ (N req)  β”‚         β”‚ Status:       β”‚           β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚ PENDING       β”‚           β”‚
β”‚                        β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜           β”‚
β”‚                                β”‚                    β”‚
β”‚  4. RESULTATS          3. PROCESSING               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”‚
β”‚  β”‚ Output   │◄────────│ Gemini traite β”‚           β”‚
β”‚  β”‚ JSONL    β”‚         β”‚ en background β”‚           β”‚
β”‚  β”‚ (N resp) β”‚         β”‚ (jusqu'a 24h) β”‚           β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚ -50% cout     β”‚           β”‚
β”‚                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Creer un Batch Job

Python
from google import genai
from google.genai import types

client = genai.Client(api_key="VOTRE_CLE")

# Methode 1 : Inline requests
batch_job = client.batches.create(
    model="gemini-2.5-flash",
    requests=[
        types.BatchRequest(
            custom_id="req-001",
            request=types.GenerateContentRequest(
                contents="Resume cet article en 3 points : ...",
                config=types.GenerateContentConfig(
                    max_output_tokens=500,
                ),
            ),
        ),
        types.BatchRequest(
            custom_id="req-002",
            request=types.GenerateContentRequest(
                contents="Traduis en anglais : ...",
            ),
        ),
        # ... jusqu'a des milliers de requetes
    ],
)

print(f"Batch ID: {batch_job.name}")
print(f"Status: {batch_job.state}")  # PENDING

Monitorer et recuperer les resultats

Python
import time

# Verifier le statut
while True:
    batch = client.batches.get(name=batch_job.name)
    print(f"Status: {batch.state}")

    if batch.state == "JOB_STATE_SUCCEEDED":
        break
    elif batch.state == "JOB_STATE_FAILED":
        print(f"Erreur: {batch.error}")
        break

    time.sleep(30)  # Verifier toutes les 30s

# Recuperer les resultats
for result in client.batches.list_results(name=batch_job.name):
    print(f"ID: {result.custom_id}")
    print(f"Reponse: {result.response.text[:100]}...")

# Lister tous les batch jobs
for job in client.batches.list():
    print(f"{job.name}: {job.state}")
Quand utiliser le Batch API ?
Utilisez-le : traitement de datasets, migration de contenu, analyses massives, generation de rapports nocturnes, preprocessing RAG.
N'utilisez pas : interactions utilisateur temps reel, chatbots, taches urgentes.

Le Batch API est un levier d'optimisation majeur. Si vous avez des taches qui peuvent attendre quelques heures, vous economisez 50% automatiquement. Je l'utilise systematiquement pour les evaluations de prompts, le processing de datasets d'entrainement, et les analyses de logs.

Safety Settings & Content Filtering

10 min Intermediaire

Objectifs

  • Comprendre les 5 categories de contenus nocifs
  • Configurer les seuils de filtrage
  • Lire les safety ratings dans les reponses
  • Connaitre les filtres non-configurables

Categories de contenus nocifs

Gemini classe les contenus en 5 categories de danger. Pour les modeles 2.5 et 3.x, le filtrage est desactive par defaut (BLOCK_NONE), vous donnant le controle total.

CategorieConstanteDescription
HarcelementHARM_CATEGORY_HARASSMENTIntimidation, menaces, bullying
Discours haineuxHARM_CATEGORY_HATE_SPEECHDiscrimination, stereotypes nocifs
Sexuellement expliciteHARM_CATEGORY_SEXUALLY_EXPLICITContenu sexuel explicite
Contenu dangereuxHARM_CATEGORY_DANGEROUS_CONTENTInstructions pour se blesser ou blesser
Integrite civiqueHARM_CATEGORY_CIVIC_INTEGRITYDesinformation electorale, manipulation

Seuils de blocage

SeuilComportement
BLOCK_NONEAucun blocage (defaut pour 2.5+)
BLOCK_ONLY_HIGHBloque uniquement les contenus a haute probabilite
BLOCK_MEDIUM_AND_ABOVEBloque medium et high
BLOCK_LOW_AND_ABOVEBloque tout sauf negligeable (le plus restrictif)

Configuration des Safety Settings

Python
from google import genai
from google.genai import types

client = genai.Client(api_key="VOTRE_CLE")

response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="Explique les risques de cybersecurite",
    config=types.GenerateContentConfig(
        safety_settings=[
            types.SafetySetting(
                category="HARM_CATEGORY_DANGEROUS_CONTENT",
                threshold="BLOCK_MEDIUM_AND_ABOVE",
            ),
            types.SafetySetting(
                category="HARM_CATEGORY_HARASSMENT",
                threshold="BLOCK_ONLY_HIGH",
            ),
            # Les categories non specifiees restent a BLOCK_NONE
        ],
    ),
)

Lire les Safety Ratings

Python
# Verifier les ratings de la reponse
for candidate in response.candidates:
    if candidate.safety_ratings:
        for rating in candidate.safety_ratings:
            print(f"Categorie: {rating.category}")
            print(f"Probabilite: {rating.probability}")
            print(f"Bloque: {rating.blocked}")

    # Verifier si la reponse a ete bloquee
    if candidate.finish_reason == "SAFETY":
        print("ATTENTION: Reponse bloquee par les filtres de securite")
        print(f"Raison: {candidate.safety_ratings}")
Filtres non-configurables
Certains filtres sont toujours actifs et ne peuvent pas etre desactives : detection de CSAM (contenu pedopornographique), generation de malware executif, et instructions pour la creation d'armes de destruction massive. Ces filtres sont imposes par Google independamment de vos reglages.
Responsabilite
Avec BLOCK_NONE par defaut sur les modeles 2.5+, vous etes responsable de filtrer les contenus inappropries cote application. Implementez vos propres garde-fous en production, surtout pour les applications grand public.

Fine-Tuning dans Google AI Studio

12 min Avance

Objectifs

  • Comprendre quand le fine-tuning est pertinent
  • Preparer un dataset au format JSONL
  • Lancer un job de fine-tuning via l'API
  • Evaluer et utiliser le modele ajuste

Quand faire du Fine-Tuning ?

Le fine-tuning (Supervised Fine-Tuning / SFT) consiste a re-entrainer un modele de base sur vos propres donnees pour l'adapter a un style, un format ou un domaine specifique. C'est un outil puissant, mais pas toujours necessaire.

ApprocheQuand l'utiliserCout
Prompt EngineeringLa plupart des cas, premier reflexeGratuit
Few-Shot ExamplesFormat specifique, style particulierTokens input
Context CachingGrande base de connaissances fixeCache storage
RAGConnaissances dynamiques, referencesEmbeddings + DB
Fine-TuningStyle tres specifique, domaine pointu, haute perf requiseTraining + hosting

Preparer les donnees d'entrainement

JSONL - training_data.jsonl
{"text_input": "Quel est le statut de la commande #12345 ?", "output": "Commande #12345 : En cours de livraison. Estimation : 2 jours ouvrables. Transporteur : Colissimo."}
{"text_input": "Je veux retourner mon produit", "output": "Procedure de retour initiee. Vous recevrez un email avec l'etiquette de retour sous 24h. Remboursement sous 5-7 jours apres reception."}
{"text_input": "Probleme avec ma facture de janvier", "output": "J'ai identifie une anomalie sur votre facture de janvier. Montant corrige : 45.90 EUR. Un avoir sera emis sous 48h."}
{"text_input": "Changer mon adresse de livraison", "output": "Adresse mise a jour avec succes. Prochaine livraison a la nouvelle adresse. Confirmation envoyee par email."}
Dataset : quantite recommandee
Minimum : 20 exemples (fonctionne mais resultats variables).
Recommande : 100-500 exemples pour des resultats robustes.
Optimal : 500-1000 exemples diversifies et de haute qualite.

Lancer le Fine-Tuning via l'API

Python
from google import genai
from google.genai import types

client = genai.Client(api_key="VOTRE_CLE")

# Preparer les exemples d'entrainement
training_data = [
    types.TuningExample(
        text_input="Quel est le statut de la commande #12345 ?",
        output="Commande #12345 : En cours de livraison..."
    ),
    types.TuningExample(
        text_input="Je veux retourner mon produit",
        output="Procedure de retour initiee..."
    ),
    # ... au moins 20 exemples
]

# Creer le job de tuning
tuning_job = client.tunings.create(
    base_model="models/gemini-2.5-flash-001-tuning",
    training_dataset=types.TuningDataset(
        examples=types.TuningExamples(
            examples=training_data
        )
    ),
    config=types.CreateTuningJobConfig(
        epoch_count=5,
        learning_rate=0.001,
        tuned_model_display_name="support-client-v1",
    ),
)

print(f"Job: {tuning_job.name}")
print(f"Status: {tuning_job.state}")

Utiliser le modele fine-tune

Python
# Une fois le tuning termine
response = client.models.generate_content(
    model=tuning_job.tuned_model.model,  # ex: tunedModels/support-client-v1-xxxxx
    contents="Le client veut modifier sa commande",
)
print(response.text)

# Lister vos modeles fine-tunes
for model in client.tunings.list():
    print(f"{model.tuned_model.model}: {model.state}")

En 30 ans d'experience, j'ai vu beaucoup de gens se precipiter sur le fine-tuning alors que du bon prompt engineering suffisait. Ma regle : essayez d'abord le prompt engineering + few-shot, puis le RAG, et ne fine-tunez que si ces approches ne donnent pas les resultats souhaites. Le fine-tuning coute en temps, en donnees et en maintenance.

Lab : Application voix interactive

20 min Avance

Objectifs

  • Construire une application voix complete avec Live API
  • Implementer le streaming audio bidirectionnel
  • Ajouter function calling et grounding en temps reel
  • Gerer les evenements de session et les erreurs

Projet : Assistant Vocal avec Outils

Construisez un assistant vocal interactif qui repond en voix, peut chercher sur Google, et executer des fonctions custom.

Etape 1 : Setup et dependances

Bash
# Installation des dependances
pip install google-genai pyaudio numpy

# Structure du projet
voice_assistant/
β”œβ”€β”€ main.py           # Point d'entree
β”œβ”€β”€ audio_handler.py  # Capture/lecture audio
β”œβ”€β”€ tools.py          # Outils custom
└── .env              # GOOGLE_API_KEY=...

Etape 2 : Definir les outils

Python - tools.py
from google.genai import types
import datetime

# Outil meteo (simule)
get_weather_decl = types.FunctionDeclaration(
    name="get_weather",
    description="Obtient la meteo actuelle d'une ville",
    parameters=types.Schema(
        type="OBJECT",
        properties={
            "city": types.Schema(type="STRING", description="Nom de la ville"),
        },
        required=["city"],
    ),
)

# Outil heure
get_time_decl = types.FunctionDeclaration(
    name="get_current_time",
    description="Retourne l'heure actuelle",
    parameters=types.Schema(type="OBJECT", properties={}),
)

def handle_function_call(name, args):
    """Execute la fonction appelee par le modele."""
    if name == "get_weather":
        city = args.get("city", "Paris")
        return {"temperature": 15, "condition": "nuageux", "city": city}
    elif name == "get_current_time":
        return {"time": datetime.datetime.now().strftime("%H:%M")}

Etape 3 : Configurer la connexion Live API

Python - main.py
from google import genai
from google.genai import types
from tools import get_weather_decl, get_time_decl, handle_function_call

client = genai.Client(api_key="VOTRE_CLE")

# Configuration avec outils et voix
live_config = types.LiveConnectConfig(
    response_modalities=["AUDIO"],
    speech_config=types.SpeechConfig(
        voice_config=types.VoiceConfig(
            prebuilt_voice_config=types.PrebuiltVoiceConfig(
                voice_name="Kore"  # Voix feminine claire
            )
        )
    ),
    tools=[
        types.Tool(function_declarations=[get_weather_decl, get_time_decl]),
        types.Tool(google_search_retrieval=types.GoogleSearchRetrieval()),
    ],
)

Etape 4 : Boucle principale audio

Python - main.py (suite)
import asyncio
import pyaudio
import numpy as np

CHUNK = 4096
FORMAT = pyaudio.paInt16
RATE = 16000

async def voice_assistant():
    p = pyaudio.PyAudio()

    # Stream d'entree (microphone)
    input_stream = p.open(format=FORMAT, channels=1, rate=RATE,
                          input=True, frames_per_buffer=CHUNK)

    # Stream de sortie (haut-parleur)
    output_stream = p.open(format=FORMAT, channels=1, rate=24000,
                           output=True, frames_per_buffer=CHUNK)

    async with client.aio.live.connect(
        model="gemini-2.5-flash",
        config=live_config
    ) as session:
        print("Assistant vocal pret ! Parlez...")

        async def send_audio():
            """Envoie l'audio du micro en continu."""
            while True:
                data = input_stream.read(CHUNK, exception_on_overflow=False)
                await session.send_realtime_input(
                    media=types.Blob(
                        data=data,
                        mime_type="audio/pcm;rate=16000"
                    )
                )
                await asyncio.sleep(0.01)

        async def receive_responses():
            """Recoit et joue les reponses."""
            async for msg in session.receive():
                # Audio du modele
                if msg.data:
                    output_stream.write(msg.data)

                # Function call
                if msg.tool_call:
                    for fc in msg.tool_call.function_calls:
                        result = handle_function_call(fc.name, fc.args)
                        await session.send_tool_response(
                            function_responses=[
                                types.FunctionResponse(
                                    name=fc.name,
                                    response=result,
                                )
                            ]
                        )

        # Executer envoi et reception en parallele
        await asyncio.gather(send_audio(), receive_responses())

asyncio.run(voice_assistant())

Etape 5 : Gestion des erreurs et reconnexion

Python
async def resilient_assistant():
    """Assistant avec reconnexion automatique."""
    max_retries = 3

    for attempt in range(max_retries):
        try:
            await voice_assistant()
        except Exception as e:
            print(f"Erreur (tentative {attempt+1}): {e}")
            if "session expired" in str(e).lower():
                print("Session expiree (15 min max). Reconnexion...")
            elif attempt < max_retries - 1:
                await asyncio.sleep(2 ** attempt)  # Backoff
            else:
                print("Echec apres 3 tentatives.")
                raise

asyncio.run(resilient_assistant())

Etape 6 : Tester l'application

Bash
# Lancer l'assistant
python main.py

# Tests a effectuer :
# 1. "Bonjour" -> Reponse vocale
# 2. "Quel temps fait-il a Lyon ?" -> Function call meteo
# 3. "Quelle heure est-il ?" -> Function call heure
# 4. "Quelles sont les dernieres nouvelles en France ?" -> Google Search
# 5. Attendre 15 min -> Test reconnexion automatique

Examen Final Phase 2

15 min Avance

Objectifs

  • Valider les connaissances des Modules 2.1, 2.2 et 2.3
  • Couvrir function calling, agents, ADK, Live API et plus
  • Obtenir la certification Phase 2

Examen Final - Outils Avances & Agents (10 questions)

1. Quels sont les 3 modes de function calling dans Gemini ?

2. Quel outil fournit un sandbox Python dans Gemini ?

3. Quel est le cout du Google Search Grounding par API ?

4. A quoi sert le framework ADK de Google ?

5. Quel protocole standardise l'integration d'outils pour les agents ?

6. Quel est le protocole de transport de la Live API ?

7. Quelle technique permet de choisir la dimension des embeddings apres entrainement ?

8. Quelle reduction de cout offre le Batch API ?

9. Combien de categories de contenus nocifs existent dans les Safety Settings ?

10. Quel est le nombre minimum d'exemples pour le fine-tuning ?

Felicitations si vous avez obtenu plus de 70% ! Vous maitrisez maintenant les outils avances de Gemini : function calling, agents ADK, Live API, embeddings, batch processing et safety. La Phase 3 vous attend pour construire des architectures RAG et des systemes distribues.