전편은 통화 한 건을 로컬에서 전사해 유형 분류 후보까지 만들었습니다. 이 안내서는 그 전사를 업무에 쓰기 전에 필요한 화자 결합, 용어 교정, 오류율 측정, 재청취 대상 선별을 다룹니다. 화자를 구분하지 않으면 신고자의 "불이 났어요"와 접수자의 "불이 난 게 맞습니까?"가 구분 없이 분류에 들어갑니다.
소방청의 똑똑한 119 인공지능(AI) 신고접수 체계처럼 신고 통화를 문자로 바꾸는 체계를 검토하거나 직접 시험할 때 이 안내서의 품질 기준을 씁니다.
- 합성·익명화 음성을 사용해 화자 라벨이 붙은 전사 품질을 검증할 수 있습니다.
- 용어 교정 전후를 동일한 골든 전사와 비교할 수 있습니다.
- 전체 평균과 잡음·겹침말 조건별 오류를 나눠 읽을 수 있습니다.
- 신뢰도가 낮은 통화를 자동 분류에서 빼고 사람 재청취로 연결할 수 있습니다.
AI에게 맡기는 프롬프트
코드를 실행할 수 있는 AI(코딩 에이전트)에게 품질 측정 코드를 맡길 때 쓰는 프롬프트입니다. 실제 신고자 정보가 없는 합성·비식별 음성만 둔 폴더에서 씁니다. 실제 통화에 돌리는 일은 기관이 승인한 내부 환경에서 따로 합니다.
[목적] 합성 통화 골든셋으로 신고 전사 파이프라인의 품질을 재는 코드를 만들고, 결과를 품질 점검 보고용 표로 정리합니다. [자료] sample 폴더: 합성 통화 음성(wav), 사람이 받아쓴 골든 전사(golden.csv: 파일 이름, 정답 전사, 잡음 조건), 용어 교정표(fix_terms.csv) [완성 기준] - 통화마다 공백을 지운 글자 오류율(CER)을 교정 전과 교정 후로 나눠 계산해 주세요. - 잡음 조건별로 평균과 통화 건수를 함께 보여 주세요. - 신뢰도가 낮은 통화를 재청취 목록으로 따로 내고, 쓴 문턱값과 그 값을 고른 근거를 적어 주세요. - 검산: 결과 행 수 = 골든셋 행 수, 조건별 건수의 합 = 전체 건수, 재청취 목록과 자동 분류 목록이 겹치지 않음 [하지 말 것] - 실제 신고 음성·전사를 쓰지 말고, sample 폴더 밖의 파일을 열지 마세요. - 음성과 전사를 외부 API나 외부 서비스로 보내지 마세요. 모델은 반입해 둔 폴더에서만 읽어 주세요. - 신뢰도가 낮은 구간을 지우지 말고 통화 전체를 재청취로 보내 주세요. - 화자 번호(SPEAKER_00 등)를 접수자·신고자 역할로 확정하지 마세요. - 출동·현장 대응 판단은 쓰지 마세요. 자료에 없는 값은 지어내지 말고 [확인 필요]로 남겨 주세요. 119 신고 음성·전사 관련 공식 데이터와 오픈 소스는 https://119-ai-studio.kr/kg/topic-call-speech.txt 에서 맥락을 먼저 파악하고, 근거는 원문 주소와 함께 정리해 주세요. 확인 기준은 https://119-ai-studio.kr/call-transcription-quality.html 안내서를 따릅니다. 작업 전에 빠진 정보가 있으면 먼저 질문해 주세요.
결과를 받은 뒤 확인할 것은 다음과 같습니다.
- 띄어쓰기만 다른 쌍(
요구조자 발견과요구조자발견)의 CER가 0으로 나오는지 봅니다. 0이 아니면 공백을 지우지 않고 계산한 것입니다. - 조건별 표에 통화 건수가 함께 있는지 봅니다.
- 검산 세 줄이 출력에 실제로 찍혔는지 봅니다.
1. 화자 결합
WhisperX는 faster-whisper(전사)와 pyannote(화자 분리)를 한 흐름으로 묶습니다. 단어 단위 시각을 맞춘 뒤 화자 구간을 겹쳐 발화마다 화자를 배정합니다. 아래 코드는 AI가 만든 코드가 이 순서를 따르는지 보는 기준입니다.
import whisperx from whisperx.diarize import DiarizationPipeline device = "cpu" audio = whisperx.load_audio("call_001.wav") # 합성 통화 # 1) 전사 (내부는 faster-whisper) model = whisperx.load_model("large-v3", device=device, compute_type="int8", language="ko") result = model.transcribe(audio, batch_size=4) # 2) 정렬: 단어 단위 시각 model_a, meta = whisperx.load_align_model(language_code="ko", device=device) result = whisperx.align(result["segments"], model_a, meta, audio, device=device) # 3) 화자 분리 결합: 접수자·신고자 2인을 가정 diarize = DiarizationPipeline(token="hf_...", device=device) segments = diarize(audio, min_speakers=2, max_speakers=2) result = whisperx.assign_word_speakers(segments, result) for s in result["segments"]: print(f'[{s.get("speaker", "?")}] {s["text"].strip()}')
모델 파일은 처음 실행할 때 Hugging Face에서 내려받으므로, 업무망에서는 미리 반입한 모델 폴더를 지정합니다. pyannote의 원격 측정은 PYANNOTE_METRICS_ENABLED=0으로 끕니다.
결합된 스크립트는 이런 모양이 됩니다(가상·합성 예시).
[SPEAKER_00] 네 119입니다 어디십니까 [SPEAKER_01] 여기 상가 2층인데 탄내가 심하게 나요
이제 분류에 신고자 발화만 골라 넣는 후보를 만들 수 있습니다. 다만 SPEAKER_00/01은 접수자·신고자 역할이 아니라 화자 분리가 붙인 묶음 번호입니다. 첫 발화의 "119입니다" 같은 표현은 역할을 추정하는 단서일 뿐이고, 신고자가 먼저 말하거나 두 사람의 말이 겹치면 역할이 뒤집힐 수 있습니다. 역할이 모호하면 통화 전체를 재청취 대상으로 남깁니다. 화자가 붙은 스크립트를 책임 소재를 가리는 근거로 쓰지 않습니다.
2. 용어 교정
일반 음성 모델은 "선착대"를 "선착 대기"로 받아쓰는 것처럼 소방 용어를 틀리게 적을 수 있습니다. 두 가지를 함께 씁니다.
- 전사 전 용어 힌트: faster-whisper에는 용어 목록을 주는
hotwords와 앞 문맥을 주는initial_prompt옵션이 있습니다. 한국어 소방 용어에 어느 쪽이 효과가 있는지는 확인된 기준이 없으므로 두 방식을 3절의 골든셋 CER로 비교합니다. - 전사 후 교정표: 자주 틀리는 표기를 담당자가 관리하는 교정표로 바꿉니다. 바꿀 표기는 법령에 정의된 용어에 맞춥니다. 예를 들어 선착대는 「화재조사 및 보고규정」 제2조제1항제21호의 용어입니다.
import re # 담당자가 관리하는 교정표: 재청취에서 새 오전사를 찾으면 한 줄씩 추가 FIX = { r"선착\s*대기": "선착대", r"요\s*구조자": "요구조자", r"공기\s*호흡기": "공기호흡기", } def fix_terms(text: str) -> str: for pat, to in FIX.items(): text = re.sub(pat, to, text) return text
re.sub 치환은 문맥을 보지 않습니다. 이름이나 지명에 같은 글자열이 들어 있으면 정상 표현도 바뀝니다. 교정 전 원문을 함께 보관하고, 규칙을 한 줄 더할 때마다 3절의 골든셋 CER로 교정 후가 실제로 나아졌는지 확인합니다. 주소·지명은 교정표에 넣지 않고 따로 평가합니다. 주소 발화와 실제 주소를 짝지은 공식 자료로 주소 음성 데이터가 있습니다.3. 품질 측정
합성·비식별 통화를 골라 사람이 정확히 받아쓴 골든 전사를 만들고, 파이프라인 출력과 비교해 오류율을 잽니다. 이 안내서는 글자 오류율(CER)을 씁니다. 단어 오류율(WER)은 띄어쓰기만 달라도 단어 하나를 통째로 틀린 것으로 셉니다.
요구조자인데 요구소자로 나왔다면 네 글자 중 하나가 달라 CER는 0.25입니다. jiwer의 cer는 기본으로 공백도 글자로 세므로 요구조자 발견과 요구조자발견도 오류로 셉니다. 띄어쓰기 차이를 오류로 세지 않으려면 비교 전에 양쪽의 공백을 지웁니다.import pandas as pd from jiwer import cer # pip install jiwer def cer_ko(ref: str, hyp: str) -> float: """공백을 지운 뒤 비교해 띄어쓰기 차이를 오류로 세지 않는다.""" return cer(ref.replace(" ", ""), hyp.replace(" ", "")) pairs = load_goldenset() # [{"ref": 사람 전사, "hyp": 파이프라인 전사, "잡음": "높음"}, ...] for p in pairs: p["cer_raw"] = cer_ko(p["ref"], p["hyp"]) # 교정 전 p["cer_fixed"] = cer_ko(p["ref"], fix_terms(p["hyp"])) # 교정 후 # 조건별 평균과 건수를 함께 본다 report = pd.DataFrame(pairs).groupby("잡음")[["cer_raw", "cer_fixed"]].agg(["mean", "count"])
| 보는 법 | 의미 |
|---|---|
| 전체 CER 추세 | 모델·설정을 바꿀 때마다 이전과 비교하고, 오르면 되돌립니다 |
| 잡음·통화품질별 CER | 사이렌·바람·차량 소음처럼 어떤 조건에서 오류가 많은지 봅니다. 한두 건뿐인 조건의 평균으로 결론을 내지 않습니다 |
| 교정 전후 CER | 교정표가 실제로 오류를 줄이는지 확인합니다 |
4. 신뢰도 라우팅
신뢰도 라우팅은 신뢰도가 낮은 통화를 자동 분류 대신 사람 재청취로 보내는 단계입니다. faster-whisper 단독 전사(전편의 WhisperModel.transcribe)는 구간마다 평균 로그확률(avg_logprob)과 무음성 확률(no_speech_prob)을 남깁니다. 1절의 WhisperX 결과에는 no_speech_prob가 없으므로 아래 함수에 그대로 넣을 수 없습니다. WhisperX 경로에서는 정렬 단계가 단어마다 남기는 점수(score)를 신호로 쓰고, 문턱은 골든셋으로 정합니다.
def route(segments) -> str: """전사 신뢰도로 분기한다. 문턱은 자기 골든셋 CER과 맞춰 조정한다.""" segments = list(segments) # transcribe()가 돌려주는 generator를 목록으로 바꾼다 if not segments: return "재청취" # 전사된 구간이 없으면 사람이 듣는다 bad = [s for s in segments if s.avg_logprob < -1.0 or s.no_speech_prob > 0.6] if len(bad) / len(segments) > 0.3: return "재청취" # 사람이 듣고 직접 처리 return "자동분류" # 비식별 후 전편의 분류 단계로
출발값 -1.0과 0.6은 faster-whisper가 디코딩을 다시 시도할 때 쓰는 기본 문턱과 같은 값이며, 119 통화로 검증한 값이 아닙니다. 구간 비율 0.3도 예시입니다.
운영 루틴 표
| 언제 | 무엇을 | 통과 기준 |
|---|---|---|
| 모델·설정 변경 시 | 골든셋 CER 회귀 | 이전 대비 오르지 않음 |
| 매주 | 재청취 대기열 처리·원인 기록 | 대기열 처리 + 교정표·골든셋 보강 |
| 매월 | 조건별 CER 리포트 | 취약 조건이 개선 추세 |
| 상시 | 화자 결합 스크립트 점검 | 접수자·신고자 뒤바뀜 사례 기록 |
설계 판단
전사 품질을 설계할 때는 어디서 자동 처리를 멈추고 사람 재청취로 돌아갈지를 정합니다.
| 방식 | 맞는 상황 | 트레이드오프 | 사람이 확인할 것 |
|---|---|---|---|
| 전사 텍스트만 생성 | 검색·교육용 초안처럼 화자 구분이 불필요한 때 | 구조가 단순하지만 누가 말했는지 알 수 없음 | 민감한 원음성의 사용 범위 |
| 화자 결합 + 용어 교정 | 대화 흐름을 검토하되 화자 뒤바뀜을 표본 점검할 수 있을 때 | 정렬·분리·교정의 오류가 이어질 수 있음 | 화자 라벨과 교정 전 원문 |
| 신뢰도 라우팅 + 재청취 | 자동 분류에 보내기 전 불확실한 통화를 걸러야 할 때 | 재청취 대기열의 용량과 대기 시간을 관리해야 함 | 재청취 대상과 최종 판단 |
외부망 없는 장비에서 전사·화자 분리·발화 구간 탐지를 함께 돌려야 하면 sherpa-onnx 같은 오프라인 도구도 후보입니다. 어느 도구든 같은 골든셋으로 CER를 비교한 뒤 고릅니다.
운영 시나리오
아래는 실제 신고 내용을 사용하지 않은 합성 통화 기반의 가상 연습입니다.
본문의 CER 코드는 골든셋을 한 번 집계하는 예제이고, route()는 "재청취"나 "자동분류" 문자열만 돌려줍니다. 대기열 등록·대기 건수·조건별 추세는 저장하지 않으므로, 아래와 같은 운영 탐지를 하려면 이 기록을 따로 남기고 사람 검토 결과와 연결해야 합니다.
가상 시나리오 1: 첫 발화 규칙이 접수자와 신고자를 뒤집은 경우
- 탐지: 신고자가 먼저 말하거나 첫 두 발화가 겹친 합성 통화를 사람이 표본 확인했더니, 첫 발화 표현으로 붙인 역할이 뒤집혀 있었습니다. 위의 코드는 이 역할 오류를 자동 탐지하지 않습니다.
- 원인 가설:
SPEAKER_00/01을 역할로 오해하고 '접수자가 항상 먼저 말한다'는 규칙을 고정했지만, 실제 발화 순서와 겹침말 때문에 그 가정이 맞지 않았다고 봅니다. - 대응: 역할이 모호한 통화는 신고자 발화만 자동 추출하지 않고 재청취로 보냅니다. 첫 발화 외의 질문·응답 흐름을 추가 단서로 쓰되, 사용 전 합성 조건별 표본을 사람이 확인합니다.
- 재발 확인: 발화 순서와 겹침을 바꾼 합성 통화로 역할 추정을 사람이 대조하고, 모호한 통화가 자동 분류로 넘어가지 않는지 확인합니다.
가상 시나리오 2: 잡음 구간의 재청취 대기열이 쌓인 경우
- 탐지: 따로 남긴 운영 기록에서 재청취 대기 건수가 늘었고, 골든셋을 조건별로 비교하니 잡음·겹침말 표본이 나빠졌습니다. 이 기록은 본문 최소 예제에 들어 있지 않습니다.
- 원인 가설: 모델 전체가 나빠졌다기보다 특정 음향 조건에서 약점이 드러났고, 재청취 인력도 함께 부족해졌다고 봅니다.
- 대응: 자동 분류로 보내기 위해 신뢰 기준을 임의로 낮추지 않습니다. 해당 조건의 재청취를 먼저 처리하고, 합성 잡음 표본으로 골든셋과 전처리 후보를 보강합니다.
- 재발 확인: 같은 합성 잡음 표본에서 조건별 CER과 재청취 분기가 기준에 맞는지 비교하고, 정상 통화가 지나치게 많이 재청취로 빠지지 않는지도 확인합니다.
한계와 리스크
| 리스크 | 발생 조건 | 영향 | 완화·사람 승인 |
|---|---|---|---|
| 화자 역할 뒤바뀜 | 화자 묶음 번호를 역할로 쓰거나 첫 발화 순서만으로 접수자를 고정함 | 신고자·접수자 발화가 틀린 역할에 속함 | 발화 순서·겹침말 조건별 합성 통화로 역할을 점검하고 사용 전 사람이 표본 승인 |
| 용어 과잉 교정 | 교정표가 문맥을 보지 않고 일반 단어까지 바꿈 | 원문의 의미가 달라지고 사후 검토가 어려워짐 | 교정 전·후를 함께 보존하고 골든 전사 비교 후 담당자가 규칙 승인 |
| 신뢰도 오용 | 재청취 대기열을 줄이려고 문턱을 낮춤 | 신뢰도가 낮은 전사가 자동 분류로 넘어감 | 조건별 CER과 대기열 용량을 함께 보고 출동 판단은 원음성과 사람에게만 두기 |
자주 묻는 질문
Q. CER가 낮으면 화자 라벨도 맞나요?
아닙니다. CER는 글자 오류만 잽니다. 화자 뒤바뀜은 대화 순서 표본 검토로 따로 확인합니다.
Q. 오전사는 모두 교정표로 바꾸면 되나요?
고정 치환은 문맥이 달라지면 정상 단어를 틀리게 바꿀 수 있습니다. 교정 전·후 텍스트를 남기고, 골든 전사에서 오류가 줄어드는 규칙만 사람이 승인합니다.
Q. 신뢰도 낮은 구간만 제거하면 분류에 쓸 수 있나요?
긴급한 내용이 바로 그 구간에 있을 수 있으므로 임의로 지우지 않습니다. 통화 전체를 재청취로 보내고 최종 판단은 사람이 원음성으로 합니다.
Q. 실제 통화로 골든셋을 만들어도 되나요?
이 안내서의 연습·검증은 합성·익명화 음성으로만 합니다. 실제 통화의 재청취·보관·활용은 소속 기관의 권한·보안·보존 절차를 따릅니다.
핵심 정리
- CER는 공백을 지운 뒤 교정 전·후를 함께 계산하고, 조건별 평균은 건수와 함께 봅니다.
- 화자 번호는 역할이 아니며, 역할이 모호하거나 신뢰도가 낮은 통화는 통화 전체를 재청취로 보냅니다.
- 신뢰도 문턱과 교정표 규칙은 예시에서 출발해 자기 골든셋으로 정하고 사람이 승인합니다.
- 연습·검증은 합성·비식별 음성으로 하고, 모델은 반입한 폴더에서 읽어 외부로 보내지 않습니다.
- 자동 전사·교정·라우팅은 출동 판단을 대신하지 않으며 원음성과 사람이 우선입니다.
다음 단계
- 119 신고 통화, 전사부터 유형 분류까지 안전하게 — 품질 검증 전의 기본 파이프라인과 비식별 경계를 다시 확인합니다.
- 개인정보 비식별 파이프라인, 이름·주소까지 자동으로 — 전사문에서 이름·주소·준식별자를 처리하고 놓침을 검증합니다.
- RAG 운영, 골든셋 회귀 평가와 가드레일 — 교정표·모델·문턱 변경 전후를 골든셋 회귀로 관리하는 방식을 익힙니다.