양방향 API를 사용하여 입력 이벤트 처리 - Amazon Nova

양방향 API를 사용하여 입력 이벤트 처리

양방향 스트림 API는 구조화된 입력 및 출력 이벤트를 갖춘 이벤트 기반 아키텍처를 사용합니다. 성공적인 대화형 애플리케이션을 구현하고 상호 작용 전반에 걸쳐 적절한 대화 상태를 유지하려면 올바른 이벤트 순서를 이해하는 것이 중요합니다.

Nova Sonic 대화는 구조화된 이벤트 시퀀스를 따릅니다. 먼저 온도 및 토큰 제한과 같은 추론 구성 파라미터가 포함된 sessionStart 이벤트를 전송합니다. 다음으로 promptStart를 전송하여 오디오 출력 형식 및 도구 구성을 정의하고, 모든 후속 이벤트에 포함되어야 하는 고유한 promptName 식별자를 할당합니다.

각 상호 작용 유형(시스템 프롬프트, 오디오 등)에 대해 세 부분으로 된 패턴을 따릅니다. contentStart를 사용하여 콘텐츠 유형과 콘텐츠 역할(SYSTEM, USER, ASSISTANT, TOOL)을 정의한 다음, 실제 콘텐츠 이벤트를 제공하고, contentEnd로 마무리하여 해당 세그먼트를 닫습니다. contentStart 이벤트는 도구 결과, 스트리밍 오디오 또는 시스템 프롬프트 중 무엇을 전송할지 지정합니다. contentStart 이벤트에는 고유한 contentName 식별자가 포함됩니다.

시스템 프롬프트 후 오디오 스트리밍이 시작되기 전에 한 번만 대화 기록을 포함할 수 있습니다. 대화 기록은 동일한 contentStart/textInput/contentEnd 패턴을 따릅니다. 각 기록 메시지의 contentStart 이벤트에 USERASSISTANT 역할을 정의해야 합니다. 이는 현재 대화에 대한 필수적인 컨텍스트를 제공하지만, 새로운 사용자 입력이 시작되기 전에 완료되어야 합니다.

오디오 스트리밍은 연속 마이크 샘플링으로 작동합니다. 초기 contentStart를 전송한 후, 오디오 프레임(각각 약 32ms)이 마이크에서 직접 캡처되어 동일한 contentName을 사용하여 즉시 audioInput 이벤트로 전송됩니다. 이러한 오디오 샘플은 캡처되는 대로 실시간으로 스트리밍되어 대화 전체에서 자연스러운 마이크 샘플링 케이던스를 유지해야 합니다. 모든 오디오 프레임은 대화가 끝나고 명시적으로 닫힐 때까지 하나의 콘텐츠 컨테이너를 공유합니다.

대화가 끝나거나 종료되어야 하는 경우 열려 있는 모든 스트림을 올바르게 닫고 올바른 순서로 세션을 끝내는 것이 중요합니다. 세션을 올바르게 끝내고 리소스 누수를 방지하려면 다음과 같은 특정 닫기 순서를 따라야 합니다.

  1. contentEnd 이벤트를 사용하여 열려 있는 모든 오디오 스트림을 닫습니다.

  2. 원래 promptName을 참조하는 promptEnd 이벤트를 전송합니다.

  3. sessionEnd 이벤트를 전송합니다.

이러한 닫기 이벤트를 건너뛰면 대화가 불완전하거나 리소스가 분리될 수 있습니다.

이러한 식별자는 계층 구조를 생성합니다. promptName은 모든 대화 이벤트를 연결하고, 각 contentName은 특정 콘텐츠 블록의 경계를 표시합니다. 이 계층 구조는 모델이 상호 작용 전반에 걸쳐 적절한 컨텍스트를 유지하도록 합니다.

Amazon Nova Sonic 입력 이벤트 흐름을 설명하는 다이어그램입니다.

입력 이벤트 흐름

이 섹션에서는 입력 이벤트 흐름의 구조를 설명합니다.

  1. RequestStartEvent

    { "event": { "sessionStart": { "inferenceConfiguration": { "maxTokens": "int", "topP": "float", "temperature": "float" } } } }
  2. PromptStartEvent

    { "event": { "promptStart": { "promptName": "string", // unique identifier same across all events i.e. UUID "textOutputConfiguration": { "mediaType": "text/plain" }, "audioOutputConfiguration": { "mediaType": "audio/lpcm", "sampleRateHertz": 8000 | 16000 | 24000, "sampleSizeBits": 16, "channelCount": 1, "voiceId": "matthew" | "tiffany" | "amy", "encoding": "base64", "audioType": "SPEECH", }, "toolUseOutputConfiguration": { "mediaType": "application/json" }, "toolConfiguration": { "tools": [{ "toolSpec": { "name": "string", "description": "string", "inputSchema": { "json": "{}" } } }] } } } }
  3. InputContentStartEvent

    • Text

      { "event": { "contentStart": { "promptName": "string", // same unique identifier from promptStart event "contentName": "string", // unique identifier for the content block "type": "TEXT", "interactive": false, "role": "SYSTEM" | "USER" | "ASSISTANT", "textInputConfiguration": { "mediaType": "text/plain" } } } }
    • Audio

      { "event": { "contentStart": { "promptName": "string", // same unique identifier from promptStart event "contentName": "string", // unique identifier for the content block "type": "AUDIO", "interactive": true, "role": "USER", "audioInputConfiguration": { "mediaType": "audio/lpcm", "sampleRateHertz": 8000 | 16000 | 24000, "sampleSizeBits": 16, "channelCount": 1, "audioType": "SPEECH", "encoding": "base64" } } } }
    • Tool

      { "event": { "contentStart": { "promptName": "string", // same unique identifier from promptStart event "contentName": "string", // unique identifier for the content block "interactive": false, "type": "TOOL", "role": "TOOL", "toolResultInputConfiguration": { "toolUseId": "string", // existing tool use id "type": "TEXT", "textInputConfiguration": { "mediaType": "text/plain" } } } } }
  4. TextInputContent

    { "event": { "textInput": { "promptName": "string", // same unique identifier from promptStart event "contentName": "string", // unique identifier for the content block "content": "string" } } }
  5. AudioInputContent

    { "event": { "audioInput": { "promptName": "string", // same unique identifier from promptStart event "contentName": "string", // same unique identifier from its contentStart "content": "base64EncodedAudioData" } } }
  6. ToolResultContentEvent

    "event": { "toolResult": { "promptName": "string", // same unique identifier from promptStart event "contentName": "string", // same unique identifier from its contentStart "content": "{\"key\": \"value\"}" // stringified JSON object as a tool result } }
  7. InputContentEndEvent

    { "event": { "contentEnd": { "promptName": "string", // same unique identifier from promptStart event "contentName": "string" // same unique identifier from its contentStart } } }
  8. PromptEndEvent

    { "event": { "promptEnd": { "promptName": "string" // same unique identifier from promptStart event } } }
  9. RequestEndEvent

    { "event": { "sessionEnd": {} } }