실패한 QA 한 줄마다 규칙 하나: LLM 대화 시스템에 Guardrail이 쌓이는 과정

이 글은 한국어 전화 Voice Agent 현장 노트 7부작 중 5부다. 내가 리드했던 프로젝트 — 공공 서비스 전화 상담용 실시간 한국어 voice agent(STT → LLM → TTS) — 를 만들면서 겪은 일을 정리한다. 1부는 STT 평가가 나를 속인 방식, 2부는 rule이 모델을 이기는 곳, 3부는 latency, 4부는 exception 한 번 없이 조용히 실패한 것들을 다뤘다. 이번 글은 dialog layer 이야기다. 그 안의 규칙이 실패한 QA row 하나마다 하나씩 불어난 과정을 따라간다. 3월 25일 하루에만 dialog service에 commit을 32개 했다. 첫 commit이 00:56, 마지막이 16:59였고, 그중 26개의 제목이 “Fix"로 시작한다. 11:00에는 한 요청 유형의 첫 안내 멘트를 바꿨다. 정작 물어야 할 질문 앞에 주의 사항이 세 문장이나 붙어 있던 것을 짧고 자연스러운 질문 하나로 줄였다. 그리고 11:07에 되돌렸다. Commit message에는 “original detailed greeting for QA compatibility"로 돌아간다고 적혀 있다. 전화로 들으면 짧은 쪽이 분명 나았다. 그런데도 진 이유는 하나, 정답지가 옛 멘트를 기준으로 쓰여 있었기 때문이다. (이 commit message를 다시 읽는 건 꽤 민망한 일이었다.) ...

2026년 8월 11일 · 9 분

아무것도 죽지 않았다: 프로덕션 음성 AI 스택의 조용한 실패들

이 글은 한국어 전화 Voice Agent 현장 노트 7부작 중 4부다. 내가 리드했던 프로젝트 — 공공 서비스 전화 상담용 실시간 한국어 voice agent(STT → LLM → TTS) — 를 만들면서 겪은 일을 정리한다. 1부는 STT 평가가 나를 어떻게 속였는지, 2부는 rule이 모델을 이기는 곳, 3부는 latency를 다뤘다. 이번에는 exception 한 번 던지지 않고 조용히 실패한 것들 이야기다. 웹 앱이 망가지면 누군가는 500 페이지라도 본다. Voice agent가 망가지면 전화를 건 사람은 아무것도 듣지 못한다. 침묵에 대고 “여보세요?“를 두어 번 하다가, 몇 초 기다리고, 끊는다. Stack trace는 caller에게 닿지 않고, 많은 경우 나한테도 닿지 않는다. ...

2026년 7월 21일 · 9 분

더 큰 모델이 더 빨리 답했다: 실시간 Voice Agent의 Latency 교훈

이 글은 한국어 전화 Voice Agent 현장 노트 7부작 중 3부다. 내가 리드했던 프로젝트 — 공공 서비스 전화 상담용 실시간 한국어 voice agent(STT → LLM → TTS) — 를 만들면서 겪은 일을 정리한다. 1부는 STT 평가가 나를 어떻게 속였는지, 2부는 rule이 모델을 이기는 지점을 다뤘다. 이번 글은 latency 이야기다: 시간이 어디로 새고 있었는지, 그리고 실제로 효과가 있었던 처방이 왜 거의 한 번도 “더 작은 모델 쓰기"가 아니었는지. 첫 latency 작업에 들어가기 전, 응답 하나가 end-to-end로 평균 4.5초 걸렸다. 전화에서 4.5초는 “느리다"가 아니라 “고장 났다"로 들린다. 그 정도 침묵이면 발신자는 전화가 끊겼나 싶어 “여보세요?“를 하고, 하필 agent가 막 대답을 시작하는 순간에 말이 겹친다. ...

2026년 6월 30일 · 9 분

Fine-Tuning이 진짜 효과가 있었나? Whisper 한국어 STT Evaluation과 Benchmarking

이 글은 한국어 STT를 위한 Whisper fine-tuning 3부작 중 3부다: Preprocessing → Training → Evaluation. 여기서는 fine-tuning한 모델이 정말 나아졌는지, 얼마나 나아졌는지를 측정한다. 1부는 전처리, 2부는 학습을 다뤘다. 학습이 끝난 모델은 그냥 디스크에 있는 checkpoint일 뿐이다. Training loss curve가 내려가는 걸 보고 기분이 좋을 수는 있지만, held-out data에 실제로 돌려서 CER, WER, category별 성능을 측정하기 전까지는 fine-tuning이 효과가 있었는지, 특정 도메인에서 오히려 망가졌는지, base model 대비 얼마나 좋아졌는지 알 수 없다. 이 글에서는 두 가지 script를 다룬다: 단일 모델 evaluation용 스크립트와, 여러 모델을 category별로 비교하는 benchmarking 스크립트. 엔지니어링 측면에서는 수천 개 audio sample, multi-GPU, 여러 model checkpoint를 I/O bottleneck이나 메모리 문제 없이 효율적으로 처리하는 데 초점을 맞췄다. ...

2026년 2월 19일 · 6 분

Precomputed Feature로 Whisper 학습하기: 한국어 STT Full Fine-Tune

이 글은 한국어 STT를 위한 Whisper fine-tuning 3부작 중 2부다: Preprocessing → Training → Evaluation. 여기서는 전처리된 dataset을 불러와 학습 루프를 돌린다. 1부는 전처리, 3부는 evaluation/benchmarking을 다룰 예정이다. Mel spectrogram과 tokenized label을 디스크에 저장해 두었다면, 다음은 이걸 training loop에 넣고 모델을 최적화하는 일이다. 말만 하면 간단한데, 막상 선택지가 쏟아진다. Full fine-tuning 할까 LoRA 할까? Learning rate랑 batch size는? Encoder-decoder에서 길이 다른 sequence는 어떻게 padding 하고, GPU 메모리를 낭비하지 않으면서 터지지 않게 할까? 이 글에서는 한국어 통화 음성에 대해 Whisper large-v3를 학습시킬 때 쓰는 training 설정과, 그 뒤에 있는 공학적 선택(trade-off)을 정리한다. ...

2026년 2월 15일 · 5 분

Mel Spectrogram을 매번 다시 계산하지 마라: Whisper Fine-tuning 전 데이터 전처리

이 글은 한국어 STT를 위한 Whisper fine-tuning 3부작 중 1부다: Preprocessing → Training → Evaluation. 이번 글에서는 data preprocessing pipeline을 소개한다. 2부와 3부에서는 각각 training loop과 evaluation/benchmarking을 다룰 예정이다. OpenAI의 오픈소스 STT 모델인 Whisper를 파인튜닝하는 과정에서 생각지 못했던 난관에 봉착했다. learning rate를 바꾸든, batch size를 키우든, 아니면 그냥 GPU가 OOM으로 터지든 — 학습을 돌릴 때마다 수십 시간을 원본 오디오 파일 처리에 쓰는 것이다. WAV 파일 로드, 16 kHz로 sample rate 변경, mel spectrogram 계산, 텍스트 tokenization로 구성된 이 전처리 과정은 매번 동일하다. 데이터는 전혀 바뀌지 않는데, 매번 데이터 준비에 드는 시간과 비용을 전부 지불하고 있었던 거다. (남몰래 줄줄 새는 EC2 대여료…) ...

2026년 2월 11일 · 5 분