서버 쪽 제어

서버 쪽 제어 (Server-side controls)

서버에서 GPT-Live 또는 Realtime 세션을 제어하는 방법을 다뤄요. 대화 이벤트를 받고, 프라이빗 도구를 실행하고, 대화를 업데이트해야 할 때 쓰는 연결 방식이에요.

출처: 문서

본문

서버에서 GPT-Live 세션 제어하기

서버가 대화 이벤트를 받아야 하거나, 프라이빗 도구를 실행하거나, 대화를 업데이트해야 할 때 기존 GPT-Live WebRTC 또는 SIP 세션에 애플리케이션 서버를 붙여요. 이 두 번째 연결을 사이드밴드 WebSocket(sideband WebSocket) 이라고 불러요. 두 연결이 한 세션을 공유하고, WebRTC 또는 SIP가 기본 오디오를 전달해요.

사이드밴드는 이벤트와 명령을 나릅니다. 도구 실행, 권한 검사, 비즈니스 규칙은 여러분의 애플리케이션이 담당해요. API 키와 도구 자격증명은 서버에 보관하세요.

사이드밴드가 필요한지 결정하기

브라우저 애플리케이션에서는 캡션과 로컬 UI 업데이트에 WebRTC 데이터 채널을 써요. 전사 처리가 서버에서 돌 때(가드레일 검사, 감정 분석, 선제적 도구 호출 등) 사이드밴드를 써요. 서버가 이벤트를 받고 같은 세션을 직접 제어하면서 브라우저 오디오는 WebRTC에 그대로 둘 수 있어요. 예시는 React to transcript fragments를 참고하세요.

백엔드가 기본 WebSocket 연결로 오디오를 스트리밍한다면, 그 연결로 이벤트를 받고 명령을 보내요. Responses 위임은 사이드밴드 없이도 동작해요. 브라우저가 데이터 채널의 함수 호출 이벤트를 인증된 백엔드로 전달해 실행할 수 있고, OpenAI 호스팅 도구는 애플리케이션 도구 실행기 없이 위임 백엔드를 통해 돌아요.

기존 세션에 연결하기

  1. 백엔드가 제어할 세션의 ID를 저장해요. WebRTC나 아웃바운드 SIP 통화에서는 POST /v1/live/sessions의 JSON 응답에서 session.id를 써요. 인바운드 SIP는 들어오는 통화를 수락한 뒤 그 웹훅의 data.session_id를 사용해요. ID를 애플리케이션의 사용자·대화 기록 옆에 보관해요.
  2. 다음 URL에서 서버의 WebSocket을 열고, 저장한 ID를 그대로 넣어요. 세션을 만들거나 수락한 프로젝트 인증으로 Authorization: Bearer *** 인증해요. 세션을 만들 때 요구한 것과 같은 연결 헤더를 포함해요.
   wss://api.openai.com/v1/live/sessions/{session_id}/attach
  1. 연결된 소켓에서 이벤트를 받고 명령을 보내요. 세션은 이미 진행 중이므로 session.start를 다시 보내지 마세요.

세션 ID는 접두사를 포함해 바꾸지 말고, 애플리케이션이 그 세션에 대한 접근을 승인했는지 확인하세요.

이벤트 관찰하고 명령 보내기

작업 이벤트 또는 명령
대화 따라가기 사용자·어시스턴트 전사 델타, 위임 이벤트, 중첩 Responses 이벤트를 받아요.
백엔드 구성 업데이트 기존 위임 모드 안에서 지원되는 설정은 session.update로 바꿔요. 프런트엔드 모델·오디오 구성 같은 시작 설정은 고정이에요.
컨텍스트 제공 지침은 session.instructions.append, 조용한 컨텍스트는 session.thinking.append, 말할 수 있는 업데이트는 session.commentary.append를 써요.
도구 결과 반환 Responses 위임으로 response.item.create를 보내고 response.create로 백엔드 작업을 이어가요.
마이크 입력 제어 session.input_audio.mute와 session.input_audio.unmute를 써요. 입력을 음소거해도 어시스턴트 출력은 멈추지 않아요.
세션 끝내기 session.close를 보내고 연결을 끊기 전에 session.closed를 받아요.

명령은 기본 연결과 같은 검증·위임 규칙을 따라요. 컨텍스트 추가에는 일반 세션 컨텍스트에 delegation_id: null을, 비null ID는 기존 클라이언트 위임을 가리켜야 해요. 구성·함수 실행·컨텍스트 추가 예시는 Delegation and tools를 참고하세요.

브라우저 세션에서는 마이크 입력과 스피커 출력을 합의된 WebRTC 미디어 트랙에 두고, 사이드밴드는 대화 이벤트·제어에, 재생 추적은 오디오 플레이어에서 해요.

반사 오디오 받기

사이드밴드는 기본 연결이 라이브 미디어를 나르는 동안 이후의 입력·출력 오디오 사본도 받아요.

이벤트 오디오 필드 타이밍
session.input_audio.append audio 타임스탬프 없음.
session.output_audio.delta delta start_ms와 end_ms가 세션 타임라인에서 출력 범위를 알려줘요.

두 페이로드 모두 기본 전송의 오디오 형식과 무관하게 24kHz raw 모노 PCM16LE base64 인코딩이에요. 두 이벤트 모두 event_id가 없어요. 반사 입력은 입력 음소거 전의 받은 오디오를 담고, 모델이 그 샘플을 소비했다는 뜻은 아니에요. 반사 출력 범위는 드롭된 프레임 구간에 구멍이 있을 수 있고, 호출자가 오디오를 들었을 때를 나타내진 않아요. 마이크 오디오는 기본 연결로만 보내고, 사이드밴드는 반사 오디오를 받는 데 써요.

각 동작에 소유자 하나 지정

각 동작을 브라우저가 처리할지 백엔드가 처리할지 정해요. 두 연결이 함수 호출 이벤트를 받으면 함수는 한 번만 실행해요. 컨텍스트 업데이트와 백엔드 작업 이어가기 요청에도 같은 소유권 규칙을 적용해요. 백엔드가 처음부터 대화를 관찰해야 한다면 일찍 연결하세요. 전사와 도구 상태(연결 전에 수집한 기록 포함)는 애플리케이션에 저장해요. 사이드밴드가 붙어 있어도 브라우저는 여전히 세션 이벤트를 받을 수 있어요. 민감한 도구 자격증명과 권한 결정은 백엔드에 두고, 대화에 필요한 컨텍스트만 반환해요.

대화 가드레일 적용

서버의 기본 WebSocket이나 사이드밴드로 대화를 모니터링하고 요청을 애플리케이션 정책에 검사해요. 검사는 애플리케이션이 실행하고, 영향을 받는 동작을 차단하며, 검사가 발동하면 시정 지침을 보내요.

대화와 함께 검사 실행

가드레일은 도착하는 대로 전사 조각을 처리하는 쓰임의 하나예요. 같은 스트림으로 이 검사들과 함께 선제적 조회를 시작하거나 UI를 업데이트할 수도 있어요.

  1. 전사 모니터링. session.input_transcript.delta 조각을 모아 사용자 요청의 탈옥 시도·민감 정보·정책 위반을 검사해요. session.output_transcript.delta로 어시스턴트 음성의 근거 없는 주장이나 앱 범위 밖의 응답을 검사해요. 각 검사를 평가한 전사와 애플리케이션 요청에 연결해 두세요.
  2. 검사를 동시에 실행. 빠르고 가벼운 모델로 대화가 이어지는 동안 요청을 평가할 수 있어요. {"triggered": true} 같은 작은 구조화 결과를 반환해 앱이 조치하도록 해요. 승인이 필요한 동작은 검사가 통과한 뒤에만 실행하고, 검사가 실패하거나 타임아웃되면 차단을 유지해요.
  3. 영향 받는 동작 차단. 검사가 발동하면 애플리케이션 상태에 요청을 차단으로 표시해요. 도구를 실행하거나 변경을 커밋하기 전에(이미 큐에 있는 작업 포함) 그 상태를 확인해요.
  4. 관련 작업 중단. 백엔드가 취소를 지원하면 애플리케이션 소유 작업을 취소하고, 차단되거나 대체된 요청의 늦은 결과는 버려요. Responses 위임에서는 영향 받는 커스텀 함수 실행을 멈추고 차단된 작업을 이어가도록 response.create를 보내지 마세요. 이미 실행 중인 호스팅 응답을 취소하거나 프런트엔드 음성을 멈추지는 않아요.
  5. 기록하고 리다이렉트. 영향 받는 요청·위임 ID와 함께 결정을 기록하고 시정 지침을 보내요.

조각 수집은 Transcript deltas, 백엔드 결과를 현재 작업에 맞추는 법은 Delegation and tools를 참고하세요.

대화 리다이렉트

가드레일 스티어링에는 session.instructions.append를 써요. 진행 중이던 음성을 중단하고 새 지침을 적용할 수 있어요. 예를 들어 앱이 요청을 차단한 뒤:

from openai.resources.live.live import AsyncLiveConnection
from openai.resources.live.sideband import AsyncSidebandConnection


async def send_update(
    connection: AsyncLiveConnection | AsyncSidebandConnection,
) -> None:
    await connection.session.instructions.append(
        event_id="guardrail_block_17",
        delegation_id=None,
        content=(
            "Stop speaking immediately. Do not continue or act on the last request. "
            "Refuse briefly, then wait."
        ),
    )

지침은 애플리케이션이 작성한 것이어야 해요. 신뢰할 수 없는 사용자 텍스트를 지침으로 복사하지 마세요. 이 세션 전체 시정에는 delegation_id: null을 쓰고 content는 500 토큰 이내로 유지하세요. client_event_id로 session.instructions.appended를 여러분의 명령과 매칭해요. 확인 응답은 추정 컨텍스트 주입 뒤에 도착해요. 호출자에게 도달하는 오디오를 멈추려면 아래 재생 제어를 써요. 특정 음성 문구를 요청하는 공개(disclosure)에는 지침을 쓰고, 예시와 재생 고려사항은 Deliver a disclosure를 참고하세요.

필요할 때 재생 제어

앱이 모델 오디오를 막아야 한다면 클라이언트나 미디어 릴레이에서 재생을 제어해요. 출력을 일시적으로 음소거·드롭하고, 로컬로 큐된 오디오를 버리고, 시정 지침을 보내요. 낡은 오디오를 비운 뒤 앱의 복구 정책에 따라 재생을 재개하세요. 지침 확인 응답은 재개 신호가 아니에요. 사이드밴드만으로는 재생을 제어하지 못하고, 시정 지침이 이미 들은 오디오를 되돌릴 수도 없어요. session.input_audio.mute는 호출자의 마이크 입력을 제어할 뿐 모델 출력을 음소거하거나 위임 작업을 취소하지 않아요.

재생 전에 음성 검사

대부분의 앱은 대화가 이어지는 동안 사용자·어시스턴트 전사를 모니터링해요. 가드레일이 발동하면 앱이 영향 받는 동작을 차단하거나 시정 지침을 보내요. 어시스턴트 음성을 재생 전에 검사해야 한다면, 호출자에게 보내기 전에 플레이어나 미디어 브리지에서 오디오를 버퍼링해요. 검사가 도는 동안 오디오와 전사 이벤트를 계속 받고, 전사는 재생과 무관하게 읽어요.

  1. 오디오와 전사 수집. 앱에서 출력 음성 활동 감지(VAD)를 구현하거나 미디어 프레임워크가 제공하는 노이즈 게이트로 후보 음성 구간을 식별해요. GPT-Live는 이 워크플로를 위한 출력 VAD·노이즈 게이트를 제공하지 않아요. 각 구간을 검사하는 데 필요한 전사를 기다려요.
  2. 승인된 오디오 내보내기. 구간이 검사를 통과하면 원래 버퍼링된 오디오를 재생 큐에 넣어요. 검사 실패, 전사 누락, 검사 타임아웃이면 구간을 버리고 앱이 정한 안전한 폴백을 써요.
  3. 인터럽트 처리. 오디오·전사·검사 결과·재생 상태를 앱 생성 ID와 연결해요. 인터럽트가 그 음성을 취소하면 버퍼·큐된 오디오를 지우고 나중에 온 승인은 무시해요.

모델이 답을 구성하는 동안 일시 중지가 후보 구간을 표시할 수 있어요. 완전한 답을 검사해야 하는 정책이라면 앱이 완료를 어떻게 확립할지 정하세요. 음성 활동 감지만으로 전체 답이 끝났다는 것을 확립할 수는 없어요. 버퍼링은 지연을 더해요. 버려진 음성은 모델의 대화 컨텍스트에 남으므로, 오디오를 보류하거나 폴백한 뒤 대화가 어떻게 이어지는지 테스트하세요.

개입 테스트

허용·차단 요청, 오탐, 느리거나 실패한 검사, 음성 중 발동, 도구 실행 중 발동, 취소된 작업의 늦은 결과를 테스트해요. 동작 차단, 애플리케이션 상태, 시정 음성, 실제 재생을 각각 검증해요. 출력을 제어한다면 큐된 오디오와 복구도 테스트에 포함해요. 작업 성공과 음성 응답 시간 비교에는 voice agent evaluation Cookbook을 사용해요.

깔끔하게 끝내기

도구가 끝나고 세션의 최종 사용량이 보고될 때까지 이벤트를 계속 받아요. session.close를 보내기 전에 session.closed 핸들러를 등록하고, 대기 중인 작업이 비워지는 동안 WebRTC 연결·데이터 채널·사이드밴드를 열어 두세요. 정리 전에 최종 세션 사용량과 Responses 이벤트에서 받은 백엔드 사용량을 저장해요. 최종 이벤트 전에 연결이 실패하면 완료를 불완전으로 기록해요. 종료 순서는 Managing sessions를 참고하세요.


Realtime API: 사이드밴드 제어 채널

Realtime API는 클라이언트가 WebRTC나 SIP로 API 서버에 직접 연결할 수 있게 해요. 하지만 도구 사용과 다른 비즈니스 로직은 프라이빗하고 클라이언트와 무관하게 유지하려고 애플리케이션 서버에 두고 싶을 거예요. "사이드밴드" 제어 채널로 연결해 도구 사용·비즈니스 로직·세부 사항을 서버 쪽에 안전하게 유지하세요. 이제 SIP와 WebRTC 연결 모두에 사이드밴드 옵션이 있어요. 사이드밴드 연결은 같은 Realtime 세션에 사용자 클라이언트와 애플리케이션 서버라는 두 개의 활성 연결이 있다는 뜻이에요. 서버 연결로 세션을 모니터링하고, 지침을 업데이트하고, 도구 호출에 응답할 수 있어요.

WebRTC에서

  1. 피어 연결을 설정할 때 Realtime API에서 SDP 응답을 받아 연결을 구성해요. WebRTC 가이드의 샘플 코드를 쓴다면 대략 이렇고, 응답의 Location 헤더에 서버에서 그 Realtime 세션에 WebSocket을 연결하는 데 쓸 수 있는 고유 call ID가 담겨 있어요.
  2. 서버에서 그 call ID로 wss://api.openai.com/v1/realtime?call_id=rtc_xxxxx URL에 연결해요.
import WebSocket from "ws";
const callId = "rtc_u1_9c6574da8b8a41a18da9308f4ad974ce";

// 진행 중인 통화를 위한 WebSocket에 연결합니다.
const url = "wss://api.openai.com/v1/realtime?call_id=" + callId;
const ws = new WebSocket(url, {
  headers: {
    Authorization: "Bearer " + process.env.OPENAI_API_KEY,
  },
});

ws.on("open", function open() {
  console.log("Connected to server.");
  ws.send(
    JSON.stringify({
      type: "session.update",
      session: {
        type: "realtime",
        instructions: "Be extra nice today!",
      },
    })
  );
});

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

이렇게 하면 클라이언트에서 구성할 필요 없이 서버에서 도구를 추가하고, 세션을 모니터링하고, 비즈니스 로직을 수행할 수 있어요.

SIP에서

  1. 사용자가 SIP를 통해 전화로 OpenAI에 연결해요.
  2. OpenAI가 애플리케이션 서버의 웹훅 URL로 웹훅을 보내 세션 상태를 알려줘요. 웹훅은 type: "realtime.call.incoming"이고 data에 call_id와 sip_headers가 담겨 있어요.
  3. 애플리케이션 서버가 웹훅의 call_id 값으로 wss://api.openai.com/v1/realtime?call_id={callId} 같은 URL에 Realtime API WebSocket을 열어요. WebSocket 연결은 SIP 통화가 살아 있는 동안 유지돼요. 이 WebSocket으로 통화를 제어하는 이벤트를 주고받을 수 있어요 — 통화 모니터링, 지침 동적 업데이트, 도구 호출 응답까지.

더 알아보기 (Learn more)

오디오 스트리밍 연결은 WebSockets 가이드, 브라우저 연결은 WebRTC, 전화 연결은 SIP를 참고하세요. 위임과 도구 구성은 Delegation and tools에 있어요.