/realtime

/realtime

실시간(WebSocket 기반) 모델 요청을 Azure, OpenAI, xAI 등 여러 제공자에 걸쳐 로드밸런싱하는 엔드포인트예요. 실시간 음성 에이전트를 LiteLLM 프록시에 연결하고 가드레일을 적용하는 방법을 안내할게요.

출처: 문서

본문

Azure + OpenAI + xAI 등에 걸친 로드밸런싱에 이 기능을 사용해요.

지원 제공자:

  • OpenAI
  • Azure
  • xAI (전체 문서 참고)
  • Google AI Studio (Gemini)
  • Vertex AI
  • Vertex AI Chirp, 전사 전용 (전체 문서 참고)
  • Bedrock
  • Meta Muse Voice, 전사 전용 (전체 문서 참고)

프록시 사용법

config에 모델 추가하기

  • OpenAI
  • OpenAI + Azure
  • xAI Grok Voice Agent
model_list:
  - model_name: openai-gpt-4o-realtime-audio
    litellm_params:
      model: openai/gpt-4o-realtime-preview-2024-10-01
      api_key: os.environ/OPENAI_API_KEY
    model_info:
      mode: realtime
model_list:
  - model_name: azure-gpt-4o-realtime-audio
    litellm_params:
      model: azure/gpt-4o-realtime-preview
      api_key: os.environ/AZURE_SWEDEN_API_KEY
      api_base: os.environ/AZURE_SWEDEN_API_BASE

  - model_name: azure-gpt-realtime
    litellm_params:
      model: azure/gpt-realtime
      api_key: os.environ/AZURE_API_KEY
      api_base: os.environ/AZURE_API_BASE
    model_info:
      mode: realtime

  - model_name: openai-gpt-4o-realtime-audio
    litellm_params:
      model: openai/gpt-4o-realtime-preview-2024-10-01
      api_key: os.environ/OPENAI_API_KEY
model_list:
  - model_name: grok-voice-agent
    litellm_params:
      model: xai/grok-voice-latest
      api_key: os.environ/XAI_API_KEY
    model_info:
      mode: realtime

전체 xAI Realtime 문서 참고 →

프록시 시작하기

litellm --config /path/to/config.yaml 

# RUNNING on http://0.0.0.0:4000

테스트

이 스크립트를 node로 실행해요 - node test.js

// test.js
const WebSocket = require("ws");

const url = "ws://0.0.0.0:4000/v1/realtime?model=openai-gpt-4o-realtime-audio";
// const url = "wss://my-azure-endpoint.openai.azure.com/openai/realtime?api-version=2024-10-01-preview&deployment=gpt-4o-realtime-preview";
const ws = new WebSocket(url, {
    headers: {
        "api-key": `sk-<your-litellm-api-key>`,
        "OpenAI-Beta": "realtime=v1",
    },
});

ws.on("open", function open() {
    console.log("Connected to server.");
    ws.send(JSON.stringify({
        type: "response.create",
        response: {
            modalities: ["text"],
            instructions: "Please assist the user.",
        }
    }));
});

ws.on("message", function incoming(message) {
    console.log(JSON.parse(message.toString()));
});

ws.on("error", function handleError(error) {
    console.error("Error: ", error);
});

Azure: GA vs beta realtime 프로토콜

Azure는 두 개의 realtime 업스트림을 노출해요. GA 엔드포인트(/openai/v1/realtime?model=<deployment>)는 GA 이벤트 스키마(session.type, output_modalities, 중첩 audio)를 사용하고, 이전 beta 엔드포인트(/openai/realtime?api-version=2024-10-01-preview&deployment=<deployment>)는 beta 스키마(modalities, voice, 평면 audio 형식)를 사용해요. beta 엔드포인트에 GA 형태의 session.update를 보내면 Unknown parameter: 'session.type'로 실패해요.

LiteLLM은 클라이언트 연결에서 업스트림을 선택해요. OpenAI-Beta: realtime=v1 헤더(openai SDK의 client.beta.realtime.connect)를 보내는 클라이언트는 beta 엔드포인트로 브리지돼요. 그 헤더가 없는 클라이언트(openai SDK의 client.realtime.connect와 대부분의 음성 에이전트 프레임워크)는 GA 엔드포인트로 브리지돼요. 전사 세션(intent=transcription)은 항상 GA를 사용해요.

from openai import AsyncOpenAI

client = AsyncOpenAI(base_url="http://0.0.0.0:4000", api_key="sk-1234")

async with client.realtime.connect(model="azure-gpt-realtime") as connection:
    await connection.session.update(
        session={"type": "realtime", "output_modalities": ["audio"], "instructions": "Please assist the user."}
    )
    async for event in connection:
        print(event.type)
        if event.type == "session.updated":
            break

클라이언트가 보내는 것과 관계없이 하나의 프로토콜을 고정하려면 배포에 realtime_protocol을 설정하거나 프록시 환경에 LITELLM_AZURE_REALTIME_PROTOCOL을 설정하세요. 배포 설정이 환경 변수를 이기고, 둘 다 클라이언트 헤더를 이겨요. 실시간 헬스 체크(mode: realtime 배포의 /health와 Admin UI의 Test Connect)는 읽을 클라이언트 헤더가 없으므로, 둘 중 하나로 고정하지 않으면 GA 엔드포인트를 프로브해요.

model_list:
  - model_name: azure-gpt-realtime
    litellm_params:
      model: azure/gpt-realtime
      api_key: os.environ/AZURE_API_KEY
      api_base: os.environ/AZURE_API_BASE
      realtime_protocol: beta # or GA
export LITELLM_AZURE_REALTIME_PROTOCOL=beta # or GA

가드레일

실시간 세션에 LiteLLM 가드레일을 적용할 수 있어요.

키 또는 팀에 가드레일 설정하기

가장 쉬운 프로덕션 설정: 가상 키나 팀에 가드레일을 붙여 클라이언트 측 변경 없이 항상 자동으로 적용되게 해요. Virtual Keys → Guardrails 및 Teams → Guardrails를 참고하세요.

가드레일 동적으로 전달 (쉬운 테스트)

WebSocket을 열 때 guardrails를 쿼리 파라미터로 전달해요. 키/팀 config를 수정하지 않고 가드레일을 테스트할 때 유용해요.

// node test.js
const WebSocket = require("ws");

const guardrails = ["your-guardrail-name"]; // comma-separated list
const url = `ws://0.0.0.0:4000/v1/realtime?model=openai-gpt-4o-realtime-audio&guardrails=${guardrails.join(",")}`;

const ws = new WebSocket(url, {
    headers: {
        "Authorization": "Bearer sk-<your-litellm-api-key>",
    },
});

ws.on("open", function open() {
    console.log("Connected — guardrails active:", guardrails);
});

ws.on("message", function incoming(message) {
    const data = JSON.parse(message);
    if (data.type === "error") {
        // Guardrail block is sent as an error event before the connection closes
        console.error("Guardrail error:", data.error.message);
    }
});

ws.on("close", function close(code, reason) {
    console.log("Closed:", code, reason.toString());
    // code 1011 = blocked by guardrail at pre_call
});

또는 Python으로:

import asyncio
import websockets

async def main():
    url = "ws://0.0.0.0:4000/v1/realtime?model=openai-gpt-4o-realtime-audio&guardrails=your-guardrail-name"
    async with websockets.connect(
        url,
        additional_headers={"Authorization": "Bearer sk-<your-litellm-api-key>"},
    ) as ws:
        print("Connected — guardrail active")
        async for msg in ws:
            import json
            data = json.loads(msg)
            if data["type"] == "error":
                print("Guardrail blocked:", data["error"]["message"])
                break

asyncio.run(main())

가드레일이 요청을 차단하면 프록시는 WebSocket을 통해 error 이벤트를 보낸 뒤 연결을 닫아요:

{
    "type": "error",
    "error": {
        "type": "guardrail_error",
        "message": "Guardrail blocked this request: <reason>"
    }
}

로깅

요청이 유실되는 것을 막기 위해 기본적으로 LiteLLM은 다음 이벤트 타입만 기록해요:

  • session.created
  • response.create
  • response.done

config에서 logged_real_time_event_types 파라미터를 설정해 이것을 재정의할 수 있어요. 예:

litellm_settings:
  logged_real_time_event_types: "*" # Log all events
  ## OR ## 
  logged_real_time_event_types: ["session.created", "response.create", "response.done"] # Log only these event types

더 알아보기 (Learn more)