Conversations interactives avec l'API Live

L'API Live permet des interactions vocales et vidéo bidirectionnelles à faible latence avec Gemini.

Ce guide explique comment configurer une conversation interactive bidirectionnelle, ajuster les paramètres audio, gérer les sessions et plus encore.

Modèles compatibles

Vous pouvez utiliser l'API Live avec les modèles suivants :

Version de modèle Niveau de disponibilité
gemini-live-2.5-flash DG privée*
gemini-live-2.5-flash-preview-native-audio Version Preview publique

* Contactez le représentant de l'équipe chargée de votre compte Google pour demander l'accès.

Démarrer une conversation

Console

  1. Ouvrez Vertex AI Studio > Diffuser en temps réel.
  2. Cliquez sur Démarrer la session pour lancer la conversation.

Pour mettre fin à la session, cliquez sur Arrêter la session.

Python

Pour activer les conversations interactives en temps réel, exécutez l'exemple suivant sur un ordinateur local avec accès au micro et aux haut-parleurs (et non dans un notebook Colab). Cet exemple configure une conversation avec l'API, ce qui vous permet d'envoyer des requêtes audio et de recevoir des réponses audio :

"""
# Installation
# on linux
sudo apt-get install portaudio19-dev

# on mac
brew install portaudio

python3 -m venv env
source env/bin/activate
pip install google-genai
"""

import asyncio
import pyaudio
from google import genai
from google.genai import types

CHUNK=4200
FORMAT=pyaudio.paInt16
CHANNELS=1
RECORD_SECONDS=5
MODEL = 'gemini-live-2.5-flash'
INPUT_RATE=16000
OUTPUT_RATE=24000

client = genai.Client(
    vertexai=True,
    project=GOOGLE_CLOUD_PROJECT,
    location=GOOGLE_CLOUD_LOCATION,
)
config = {
    "response_modalities": ["AUDIO"],
    "input_audio_transcription": {},  # Configure input transcription
    "output_audio_transcription": {},  # Configure output transcription
}

async def main():
    print(MODEL)
    p = pyaudio.PyAudio()
    async with client.aio.live.connect(model=MODEL, config=config) as session:
        #exit()
        async def send():
            stream = p.open(
                format=FORMAT, channels=CHANNELS, rate=INPUT_RATE, input=True, frames_per_buffer=CHUNK)
            while True:
                frame = stream.read(CHUNK)
                await session.send(input={"data": frame, "mime_type": "audio/pcm"})
                await asyncio.sleep(10**-12)
        async def receive():
            output_stream = p.open(
                format=FORMAT, channels=CHANNELS, rate=OUTPUT_RATE, output=True, frames_per_buffer=CHUNK)
            async for message in session.receive():
                if message.server_content.input_transcription:
                  print(message.server_content.model_dump(mode="json", exclude_none=True))
                if message.server_content.output_transcription:
                  print(message.server_content.model_dump(mode="json", exclude_none=True))
                if message.server_content.model_turn:
                    for part in message.server_content.model_turn.parts:
                        if part.inline_data.data:
                            audio_data=part.inline_data.data
                            output_stream.write(audio_data)
                            await asyncio.sleep(10**-12)
        send_task = asyncio.create_task(send())
        receive_task = asyncio.create_task(receive())
        await asyncio.gather(send_task, receive_task)

asyncio.run(main())
      

Python

Configurez une conversation avec l'API qui vous permet d'envoyer des requêtes textuelles et de recevoir des réponses audio :

# Set model generation_config
CONFIG = {"response_modalities": ["AUDIO"]}

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {bearer_token[0]}",
}

async def main() -> None:
    # Connect to the server
    async with connect(SERVICE_URL, additional_headers=headers) as ws:

        # Setup the session
        async def setup() -> None:
            await ws.send(
                json.dumps(
                    {
                        "setup": {
                            "model": "gemini-live-2.5-flash",
                            "generation_config": CONFIG,
                        }
                    }
                )
            )

            # Receive setup response
            raw_response = await ws.recv(decode=False)
            setup_response = json.loads(raw_response.decode("ascii"))
            print(f"Connected: {setup_response}")
            return

        # Send text message
        async def send() -> bool:
            text_input = input("Input > ")
            if text_input.lower() in ("q", "quit", "exit"):
                return False

            msg = {
                "client_content": {
                    "turns": [{"role": "user", "parts": [{"text": text_input}]}],
                    "turn_complete": True,
                }
            }

            await ws.send(json.dumps(msg))
            return True

        # Receive server response
        async def receive() -> None:
            responses = []

            # Receive chucks of server response
            async for raw_response in ws:
                response = json.loads(raw_response.decode())
                server_content = response.pop("serverContent", None)
                if server_content is None:
                    break

                model_turn = server_content.pop("modelTurn", None)
                if model_turn is not None:
                    parts = model_turn.pop("parts", None)
                    if parts is not None:
                        for part in parts:
                            pcm_data = base64.b64decode(part["inlineData"]["data"])
                            responses.append(np.frombuffer(pcm_data, dtype=np.int16))

                # End of turn
                turn_complete = server_content.pop("turnComplete", None)
                if turn_complete:
                    break

            # Play the returned audio message
            display(Markdown("**Response >**"))
            display(Audio(np.concatenate(responses), rate=24000, autoplay=True))
            return

        await setup()

        while True:
            if not await send():
                break
            await receive()
      

Démarrez la conversation, saisissez vos requêtes, ou saisissez q, quit ou exit pour quitter.

await main()
      

Modifier les paramètres de langue et de voix

L'API Live utilise Chirp 3 pour prendre en charge les réponses vocales synthétisées dans une variété de voix HD et de langues. Pour obtenir la liste complète et des démos de chaque voix, consultez Chirp 3 : voix HD.

Pour définir la langue et la voix de la réponse :

Console

  1. Ouvrez Vertex AI Studio > Diffuser en temps réel.
  2. Développez Sorties et sélectionnez une voix dans la liste déroulante Voix.
  3. Dans le même panneau, sélectionnez une langue dans la liste déroulante Langue.
  4. Cliquez sur Démarrer la session pour démarrer la session.

Python

config = LiveConnectConfig(
    response_modalities=["AUDIO"],
    speech_config=SpeechConfig(
        voice_config=VoiceConfig(
            prebuilt_voice_config=PrebuiltVoiceConfig(
                voice_name=voice_name,
            )
        ),
        language_code="en-US",
    ),
)
      

Modifier les paramètres de détection de l'activité vocale

La détection de l'activité vocale (VAD, Voice Activity Detection) permet au modèle de reconnaître quand une personne parle. C'est essentiel pour créer des conversations naturelles, car cela permet à un utilisateur d'interrompre le modèle à tout moment.

Le modèle détecte automatiquement l'activité vocale (VAD) sur un flux d'entrée audio continu. Vous pouvez configurer les paramètres de la VAD à l'aide du champ realtimeInputConfig.automaticActivityDetection du message de configuration. Lorsque la VAD détecte une interruption, la génération en cours est annulée et supprimée. Seules les informations déjà envoyées au client sont conservées dans l'historique de la session. Le serveur envoie ensuite un message pour signaler l'interruption.

Si le flux audio est mis en pause pendant plus d'une seconde (par exemple, si l'utilisateur désactive le micro), envoyez un événement audioStreamEnd pour vider l'audio mis en cache. Le client peut reprendre l'envoi des données audio à tout moment.

Vous pouvez également désactiver la VAD automatique en définissant realtimeInputConfig.automaticActivityDetection.disabled sur true dans le message de configuration. Dans cette configuration, le client détecte la parole de l'utilisateur et envoie les messages activityStart et activityEnd au moment opportun. Aucun audioStreamEnd n'est envoyé. Les interruptions sont indiquées par activityEnd.

Python

config = LiveConnectConfig(
    response_modalities=["TEXT"],
    realtime_input_config=RealtimeInputConfig(
        automatic_activity_detection=AutomaticActivityDetection(
            disabled=False,  # default
            start_of_speech_sensitivity=StartSensitivity.START_SENSITIVITY_LOW, # Either START_SENSITIVITY_LOW or START_SENSITIVITY_HIGH
            end_of_speech_sensitivity=EndSensitivity.END_SENSITIVITY_LOW, # Either END_SENSITIVITY_LOW or END_SENSITIVITY_HIGH
            prefix_padding_ms=20,
            silence_duration_ms=100,
        )
    ),
)

async with client.aio.live.connect(
    model=MODEL_ID,
    config=config,
) as session:
    audio_bytes = Path("sample.pcm").read_bytes()

    await session.send_realtime_input(
        media=Blob(data=audio_bytes, mime_type="audio/pcm;rate=16000")
    )

    # if stream gets paused, send:
    # await session.send_realtime_input(audio_stream_end=True)

    response = []
    async for message in session.receive():
        if message.server_content.interrupted is True:
            # The model generation was interrupted
            response.append("The session was interrupted")

        if message.text:
            response.append(message.text)

    display(Markdown(f"**Response >** {''.join(response)}"))
      

Prolonger une session

La durée maximale par défaut d'une session de conversation est de 10 minutes. Une notification goAway (BidiGenerateContentServerMessage.goAway) est envoyée au client 60 secondes avant la fin de la session.

Vous pouvez prolonger la durée de la session par incréments de 10 minutes à l'aide du SDK Gen AI. Vous pouvez prolonger une session autant de fois que vous le souhaitez. Pour obtenir un exemple, consultez Activer et désactiver la reprise de session.

Fenêtre de contexte

La fenêtre de contexte de l'API Live est utilisée pour stocker les données diffusées en temps réel (25 jetons par seconde (TPS) pour l'audio et 258 TPS pour la vidéo) et d'autres contenus, y compris les entrées textuelles et les sorties de modèle.

Si la fenêtre de contexte dépasse la longueur maximale (définie à l'aide du curseur Taille max. du contenu dans Vertex AI Studio ou trigger_tokens dans l'API), les tours les plus anciens sont tronqués à l'aide de la compression de la fenêtre de contexte pour éviter une fin de session abrupte. La compression de la fenêtre de contexte se déclenche lorsque la fenêtre de contexte atteint sa longueur maximale (définie dans Vertex AI Studio à l'aide du curseur Taille du contexte cible ou à l'aide de target_tokens dans l'API). Elle supprime les parties les plus anciennes de la conversation jusqu'à ce que le nombre total de jetons revienne à cette taille cible.

Par exemple, si la longueur maximale du contexte est définie sur 32000 jetons et que la taille cible est définie sur 16000 jetons :

  1. Tour 1 : la conversation commence. Dans cet exemple, la requête utilise 12 000 jetons.
    • Taille totale du contexte : 12 000 jetons
  2. Tour 2 : vous faites une autre demande. Cette requête utilise 12 000 jetons supplémentaires.
    • Taille totale du contexte : 24 000 jetons
  3. Tour 3 : Vous faites une autre demande. Cette requête utilise 14 000 jetons.
    • Taille totale du contexte : 38 000 jetons

Étant donné que la taille totale du contexte est désormais supérieure à la limite de 32 000 jetons, la compression de la fenêtre de contexte est déclenchée. Le système revient au début de la conversation et commence à supprimer les anciens tours jusqu'à ce que la taille totale des jetons soit inférieure à l'objectif de 16 000 jetons :

  • Il supprime Tour 1 (12 000 jetons). Le total est désormais de 26 000 jetons, ce qui est toujours supérieur à l'objectif de 16 000 jetons.
  • Il supprime le tour 2 (12 000 jetons). Le total est désormais de 14 000 jetons.

Le résultat final est que seul Tour 3 reste dans la mémoire active, et la conversation se poursuit à partir de ce point.

Les longueurs minimales et maximales pour la longueur du contexte et la taille cible sont les suivantes :

Paramètre (option d'API) Valeur minimale Valeur maximale
Longueur maximale du contexte (trigger_tokens) 5 000 128 000
Taille du contexte cible (target_tokens) 0 128 000

Pour définir la fenêtre de contexte :

Console

  1. Ouvrez Vertex AI Studio > Diffuser en temps réel.
  2. Cliquez pour ouvrir le menu Avancé.
  3. Dans la section Contexte de session, utilisez le curseur Taille maximale du contexte pour définir la taille du contexte sur une valeur comprise entre 5 000 et 128 000.
  4. (Facultatif) Dans la même section, utilisez le curseur Taille du contexte cible pour définir la taille cible sur une valeur comprise entre 0 et 128 000.

Python

Définissez les champs context_window_compression.trigger_tokens et context_window_compression.sliding_window.target_tokens dans le message de configuration :

config = types.LiveConnectConfig(
      temperature=0.7,
      response_modalities=['TEXT'],
      system_instruction=types.Content(
          parts=[types.Part(text='test instruction')], role='user'
      ),
      context_window_compression=types.ContextWindowCompressionConfig(
          trigger_tokens=1000,
          sliding_window=types.SlidingWindow(target_tokens=10),
      ),
  )
      

Sessions simultanées

Vous pouvez avoir jusqu'à 5 000 sessions simultanées par projet.

Mettre à jour les instructions système pendant une session

L'API Live vous permet de mettre à jour les instructions système pendant une session active. Cela vous permet d'adapter les réponses du modèle, par exemple en changeant la langue de la réponse ou en modifiant le ton.

Pour mettre à jour les instructions système en cours de session, vous pouvez envoyer du contenu textuel avec le rôle system. Les nouvelles instructions système s'appliqueront pour le reste de la session.

Python

session.send_client_content(
      turns=types.Content(
          role="system", parts=[types.Part(text="new system instruction")]
      ),
      turn_complete=False
  )
      

Activer et désactiver la reprise de session

La reprise de session vous permet de vous reconnecter à une session précédente dans un délai de 24 heures. Pour ce faire, nous stockons les données mises en cache, y compris les requêtes textuelles, vidéo et audio, ainsi que les sorties du modèle. La confidentialité au niveau du projet est appliquée à ces données mises en cache.

Par défaut, la reprise de session est désactivée.

Pour activer la fonctionnalité de reprise de session, définissez le champ sessionResumption du message BidiGenerateContentSetup. Si cette option est activée, le serveur prend régulièrement un instantané des contextes de la session en cours mise en cache et le stocke dans la mémoire de stockage interne.

Lorsqu'un instantané est pris, un resumptionUpdate est renvoyé avec l'ID de handle que vous pouvez enregistrer et utiliser ultérieurement pour reprendre la session à partir de l'instantané.

Voici un exemple d'activation de la reprise de session et de récupération de l'ID de handle :

Python

import asyncio
from google import genai
from google.genai import types

client = genai.Client(
    vertexai=True,
    project=GOOGLE_CLOUD_PROJECT,
    location=GOOGLE_CLOUD_LOCATION,
)
model = "gemini-live-2.5-flash"

async def main():
    print(f"Connecting to the service with handle {previous_session_handle}...")
    async with client.aio.live.connect(
        model=model,
        config=types.LiveConnectConfig(
            response_modalities=["AUDIO"],
            session_resumption=types.SessionResumptionConfig(
                # The handle of the session to resume is passed here,
                # or else None to start a new session.
                handle=previous_session_handle
            ),
        ),
    ) as session:
        while True:
            await session.send_client_content(
                turns=types.Content(
                    role="user", parts=[types.Part(text="Hello world!")]
                )
            )
            async for message in session.receive():
                # Periodically, the server will send update messages that may
                # contain a handle for the current state of the session.
                if message.session_resumption_update:
                    update = message.session_resumption_update
                    if update.resumable and update.new_handle:
                        # The handle should be retained and linked to the session.
                        return update.new_handle

                # For the purposes of this example, placeholder input is continually fed
                # to the model. In non-sample code, the model inputs would come from
                # the user.
                if message.server_content and message.server_content.turn_complete:
                    break

if __name__ == "__main__":
    asyncio.run(main())
      

Pour que la session reprenne de façon fluide, activez le mode transparent :

Python

types.LiveConnectConfig(
            response_modalities=["AUDIO"],
            session_resumption=types.SessionResumptionConfig(
                transparent=True,
    ),
)
      

Une fois le mode transparent activé, l'index du message client correspondant à l'instantané de contexte est renvoyé explicitement. Cela permet d'identifier le message client que vous devez renvoyer lorsque vous reprenez la session à partir du handle de reprise.

En savoir plus

Pour en savoir plus sur l'utilisation de l'API Live, consultez les ressources suivantes :