신고 음성과 전사 텍스트에는 신고자의 목소리·이름·전화번호·위치·환자 상태가 그대로 담겨 있어 119 데이터 가운데 가장 민감한 자료입니다. 이 안내서는 119긴급신고 통화를 승인된 내부 환경에서 전사·비식별·분류하는 과정을 합성 자료로 익히는 실습이며, 분류 결과는 사람의 배정을 돕는 후보입니다.
소방청 2022년 보도자료는 신고 통화를 문자로 바꾸고 핵심 단어로 출동대 편성과 대처 안내를 돕는 똑똑한 119 인공지능(AI) 신고접수 체계의 시범운영 결과를 언급합니다. 이 안내서는 그 체계를 대신하지 않고 결과의 검산 기준을 다룹니다.
- 음성·전사·비식별문·분류 후보의 민감도와 이동 경계를 구분할 수 있습니다.
- 모델 파일 반입과 선택적 화자 분리의 역할을 설명할 수 있습니다.
- 비식별 뒤 허용 라벨과 근거 문장으로 분류 결과를 검산할 수 있습니다.
- 불확실한 전사와 분류를 사람 재청취·확인 대상으로 보낼 수 있습니다.
AI에게 맡기는 프롬프트
기관이 승인한 내부 환경의 코딩 에이전트(파일을 읽고 코드를 실행하는 AI 도구)에게 시험용 파이프라인을 맡길 때 쓰는 프롬프트입니다. 외부 AI 서비스가 아니라 승인된 내부 환경에서, 실제 신고자·환자 정보가 없는 합성 통화로만 씁니다.
[목적] 합성 신고 통화를 전사하고 개인정보를 가린 뒤, 유형·긴급도 후보와 근거 문장을 만드는 시험용 파이프라인을 만듭니다. 결과는 사람이 검토 순서를 정할 때 참고하는 후보입니다. [자료] sample 폴더: 합성 통화 음성과 사람이 작성한 기준 전사(실제 신고 음성 없음). 모델 파일은 models 폴더에 미리 반입돼 있습니다. [완성 기준] - 통화마다 유형(화재·구조·구급·기타·확인필요), 긴급도(높음·보통·낮음·확인필요), 근거 문장을 적은 결과 파일을 만들어 주세요. - 결과 수와 입력 통화 수, 허용 라벨, 근거 문장이 비식별 전사에 실제로 있는지를 검산하고 그 결과를 출력해 주세요. - 근거가 약한 통화는 추측해 채우지 말고 확인필요로 두세요. [하지 말 것] - 음성과 전사를 외부 AI 서비스나 외부 전사 서비스로 보내지 마세요. 모델은 models 폴더에서만 읽고 실행 중 내려받지 마세요. - sample 폴더 밖의 파일은 열지 마세요. - 출동 배정이나 우선순위를 확정하는 기능은 만들지 마세요. 맥락은 https://119-ai-studio.kr/kg/topic-call-speech.txt 에서 먼저 파악하고, 근거는 원문 주소와 함께 정리해 주세요. 확인 기준은 https://119-ai-studio.kr/call-transcription-triage.html 안내서를 따릅니다. 자료에 없는 값은 [확인 필요]로 남겨 주세요. 작업 전에 빠진 정보가 있으면 먼저 질문해 주세요.
결과를 받은 뒤 확인할 것은 다음과 같습니다.
- 결과 수, 허용 라벨, 근거 문장 검산 결과가 출력에 실제로 찍혔는지 봅니다.
- 모델을 models 폴더에서 읽었고 실행 중 외부 연결이 없었는지 확인합니다.
- 분류에 넣은 전사가 비식별본인지, 확인필요로 둔 통화가 사람 검토 목록에 남았는지 봅니다.
승인된 내부 환경에서 하는 이유
음성을 외부 전사 서비스나 클라우드에 올리면 복사본과 로그가 어디에 남는지 기관이 확인하기 어렵습니다. 그래서 전사·비식별·분류는 승인된 내부 환경을 기본으로 둡니다. 외부 처리가 꼭 필요하면 비식별에 더해 개인정보·보안 담당자의 별도 승인을 먼저 받아야 하며, 비식별만으로 외부 전송 권한이 생기지 않습니다.
여기서 "로컬"은 음성과 전사가 승인된 장비 밖으로 나가지 않는다는 뜻입니다. 모델 파일을 처음 내려받을 때와 화자 분리 모델의 인증 토큰을 쓸 때는 외부 연결이 생기므로, 망분리 환경에서는 모델 파일을 승인된 경로로 미리 반입합니다.
동작 원리
전사 모델은 음성을 짧은 시간 구간의 텍스트 후보로 바꾸고, 화자 분리는 같은 시간축에 누가 말했는지 구간 후보를 붙입니다. 화자 분리를 생략해도 전사는 되지만 접수자의 질문과 신고자의 진술을 나눠 다루기 어렵습니다.
전사 직후 텍스트는 음성과 같은 민감 자료로 봅니다. 비식별 단계는 신원 식별 값을 가리고 사건 유형 표현만 남기며, 마스킹 전·후를 공개 로그에 함께 남기지 않습니다.
분류 단계는 비식별된 텍스트를 고정 라벨 집합에 매핑하고, 선택 근거가 된 문장을 함께 냅니다. 아래 최소 코드는 결과 수, type·urgency 허용집합, 근거 필드의 존재만 확인하며, 불확실하면 확인필요 경로로 보냅니다.
가상 상황: 동시다발 신고 때 검토 순서 정하기
다음은 학습용 가상 상황입니다. 새벽에 한 지역에 신고가 몰려 접수석 세 자리에 일곱 통이 겹쳐 들어옵니다. 통화를 접수하는 요원들은 통화마다 끝까지 듣고 유형과 긴급도를 가릴 시간이 부족합니다.
녹음된 통화가 분류 후보로 정리되면 요원은 "긴급도 높음"과 "확인필요"로 표시된 건부터 다시 듣습니다. 파이프라인은 먼저 볼 순서를 제안할 뿐이며 배정은 사람이 정합니다.
가상 사례: 품질 담당자의 합성 통화 전사 검수
다음은 접수 폭주 사례와 다른 가상 사례입니다. 품질 담당자가 전사 모델을 바꾼 뒤 교육용 합성 음성과 사람이 작성한 기준 전사로 차이를 봅니다. 차이는 용어 오류, 숫자 오류, 겹침 발화 누락, 빈 구간으로 나누고, 분류 후보가 달라진 건은 전사 오류 때문인지 분류 규칙 때문인지 가립니다.
문장이 그럴듯하다는 이유로 숫자·지명 오류를 놓치면 실패합니다. 담당자는 오류 구간을 다시 듣고 변경 전후 결과를 기록하며, 합성 자료의 결과를 실통화 안전성의 근거로 쓰지 않습니다.
파이프라인 4단
| 단계 | 무엇을 | 도구 | 데이터 위치 |
|---|---|---|---|
| 1 전사 | 음성 → 텍스트 | faster-whisper | 승인된 내부 환경 |
| 2 화자 분리(선택) | 신고자/접수자 구분 | pyannote | 승인된 내부 환경 |
| 3 비식별 | 전사에서 개인정보 제거 | 개인정보 점검 절차 | 승인된 내부 환경 |
| 4 분류 | 유형·긴급도 후보 | 프롬프트 + 검산 | 승인된 내부 환경; 외부 전송은 별도 승인 |
선택지와 트레이드오프
모든 통화에 같은 처리를 강제하기보다 품질·민감도·운영 목적에 맞춰 단계를 고릅니다.
| 선택지 | 맞는 상황 | 장점 | 주의할 점 |
|---|---|---|---|
| 로컬 전사 + 화자 분리 | 화자별 발화를 나눠 검토해야 할 때 | 신고자 발화 후보를 별도로 볼 수 있음 | 화자 바뀜·겹침 오류를 사람이 확인해야 함 |
| 규칙 기반 키워드 후보 | 라벨 규칙이 좁고 생성형 출력이 필요 없을 때 | 동작과 근거를 비교적 직접 설명 가능 | 표현 변화와 문맥을 놓쳐 확인필요가 늘 수 있음 |
| 비식별 후 제한된 분류 프롬프트 | 다양한 표현을 고정 라벨로 묶어야 할 때 | 근거 문장과 후보를 정해진 형식으로 요청 가능 | 비식별 미탐·환각·잘못된 근거를 사람 검토해야 함 |
오프라인 음성 도구 sherpa-onnx와, 키워드 규칙용 한국어 형태소 분석기 kiwipiepy도 후보입니다.
1. 로컬 전사: faster-whisper
모델 이름만 주면 Hugging Face Hub에서 내려받으므로, 망분리 환경에서는 반입한 폴더를 줍니다.
from faster_whisper import WhisperModel # CPU + INT8 양자화(모델을 가볍게 해 메모리를 적게 씀) # 반입 폴더에 tokenizer.json 까지 있어야 내려받기를 안 한다 from pathlib import Path model_dir = Path("models/faster-whisper-large-v3") missing = [f for f in ("model.bin", "config.json", "tokenizer.json") if not (model_dir / f).exists()] assert not missing, f"반입 폴더에 없는 파일: {missing}" model = WhisperModel(str(model_dir), device="cpu", compute_type="int8", local_files_only=True) # language="ko"로 한국어 고정, 타임스탬프 포함 segments, info = model.transcribe("call_001.wav", language="ko", beam_size=5) lines = [f"[{s.start:.1f}-{s.end:.1f}] {s.text.strip()}" for s in segments] transcript = "\n".join(lines) # 전사는 여기서부터 '민감 데이터'로 취급
beam_size는 함께 비교하는 후보 문장의 수로, 클수록 느려집니다. 속도는 장비마다 다르므로 large-v3, large-v3-turbo 같은 후보를 같은 합성 통화로 돌려 처리 시간과 오류를 함께 잽니다.
2. 화자 분리(선택): 신고자 발화 추리기
통화 전체를 분류에 넣으면 접수자의 확인 질문("불이 난 게 맞습니까?")이 신고자의 진술과 섞여 유형 판단을 흐립니다. pyannote는 모델 사용 조건 동의 뒤 받은 토큰으로 처음 내려받고, 추론은 로컬에서 실행합니다. 선택형 사용 통계는 PYANNOTE_METRICS_ENABLED=0으로 끕니다.
from pyannote.audio import Pipeline # 망분리 환경에서는 반입한 모델 폴더(config.yaml 포함) 경로를 대신 줌 pipeline = Pipeline.from_pretrained("pyannote/speaker-diarization-community-1", token="hf_...") output = pipeline("call_001.wav") # 추론은 로컬에서 실행 for turn, speaker in output.speaker_diarization: print(f"{turn.start:.1f}-{turn.end:.1f} {speaker}")
전사와 화자 구간을 묶어 발화마다 화자를 붙이는 방법은 신고 전사 심화, 화자 결합과 품질 관리에서 이어집니다.
3. 전사 비식별: 분류에 넣기 전
외부 처리가 별도로 승인된 경우에도 언어모델 분류에 넣기 전에 반드시 비식별합니다. 개인정보, AI에 넣기 전에 점검하기의 3단 점검(정규식 → 문맥 → 사람)을 전사에 적용하고, 자동 마스킹 뒤에도 이름·상세 주소는 사람이 최종 확인합니다. 아래 값은 모두 지어낸 합성값입니다.
[비식별 전, 전부 합성 예시] [6.0-9.5] 저는 김하늘이고요 한빛로 12길 34, 301호인데 베란다에서 연기가 나요 [비식별 후] [6.0-9.5] 저는 [이름]이고요 [주소]인데 베란다에서 연기가 나요
4. 유형·긴급도 분류: 후보를 만들되 단정하지 않기
분류는 고정 라벨 안에서 고르고 근거 문장을 붙이게 합니다. 실행기가 지원하면 출력 스키마에 허용 라벨을 적어 출력 자체를 제한하고(로컬 AI의 JSON 추출 예제), 그래도 아래 검산을 돌립니다.
아래는 비식별된 신고 전사입니다. 유형은 [화재, 구조, 구급, 기타] 중에서만 고르세요. 긴급도는 [높음, 보통, 낮음] 중에서만 고르세요. 판단 근거가 된 전사 문장을 그대로 인용해 함께 적으세요. 근거가 약하면 유형/긴급도를 "확인필요"로 두세요. 추측해서 채우지 마세요.
ALLOWED_TYPE = {"화재", "구조", "구급", "기타", "확인필요"}
ALLOWED_URGENCY = {"높음", "보통", "낮음", "확인필요"}
assert len(results) == len(transcripts), "검산 실패: 분류 수 ≠ 입력 수"
assert all(r["type"] in ALLOWED_TYPE for r in results), "허용 라벨 밖의 type이 있습니다"
assert all(r.get("urgency") in ALLOWED_URGENCY for r in results), "허용 라벨 밖의 urgency가 있습니다"
assert all(r.get("evidence") and isinstance(r["evidence"], str) for r in results), "근거 필드가 비어 있거나 문자열이 아닙니다"
현재 네 assert는 필드의 존재와 기본 형식만 검사합니다. 근거 문장이 비식별 전사에 실제로 있는지는 별도 검사로 확인하고, 그 검사를 통과해도 근거의 의미가 분류를 실제로 뒷받침하는지는 담당자가 확인합니다. 이 검사와 라우팅을 구현한 뒤에야 근거가 비었거나 확인필요인 건을 사람에게 자동으로 올릴 수 있습니다.
자주 하는 실수와 한계
- 오전사를 사실로 믿는 경우: 전사 모델은 소방 용어·지명·숫자를 잘못 받아쓸 수 있습니다("삼 동"↔"산 동"). 신뢰도가 낮은 통화는 원음성을 다시 듣습니다.
- "확인필요"를 흘려보내는 경우: 근거가 약한 건을 자동으로 채우면 긴급 신고가 후순위로 밀릴 수 있습니다. "확인필요"는 사람에게 올리는 상태로 다룹니다.
- 짧거나 겹치는 통화를 과신하는 경우: 동시 발화나 몇 초짜리 통화에서는 전사와 화자 분리가 함께 흔들립니다. 신뢰도로 걸러 재청취로 보내는 방법은 심화편에서 다룹니다.
- 실통화로 연습하는 경우: 실제 신고를 바탕으로 하지 않은 가상 대본으로 시험용 음성을 따로 준비합니다. 이 사이트는 합성 통화 음성 파일을 제공하지 않습니다. 실제 신고 접수 통화로 만든 AI 허브의 119 지능형 신고접수 음성 인식 데이터는 신청·승인이 필요하고, 비식별 처리 방식이 적혀 있지 않습니다. 기관 승인 환경에서 검토할 때도 이용 조건을 먼저 확인합니다.
- 한국어 신고만 가정하는 경우: 외국인 신고는 구급 주제 시나리오 녹음이 든 다국어 일상대화 실시간 통번역 데이터로 따로 평가합니다.
문제 해결
| 증상 | 가능한 원인 | 처방 | 확인 |
|---|---|---|---|
| 전사 일부가 비거나 반복됨 | 음질·겹침 발화·구간 분할 문제 | 해당 시간 구간을 실패 후보로 남기고 사람이 재청취 | 원음성 시간축과 전사 구간의 누락·중복 확인 |
| 접수자 질문이 신고자 진술로 분류됨 | 화자 분리 오류 또는 전체 전사를 그대로 사용 | 화자 구간을 재확인하고 불확실 발화는 혼합 상태로 유지 | 화자별 샘플을 사람이 듣고 표지와 비교 |
| 비식별 뒤 이름·주소 일부가 남음 | 자동 패턴이 한국어 문맥형 정보를 놓침 | 분류를 멈추고 문맥 점검과 사람 확인으로 되돌림 | 승인된 합성 예시와 별도 검토에서 미탐 여부 확인 |
| 분류 결과 수가 입력보다 적음 | 빈 전사·파싱 실패·응답 누락 | 누락 ID를 확인필요로 분리하고 자동 배정에서 제외 | 입력 ID와 결과 ID를 양방향 대조 |
자주 묻는 질문
Q. 로컬에서 전사하면 개인정보 검토는 필요 없나요?
로컬 처리는 외부 전송을 줄이는 선택입니다. 전사 텍스트 자체는 여전히 민감하므로 접근·저장·비식별·사람 확인이 필요합니다.
Q. 비식별로 주소가 가려지면 분류 근거가 부족하지 않나요?
유형 분류에 필요한 사건 표현과 신원 식별 값은 구분합니다. 필요한 맥락까지 사라졌다면 추측으로 채우지 않고 확인필요로 남겨 접수자가 원통화에서 확인합니다. 주소 인식을 따로 시험하려면 주소 음성 데이터와 주소 검색·정규화 API를 승인된 환경에서 검토합니다.
Q. 긴급도 후보가 높음이면 먼저 자동 배정해도 되나요?
이 결과는 사람 검토 순서를 돕는 후보입니다. 출동 자원 배정과 우선순위는 담당자가 원음성과 업무 기준으로 결정합니다. 사람 확인 없이 AI 결과대로 처리하는 단계를 검토한다면 인공지능기본법 카드와 사업 사전검토의 생명·안전 질문에서 확인할 문서와 협의할 부서를 먼저 봅니다.
핵심 정리
- 음성, 원전사, 비식별문, 분류 후보는 단계별 민감도와 사용 범위가 다르며, 모델 파일은 승인된 경로로 미리 반입합니다.
- 화자 분리는 선택 단계이며 오류가 있으면 신고자·접수자 발화가 뒤섞일 수 있습니다.
- 현재 최소 코드는 결과 수·허용 라벨·근거 필드의 존재만 확인합니다.
urgency가 전사 내용과 맞는지, 근거 문장이 전사에 있는지 같은 근거 필드 검사는 별도로 구현하고, 근거 의미와 비식별 미탐은 사람이 확인합니다. - 불확실한 통화는 자동 확정하지 않고
확인필요와 재청취 경로로 보냅니다.
다음 단계
- 신고 전사 심화, 화자 결합과 품질 관리 — 전사·화자 시간축 결합과 오류율·신뢰도 라우팅으로 넓힙니다.
- 개인정보 비식별 파이프라인, 이름·주소까지 자동으로 — 전사 비식별을 탐지·가명화·재현율 검증 흐름으로 구체화합니다.
- 학습 데이터셋 — 119 신고 음성·주소 음성처럼 평가에 쓸 공식 데이터와 이용 조건을 확인합니다.