라이브 세션 시작 및 관리

Gemini Live API는 세션이라고 하는 연속적인 오디오 또는 텍스트 스트림을 처리하여 지연 시간이 짧은 음성 및 텍스트 상호작용을 지원하고, 즉각적이고 사람과 유사한 음성 대답을 제공합니다. 초기 핸드셰이크부터 정상 종료까지 세션 수명 주기 관리는 개발자가 제어합니다.

이 페이지에서는 Gemini Live API를 사용하여 Gemini 모델과의 대화 세션을 시작하는 방법을 보여줍니다. Vertex AI Studio, 생성형 AI SDK 또는 WebSockets를 사용하여 세션을 시작할 수 있습니다.

이 페이지에서는 다음 작업을 수행하는 방법도 보여줍니다.

  • 기본 시간 제한을 초과하여 세션 연장
  • 이전 세션 재개
  • 세션 중에 시스템 요청 사항 업데이트
  • 세션의 컨텍스트 윈도우 구성
  • 세션의 스크립트 작성 사용 설정

세션 수명

압축하지 않으면 오디오 전용 세션은 15분으로 제한되고 오디오-동영상 세션은 2분으로 제한됩니다. 이러한 한도를 초과하면 세션이 종료되지만 컨텍스트 윈도우 압축을 사용하여 세션을 무제한으로 연장할 수 있습니다.

연결 수명은 약 10분으로 제한됩니다. 연결이 종료되면 세션도 종료됩니다. 이 경우 세션 재개를 사용하여 여러 연결에서 활성 상태를 유지하도록 단일 세션을 구성할 수 있습니다. 연결이 종료되기 전에 GoAway 메시지가 표시되므로 추가 조치를 취할 수 있습니다.

최대 동시 실행 세션

사용한 만큼만 지불하는 요금제(PayGo)에서는 프로젝트당 최대 1,000개의 동시 세션을 사용할 수 있습니다. 프로비저닝된 처리량을 사용하는 고객에게는 이 한도가 적용되지 않습니다.

세션 시작

다음 탭에서는 Vertex AI Studio, 생성형 AI SDK 또는 WebSockets를 사용하여 실시간 대화 세션을 시작하는 방법을 보여줍니다.

콘솔

  1. Vertex AI Studio > 실시간 스트리밍을 엽니다.
  2. 세션 시작을 클릭하여 대화를 시작합니다.

세션을 종료하려면 세션 중지를 클릭합니다.

Python

시작하기 전에 API 키 또는 애플리케이션 기본 사용자 인증 정보(ADC)를 사용해 Vertex AI에 인증해야 합니다.

gcloud auth application-default login
      

인증 설정에 대한 자세한 내용은 빠른 시작을 참조하세요.

import asyncio
from google import genai

# Replace the PROJECT_ID and LOCATION with your Project ID and location. 
client = genai.Client(vertexai=True, project="PROJECT_ID", location="LOCATION")

# Configuration
MODEL = "gemini-live-2.5-flash-preview-native-audio-09-2025"
config = {
   "response_modalities": ["audio"],
}

async def main():
   # Establish WebSocket session
   async with client.aio.live.connect(model=MODEL, config=config) as session:
       print("Session established. Sending audio...")

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

Python

WebSocket을 사용하는 경우 표준 WebSocket 핸드셰이크를 사용하여 연결이 설정됩니다. 엔드포인트는 리전별이며 인증에 OAuth 2.0 Bearer 토큰을 사용합니다. 이 시나리오에서는 인증 토큰이 일반적으로 WebSocket 헤더(예: Authorization: Bearer [TOKEN])에 전달됩니다.

import asyncio
import websockets

# Replace the PROJECT_ID and LOCATION with your Project ID and location. 
PROJECT_ID = "PROJECT_ID"
LOCATION = "LOCATION"

# Authentication
token_list = !gcloud auth application-default print-access-token
ACCESS_TOKEN = token_list[0]

# Configuration
MODEL_ID = "gemini-live-2.5-flash-preview-native-audio-09-2025"
MODEL = f"projects/{PROJECT_ID}/locations/{LOCATION}/publishers/google/models/{MODEL_ID}"
config = {
   "response_modalities": ["audio"],
}

# Construct the WSS URL
HOST = f"{LOCATION}-aiplatform.googleapis.com"
URI = f"wss://{HOST}/ws/google.cloud.aiplatform.v1.LlmBidiService/BidiGenerateContent"

async def main():
   headers = {"Authorization": f"Bearer {ACCESS_TOKEN}"}
  
   async with websockets.connect(URI, additional_headers=headers) as ws:
       print("Session established.")

       # Send Setup (Handshake)
       await ws.send(json.dumps({
           "setup": {
               "model": MODEL,
               "generation_config": config
           }
       }))
    # Send audio/video ...

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

세션 연장

대화 세션의 최대 길이 기본값은 10분입니다. 세션이 종료되기 60초 전에 goAway 알림(BidiGenerateContentServerMessage.goAway)이 클라이언트에 전송됩니다.

10분 연결 제한을 초과하여 세션을 연장하려면 세션 재개를 사용하여 다시 연결해야 합니다. goAway 알림을 수신하거나 다른 이유로 연결이 종료되면 세션 중에 획득한 세션 핸들을 사용하여 새 연결을 시작할 수 있습니다. 이렇게 하면 새 연결에서 컨텍스트가 그대로 유지된 상태로 세션이 재개됩니다. 이 작업은 횟수 제한 없이 수행할 수 있습니다. 세션 재개 예시는 이전 세션 재개를 참조하세요.

다음 예시에서는 goAway 알림을 리슨하여 임박한 세션 종료를 감지하는 방법을 보여줍니다.

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)
      

이전 세션 재개

Gemini Live API는 사용자가 일시적인 연결 해제(예: Wi-Fi에서 5G로 전환) 중에 대화 컨텍스트를 잃지 않도록 세션 재개를 지원합니다. 24시간 이내에 이전 세션을 재개할 수 있습니다. 세션 재개는 텍스트, 동영상, 오디오 프롬프트, 모델 출력 등 캐시된 데이터를 저장하여 이루어집니다. 캐시된 데이터에는 프로젝트 수준의 개인 정보 보호가 적용됩니다.

기본적으로 세션 재개는 중지되어 있습니다. 세션 재개를 사용 설정하려면 BidiGenerateContentSetup 메시지의 sessionResumption 필드를 설정합니다. 사용 설정된 경우 서버는 session_id 및 재개 토큰이 포함된 SessionResumptionUpdate 메시지를 주기적으로 전송합니다. WebSocket이 연결 해제되면 클라이언트는 다시 연결하고 새 설정 메시지에 이러한 사용자 인증 정보를 포함할 수 있습니다. 그러면 서버가 이전 컨텍스트를 복원하여 대화가 원활하게 계속될 수 있습니다.

재개 기간은 유한합니다(일반적으로 약 10분). 이 시간 내에 클라이언트가 다시 연결되지 않으면 서버 리소스를 확보하기 위해 세션 상태가 삭제됩니다.

다음 예시에서는 서비스에 연결하고, 세션 재개 핸들을 가져오고, 연결 해제를 시뮬레이션한 다음, 핸들을 사용하여 다시 연결하여 세션을 재개합니다.

Python

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

# Replace the PROJECT_ID and LOCATION with your Project ID and location.
client = genai.Client(vertexai=True, project="PROJECT_ID", location="LOCATION")

# Configuration
MODEL = "gemini-live-2.5-flash-preview-native-audio-09-2025"

async def resumable_session_example():
    """Demonstrates session resumption by connecting, disconnecting, and reconnecting."""
    session_handle = None

    print("Starting a new session...")
    try:
        async with client.aio.live.connect(
            model=MODEL,
            config=types.LiveConnectConfig(
                response_modalities=["audio"],
                session_resumption_config=types.SessionResumptionConfig(handle=None),
            ),
        ) as session:
            await session.send_content(
                content=types.Content(role="user", parts=[types.Part(text="Hello!")])
            )
            async for message in session.receive():
                if message.session_resumption_update:
                    update = message.session_resumption_update
                    if update.resumable and update.new_handle:
                        session_handle = update.new_handle
                        print(f"Received session handle: {session_handle}")
                        # For demonstration, we break to simulate a disconnect
                        # after receiving a handle.
                        break
                if message.server_content and message.server_content.turn_complete:
                    break
    except websockets.exceptions.WebSocketException as e:
        print(f"Initial connection failed: {e}")
        return

    if not session_handle:
        print("Did not receive a session handle. Cannot demonstrate resumption.")
        return

    print(f"\nSimulating disconnect and reconnecting with handle {session_handle}...")

    try:
        async with client.aio.live.connect(
            model=MODEL,
            config=types.LiveConnectConfig(
                response_modalities=["audio"],
                session_resumption_config=types.SessionResumptionConfig(handle=session_handle),
            ),
        ) as session:
            print("Successfully resumed session.")
            await session.send_content(
                content=types.Content(role="user", parts=[types.Part(text="I am back!")])
            )
            async for message in session.receive():
                if message.session_resumption_update:
                    update = message.session_resumption_update
                    if update.resumable and update.new_handle:
                        session_handle = update.new_handle
                        print(f"Received updated session handle: {session_handle}")
                if message.server_content:
                    print(f"Received server content: {message.server_content}")
                    if message.server_content.turn_complete:
                        break
            print("Resumed session finished.")
    except websockets.exceptions.WebSocketException as e:
        print(f"Failed to resume session: {e}")

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

투명 모드로 원활한 세션 재개 사용 설정

세션 재개를 사용 설정할 때 투명 모드를 사용 설정하여 사용자의 재개 프로세스를 더 원활하게 만들 수도 있습니다. 투명 모드가 사용 설정되면 컨텍스트 스냅샷에 해당하는 클라이언트 메시지의 색인이 명시적으로 반환됩니다. 이렇게 하면 재개 핸들에서 세션을 재개할 때 다시 전송해야 하는 클라이언트 메시지를 식별할 수 있습니다.

투명 모드를 사용 설정하려면 다음 단계를 따르세요.

Python

config = {
   "response_modalities": ["audio"],
   "session_resumption_config": {
    "transparent": True,
   }
}
      

세션 중에 시스템 요청 사항 업데이트

Gemini Live API를 사용하면 활성 세션 중에 시스템 요청 사항을 업데이트할 수 있습니다. 이를 사용하여 대답 언어를 변경하거나 어조를 수정하는 등 모델의 대답을 조정합니다.

세션 중에 시스템 요청 사항을 업데이트하려면 system 역할로 텍스트 콘텐츠를 전송하면 됩니다. 업데이트된 시스템 요청 사항이 남은 세션 동안 적용됩니다.

Python

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

세션의 컨텍스트 윈도우 구성

Gemini Live API 컨텍스트 윈도우는 실시간 스트리밍 데이터(오디오의 경우 초당 토큰(TPS) 25개, 동영상의 경우 TPS 258개)와 텍스트 입력, 모델 출력 등 기타 콘텐츠를 저장하는 데 사용됩니다. 세션의 컨텍스트 윈도우 한도는 다음과 같습니다.

  • 네이티브 오디오 모델의 경우 128,000개 토큰
  • 기타 Live API 모델의 경우 32,000개 토큰

장기 실행 세션에서는 대화가 진행됨에 따라 오디오 및 텍스트 토큰의 기록이 누적됩니다. 이 기록이 모델의 한도를 초과하면 모델이 할루시네이션을 일으키거나 속도가 느려지거나 세션이 강제로 종료될 수 있습니다. 더 긴 세션을 사용 설정하려면 세션 구성의 일부로 contextWindowCompression 필드를 설정하여 컨텍스트 윈도우 압축을 사용 설정하면 됩니다.

컨텍스트 윈도우 압축은 사용 설정된 경우 서버 측 슬라이딩 윈도우를 사용하여 가장 오래된 턴을 자릅니다. 누적된 토큰이 정의된 최대 길이(Vertex AI Studio의 최대 콘텐츠 크기 슬라이더 또는 API의 trigger_tokens를 사용하여 설정)를 초과하면, 서버는 한도 내에서 컨텍스트를 유지하기 위해 가장 오래된 턴을 자동으로 삭제하거나 요약합니다. ContextWindowCompressionConfig에서 슬라이딩 윈도우 메커니즘과 압축을 트리거하는 target_tokens 파라미터에 정의된 토큰 수를 구성할 수 있습니다.

이렇게 하면 '메모리'가 지속적으로 관리되므로 사용자의 관점에서 이론적으로 무한한 세션 기간이 가능합니다. 압축이 없으면 오디오 전용 세션이 엄격한 제한에 도달하기 전에 약 15분으로 제한될 수 있습니다.

컨텍스트 길이와 대상 크기의 최소 및 최대 길이는 다음과 같습니다.

설정(API 플래그) 최솟값 최댓값
최대 컨텍스트 길이(trigger_tokens) 5,000 128,000
대상 컨텍스트 크기(target_tokens) 0 128,000

컨텍스트 윈도우를 설정하려면 다음 단계를 따르세요.

콘솔

  1. Vertex AI Studio > 실시간 스트리밍을 엽니다.
  2. 클릭하여 고급 메뉴를 엽니다.
  3. 세션 컨텍스트 섹션에서 최대 컨텍스트 크기 슬라이더를 사용하여 컨텍스트 크기를 5,000~128,000 사이의 값으로 설정합니다.
  4. (선택사항) 동일한 섹션에서 대상 컨텍스트 크기 슬라이더를 사용하여 대상 크기를 0~128,000 사이의 값으로 설정합니다.

Python

설정 메시지에서 context_window_compression.trigger_tokenscontext_window_compression.sliding_window.target_tokens 필드를 설정합니다.

config = {
   "response_modalities": ["audio"],
   # Configures compression
   "context_window_compression" : {
    "trigger_tokens": 10000,
    "sliding_window": {"target_tokens" : 512}
   }
}
      

세션의 오디오 스크립트 작성 사용 설정

입력 및 출력 오디오 모두에 대해 스크립트 작성을 사용 설정할 수 있습니다.

스크립트를 받으려면 세션 구성을 업데이트해야 합니다. input_audio_transcriptionoutput_audio_transcription 객체를 추가하고 textresponse_modalities에 포함되어 있는지 확인해야 합니다.

config = {
    "response_modalities": ["audio", "text"],
    "input_audio_transcription": {},
    "output_audio_transcription": {},
}

응답 처리

다음 코드 샘플은 구성된 세션을 사용하여 연결하고 오디오 데이터와 함께 텍스트 부분(스크립트)을 추출하는 방법을 보여줍니다.

# Receive Output Loop
async for message in session.receive():
    server_content = message.server_content
    if server_content:
        # Handle Model Turns (Audio + Text)
        model_turn = server_content.model_turn
        if model_turn and model_turn.parts:
            for part in model_turn.parts:
                # Handle Text (Transcriptions)
                if part.text:
                    print(f"Transcription: {part.text}")
                # Handle Audio
                if part.inline_data:
                    audio_data = part.inline_data.data
                    # Process audio bytes...
                    pass

        # Check for turn completion
        if server_content.turn_complete:
            print("Turn complete.")

다음 단계