우리의 Voice AI 지연 시간 벤치마킹 도구를 오픈 소스로 공개합니다
요약
Voice AI 에이전트의 지연 시간 문제를 해결하기 위해 개발된 오픈 소스 벤치마킹 도구 `vox-bench`를 소개합니다. 평균 지연 시간 대신 단계별 꼬리 지연 시간(Tail Latency)을 측정하여 자연스러운 대화 경험을 유지하는 방법을 다룹니다.
핵심 포인트
- 평균 지연 시간은 특정 구간의 급격한 지연을 감지하지 못함
- 자연스러운 대화를 위해 왕복 시간(RTT)을 800ms 미만으로 유지 필수
- 단계별(per-stage) 및 백분위수(per-percentile) 지연 시간 추적의 중요성
- 오픈 소스 벤치마킹 도구 `vox-bench` 공개
지난달, 우리 TTS (Text-to-Speech) 파이프라인에서 발생한 340ms의 급증으로 인해 Loquent 통화자의 12%가 AI의 응답 도중에 말을 가로질러 말하는 현상이 발생했습니다. 우리는 잘못된 지표를 측정하고 있었기 때문에 6시간 동안 이를 감지하지 못했습니다. 즉, 각 파이프라인 단계에서의 꼬리 지연 시간 (Tail Latency) 대신 평균 지연 시간 (Average Latency)을 측정하고 있었습니다. 그 사건이 바로 우리가 vox-bench를 구축한 이유이며, 오늘 이를 공개하는 이유입니다.
이것이 필요했던 이유
치과 예약, 환자 접수, 업무 시간 외 분류 등 한 달에 수천 건의 실시간 전화 통화를 처리하는 Voice AI 에이전트를 구축할 때, 지연 시간 (Latency)은 있으면 좋은 지표가 아닙니다. 그것은 인간처럼 느껴지는 대화와 고장 난 IVR (Interactive Voice Response)과 대화하는 느낌 사이의 차이입니다.
우리의 Loquent 파이프라인은 다섯 단계로 구성됩니다: Twilio 미디어 스트림 수집, Deepgram을 통한 음성-텍스트 변환 (STT), Anthropic Claude를 통한 LLM 추론 (OpenAI를 폴백 (Fallback)으로 사용), ElevenLabs를 통한 텍스트-음성 변환 (TTS), 그리고 Twilio를 통한 오디오 스트리밍 재전송입니다. 각 단계는 시간을 추가합니다. 통화자가 말을 멈춘 순간부터 AI의 응답을 듣는 순간까지의 총 왕복 시간 (Round-trip time)은 자연스럽게 느껴지기 위해 800ms 미만으로 유지되어야 합니다. 1.2초를 넘어가면 통화자는 말을 반복하기 시작합니다. 1.8초를 넘어가면 전화를 끊어버립니다.
우리는 Loquent를 운영 환경에서 6개월 동안 10,000건 이상의 통화에 걸쳐 추적했기 때문에 이 수치들을 알고 있습니다. 하지만 처음 4개월 동안 우리는 이를 잘못 추적하고 있었습니다.
우리가 잘못하고 있었던 점
우리의 기존 모니터링은 간단했습니다. Twilio에서 오디오가 들어왔을 때의 타임스탬프를 기록하고, 오디오를 다시 보냈을 때의 타임스탬프를 기록했습니다. 총 왕복 시간 (Total round-trip time). 단 하나의 숫자였습니다. 그리고 한동안은 평균 약 650ms로 아주 좋아 보였습니다.
문제는 평균값이 우리에게 거의 아무것도 알려주지 않았다는 점입니다. 제공업체 측의 배포(deployment) 과정에서 ElevenLabs의 지연 시간(latency)이 p50 기준 120ms에서 p95 기준 340ms로 급증했을 때, 우리의 전체 평균은 650ms에서 710ms로 겨우 움직였습니다. 여전히 우리의 알림 임계값(alerting thresholds) 기준으로는 "괜찮은" 수준이었습니다. 하지만 호출의 12%는 1.4초 이상의 응답 시간을 기록하고 있었고, 해당 사용자들은 AI가 응답하기도 전에 이미 다시 말을 걸고 있었습니다. 그 결과 대화의 혼란이 발생했습니다. 응답이 끊기고, 질문이 반복되며, 사용자들이 "여보세요? 거기 있나요?"라고 말하는 상황이 벌어졌습니다.
우리에게는 단계별(per-stage), 백분위수별(per-percentile) 지연 시간 추적이 필요했습니다. 우리가 찾아낸 그 어떤 것도 우리가 정확히 필요로 하는 기능을 제공하지 않았습니다.
현재 존재하는 것들 (그리고 왜 충분하지 않았는가)
우리는 자체적인 도구를 만들기 전에 여러 옵션을 평가했습니다:
범용 APM 도구 (Generic APM tools) (Datadog, New Relic) — HTTP 요청 지연 시간에는 훌륭하지만, Voice AI 파이프라인의 단계들을 이해하지 못합니다. 커스텀 스팬(custom spans)을 구현할 수는 있지만, 도메인 모델을 직접 구축해야 합니다. 우리는 Datadog을 사용하여 두 달 동안 이를 시도했습니다. 대시보드는 팀원 중 누구도 빠르게 파악할 수 없는 커스텀 메트릭(custom metrics)의 벽이 되어버렸습니다.
제공업체 전용 대시보드 (Provider-specific dashboards) — Deepgram과 ElevenLabs 모두 대시보드에 지연 시간 메트릭을 제공하지만, 오직 자신들의 단계만을 보여줍니다. Deepgram의 STT(Speech-to-Text) 급증을 전체 응답 시간에 미치는 하류 효과(downstream effects)와 상관관계로 분석할 수 없습니다. 또한, 이들은 네트워크 전송(network transit)을 포함한 사용자의 서버 관점이 아닌, 자신들의 관점에서 측정합니다.
부하 테스트 도구 (Load testing tools) (k6, Locust) — 실시간 WebSocket 오디오 스트림이 아닌 HTTP 엔드포인트를 위해 설계되었습니다. 이를 억지로 맞춰 사용할 수는 있지만, 현실적인 음성 대화 패턴(가변적인 발화 길이, 중단, 침묵 간격 등)을 시뮬레이션하는 것 자체가 하나의 프로젝트가 됩니다.
우리는 Voice AI 파이프라인을 위해 특수 제작된 무언가가 필요했습니다. 그래서 직접 만들었습니다.
vox-bench의 작동 방식
vox-bench는 Voice AI 파이프라인의 각 단계를 독립적으로 또는 조합하여 벤치마킹하는 TypeScript CLI 도구입니다. 주요 기능은 다음과 같습니다:
단계별 벤치마킹 (Per-stage benchmarking). STT 제공업체, LLM, 그리고 TTS 제공업체를 지정하세요. 도구는 현실적인 오디오 샘플(다양한 길이를 가진 200개의 의료 도메인 발화 코퍼스 포함)을 전송하고 각 단계를 독립적으로 측정하여 지연 시간 (latency)을 측정합니다. 각 제공업체에 대해 p50, p95, p99 및 최대값 (max)을 확인할 수 있습니다.
파이프라인 시뮬레이션 (Pipeline simulation). 단계들을 서로 연결하면 vox-bench가 전체 대화 왕복 (round-trips) 과정을 시뮬레이션합니다. 이는 전체 첫 번째 바이트 도달 시간 (TTFB, Time-to-First-Byte)과 완료 시간 (time-to-complete)을 측정하며, 이를 단계별로 세분화하여 보여줍니다. 여기서 복합적인 효과를 포착할 수 있습니다. 예를 들어, STT가 50ms 증가하고 LLM이 80ms 증가하여 전체 시간이 임계값을 넘어서는 상황을 확인할 수 있습니다.
제공업체 비교 (Provider comparison). 동일한 벤치마크를 여러 제공업체에 대해 동시에 실행하세요. 저희가 이 기능을 만든 이유는 Deepgram Nova-2에서 Nova-3로 전환했을 때 실제로 p95 STT 지연 시간이 줄어드는지 평가해야 했기 때문입니다 (실제로 줄어들었습니다. 저희의 의료 발화 기준으로 평균 35ms가 감소했지만, 긴 문장에서 p99는 12ms 증가했습니다). YAML 파일에서 제공업체를 구성하면 vox-bench가 이들을 일대일로 비교 실행합니다.
회귀 탐지 (Regression detection). vox-bench를 정기적으로 실행하고 (저희는 6시간마다 실행되는 GitHub Action을 사용합니다), 결과를 기준점 (baseline)과 비교하세요. 만약 어떤 단계의 p95가 설정된 임계값보다 더 많이 움직이면 경고를 보냅니다. 이는 저희에게 큰 손실을 입혔던 ElevenLabs의 급격한 지연 시간 상승 (spike)을 잡아낼 수 있었던 기능입니다.
대화 패턴 시뮬레이션 (Conversation pattern simulation). 실제 통화는 "오디오 전송, 응답 수신, 반복"식으로 이루어지지 않습니다. 통화자는 말을 끊기도 하고, 문장 중간에 멈추기도 하며, 3초 동안 "음"이라고 말하기도 합니다. vox-bench에는 healthcare-intake (의료 접수), appointment-booking (예약), general-inquiry (일반 문의)와 같은 대화 프로필이 포함되어 있으며, 이는 저희의 Loquent 통화 데이터에서 추출한 현실적인 상호작용 패턴을 모델링합니다.
벤치마크가 실제로 보여주는 것
저희는 지난 두 달 동안 내부적으로 vox-bench를 실행해 왔습니다. 현재 운영 중인 스택의 데이터는 다음과 같습니다:
Deepgram Nova-3 STT: p50 = 180ms, p95 = 245ms, p99 = 310ms. 분산(Variance)은 거의 전적으로 발화 길이(Utterance length)에 의해 결정됩니다. 3초 미만의 오디오는 빠르게 처리됩니다. 6~7초를 넘어서면(예를 들어 증상을 설명하는 전체 문장), 지연 시간(Latency)이 급증합니다. 저희의 결론은 다음과 같습니다: 가능한 경우 통화자가 더 짧게 응답하도록 프롬프트(Prompt)를 설계하십시오.
Anthropic Claude (Haiku) LLM: p50 = 210ms TTFB, p95 = 340ms, p99 = 480ms. 이는 스트리밍(Streaming) 방식입니다. 즉, 첫 번째 토큰(Token)이 도착하는 즉시 TTS로 전송을 시작합니다. Claude Sonnet도 테스트했습니다: p50 = 380ms TTFB, p95 = 620ms. 음성 서비스에는 Haiku가 승리합니다. 저희의 사용 사례(예약 일정 관리, FAQ 답변, 접수 질문)에서 Haiku와 Sonnet 사이의 품질 차이는 무시할 수 있는 수준이지만, 지연 시간의 차이는 엄청납니다.
ElevenLabs TTS: p50 = 130ms, p95 = 220ms, p99 = 350ms. 저희 파이프라인(Pipeline)에서 가장 변동성이 큰 단계입니다. 제공업체 측의 용량 문제로 추정되는 상황(항상 동부 표준시(ET) 오후 2~4시 사이)에서 p99가 600ms에 도달하는 것을 확인했습니다. vox-bench는 배포 후 일주일 만에 이 패턴을 포착했습니다.
전체 파이프라인 (End-to-end): p50 = 620ms, p95 = 890ms, p99 = 1,150ms. 저희의 p99는 "자연스럽게 느껴지는" 임계값인 800ms를 상회하지만, "통화자가 말을 반복하게 되는" 선인 1.2초보다는 낮습니다. 저희는 이 트레이드오프(Tradeoff)를 수용하기로 했습니다. p99를 800ms 미만으로 최적화하려면 응답을 미리 생성하거나(품질 저하), 더 빠르지만 품질이 낮은 TTS로 전환해야 하기 때문입니다(품질 저하). 현재로서는 응답의 5~6%가 약간 지연되는 것처럼 느껴지는 것은 허용 가능한 수준입니다.
아키텍처 (The architecture)
vox-bench는 TypeScript (Node.js 20+)로 구축되었습니다. 저희의 전체 Loquent 백엔드가 TypeScript/NestJS로 구성되어 있어, 팀원들이 언어를 전환(Context-switching)하는 번거로움 없이 도구를 확장할 수 있도록 TypeScript를 선택했습니다.
주요 구성 요소: 프로바이더 어댑터 계층 (현재 Deepgram, OpenAI Whisper, Anthropic Claude, OpenAI GPT, ElevenLabs, Google Cloud TTS 지원), 적절한 스트리밍 (Streaming)과 함께 각 단계를 체이닝(Chaining)하는 파이프라인 오케스트레이터 (Pipeline orchestrator), t-digest 알고리즘을 사용하여 백분위수 (Percentiles)를 계산하는 통계 엔진 (모든 측정값을 저장하지 않고도 정확한 백분위수 산출 가능), 그리고 결과를 JSON, Markdown 테이블로 출력하거나 웹훅 (Webhooks)을 통해 모니터링 시스템으로 전송하는 리포터 (Reporter)입니다.
전체 코드는 약 3,200줄의 TypeScript로 이루어져 있습니다. 마법 같은 기교는 없습니다.
주요 발견 사항
-
TTS는 가장 변동성이 큰 단계입니다. STT와 LLM 지연 시간 (Latency)은 비교적 예측 가능합니다. TTS 프로바이더들이 가장 큰 편차를 보이며, 이 편차는 시간대에 따라 달라집니다. 다양한 시간대에 벤치마킹을 수행하지 않으면 잘못된 수치를 얻게 될 것입니다.
-
Voice AI에서 평균 지연 시간은 무의미한 지표입니다. 통화 경험을 결정하는 것은 p95 및 p99입니다. 650ms의 평균 지연 시간은 대화의 5%를 끊긴 것처럼 느끼게 만드는 1.4초의 p99를 숨길 수 있습니다.
-
스트리밍 (Streaming)이 모든 것을 바꿉니다. 스트리밍이 없다면 (TTS로 보내기 전에 LLM 응답이 완료될 때까지 기다린다면), 우리의 p50 총 지연 시간은 1,100ms 이상이 되었을 것입니다. 스트리밍을 사용하면 620ms가 됩니다. 만약 여러분의 Voice AI 파이프라인이 모든 단계에서 스트리밍을 사용하지 않고 있다면, 다른 무엇을 최적화하기 전에 그것부터 수정하십시오.
-
프로바이더 지연 시간은 콘텐츠 도메인에 따라 다릅니다. 우리의 의료 관련 발화 (Utterances) 벤치마킹 결과, 의료 용어 때문에 일반적인 대화보다 STT가 15-20% 더 느렸습니다. 항상 일반적인 테스트 문구가 아닌, 해당 도메인을 대표하는 오디오로 벤치마킹하십시오.
-
벤치마킹을 정기적으로 수행하십시오. 프로바이더의 성능은 정적이지 않습니다. 일정한 주기 (Cadence)로 벤치마킹을 실행하고 추세를 추적하십시오.
vox-bench의 회귀 탐지 (Regression detection) 기능은 우리 애플리케이션 모니터링이 놓친 프로바이더 측의 성능 저하를 세 차례나 포착했습니다.
찾는 방법
저장소는 github.com/Autor-Technologies/vox-bench에서 확인하실 수 있습니다. MIT 라이선스가 적용되었습니다. README 파일에 빠른 시작(Quickstart) 안내가 포함되어 있으며, API 키가 준비되어 있다면 5분 이내에 본인의 프로바이더(Provider)를 대상으로 벤치마크를 실행할 수 있습니다.
저희는 의료 대화 프로필(Healthcare conversation profiles)과 오디오 코퍼스(Audio corpus)를 포함했습니다. 만약 다른 도메인을 위한 Voice AI를 구축 중이라면, 직접 프로필을 생성할 수 있습니다. 형식은 문서화되어 있으며, 본인의 통화 녹음 파일로부터 프로필을 생성해 주는 생성기 스크립트(Generator script)도 제공됩니다.
저희는 이 도구를 내부적으로 활발히 사용하고 있습니다. 버그를 발견하거나 프로바이더 어댑터(Provider adapter)를 추가하고 싶다면 PR(Pull Request)을 환영합니다. 만약 Voice AI를 구축하면서 지연 시간 최적화(Latency optimization)에 대해 논의하고 싶다면, 저희도 아마 여러분이 겪고 있는 것과 동일한 문제에 부딪혔을 것입니다.
유사한 것을 만들고 계신다면, 저희에게 알려주세요. hello@autor.ca로 연락하시거나 autor.ca를 방문해 주시기 바랍니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기