Session management with Live API

En la API de Live, una sesión hace referencia a una conexión persistente en la que la entrada y la salida se transmiten de forma continua a través de la misma conexión (obtén más información sobre cómo funciona). Este diseño de sesión único permite una latencia baja y admite funciones únicas, pero también puede presentar desafíos, como límites de tiempo de la sesión y finalización anticipada. En esta guía, se abordan estrategias para superar los desafíos de administración de sesiones que pueden surgir cuando se usa la API de Live.

Ciclo de vida de la sesión

Sin compresión, las sesiones de solo audio se limitan a 15 minutos y las sesiones de audio y video se limitan a 2 minutos. Si superas estos límites, se finalizará la sesión (y, por lo tanto, la conexión), pero puedes usar la compresión de la ventana de contexto para extender las sesiones por un tiempo ilimitado.

La vida útil de una conexión también es limitada, alrededor de 10 minutos. Cuando finaliza la conexión, también finaliza la sesión. En este caso, puedes configurar una sola sesión para que permanezca activa en varias conexiones con la reanudación de la sesión. También recibirás un mensaje GoAway antes de que finalice la conexión, lo que te permitirá realizar más acciones.

Compresión de la ventana de contexto

Para habilitar sesiones más largas y evitar la terminación abrupta de la conexión, puedes habilitar la compresión de la ventana de contexto configurando el campo contextWindowCompression como parte de la configuración de la sesión.

En ContextWindowCompressionConfig, puedes configurar un mecanismo de ventana deslizante y la cantidad de tokens que activa la compresión.

Python

from google.genai import types

config = types.LiveConnectConfig(
    response_modalities=["AUDIO"],
    context_window_compression=(
        # Configures compression with default parameters.
        types.ContextWindowCompressionConfig(
            sliding_window=types.SlidingWindow(),
        )
    ),
)

JavaScript

const config = {
  responseModalities: [Modality.AUDIO],
  contextWindowCompression: { slidingWindow: {} }
};

Reanudación de la sesión

Para evitar que se cierre la sesión cuando el servidor restablezca periódicamente la conexión de WebSocket, configura el campo sessionResumption dentro de la configuración de configuración.

Si pasas esta configuración, el servidor enviará mensajes SessionResumptionUpdate, que se pueden usar para reanudar la sesión pasando el último token de reanudación como SessionResumptionConfig.handle de la conexión posterior.

Python

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

client = genai.Client()
model = "gemini-live-2.5-flash-preview"

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

JavaScript

import { GoogleGenAI, Modality } from '@google/genai';

const ai = new GoogleGenAI({});
const model = 'gemini-live-2.5-flash-preview';

async function live() {
  const responseQueue = [];

  async function waitMessage() {
    let done = false;
    let message = undefined;
    while (!done) {
      message = responseQueue.shift();
      if (message) {
        done = true;
      } else {
        await new Promise((resolve) => setTimeout(resolve, 100));
      }
    }
    return message;
  }

  async function handleTurn() {
    const turns = [];
    let done = false;
    while (!done) {
      const message = await waitMessage();
      turns.push(message);
      if (message.serverContent && message.serverContent.turnComplete) {
        done = true;
      }
    }
    return turns;
  }

console.debug('Connecting to the service with handle %s...', previousSessionHandle)
const session = await ai.live.connect({
  model: model,
  callbacks: {
    onopen: function () {
      console.debug('Opened');
    },
    onmessage: function (message) {
      responseQueue.push(message);
    },
    onerror: function (e) {
      console.debug('Error:', e.message);
    },
    onclose: function (e) {
      console.debug('Close:', e.reason);
    },
  },
  config: {
    responseModalities: [Modality.TEXT],
    sessionResumption: { handle: previousSessionHandle }
    // The handle of the session to resume is passed here, or else null to start a new session.
  }
});

const inputTurns = 'Hello how are you?';
session.sendClientContent({ turns: inputTurns });

const turns = await handleTurn();
for (const turn of turns) {
  if (turn.sessionResumptionUpdate) {
    if (turn.sessionResumptionUpdate.resumable && turn.sessionResumptionUpdate.newHandle) {
      let newHandle = turn.sessionResumptionUpdate.newHandle
      // ...Store newHandle and start new session with this handle here
    }
  }
}

  session.close();
}

async function main() {
  await live().catch((e) => console.error('got error', e));
}

main();

Recibir un mensaje antes de que se desconecte la sesión

El servidor envía un mensaje GoAway que indica que la conexión actual se finalizará pronto. Este mensaje incluye timeLeft, que indica el tiempo restante y te permite realizar más acciones antes de que la conexión se cierre como ABORTED.

Python

async for response in session.receive():
    if response.go_away is not None:
        # The connection will soon be terminated
        print(response.go_away.time_left)

JavaScript

const turns = await handleTurn();

for (const turn of turns) {
  if (turn.goAway) {
    console.debug('Time left: %s\n', turn.goAway.timeLeft);
  }
}

Recibir un mensaje cuando se complete la generación

El servidor envía un mensaje generationComplete que indica que el modelo terminó de generar la respuesta.

Python

async for response in session.receive():
    if response.server_content.generation_complete is True:
        # The generation is complete

JavaScript

const turns = await handleTurn();

for (const turn of turns) {
  if (turn.serverContent && turn.serverContent.generationComplete) {
    // The generation is complete
  }
}

¿Qué sigue?

Explora más formas de trabajar con la API de Live en la guía completa de Funciones, la página Uso de herramientas o el libro de recetas de la API de Live.