Conversas interativas com a API Live

A API Live permite interações bidirecionais de voz e vídeo de baixa latência com o Gemini.

Este guia explica como configurar uma conversa interativa bidirecional, ajustar as configurações de áudio, gerenciar sessões e muito mais.

Modelos compatíveis

É possível usar a API Live com os seguintes modelos:

Versão do modelo Nível de disponibilidade
gemini-live-2.5-flash Disponibilidade geral particular*
gemini-live-2.5-flash-preview-native-audio Pré-lançamento público

* Entre em contato com o representante da equipe da sua Conta do Google para solicitar acesso.

Iniciar uma conversa

Console

  1. Abra Vertex AI Studio > Transmitir em tempo real.
  2. Clique em Iniciar sessão para começar a conversa.

Para encerrar a sessão, clique em Parar sessão.

Python

Para ativar conversas interativas em tempo real, execute o exemplo a seguir em um computador local com acesso a microfone e alto-falante (não um notebook do Colab). Este exemplo configura uma conversa com a API, permitindo enviar comandos de áudio e receber respostas de áudio:

"""
# 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

Configure uma conversa com a API que permite enviar comandos de texto e receber respostas de áudio:

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

Inicie a conversa, insira seus comandos ou digite q, quit ou exit para sair.

await main()
      

Mudar as configurações de idioma e voz

A API Live usa o Chirp 3 para oferecer suporte a respostas de fala sintetizada em uma variedade de vozes e idiomas em alta definição. Para ver uma lista completa e demonstrações de cada voz, consulte Chirp 3: vozes em alta definição.

Para definir a voz e o idioma da resposta:

Console

  1. Abra Vertex AI Studio > Transmitir em tempo real.
  2. No expansor Saídas, selecione uma voz no menu suspenso Voz.
  3. No mesmo item, selecione um idioma no menu suspenso Idioma.
  4. Clique em Iniciar sessão para começar.

Python

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

Mudar as configurações de detecção de atividade de voz

A detecção de atividade de voz (VAD, na sigla em inglês) permite que o modelo reconheça quando uma pessoa está falando. Isso é essencial para criar conversas naturais, já que permite que um usuário interrompa o modelo a qualquer momento.

O modelo realiza automaticamente a detecção de atividade de voz (VAD) em um fluxo de entrada de áudio contínuo. É possível configurar as opções de VAD usando o campo realtimeInputConfig.automaticActivityDetection da mensagem de configuração. Quando a VAD detecta uma interrupção, a geração em andamento é cancelada e descartada. Apenas as informações já enviadas ao cliente são mantidas no histórico da sessão. O servidor envia uma mensagem para informar sobre a interrupção.

Se o stream de áudio pausar por mais de um segundo (por exemplo, se o usuário desativar o microfone), envie um evento audioStreamEnd para limpar o áudio em cache. O cliente pode retomar o envio de dados de áudio a qualquer momento.

Se preferir, desative a VAD automática definindo realtimeInputConfig.automaticActivityDetection.disabled como true na mensagem de configuração. Com essa configuração, o cliente detecta a fala do usuário e envia mensagens activityStart e activityEnd nos momentos adequados. Um audioStreamEnd não é enviado. As interrupções são marcadas por 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)}"))
      

Ampliar uma sessão

A duração máxima padrão de uma sessão de conversa é de 10 minutos. Uma notificação goAway (BidiGenerateContentServerMessage.goAway) é enviada ao cliente 60 segundos antes do fim da sessão.

É possível aumentar a duração da sessão em incrementos de 10 minutos usando o SDK da IA generativa. Não há limite para o número de vezes que você pode estender uma sessão. Para um exemplo, consulte Ativar e desativar a retomada de sessão.

Janela de contexto

A janela de contexto da API Live é usada para armazenar dados transmitidos em tempo real (25 tokens por segundo (TPS) para áudio e 258 TPS para vídeo) e outros conteúdos, incluindo entradas de texto e saídas de modelo.

Se a janela de contexto exceder o tamanho máximo (definido usando o controle deslizante Tamanho máximo do conteúdo no Vertex AI Studio ou trigger_tokens na API), as conversas mais antigas serão truncadas usando a compressão da janela de contexto para evitar o encerramento abrupto da sessão. A compressão da janela de contexto é acionada quando ela atinge o comprimento máximo (definido no Vertex AI Studio usando o controle deslizante Tamanho do contexto de destino ou usando target_tokens na API) e exclui as partes mais antigas da conversa até que a contagem total de tokens volte ao tamanho de destino.

Por exemplo, se o tamanho máximo do contexto for definido como 32000 tokens e o tamanho desejado for 16000 tokens:

  1. Turno 1:a conversa começa. Neste exemplo, a solicitação usa 12.000 tokens.
    • Tamanho total do contexto: 12.000 tokens
  2. Turno 2:você faz outra solicitação. Essa solicitação usa mais 12.000 tokens.
    • Tamanho total do contexto: 24.000 tokens
  3. Turno 3:você faz outra solicitação. Essa solicitação usa 14.000 tokens.
    • Tamanho total do contexto: 38.000 tokens

Como o tamanho total do contexto agora é maior que o máximo de 32.000 tokens, a compressão da janela de contexto é acionada. O sistema volta ao início da conversa e começa a excluir turnos antigos até que o tamanho total do token seja menor que a meta de 16.000 tokens:

  • Ele exclui Turn 1 (12.000 tokens). O total agora é de 26.000 tokens, o que ainda é maior do que a meta de 16.000 tokens.
  • Ele exclui Turn 2 (12.000 tokens). O total agora é de 14.000 tokens.

O resultado final é que apenas o Turn 3 permanece na memória ativa, e a conversa continua a partir desse ponto.

Os comprimentos mínimo e máximo para o comprimento do contexto e o tamanho da meta são:

Configuração (flag da API) Valor mínimo Valor máximo
Tamanho máximo de contexto (trigger_tokens) 5.000 128.000
Tamanho do contexto pretendido (target_tokens) 0 128.000

Para definir a janela de contexto:

Console

  1. Abra Vertex AI Studio > Transmitir em tempo real.
  2. Clique para abrir o menu Avançado.
  3. Na seção Contexto da sessão, use o controle deslizante Tamanho máximo do contexto para definir um valor entre 5.000 e 128.000.
  4. (Opcional) Na mesma seção, use o controle deslizante Tamanho do contexto de destino para definir o tamanho de destino como um valor entre 0 e 128.000.

Python

Defina os campos context_window_compression.trigger_tokens e context_window_compression.sliding_window.target_tokens na mensagem de configuração:

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

Sessões simultâneas

É possível ter até 5.000 sessões simultâneas por projeto.

Atualizar instruções do sistema durante uma sessão

Com a API Live, é possível atualizar as instruções do sistema durante uma sessão ativa. Use isso para adaptar as respostas do modelo, como mudar o idioma ou modificar o tom.

Para atualizar as instruções do sistema no meio da sessão, envie conteúdo de texto com a função system. A instrução atualizada vai permanecer em vigor durante o restante da sessão.

Python

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

Ativar e desativar a retomada da sessão

Com a retomada de sessão, você pode se reconectar a uma sessão anterior em até 24 horas. Isso é feito armazenando dados em cache, incluindo texto, vídeo, comandos de áudio e saídas do modelo. A privacidade no nível do projeto é aplicada a esses dados armazenados em cache.

Por padrão, a retomada de sessão está desativada.

Para ativar o recurso de retomada de sessão, defina o campo sessionResumption da mensagem BidiGenerateContentSetup. Se ativado, o servidor fará periodicamente um snapshot dos contextos de sessão em cache atuais e o armazenará no armazenamento interno.

Quando um snapshot é criado com sucesso, um resumptionUpdate é retornado com o ID do identificador que você pode registrar e usar mais tarde para retomar a sessão do snapshot.

Confira um exemplo de como ativar a retomada de sessão e recuperar o ID do identificador:

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

Para retomar a sessão sem problemas, ative o modo transparente:

Python

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

Depois que o modo transparente é ativado, o índice da mensagem do cliente que corresponde ao snapshot de contexto é retornado explicitamente. Isso ajuda a identificar qual mensagem do cliente você precisa enviar novamente ao retomar a sessão do identificador de retomada.

Mais informações

Para mais informações sobre como usar a API Live, consulte: