quest_PoC

개선 효과 검증 결과

노트북 notebooks/earnings_call_briefing_poc.ipynb를 로컬 CPU 환경(Windows, GPU 미사용)에서 여러 차례 전체 실행해 얻은 실측치입니다. 실행 로그 원본은 노트북 파일에 셀 출력으로 그대로 남아 있습니다. TTS 음성이 실행마다 미세하게 달라질 수 있어 처리 시간·문자 유사도는 실행 간에 다소 변동이 있습니다(아래에 그 변동까지 정직하게 기록했습니다).

0. 정확도/누락 개선 2차 반영 (2026-09-26)

1차 검증(아래 1~4번)에서 발견된 문제에 대응해 세 가지를 추가로 반영하고 재검증했습니다.

반영한 것 목적
Whisper initial_prompt에 회계 용어 사전 주입 전문용어 오인식 완화
매칭을 공백 제거 사본(normalize)에서 수행하도록 일반화 Whisper가 “부채비율”→”부채 비율”처럼 임의로 띄어 써서 생기는 누락을 근본적으로 흡수
condition_on_previous_text=False 검증 중 실제로 발생한 문제(아래 참고)를 해결

검증 중 실제로 발생한 문제: medium 모델 비교에 initial_prompt를 함께 넣었더니 Whisper가 반복 루프(hallucination loop)에 빠져 30분 타임아웃이 발생했습니다. 원인은 condition_on_previous_text=True(기본값)가 한 세그먼트의 디코딩 오류를 다음 세그먼트까지 전파시키는, 문서화된 Whisper 불안정성입니다. condition_on_previous_text=False로 막았고, 모델 크기 비교는 initial_prompt 없이(모델 크기 자체의 영향만 분리해서) 다시 설계했습니다. 이 자체도 “정확도 개선을 시도하다가 실제로 새 문제를 만났고, 원인을 진단해 고친” 사례입니다.

결과: 확실히 좋아진 것

항목 이전 이후 비고
핵심 재무 숫자 인식 5개 중 4개 (1만5천 실패) 5개 중 5개 공백-무관 매칭으로 완전 해결
다중 시나리오(A/B/C) — 수정판 로직 3개 중 3개 통과 (다만 “부채비율” 앞뒤 공백 있는 경우에만 우연히 통과) 3개 중 3개 통과, 공백 변형과 무관하게 항상 통과 이번 실행에서는 시나리오 A조차 원본 STT가 “부채 비율”/”유동 비율”로 띄어 썼는데도(즉 이전 방식이면 실패했을 상황) 수정판은 안정적으로 통과함 — 개선이 실제로 효과가 있음을 반대로 증명
STT 처리 시간 87.7~137.9초 29.3초 condition_on_previous_text=False가 예상 밖의 부수 효과로 디코딩을 크게 단축시킴(세그먼트가 9개→18개로 더 잘게 나뉨)
처리 시간 절감률 34~52% 83.8% 위 처리 시간 단축의 직접적 결과
전문용어 일부 “손익”→”소닉”, “총계”→”총개” “손익”→손익(정확), “총계”→총계(정확, 띄어쓰기만 다름) initial_prompt 효과가 실제로 확인됨

결과: 그대로이거나, 오히려 나빠진 것 (과장하지 않고 정직하게)

항목 이전 이후
STT 문자 유사도 89.7~91.3% 89.1%
WER (jiwer) 49.1% 57.1%
“당기순이익”→”단기순위익” 오인식 그대로 오인식
“질의응답”→”지류응답” 오인식 그대로 오인식
“매출채권”→”매출책권” 오인식 그대로 오인식
“재무건전성”→”제무 권전성” 오인식 그대로 오인식 (오히려 새 오류 추가)

해석: initial_prompt는 프롬프트에 넣은 단어와 발음·문맥이 가까운 일부 용어(“손익”, “총계”)는 확실히 고쳤지만, 모든 오인식을 없애주지는 않았습니다. 전체 문자 유사도가 오르지 않은 것은 TTS 음성 자체가 실행마다 조금씩 달라지는 변동 폭 안에 있는 것으로 보입니다(같은 이유로 이전 실행들 사이에서도 89.7%~91.3%로 흔들렸습니다). 이번 개선의 진짜 효과는 “전체 정확도 점수”가 아니라, 사용자가 실제로 지적한 “누락”(핵심 숫자 1개, 공백 변형에 따른 리스크 탐지 실패)이 재현 가능하게 사라졌다는 것입니다.

남은 전문용어 오인식에 대한 다음 단계: 이번에 남은 오류들(“질의응답”, “매출채권” 등)은 initial_prompt만으로는 부족하다는 뜻이므로, VALIDATION_RESULTS.md 4번 섹션의 “개선 방안”에 있는 STT 이후 LLM 보정 단계(Claude가 문맥으로 “지류응답”을 “질의응답”으로 교정)가 다음으로 시도해볼 만한 방법입니다. 리스크 판단에 쓰이는 숫자에는 여전히 영향이 없었습니다(아래 1번 참고).

0-1. Grounding 버그 발견 및 수정 (2026-09-27)

리스크별 근거 오디오를 재생하는 기능(3-4번 참고)을 만들다가, 저장된 STT 원본(stt_result.json)을 직접 열어 확인하는 과정에서 실제 버그를 발견했습니다.

문제: 근거 세그먼트를 찾는 find_segment_for(keyword, segments)가 “부채”/”유동”이라는 2글자 키워드로 첫 번째 매칭 세그먼트를 반환하고 있었습니다. 그런데 “부채”라는 글자는 진짜 리스크인 “부채비율”(233%)뿐 아니라, 재무상태표를 읽는 훨씬 이른 구간의 “부채총계”에도 들어 있습니다.

리스크 실제 발언 위치(진짜 근거) 수정 전 grounding이 가리키던 곳 문제
높은 부채비율 (233%) 68.6~76.5초: “…현재 부채 비율은 233% 수준으로…” 37.5~43.5초: “자산 총계는 20만… 부채 총계는 14만…” 전혀 다른 발언(재무상태표 낭독)을 근거로 잘못 표시
단기 유동성 부족 (88.9%) 76.5~84.4초: “유동 비율도 88.9%로 100%를 밑돌고…” 46.7~53.7초: “유동자산은 8만… 유동부채는 9만…” 마찬가지로 다른 발언을 근거로 잘못 표시

왜 지금까지 몰랐나: 문자 유사도·WER·다중 시나리오 통과 여부 같은 정량 지표는 전부 “숫자가 맞았는가”만 확인하고 “그 숫자의 근거로 표시된 타임스탬프가 진짜 맞는가”는 확인하지 않았습니다. 이 프로젝트의 핵심 가치인 “타임스탬프 근거”를 실제로 재생해서 듣기 전까지는 드러나지 않는 종류의 버그였습니다.

수정: find_segment_for_value(value_str, segments)로 교체 — 리스크 제목의 느슨한 키워드 대신, 정규식이 실제로 매칭한 숫자(“233”, “88.9”)가 “비율”이라는 단어와 함께 등장하는 세그먼트를 찾습니다. mock_extract_risks도 이 값(matched_value)을 함께 반환하도록 수정했습니다.

수정 후 재실행 결과 (실측 확인됨):

{
  "title": "높은 부채비율",
  "segment_start": 68.6,
  "grounded": true
}
{
  "title": "단기 유동성 부족",
  "segment_start": 76.52,
  "grounded": true
}

→ 68.6초, 76.52초 모두 위 표의 “진짜 근거” 구간과 정확히 일치합니다. 동시에, 이 정확한 구간의 STT 신뢰도가 낮게 나와(no_speech_prob≈0.71) 3-3번에서 만든 저신뢰도 경고가 이번 실행에서 처음으로 실제 발동했습니다 — 아래 3-4번과 6번에 원본 그대로 남깁니다.

0-2. 실제 기업 공개 데이터로 검증 (2026-09-28)

지금까지는 전부 우리가 직접 쓴 가상 대본으로만 검증했습니다. 사용자 요청으로, 실제 상장기업이 공개 배포한 보도자료로 처음 검증해봤습니다 — SK하이닉스 2026년 2분기 경영실적 발표 보도자료(2026-07-29) 핵심 문단을 그대로 발췌해 같은 파이프라인(TTS→Whisper→목업 리스크 로직)에 넣었습니다. (노트북 13번 섹션)

실제 회사 음성/영상은 사용하지 않았습니다 — SK하이닉스 IR 페이지의 컨퍼런스콜 다시듣기는 3rd party 스트리밍 서비스(teletogether.com)로 세션 기반 팝업 재생만 지원해 파일로 내려받을 수 없었고, 유튜브에서 오디오를 추출하는 것도 이용약관 위반이라 하지 않았습니다. 대신 회사가 직접 공개 배포한 보도자료 텍스트를 TTS로 합성해 사용했습니다 — 저작권 문제가 없고, 실제 기업의 진짜 재무 숫자·용어를 담고 있습니다.

항목 결과
STT 문자 유사도 (실제 보도자료 원문 대비) 88.8% — 가상 대본(89.1%)과 거의 동일
STT 처리 시간 137.3초 (9.9초 분량 음성 대비 느림 — 자세한 원인은 아래 참고)
목업 리스크 로직 탐지 결과 없음 (예상된 결과)

목업 리스크 로직이 아무것도 못 찾은 이유: 이 보도자료는 사상 최대 실적을 낸 분기라 부채비율·유동비율 같은 리스크 언급이 전혀 없습니다. 우리 목업 로직(mock_extract_risks)은 정확히 이 두 지표만 찾도록 좁게 만들어져 있어서, 다른 종류의 실제 공시에는 일반화되지 않습니다. 이건 버그가 아니라 목업 로직의 설계 범위 자체가 좁다는 것을 실제 데이터로 재확인한 것입니다 — 실전에서 이 지점을 해결하려면 정규식이 아니라 실제 Claude API 호출(범용 리스크 추출)이 필요합니다(ROADMAP.md 참고).

실제 텍스트에서 새로 관찰된 오인식 (가상 대본에서는 안 나왔던 패턴):

숫자(79조 3,187억 원, 257%, 557%, 33.6조 원 등)는 전부 정확히 인식되어, 핵심 재무 수치 인식은 실제 데이터에서도 유지되는 것으로 보입니다 — 다만 이번엔 목업 로직이 그 숫자들을 애초에 찾지 않는 종류의 리스크라 별도로 검증하지는 못했습니다.


1. 정량 검증 (최신 실행 기준)

항목 결과 비고
STT 문자 유사도 (원본 대본 대비) 89.1% difflib.SequenceMatcher 기반, 공백 제거 후 비교 (실행 간 89~91% 변동)
WER (Word Error Rate, jiwer) 57.1% 한국어는 공백 기준 어절 분리가 명확하지 않아 실제 품질보다 나쁘게 나오는 경향 (위 0번 참고)
핵심 재무 숫자 인식률 5개 중 5개 (233%, 88.9%, 20%, 12만, 1만5천) 공백-무관 매칭으로 완전 해결
오디오 길이 103초 TTS로 생성한 샘플 실적발표 음성
STT 처리 시간 29.3~64.0초 (모델: small, CPU) 같은 코드도 CPU 부하에 따라 실행마다 처리 시간이 크게 달라짐(정직하게 범위로 기록)
수작업 예상 소요시간 (청취+메모, 1.75배 가정) 180초 PROBLEM_DEFINITION.md의 “녹음 길이의 1.5~2배” 가정 중간값 적용
처리 시간 절감률 64.5~83.8% 위와 같은 이유로 범위로 기록 — 최악의 경우(64.5%)도 여전히 큰 절감

2. 정성 검증 — 파이프라인 간 일관성

기존 AI-project_MVP가 재무제표 Excel(financial_sample.xlsx, 부채비율 233%·유동비율 88.9%)에서 찾아냈던 리스크와, 이번 PoC가 같은 숫자를 담은 음성에서 찾아낸 리스크를 비교한 결과:

리스크 Excel 경로 (기존 프로젝트) 음성 경로 (이번 PoC) 일치 여부
단기 유동성 부족 (유동비율 88.9%) 탐지됨 탐지됨 (근거: 1분 16초 발언) ✅ 일치
높은 부채비율 (233%) 탐지됨 탐지됨 (근거: 1분 8초 발언) ✅ 일치

(위 타임스탬프는 0-1번에서 설명한 grounding 버그를 수정한 이후의 정확한 값입니다.)

→ 입력 채널이 텍스트(Excel)에서 음성으로 바뀌어도 동일한 리스크가 동일하게 탐지됨을 실측으로 확인했습니다. 모든 리스크에 타임스탬프 근거가 자동으로 붙어, 해당 발언을 바로 찾아 재생할 수 있습니다.

(이번 실행은 ANTHROPIC_API_KEY 없이 목업 모드로 진행됐습니다. 실제 Claude 호출 시 문구는 더 자연스러워지지만 판단 로직(원문 인용 기반 + 아래 3-3의 grounding 검증)은 동일합니다.)

3. 추가 검증 (정확도/안정성 강화)

3-1. Whisper 모델 크기 비교 (정확도 vs 속도)

같은 오디오를 base/small/medium 세 모델로 각각 전사해 비교했습니다 (initial_prompt 없이, 모델 크기 자체의 영향만 분리).

모델 처리 시간 문자 유사도
base 9.4~15.3초 80.0%
small (채택) 29.3~64.0초 89.1%
medium 305.1~485.6초 (5.1~8.1분) 91.0%

해석: medium이 이번엔 small보다 정확도가 약간 높게 나왔지만(91.0% vs 89.1%), 13배 더 느립니다. base는 가장 빠르지만 정확도가 5%p 이상 낮습니다. 실시간성이 중요한 이 유스케이스(수 분 안에 브리핑 확인)에서는 small이 여전히 합리적인 균형점입니다. (n=1 샘플 비교라 일반화에는 주의가 필요합니다 — 실제로 이전 실행에서는 medium이 small보다 근소하게 낮게 나온 적도 있어, 두 모델의 정확도 차이는 이 정도 샘플 크기에서는 오차 범위에 가깝다고 보는 것이 정확합니다.)

3-2. 다중 시나리오 검증 — 발견한 버그와 수정 효과의 재확인

샘플 1개만으로는 “우연히 잘 나온 것”인지 확인할 수 없어, 재무 프로필이 다른 시나리오 2개를 추가했습니다.

최초 구현(mock_extract_risks_naive — “유동비율”/”부채비율”이라는 단어가 텍스트에 등장하기만 하면 무조건 리스크로 판단, 공백 처리 없음)과, 실제 수치를 정규식+공백무관 매칭으로 판단하는 수정판을 비교한 결과:

시나리오 기대 결과 수정 전(키워드 매칭) 수정 후(공백무관 임계값 판정)
A (원본, 리스크 2건) 유동성 부족 + 높은 부채비율 ❌ 이번 실행에서는 STT가 “부채 비율”/”유동 비율”로 띄어 써서 둘 다 누락 ✅ 일치
B (건전전자, 리스크 0건) (없음) ✅ 일치 ✅ 일치
C (성장전자, 부채비율만) 높은 부채비율만 ❌ 누락 ✅ 일치

의미: 이번 실행에서는 원본 시나리오 A조차 최초 구현(키워드 매칭)으로는 리스크를 하나도 탐지하지 못했습니다 — Whisper가 “부채비율”/”유동비율”을 매번 띄어 쓴 탓입니다. 반면 수정판(공백 제거 후 매칭)은 이런 변형과 무관하게 3개 시나리오 모두 정확히 통과했습니다. 이는 “공백-무관 매칭” 수정이 특정 케이스 하나를 땜질한 게 아니라, 실제로 반복 재현되는 근본 문제를 해결했다는 것을 재확인시켜 줍니다.

3-3. 정확도/보안 가드 (코드 레벨)

3-4. 확장 기능 검증 (2026-09-27 추가)

두 가지 실제 예시(사진 검색기, 스쿼트 보조도구) 및 확장 아이디어 논의에서 나온 요청을 반영해 세 기능을 추가하고, 실제로 실행해 검증했습니다. (ROADMAP.md에는 이번에 구현하지 않기로 한 나머지 확장 아이디어를 정리했습니다.)

리스크별 근거 오디오 재생: 각 리스크의 근거 세그먼트만 잘라 notebooks/runs/<RUN_ID>/evidence_*.mp3로 저장하고 노트북에서 재생합니다. 이 기능을 만드는 과정에서 0-1번의 grounding 버그를 발견했습니다 — “검산 기능을 만드는 행위 자체가 검산이었다”는 두 예시의 교훈을 그대로 재현한 셈입니다.

발표 vs 질의응답(Q&A) 구간 분리: 진짜 화자 분리 없이, “질문”이라는 전환 문구(정확히 인식되는 단어를 선택 — “질의응답”은 매번 “지류응답”으로 오인식되어 마커로 쓰지 않았습니다)를 기준으로 구간을 나눴습니다. 실행 결과:

질의응답 구간 시작 추정 시각: 56.88초
[발표(Presentation)] 리스크 0건
[질의응답(Q&A)] 리스크 2건
  - 단기 유동성 부족 (76.5s)
  - 높은 부채비율 (68.6s)

두 리스크 모두 Q&A 구간(애널리스트 질문에 대한 경영진 답변)에서 나온 것으로 정확히 분류됐습니다 — 실제로 대본상 두 수치 모두 질의응답 중 언급되므로 맞는 결과입니다. 한계: 발화자가 누구인지는 모르므로 “경영진이 먼저 밝힌 리스크”와 “애널리스트가 캐물어서 나온 리스크”는 구분하지 못합니다.

음성-재무제표 십자 검증: 음성에서 뽑은 수치를 (1) 정확한 재무제표, (2) 일부러 틀리게 만든 재무제표와 각각 대조했습니다. 실행 결과:

음성에서 추출한 수치: {'매출_성장률': 20.0, '부채비율': 233.0, '유동비율': 88.9}
[정확한 재무제표] 대조 결과:
  불일치 없음
[오타가 있는 재무제표(가정)] 대조 결과:
  ⚠️ 매출_성장률: 음성=20.0 vs 재무제표=8

같은 파이프라인이 정확한 재무제표와는 일치하고, 의도적으로 틀리게 만든 재무제표(매출 성장률 8%로 변경)와는 그 불일치를 정확히 잡아냈습니다.

4. Failure case — STT 자체의 한계 (2차 반영 후에도 남은 것)

initial_prompt 반영 후 재확인한 결과입니다.

원문 1차 검증 때 STT 결과 2차(initial_prompt 반영 후) STT 결과 개선 여부
손익 소닉 손익 ✅ 개선됨
자산총계/부채총계/자본총계 자산총개/부채총개/자본총개 자산 총계/부채 총계/자본 총계 (띄어쓰기만 다름) ✅ 개선됨
당기순이익 단기순위익 단기순위익 ➖ 그대로
질의응답 지류응답 지류응답 ➖ 그대로
매출채권 매출책권 매출책권 ➖ 그대로
재무건전성 (관찰 안 됨) 제무 권전성 ⚠️ 새로 관찰됨

중요한 점: 위 오인식은 모두 서술어·용어 표현에 국한되었고, 리스크 판단에 실제로 쓰이는 숫자(부채비율 233%, 유동비율 88.9%, 매출 성장률 20% 등)는 5개 항목 모두 정확히 인식되었습니다(1번 섹션 참고).

다음 단계로 시도해볼 만한 것 (아직 반영 안 함)

5. 재현 방법

pip install openai-whisper gTTS anthropic jupyter nbconvert jiwer
# ffmpeg 필요 (Whisper 오디오 디코딩용)
jupyter nbconvert --to notebook --execute --inplace notebooks/earnings_call_briefing_poc.ipynb

또는 Colab에서 바로 열기 (README 참고). medium 모델 비교 셀(8번 섹션)은 다운로드 용량(~1.5GB)과 CPU 처리 시간이 크므로, 빠르게 재현만 하고 싶다면 해당 셀은 건너뛰어도 나머지 파이프라인은 정상 동작합니다.

독립 재현 검증: 위 단계를 이 저장소와 무관한 완전히 새 폴더에 클론하고 새 가상환경을 만들어 그대로 따라 해봤습니다. 처음에는 jupyter/nbconvert가 빠져 있어 실행 자체가 안 됐던 것을 발견해 위 명령에 반영했고, 반영 후에는 에러 없이 동일하게 재현되는 것을 확인했습니다.

6. 전체 실측 원본 데이터 (2026-09-27 실행, RUN_ID=20260927_000817)

요약·표로 가공하기 전의 원본 데이터입니다. notebooks/runs/20260927_000817/에서 그대로 재현 가능합니다.

6-1. STT 세그먼트 전체 (18개, 신뢰도 포함)

# 시작(s) 끝(s) avg_logprob no_speech_prob 전사 텍스트
0 0.00 12.68 -0.177 0.038 안녕하십니까? 예시전자 IR 담당자입니다. 지금부터 2024년 4분기 실적 발표를 시작하겠습니다. 먼저 손익 실적입니다.
1 12.68 22.22 -0.173 0.025 2024년 매출액은 12만 100만원으로 전년동기 10만 100만원 대비 20% 성장했습니다.
2 22.22 31.74 -0.173 0.025 영업이익은 1만 5천백만원을 기록해 전년동기 8천백만원 대비 큰 폭으로 개선되었습니다.
3 31.74 35.08 -0.173 0.025 단기순위익은 9천백만원입니다.
4 35.08 37.48 -0.173 0.025 다음은 재무상태입니다.
5 37.48 43.48 -0.226 0.059 자산 총계는 20만 100만 원 부채 총계는 14만 100만 원
6 43.48 46.72 -0.226 0.059 자본 총계는 6만 100만 원 입니다.
7 46.72 53.72 -0.226 0.059 유동자사는 8만 100만 원 유동부채는 9만 100만 원으로 집게 되었습니다.
8 53.72 56.88 -0.226 0.059 이제 지류응답 시간을 갖겠습니다.
9 56.88 58.78 -0.226 0.059 질문 주셨습니다.
10 58.78 61.96 -0.226 0.059 부채 비율이 다소 높아 보이는데 제무
11 61.96 68.60 -0.171 0.709 관전성에 문제가 없는지 설명 부탁드립니다. 답변드리겠습니다. 말씀하신
12 68.60 76.52 -0.171 0.709 대로 현재 부채 비율은 233% 수준 으로 전년 대비 상승했습니다. 또한
13 76.52 84.36 -0.171 0.709 유동 비율도 88.9%로 100%를 밑 돌고 있어 단기 유동성 관리가 필요한
14 84.36 90.00 -0.171 0.709 상황이라는 점은 저희도 인지하고 있습니다. 이에 따라 단기 차입금
15 90.00 96.90 -0.196 0.166 한도 확보와 매출책권 회수 강화를 통해 유동성을 개선할 계획입니다.
16 96.90 102.12 -0.196 0.166 추가 질문이 없으시면 이상으로 실적 발표를 마치겠습니다.
17 102.12 103.12 -0.196 0.166 감사합니다.

굵게 표시한 세그먼트(11~13번)가 두 리스크의 실제 근거 구간입니다. 공교롭게 이 구간의 no_speech_prob이 0.709로, 우리 경고 임계값(0.5)을 넘어 실제로 저신뢰도 경고가 발동했습니다(0-1번 참고) — 짧은 침묵이나 TTS 억양 변화가 원인으로 추정되며, 실제 청취로는 내용 인식에 문제가 없었습니다(사람이 들었을 때 이 구간이 실제로 이상하게 들리는지는 오디오 파일로 직접 확인 가능합니다).

6-2. 최종 리스크 판정 원본 (risks.json)

[
  {
    "title": "단기 유동성 부족",
    "description": "유동비율이 88.9%로 100%를 밑돈다는 발언이 확인됨",
    "severity": "medium",
    "segment_start": 76.52,
    "grounded": true,
    "segment_confidence": {
      "avg_logprob": -0.17092245527841513,
      "no_speech_prob": 0.7088186740875244
    }
  },
  {
    "title": "높은 부채비율",
    "description": "부채비율이 233%로 200%를 초과한다는 발언이 확인됨",
    "severity": "high",
    "segment_start": 68.6,
    "grounded": true,
    "segment_confidence": {
      "avg_logprob": -0.17092245527841513,
      "no_speech_prob": 0.7088186740875244
    }
  }
]