01
왜 다시 STT → LLM → TTS일까?
STT → LLM → TTS 구조에서는 음성 인식, 답변 생성, 음성 합성이 순서대로 이어집니다. LLM이 느리면 뒤의 단계도 기다려야 하고, 비용에는 STT와 TTS 요금도 더해집니다. 여기서 한 가지 가설을 세웠습니다. Cerebras로 LLM 추론을 가속하면, 이 조합도 비용을 고려한 응답 속도에서 OpenAI의 음성 네이티브 모델과 경쟁할 수 있을까요?
이 프로젝트는 빠른 토큰 생성이 실제 음성 응답의 기다림을 얼마나 줄이는지 살펴봅니다. 사용자는 발화문 정제, 음성 합성, 전송과 재생을 거쳐 첫 답변을 듣습니다. 각 단계의 지연과 비용을 연결해, 가속된 LLM 조합이 음성 네이티브 모델에 얼마나 가까워지는지 확인합니다.
02
두 음성 경로는 어디에서 달라질까?
화면에서 Cerebras 기반 파이프라인과 OpenAI Realtime을 선택합니다. 비교 대상은 추론 가속을 사용하는 STT → LLM → TTS 조합과 음성을 직접 입출력하는 모델입니다. 모델명과 실행 구성은 다음과 같습니다.
| 비교 항목 | Cerebras 기반 STT → LLM → TTS | OpenAI Realtime · 음성 네이티브 |
|---|---|---|
| 입력 음성 처리 | ElevenLabs Scribe v2 Realtime · scribe_v2_realtime · 한국어(ko) | gpt-realtime에 음성 입력 · 별도 STT 단계로 분해하지 않음 |
| 응답 생성 | Cerebras 직접 호출 · gpt-oss-120b | OpenAI gpt-realtime |
| 발화문·음성 생성 | Speech Text Agent: gpt-oss-120b · TTS: ElevenLabs Flash v2.5 · eleven_flash_v2_5 | 동일 Realtime 세션에서 음성 출력 · 기본 voice: marin |
| 실행 구조 | LangChain + LangGraph · Main → Speech Text → TTS | 자체 Realtime client · 브라우저 WebRTC + 서버 sideband |
| 외부 도구 | firecrawl_search · 전용 API 키 설정 시 등록 | 현재 비교 세션 tools=[] |
| 연결·관측 | Scribe WebSocket / 서버의 TTS 스트리밍 · OTel → LangSmith | 음성: WebRTC / 관측: sideband WebSocket · OTel → 동일 LangSmith 프로젝트 |
같은 발화 대본으로 첫 음성 응답까지의 지연과 턴당·대화 누적 비용을 비교합니다. PTT와 자동 대화(VAD)는 측정 시작점이 달라 각각 구분합니다.

Cerebras 경로에서는 왜 LLM을 두 번 부를까?
브라우저의 음성을 ElevenLabs Scribe가 텍스트로 바꿉니다. LangGraph는 Main Agent → Speech Text Agent → Speech Synthesis Node를 순서대로 실행합니다. 두 에이전트는 Cerebras를 직접 호출합니다. 마지막 TTS 노드는 ElevenLabs로 음성을 합성하고, 브라우저에 청크 단위로 전달합니다.
화면에서 읽는 답변과 귀로 듣는 답변은 표현 방식이 다릅니다. Main Agent의 표·목록·코드·마크다운을 그대로 TTS에 보내면 기호가 발화에 섞이거나 표의 관계를 알아듣기 어렵습니다. 반대로 모든 답변을 짧은 구어체로 제한하면 상세한 설명과 구조화된 출력이 필요한 작업을 제약합니다. 두 LLM의 역할을 나눈 이유입니다.
Main Agent는 질문을 해결하고 화면용 답변을 만듭니다. Speech Text Agent는 그 최종 답변의 내용을 유지하면서 표와 목록을 문장으로 바꾸고 불필요한 서식을 정리합니다. 대화 이력 전체를 넘기지 않고 매 턴 새 문맥으로 호출합니다. 핵심 역할은 요약이 아니라 발화에 맞춘 표현 변환입니다.

발화문 정제를 추가하면 지연·비용과 듣는 경험이 어떻게 달라질까요? Main Agent의 답변을 바로 TTS에 보내는 LLM 1회 구조와, 정제를 거치는 2회 구조의 비교 질문입니다. 현재 Cerebras 경로에는 정제 에이전트가 포함돼 있습니다. 이 단계의 시간과 사용량을 따로 추적해 역할 분리에 드는 비용을 확인합니다.
OpenAI Realtime은 음성을 어떻게 주고받을까?
OpenAI 경로는 브라우저와 gpt-realtime을 WebRTC로 연결해 음성을 주고받습니다. 앱에서 STT·발화문 정제·TTS 단계를 따로 조립하지 않습니다. 백엔드는 같은 세션에 sideband WebSocket으로 연결해 응답 이벤트와 사용량을 수집합니다.

기본 입력은 연결 상태에서 말하면 발화를 감지하는 자동 대화입니다. 연결 전에 누르고 말하기(PTT)를 선택할 수도 있습니다. 두 모드 모두 같은 WebRTC 연결을 사용하며, 발화 종료와 응답 시작을 정하는 규칙이 달라집니다.
03
동등한 비교를 위해 맞춰야 할 조건
PTT(Push-to-Talk)와 VAD(Voice Activity Detection)는 발화 종료와 응답 시작을 정하는 방식입니다. WebRTC·WebSocket은 음성과 이벤트를 전달하는 연결 방식입니다. 실험에서는 연결 준비·유지 여부와 턴 종료 정책을 별도 조건으로 기록합니다. 자동 대화와 수동 입력의 차이를 연결 프로토콜의 성능 차이로 해석하지 않기 위해서입니다.
주 비교는 C-PTT와 O-PTT의 버튼 해제 → 첫 출력 신호입니다. O-VAD는 자동 대화의 사용 경험을 보는 별도 조건입니다. 현재 구현의 차이는 다음과 같습니다.
| 비교 모드 | 입력 종료·응답 시작 방식 | 지연의 시작점 |
|---|---|---|
| C-PTT Cerebras 수동 입력 | 버튼 해제 → 남은 PCM 전송 → 최종 전사 확정 → LLM | 버튼 해제 최종 전사 대기 포함 |
| O-PTT OpenAI 수동 입력 | VAD 비활성화 → 수동 commit → 응답 생성 요청 | 버튼 해제 commit·응답 요청 포함 |
| O-VAD OpenAI 자동 대화 | server_vad가 발화 종료 감지 무음 대기 설정: 500ms | 브라우저의 speech_stopped 수신 그 이전 대기는 제외 |

O-VAD의 측정값에는 500ms 무음 대기와 종료 이벤트 수신 이전 구간이 빠집니다. 이 값을 PTT와 섞어 순위를 내거나, 설정값 500ms를 더해 실제 발화 종료 지연으로 보정하지 않습니다. 실제 발화 종료부터의 전체 지연을 비교하려면 공통 입력 음성의 종료 기준이 별도로 필요합니다.
같은 PTT라도 전송 경계는 다릅니다. Cerebras는 남은 PCM을 전송한 뒤 최종 전사를 기다립니다. OpenAI는 WebRTC로 음성을 보내고 별도 제어 경로로 commit을 요청합니다. 마지막 오디오의 도착과 commit 순서, 재생 버퍼, 마이크 설정을 함께 확인해야 합니다. PTT로 입력 조작과 측정 시작점을 맞춰도 전송·모델 조건까지 같아지지는 않습니다.
OpenAI 공식 문서: Realtime 대화와 PTT · VAD 설정 · WebRTC 연결
04
지연과 비용의 실험 기준 — OTel로 무엇을 기록할까?
OpenTelemetry로 이벤트·구간 시간·사용량을 수집하고, LangSmith에서 같은 turn ID의 trace로 확인합니다. 비용은 관측한 사용량에 단가를 적용해 계산합니다. OTel이 공급자의 실제 청구액을 가져오는 것은 아닙니다.
| 측정 항목 | 측정 경계 / 기록 | 해석 기준 |
|---|---|---|
| 응답 시작 지연 주 지표 | 입력 종료 기준점 → 첫 브라우저 출력 신호 PTT와 VAD를 구분 | 케이스별 표본 수·평균·p50·p95 물리적 스피커 소리의 실측은 아님 |
| STT 확정·준비 | Cerebras: 버튼 해제 → 최종 전사 stt_final_after_release_ms 연결 준비는 stt_setup_ms로 분리 | 입력 종료 처리와 연결 준비를 분리 첫 partial은 최종 전사 완료가 아님 |
| LLM·발화문·TTS | Main / Speech Text의 TTFT·전체 생성 TTS 시작 → 첫 오디오 청크 | 추론 가속이 전체 지연에 기여하는 구간 서로 겹치는 시간을 단순 합산하지 않음 |
| 도구 실행 | 도구명·호출 수·성공/실패 tool_elapsed_ms / 추가 LLM 호출 | 도구 대기와 후속 추론을 분리 도구가 실제 호출된 턴을 확인 |
| 사용량·턴 비용 | LLM 토큰 / STT 전송 음성 길이 / TTS 문자 Realtime text·audio·cache usage | 사용량 × 적용 단가로 USD 추정 정답률이나 답변 품질 점수는 산출하지 않음 |
| 실행 전체 비용 | 중복 없는 turn_id의 확인된 비용 합 완료·중단·오류·미산정 수 | 완료 턴 평균과 전체 실행 합계를 구분 누락 사용량을 0으로 대체하지 않음 |
브라우저 시간은 performance.now()로 계산한 명시적 지표를 읽습니다. LangSmith의 span duration은 브라우저 체감 지연과 같지 않습니다. 첫 출력은 공통 RMS 기준으로 감지하며, OpenAI 내부를 STT·LLM·TTS로 추정 분해하지 않습니다.
| 경로 | 추정 비용의 구성 | OTel / LangSmith에서 확인할 값 |
|---|---|---|
| Cerebras | Main의 모든 LLM 호출 + 발화문 정제 + STT 음성 길이 × 단가 + TTS 문자 수 × 단가 | cost_llm_usd / cost_stt_usd cost_tts_usd / cost_total_usd usage_model_calls |
| OpenAI Realtime | 텍스트·오디오 입력/출력 토큰 캐시 입력을 구분해 단가 적용 | provider usage → cost_total_usd text / audio / cached 사용량 |
| 외부 도구 | 추가 LLM 호출 비용 + 도구 서비스 비용 | LLM 비용은 호출별 usage에 포함 Firecrawl 자체 요금은 현재 합계 밖 별도 사용량·단가가 있어야 전체 비용 산정 |
비용은 custom metadata의 cost_total_usd·cost_status·cost_missing과 적용 단가로 확인합니다. LangSmith 기본 Cost/Token 칸만으로 집계하지 않습니다. 중단·오류에도 확인된 사용량은 포함하고, 누락은 미산정으로 남깁니다.
STT 비용에는 준비 시간을 제외한 전송 PCM 길이를 사용합니다. 도구 요금이나 실패 세션 등 집계 밖 항목이 있으면 전체 청구 총액과 구분합니다.
05
테스트 시나리오 — 어떤 실행 조건을 바꾸어 볼까?
도구 호출, 발화문 정제, 입력·출력 길이와 대화 문맥을 바꾸며 지연·비용을 비교합니다. 실험 단위는 에이전트의 실행 경로와 사용 조건입니다. 발화 대본은 같은 조건을 반복하기 위한 입력 예시로 사용합니다. 대화 정답률을 채점하는 벤치마크는 아닙니다.
| 실험 시나리오 | 비교 조건 | 확인할 지연·비용 |
|---|---|---|
| S01 · 도구 없는 기본 응답 | Cerebras vs OpenAI 양쪽 도구 목록 비움 / 동일 PTT 입력·응답 길이 범위 고정 | 음성 경로 자체의 응답 시작 지연 STT·LLM·TTS 포함 턴 비용 |
| S02 · 도구 호출 추가 | 도구 0회 vs 검색 1회 firecrawl_search와 동일 결과를 반환하는 대조 입력 검색 결과 크기·후속 응답 길이 통제 | 도구 대기 + 추가 LLM 추론 + 음성화 호출 전후 전체 지연·비용 증가분 |
| S03 · 도구 지연·실패 | 동일 도구 결과에 지연 0/500/1,500ms 성공 / timeout / 오류 조건 분리 | 외부 대기가 첫 응답을 늦추는 정도 실패·재시도·취소에 쓰인 비용 |
| S04 · 발화문 정제 유무 | Cerebras: Main 답변 직접 TTS vs 정제 후 TTS 단계 비교에는 같은 Main 최종 답변 사용 | 정제 LLM의 추가 지연·토큰 발화 길이 변화에 따른 TTS 비용 |
| S05 · 입력·출력 부하 | 짧은/긴 입력 × 짧은/긴 응답 기존 L01–L04 대본으로 조건 재현 | 입력 음성 길이·실제 출력량별 첫 응답 지연과 턴 비용 |
| S06 · 연결·문맥 누적 | 새 연결 첫 턴 vs 후속 턴 같은 연결에서 10턴 유지 기존 L05–L06 활용 | 연결 준비와 응답 지연 분리 문맥·캐시 사용량과 누적 비용 |
| S07 · 발화 종료·중단 | 같은 Realtime 모델에서 PTT / VAD 구분 발화 중 멈춤 / 답변 중 끼어들기 | 응답 분할·추가 생성·중단 여부 중단된 응답의 사용량과 비용 |
구현 범위와 비교 조건도 구분합니다. 현재 Cerebras는 Main → Speech Text → TTS의 정제 포함 경로이며, 전용 키가 있으면 Firecrawl 도구가 등록됩니다. OpenAI 비교 세션은 tools=[]입니다. S01의 ‘도구 비활성화’는 실제 등록 목록으로 확인하고, 단순히 도구를 호출하지 않은 턴과 구분합니다.
S02·S03의 두 시스템 비교에는 동일 도구 계약·결과·지연·오류 조건이 필요합니다. OpenAI 도구 연결과 제어 가능한 도구 응답은 이 비교를 위한 추가 구성입니다. S04의 정제 생략 경로도 별도 대조 구성입니다. 현재 정제 단계의 trace만으로 정제를 뺀 시스템의 전체 지연을 단정하지 않습니다.
표본은 시나리오·모드·반복·턴 위치·실제 도구 호출 수로 구분합니다. 같은 마이크·브라우저·네트워크에서 실행하고, 입력 길이·출력량·연결 상태·구현 버전을 기록합니다. 임시 전사를 제출하던 수정 전 결과와 scribe-manual-final-v1의 최종 전사 제출 결과는 분리합니다.
양쪽에서 같은 조건을 동일한 횟수로 반복하되 실행 순서를 교차합니다. 표본이 적으면 개별 값·중앙값·범위를 함께 제시합니다.
완료되고 출력 신호가 있는 턴의 지연과, 모든 시도의 완료·오류·중단·미산정 건수를 함께 제시합니다. 비용은 완료 턴 평균과 실행 전체 합계를 구분합니다. 결과 JSON과 trace는 turn ID로 연결하고, 시나리오 조건은 실행 기록에 함께 보관합니다.
모델·음성·문맥 처리 방식이 다르므로 이 비교는 두 시스템의 설계 선택에 따른 trade-off를 보여줍니다. Cerebras 가속만의 인과 효과를 주장하려면 같은 모델·파이프라인에서 추론 제공자만 바꾼 별도 대조군이 필요합니다.
06
지연·비용·사용자 경험은 어떻게 달라질까?
[결과 그림 1 · 실행 시나리오별 응답 시작 latency와 비용]
[결과 표 1 · 시나리오·모드·조건별 표본 수, 평균·p50·p95 latency, 턴당 비용]
[결과 그림 2 · 10턴 대화의 턴별 latency와 누적 비용]
[결과 그림 3 · Cerebras의 LLM·발화 정제·TTS·브라우저 관측 지점별 trace]
[결과 표 2 · 도구 호출 수·지연·실패 조건별 추가 지연, LLM 비용, 도구 요금]
[결과 표 3 · LLM 1회·2회: 전체 응답 시작 지연, 정제 단계 지연, 턴당 비용]
[사용자 경험 메모 · 첫 응답의 기다림, 대화 흐름, 표·목록의 발화 방식]
[결과 해석 · 음성 네이티브 모델 대비 latency·cost와 발화문 정제의 trade-off]
07
이 비교로 어떤 설계 판단을 보여주고 싶을까?
이 프로젝트에서 보여주려는 것은 빠른 LLM이 실제 음성 대화에 얼마나 도움이 되는지 판단하는 과정입니다. Cerebras 파이프라인과 OpenAI Realtime을 같은 화면에서 비교하고, 각 턴의 응답 시작 지연과 비용을 연결했습니다. 화면용 답변과 발화문을 분리한 이유, LLM을 한 번 더 호출하는 비용도 함께 살펴봅니다. 이 결과와 사용 경험을 음성 에이전트의 구조를 선택하는 근거로 삼고자 합니다.