Realtime

Realtime

Realtime은 실험적 기능이에요.

이 가이드는 WebSocket을 통한 레거시 토큰 기반, 턴 기반 실시간 대화를 다룹니다. 이 세션들은 브라우저에서 실행되고, 서버에서 만든 단기 토큰(short-lived token)을 사용해 프로바이더에 직접 연결해요. AI Gateway 를 통해 연결을 라우팅할 수도 있어요.

OpenAI Live의 연속 JSON/PCM16 WSS 릴레이 런타임과 애플리케이션 핸들 클라이언트 위임에 대해서는 experimental_useRealtime 을 참조하세요.

일반적인 흐름은:

  1. 브라우저가 설정(setup) 엔드포인트를 호출.
  2. 서버가 experimental_realtime.getToken() 으로 단기 실시간 토큰을 생성.
  3. 브라우저가 프로바이더 또는 AI Gateway에 WebSocket 연결을 엶.
  4. 모델이 오디오, 텍스트, tool 호출을 브라우저로 스트리밍.
  5. tool 호출은 여러분의 애플리케이션에서 onToolCall 로 처리.

연속 OpenAI Live 대화의 경우 애플리케이션 소유 WebSocket 릴레이 또는 api.session 을 통한 선택적 WebRTC를 사용하세요. Live는 클라이언트 위임을 사용해요. 여러분의 애플리케이션이 위임된 작업을 처리하고 아래의 턴 기반 tool 루프 대신 컨텍스트를 제출해요. SDP 설정, 서버 소유 권한, 캡처 소유권, 정상 종료에 대해서는 experimental_useRealtime reference 를 보세요.

출처: 문서

본문

설정 엔드포인트 (Setup Endpoint)

실시간 프로바이더용 단기 토큰을 반환하는 설정 엔드포인트를 만드세요. 이 엔드포인트는 세션에 tool 정의를 첨부할 수도 있어요.

import { openai } from '@ai-sdk/openai';
import { experimental_getRealtimeToolDefinitions, tool } from 'ai';
import { z } from 'zod';

const tools = {
  getWeather: tool({
    description: 'Get the current weather for a city',
    inputSchema: z.object({
      city: z.string().describe('The city to get weather for'),
    }),
  }),
};

export async function POST(request: Request) {
  const body = await request.json().catch(() => ({}));
  const toolDefinitions = await experimental_getRealtimeToolDefinitions({
    tools,
  });

  const token = await openai.experimental_realtime.getToken({
    model: 'gpt-realtime',
    sessionConfig: {
      ...body.sessionConfig,
      tools: toolDefinitions,
    },
  });

  return Response.json({
    ...token,
    tools: toolDefinitions,
  });
}
프로덕션에서는 설정 엔드포인트를 인증하고 rate-limit 하세요. 서버 측 API 키로 실시간 세션을 만들기 때문이에요.

AI Gateway

지원되는 업스트림 프로바이더 전반에서 동일한 실시간 클라이언트 코드가 동작하길 원한다면 AI Gateway 를 사용하세요. Gateway는 실시간 이벤트를 서버 측에서 정규화하며, 브라우저는 여전히 단기 클라이언트 시크릿만 받아요.

서버 측 설정 엔드포인트에서 단기 Gateway 실시간 토큰을 만드세요:

import { gateway } from 'ai';

export async function POST() {
  const token = await gateway.experimental_realtime.getToken({
    model: 'openai/gpt-realtime-2',
  });

  return Response.json(token);
}

그런 다음 브라우저에서 일치하는 Gateway 실시간 모델을 사용하세요:

'use client';

import { experimental_useRealtime } from '@ai-sdk/react';
import { gateway } from 'ai';

const model = gateway.experimental_realtime('openai/gpt-realtime-2');
const sessionConfig = {
  instructions: 'You are a helpful assistant. Be concise.',
  inputAudioTranscription: {},
  voice: 'alloy',
  turnDetection: { type: 'server-vad' as const },
};

export default function RealtimePage() {
  const realtime = experimental_useRealtime({
    model,
    api: {
      token: '/api/realtime/setup',
    },
    sessionConfig,
  });

  // ...
}
`gateway.experimental_realtime.getToken()` 은 여러분의 Gateway 자격 증명을 사용해 `vcst_` 클라이언트 시크릿을 발급하므로 서버에서 실행되어야 해요. 브라우저에서 `gateway.experimental_realtime()` 으로 실시간 모델을 만드는 것은 안전해요.

tool 정의는 AI Gateway에서도 동일하게 동작해요. 설정 엔드포인트에서 experimental_getRealtimeToolDefinitions() 로 AI SDK tools를 변환하고 토큰과 함께 정의를 반환하세요. 훅은 WebSocket이 열린 후 세션 업데이트에 포함해요.

클라이언트 세션 (Client Session)

experimental_useRealtime 훅을 사용해 실시간 모델에 연결하고, 마이크 오디오를 캡처하고, 모델 오디오를 재생하고, 텍스트 메시지를 보내고, 메시지를 렌더링하세요.

'use client';

import { openai } from '@ai-sdk/openai';
import { experimental_useRealtime } from '@ai-sdk/react';

const model = openai.experimental_realtime('gpt-realtime');
const sessionConfig = {
  instructions: 'You are a helpful assistant. Be concise.',
  inputAudioTranscription: {},
  voice: 'alloy',
  turnDetection: { type: 'server-vad' as const },
};

export default function RealtimePage() {
  const realtime = experimental_useRealtime({
    model,
    api: {
      token: '/api/realtime/setup',
    },
    sessionConfig,
  });

  return (
    <div>
      <button onClick={realtime.connect}>Connect</button>
      <button onClick={realtime.disconnect}>Disconnect</button>

      {realtime.messages.map(message => (
        <div key={message.id}>
          <strong>{message.role}</strong>
          {message.parts.map((part, index) =>
            part.type === 'text' ? <span key={index}>{part.text}</span> : null,
          )}
        </div>
      ))}
    </div>
  );
}

모델 및 세션 설정 객체는 렌더링 간에 안정적으로 유지하세요. 위처럼 모듈 스코프를 사용하거나, 설정이 props에 의존할 때는 useMemo 를 사용하세요. 둘 중 하나라도 교체하면 훅의 세션이 교체돼요.

Tool 호출 (Tool Calling)

실시간 tool 실행은 클라이언트 중심이에요. 프로바이더가 WebSocket을 통해 tool 호출을 보내고, 여러분의 애플리케이션이 onToolCall 로 처리해요. 결과를 즉시 사용할 수 있으면 onToolCall 에서 반환하세요. SDK가 그것을 tool 출력으로 프로바이더에 다시 보내요.

서버 지원 tools의 경우 onToolCall 에서 앱 특화 API 엔드포인트를 호출하세요. 일반적인 "이름으로 tool 실행" 라우트는 피하세요. 앱 특화 엔드포인트는 일반 인증, 인가, 검증, rate limiting 규칙을 사용할 수 있어 보안이 더 쉽기 때문이에요.

서버 지원 Tool 엔드포인트

import { z } from 'zod';

const inputSchema = z.object({
  city: z.string(),
});

export async function POST(request: Request) {
  const input = inputSchema.safeParse(await request.json());

  if (!input.success) {
    return Response.json({ error: 'Invalid input' }, { status: 400 });
  }

  return Response.json({
    city: input.data.city,
    temperature: 72,
    condition: 'sunny',
  });
}

클라이언트 Tool 핸들러

import { openai } from '@ai-sdk/openai';
import { experimental_useRealtime } from '@ai-sdk/react';

const model = openai.experimental_realtime('gpt-realtime');

export default function RealtimePage() {
  const realtime = experimental_useRealtime({
    model,
    api: {
      token: '/api/realtime/setup',
    },
    onToolCall: async ({ toolCall }) => {
      if (toolCall.toolName === 'getWeather') {
        const response = await fetch('/api/weather', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(toolCall.args),
        });

        if (!response.ok) {
          throw new Error('Weather lookup failed');
        }

        return response.json();
      }
    },
  });

  // ...
}

tool이 사용자 상호작용이나 다른 비동기 프로세스를 필요로 할 때 addToolOutput 으로 tool 출력을 수동으로 제출할 수도 있어요:

realtime.addToolOutput(toolCallId, {
  approved: true,
});

지원되는 프로바이더 (Supported Providers)

실시간 모델은 실시간 WebSocket API를 노출하는 프로바이더에서 사용할 수 있어요:

import { openai } from '@ai-sdk/openai';
import { google } from '@ai-sdk/google';
import { xai } from '@ai-sdk/xai';

const openaiModel = openai.experimental_realtime('gpt-realtime');
const googleModel = google.experimental_realtime(
  'gemini-3.1-flash-live-preview',
);
const xaiModel = xai.experimental_realtime('grok-voice-latest');

세션을 정규화해 업스트림 프로바이더 전반에서 동일한 클라이언트 코드가 동작하게 하는 AI Gateway 를 통해서도 실시간을 라우팅할 수 있어요:

import { gateway } from '@ai-sdk/gateway';

const gatewayModel = gateway.experimental_realtime('openai/gpt-realtime-2');

gateway.experimental_realtime.getToken() 은 서버에서 단기 Gateway 클라이언트 시크릿을 발급해요. 브라우저는 그 토큰을 사용해 Gateway WebSocket을 엽니다. SDK가 Gateway 특화 WebSocket 서브프로토콜을 처리해 줘요. Gateway 특화 토큰 및 프로바이더 옵션 세부사항은 AI Gateway realtime docs 를 보세요.

더 알아보기 (Learn more)

전체 사이트맵