Appel de fonction asynchrone avec l'API Gemini Live

Lorsque vous créez des agents vocaux en temps réel, certains appels de fonction peuvent bloquer l'exécution du modèle, ce qui entraîne la mise en pause du flux audio et l'attente silencieuse de l'utilisateur. Avec l'API Gemini Live, tous les appels de fonction sont non bloquants par défaut, ce qui vous permet d'exécuter des fonctions en parallèle du flux de conversation principal. Ce processus est appelé appel de fonction asynchrone. Votre backend peut traiter des tâches lourdes telles que la recherche de prix de vols en direct ou l'interrogation d'API externes complexes en arrière-plan, tandis que le modèle continue d'écouter, de parler et de converser naturellement avec l'utilisateur. L'API Gemini Live permet aux appels de fonction de s'exécuter en arrière-plan sans interrompre l'interaction de l'utilisateur avec le modèle, ce qui permet des interactions plus fluides et en temps réel.

L'appel de fonction asynchrone vous permet d'effectuer des tâches telles que la prise de rendez-vous, la définition de rappels ou la récupération de données sans mettre en pause la conversation. Par exemple, un utilisateur peut demander à réserver un vol et demander immédiatement des informations météorologiques pendant que la réservation est traitée en arrière-plan.

Exemple d'appel de fonction asynchrone

Cet exemple montre un utilisateur qui réserve un vol et demande l'heure à New York pendant que la fonction book_ticket s'exécute de manière asynchrone en arrière-plan :

User: Please book the 2:00 PM flight to New York for me.

Model: function_call: {name: "book_ticket"}
//(The "book_ticket" function call is sent to the client.)
//(Right after the "book_ticket" function call is received, the client sends a text message to the model: "repeat this sentence 'I'm booking your ticket now, please wait.'")
//(The client runs the function call asynchronously in the background.)
Model: I'm booking your ticket now, please wait.

User: What is the current time in New York?

Model: The current time in New York is 12:00pm.

//(Once the book_ticket function finishes, the client sends the result.)
Function_response: {name: "book_ticket", response: {booking_status: "booked"}}

Model: Your flight has been booked. Expect a confirmation text on your phone within 5 minutes.

Implémenter l'appel de fonction asynchrone

Cette section fournit une série d'exemples utilisant la version Python du SDK Agent Platform pour créer une architecture simultanée très réactive qui utilise la capacité d'appel de fonction asynchrone de l'API Gemini Live. Les exemples sont répartis dans les tâches suivantes :

Définir vos outils

L'appel de fonction asynchrone est activé au niveau du modèle. Vous pouvez donc spécifier les outils que vous souhaitez utiliser dans la configuration de la requête, comme vous le feriez pour tout appel d'API Gemini standard dans Gemini Enterprise Agent Platform. Cela permet au modèle de continuer à discuter pendant que votre outil s'exécute :

from google import genai
from google.genai import types

# 1. A tool that takes a long time to execute
search_live_flights = {
    "name": "search_live_flights",
    "description": "Searches airlines for current flight prices. Can take up to 10 seconds."
}

# 2. A tool that executes instantly
get_current_weather = {
    "name": "get_current_weather",
    "description": "Gets the current weather for a given city."
}

tools = [{"function_declarations": [search_live_flights, get_current_weather]}]

Gérer les appels de fonction à partir du flux de messages

Lorsque le modèle doit appeler une ou plusieurs fonctions, l'API Gemini Live envoie un événement tool_call via le flux de messages en temps réel.

Votre backend ne doit pas bloquer le flux, car le modèle s'attend à continuer à s'exécuter. Lorsque vous recevez un appel pour une fonction lente (comme search_live_flights), vous devez le transmettre à un worker en arrière-plan. Si vous utilisez un await directement dans votre boucle de message principale pour une tâche de 10 secondes, la connexion sera figée. Les tâches rapides (comme get_current_weather) peuvent être attendues sans risque.

import asyncio

async def handle_stream(session):
    async for response in session.receive():
        # Check if the model is asking to use a tool
        if response.tool_call is not None:
            for fc in response.tool_call.function_calls:

                if fc.name == "search_live_flights":
                    # Pass to a background task so we don't block the receive loop!
                    asyncio.create_task(background_flight_search(fc.id, fc.args, session))

                elif fc.name == "get_current_weather":
                    # Instant lookups can be safely awaited directly
                    await instant_weather_lookup(fc.id, fc.args, session)

Gérer les attentes des utilisateurs

Pour gérer les attentes lors d'appels de fonctions asynchrones de longue durée, il est recommandé que le client envoie un message texte. Ce message doit inciter le système à informer l'utilisateur que sa demande est en cours de traitement et à lui demander de patienter. Par exemple, une fois qu'un appel de fonction est reçu par le client, celui-ci peut envoyer un message texte au modèle, tel que "répète cette phrase : 'Je réserve votre billet maintenant, veuillez patienter.'".

L'exemple de boîte de dialogue suivant illustre cet échange :

User: Please book the 2:00 PM flight to New York for me.
Model: function_call: {name: "book_ticket"}
//(The "book_ticket" function call is sent to the client.)
//(Right after the "book_ticket" function call is received, the client sends a text message to the model: "repeat this sentence 'I'm booking your ticket now, please wait.'")
//(The client runs the function call asynchronously in the background.)
Model: I'm booking your ticket now, please wait.
User: What is the current time in New York?
Model: The current time in New York is 12:00pm.
//(Once the "book_ticket" function call finishes, the client sends in the response.)
Function_response: {name: "book_ticket", response: {booking_status: "booked"}}
Model: Your flight has been booked. Expect a confirmation text on your phone within 5 minutes.

Cette stratégie de messagerie proactive présente les avantages suivants :

  • Informer l'utilisateur des opérations système en cours, ce qui permet de gérer les attentes lors des appels de fonctions de longue durée.
  • Réduit la fréquence des requêtes utilisateur courtes et redondantes, telles que hello? ou are you there?. Elles se produisent souvent pendant de longues périodes de silence du système, lorsque des appels de fonction asynchrones sont en cours de traitement. Cela peut minimiser le risque d'appels de fonction en double déclenchés par ces demandes répétées des utilisateurs.
  • Fournir une invite système supplémentaire peut réduire la probabilité de créer des appels en double lors des interactions suivantes.

Gérer les appels de fonction en double

Il existe une faible probabilité que le modèle génère des appels de fonction en double avant de recevoir une réponse au premier appel. Si votre cas d'utilisation le permet, votre application peut ignorer les appels de fonction en double si une réponse pour le même appel de fonction est toujours en attente.

L'exemple suivant montre comment un client peut ignorer un appel de fonction en double :

User: Please book the 2:00 PM flight to New York for me.

Model: function_call: {name: "book_ticket"}
//(The "book_ticket" function call is sent to the client. It is running asynchronously in the background.)

User: What is the current time in New York?
Model: The current time in New York is 12:00pm. + function_call: {name: "book_ticket"}
//(The duplicated "book_ticket" can be ignored by the client since the response for the first "book_ticket" has not been sent to the model yet.)

//(The first "book_ticket" function call finishes, and client sends in the response.)
Function_response: {name: "book_ticket", response: {booking_status: "booked"}}

Model: Your flight has been booked. Expect a confirmation text on your phone within 5 minutes.

Gérer les réponses de fonctions asynchrones

Lorsqu'un appel de fonction asynchrone est terminé, votre application envoie le résultat au modèle dans un function_response. Pendant que votre backend traite un appel de fonction, comme la recherche de vols, l'utilisateur peut poser au modèle une question complètement différente, par exemple "Quel temps fait-il à Londres ?". Le modèle répondra à la requête en temps réel, en parallèle de l'exécution de l'appel de fonction. Étant donné que l'utilisateur peut être en interaction avec le modèle lorsque l'exécution de la fonction est terminée, vous pouvez spécifier une règle qui définit la manière dont le modèle doit gérer cette réponse entrante. Vous pouvez spécifier l'une des règles suivantes :

Pour spécifier une règle, incluez le champ scheduling dans la charge utile function_response :

{
  "name": "book_ticket",
  "scheduling": "WHEN_IDLE",
  "response": {
    "booking_status": "booked"
  }
}

Si vous omettez le champ scheduling, l'API Gemini Live utilise sa méthode d'origine pour gérer les réponses de fonction afin d'assurer la rétrocompatibilité.

L'exemple Python suivant montre comment mettre en forme et envoyer un function_response avec scheduling="WHEN_IDLE" pour attendre une pause naturelle dans la conversation avant d'annoncer les résultats :

aearcync def background_flight_search(call_id, args, session):
    # 1. Simulate a slow API call taking 5 seconds
    await asyncio.sleep(5)
    flight_data = ["Air Canada AC758: $350", "WestJet WS12: $290"]

    # 2. Format the response
    function_response = types.FunctionResponse(
        id=call_id,
        name="search_live_flights",
        response={ "status": "success", "flights": flight_data },
        scheduling="WHEN_IDLE" # Wait for a moment to tell the user
    )

    # 3. Send it back into the live session
    await session.send_tool_response(function_responses=[function_response])

Les règles suivantes peuvent être spécifiées dans le champ scheduling pour gérer les réponses des fonctions :

Stratégie de réponse SILENT

Avec la règle SILENT, la réponse de la fonction est ajoutée au contexte du modèle, mais le modèle ne génère pas de réponse pour celle-ci, et toute interaction utilisateur en cours n'est pas interrompue.

User: Please book the 2:00 PM flight to New York for me.

Model: function_call: {name: "book_ticket"}
//(The book_ticket function call is sent to the client and starts running asynchronously in the background.)

User: What is the current time in New York?
Model: The current time in New York is 12:00pm.

//(The book_ticket function finishes, and client sends the result with scheduling: "SILENT".)
Function_response: {name: "book_ticket", scheduling: "SILENT", response: {booking_status: "booked"}}
//(The model doesn't generate a response for the function response.)

User: Is my flight ticket booked?
Model: Yes. Your flight has been booked.

Stratégie de réponse WHEN_IDLE

Avec la règle WHEN_IDLE, le modèle génère une réponse à la réponse de la fonction uniquement lorsqu'il n'y a pas d'interaction de l'utilisateur active. Si une interaction utilisateur est en cours, le modèle attend qu'elle se termine avant de générer une réponse pour éviter toute interruption.

User: Please book the 2:00 PM flight to New York for me.

Model: function_call: {name: "book_ticket"}
//(The book_ticket function call is sent to the client and starts running asynchronously in the background.)

User: What is the current time in New York?

//(The book_ticket function finishes, and client sends the result with scheduling: "WHEN_IDLE".)
Function_response: {name: "book_ticket", scheduling: "WHEN_IDLE", response: {booking_status: "booked"}}
//(The ongoing interaction about the time is not interrupted.)

Model: The current time in New York is 12:00pm.
//(After responding to the user's time query, the model issues the response for the book_ticket function.)
Model: Your flight has been booked. Expect a confirmation text on your phone within 5 minutes.

Stratégie de réponse INTERRUPT

Avec la règle INTERRUPT, le modèle génère immédiatement une réponse à la réponse de la fonction, ce qui interrompt toute interaction de l'utilisateur en cours.

User: Please book the 2:00 PM flight to New York for me.

Model: function_call: {name: "book_ticket"}
//(The book_ticket function call is sent to the client and starts running asynchronously in the background.)

User: What is the current time in New York?

//(The book_ticket function finishes, and client sends the result with scheduling: "INTERRUPT".)
Function_response: {name: "book_ticket", scheduling: "INTERRUPT", response: {booking_status: "booked"}}
//(The ongoing interaction about the time is interrupted, and model skips responding to it.)

Model: Your flight has been booked. Expect a confirmation text on your phone within 5 minutes.

Bonnes pratiques

  • Concevez votre application pour la simultanéité : déchargez toujours les outils lents (comme l'interrogation d'API externes ou l'exécution de pipelines RAG) sur des tâches en arrière-plan dans votre backend. Laissez le modèle continuer à gérer le flux audio actif.
  • Évitez d'utiliser INTERRUPT, sauf si c'est nécessaire : utilisez INTERRUPT pour les alertes critiques. Pour les tâches en arrière-plan, SILENT ou WHEN_IDLE offre une expérience utilisateur beaucoup plus fluide et agréable.
  • Tours de discussion indépendants : dans l'API Gemini Live, l'exécution des outils est totalement indépendante des tours de discussion. La conversation peut se ramifier, se poursuivre et se dérouler naturellement pendant que votre outil traite la demande en arrière-plan.
  • La mise en garde "Silent" : Il est possible que le modèle tente encore de narrer verbalement l'exécution d'un outil, même s'il est programmé comme SILENT. Pour imposer un silence total, ajoutez des garde-fous explicites à vos instructions système (par exemple, "Lorsque vous utilisez [Nom de l'outil], effectuez une EXÉCUTION SILENCIEUSE et ne dites rien"), ou utilisez un modèle de backend "fire-and-forget" où vous n'envoyez pas de FunctionResponse au modèle.

Étapes suivantes

Présentation

Obtenez une présentation de l'API Live.

Référence

Guide de référence de l'API Live.

Guide

Découvrez comment démarrer et gérer des sessions en direct avec l'API Live.

Guide

Découvrez comment configurer les fonctionnalités Gemini pour l'API Live.