Chiamata di funzione asincrona con l'API Gemini Live

Quando crei agenti vocali in tempo reale, alcune chiamate di funzione possono bloccare l'esecuzione del modello, causando l'interruzione del flusso audio e l'utente che rimane in attesa in silenzio. Con l'API Gemini Live, tutte le chiamate di funzione non sono bloccanti per impostazione predefinita, il che ti consente di eseguire le funzioni in parallelo con il flusso di conversazione principale. Questo processo è chiamato chiamata di funzione asincrona. Il backend può elaborare attività complesse come la ricerca dei prezzi dei voli in tempo reale o l'esecuzione di query su API esterne complesse in background, mentre il modello continua ad ascoltare, parlare e conversare in modo naturale con l'utente. L'API Gemini Live consente alle chiamate di funzione di essere elaborate in background senza interrompere l'interazione dell'utente con il modello, consentendo interazioni più fluide e in tempo reale.

La chiamata di funzione asincrona ti consente di completare attività come la prenotazione di appuntamenti, l'impostazione di promemoria o il recupero di dati senza mettere in pausa la conversazione. Ad esempio, un utente può richiedere di prenotare un volo e chiedere immediatamente informazioni sul meteo mentre la prenotazione viene elaborata in background.

Esempio di chiamata di funzione asincrona

Questo esempio mostra un utente che prenota un volo e chiede l'ora a New York mentre la funzione book_ticket viene eseguita in modo asincrono in background:

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.

Implementare la chiamata di funzione asincrona

Questa sezione fornisce una serie di esempi che utilizzano la versione Python dell'SDK Agent Platform per creare un'architettura simultanea e altamente reattiva che utilizza la funzionalità di chiamata di funzione asincrona dell'API Gemini Live. Gli esempi sono suddivisi nelle seguenti attività:

Definisci gli strumenti

La chiamata di funzione asincrona è abilitata a livello di modello, quindi puoi specificare gli strumenti che vuoi utilizzare nella configurazione della richiesta come faresti per qualsiasi API Gemini standard nella chiamata di Gemini Enterprise Agent Platform. In questo modo, il modello può continuare a conversare mentre lo strumento viene eseguito:

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]}]

Gestisci le chiamate di funzione dal flusso di messaggi

Quando il modello deve chiamare una o più funzioni, l'API Gemini Live invia un evento tool_call tramite il flusso di messaggi in tempo reale.

Il backend non deve bloccare il flusso perché il modello prevede di continuare a essere eseguito. Quando ricevi una chiamata per una funzione lenta (ad esempio search_live_flights), devi passarla a un worker in background. Se utilizzi un await direttamente nel ciclo di messaggi principale per un'attività di 10 secondi, la connessione verrà bloccata. Le attività rapide (ad esempio get_current_weather) possono essere attese in sicurezza.

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)

Gestisci le aspettative degli utenti

Per gestire le aspettative durante le chiamate di funzione asincrone a lunga esecuzione, ti consigliamo di chiedere al client di avviare un messaggio di testo. Questo messaggio deve richiedere al sistema di informare l'utente che la richiesta è in fase di elaborazione e di chiedere la sua pazienza. Ad esempio, dopo che il client ha ricevuto una chiamata di funzione, può inviare un messaggio di testo al modello, ad esempio: "ripeti questa frase: 'Sto prenotando il tuo biglietto, attendi'".

La seguente finestra di dialogo di esempio mostra questo scambio:

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.

Questa strategia di messaggistica proattiva presenta i seguenti vantaggi:

  • Informa l'utente delle operazioni di sistema correnti, il che gestisce le aspettative durante le chiamate di funzione a lunga esecuzione.
  • Riduce la frequenza dei prompt utente brevi e ridondanti, ad esempio "ciao?" o "ci sei?". Questi si verificano spesso durante i lunghi periodi di silenzio del sistema durante l'elaborazione delle chiamate di funzione asincrone. In questo modo è possibile ridurre al minimo il rischio di chiamate di funzione duplicate attivate da queste richieste utente ripetute.
  • Fornire un prompt di sistema aggiuntivo può ridurre la probabilità di creare chiamate duplicate nelle interazioni successive.

Gestire le chiamate di funzione duplicate

Esiste una piccola probabilità che il modello generi chiamate di funzione duplicate prima di ricevere una risposta alla prima chiamata. Se il tuo caso d'uso lo consente, l'applicazione può ignorare le chiamate di funzione duplicate se una risposta alla stessa chiamata di funzione è ancora in attesa.

L'esempio seguente mostra come un client può ignorare una chiamata di funzione duplicata:

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.

Gestire le risposte di funzione asincrone

Al termine di una chiamata di funzione asincrona, l'applicazione invia il risultato al modello in una function_response. Mentre il backend elabora una chiamata di funzione, ad esempio la ricerca di voli, l'utente potrebbe porre al modello una domanda completamente diversa, ad esempio "Che tempo fa a Londra?". Il modello risponderà alla richiesta in tempo reale, in parallelo con l'esecuzione della chiamata di funzione. Poiché l'utente potrebbe essere in un'interazione continua con il modello al termine dell'esecuzione della funzione, puoi specificare una policy che definisce il modo in cui il modello deve gestire questa risposta in entrata. Puoi specificare una delle seguenti policy:

Per specificare una policy, includi il campo scheduling nel payload function_response:

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

Se ometti il campo scheduling, l'API Gemini Live utilizza il metodo originale per la gestione delle risposte di funzione per la compatibilità con le versioni precedenti.

Il seguente esempio Python mostra come formattare e inviare una function_response con scheduling="WHEN_IDLE" per attendere una pausa naturale nella conversazione prima di annunciare i risultati:

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])

Nel campo scheduling è possibile specificare le seguenti policy per la gestione delle risposte di funzione:

Policy di risposta SILENT

Con la policy SILENT, la risposta di funzione viene aggiunta al contesto del modello, ma il modello non genera una risposta e l'interazione utente in corso non viene interrotta.

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.

Policy di risposta WHEN_IDLE

Con la policy WHEN_IDLE, il modello genera una risposta alla risposta di funzione solo quando non è presente un'interazione utente attiva. Se è in corso un'interazione utente, il modello attende il completamento prima di generare una risposta per evitare interruzioni.

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.

Policy di risposta INTERRUPT

Con la policy INTERRUPT, il modello genera immediatamente una risposta alla risposta di funzione, interrompendo qualsiasi interazione utente in corso.

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.

Best practice

  • Progettare per la simultaneità: scarica sempre gli strumenti lenti (ad esempio l'esecuzione di query su API esterne o l'esecuzione di pipeline RAG) nelle attività in background nel backend. Consenti al modello di continuare a gestire lo stream audio attivo.
  • Evita INTERRUPT se non necessario: utilizza INTERRUPT per gli avvisi critici. Per le attività in background, SILENT o WHEN_IDLE offrono un'esperienza utente molto più fluida e cortese.
  • Turni di chat indipendenti: nell'API Gemini Live, l'esecuzione degli strumenti è completamente indipendente dai turni di chat. La conversazione può ramificarsi, continuare e fluire in modo naturale mentre lo strumento viene elaborato in background.
  • Avviso "Silenzioso": il modello potrebbe comunque provare occasionalmente a narrare verbalmente l'esecuzione di uno strumento anche se è pianificato come SILENT. Per applicare il silenzio effettivo, aggiungi guardrail espliciti alle istruzioni di sistema (ad esempio, "Quando utilizzi [Nome strumento], esegui un'ESECUZIONE SILENZIOSA e non dire nulla") oppure utilizza un pattern di backend "fire-and-forget" in cui non invii affatto una FunctionResponse al modello.

Passaggi successivi

Panoramica

Scopri una panoramica dell'API Live.

Riferimento

Guida di riferimento per l'API Live.

Guida

Scopri come avviare e gestire le sessioni live con l'API Live.

Guida

Scopri come configurare le funzionalità di Gemini per l'API Live.