"추측을 넣어 놓고 되무를 순 없어. 그러니 더 이상 추측이 아닌 부분만 넣어."
불일치
Whisper 계열 모델은 근본적으로 배치 야. 오디오 덩어리를 주면 전사를 받아. 그런데 좋은 받아쓰기는 스트리밍 처럼 느껴져. 말하는 대로 단어가 나타나니까. 순진하게 다리를 놓으면, 그러니까 '30초 녹음하고, 한 번 전사하고, 붙여넣기' 하면 기술적으론 되지만 죽은 느낌이야. 말하는 동안 아무 반응이 없고, 끝나고 한참 멈춰 있거든. 라이브한 느낌을 내려면 배치 모델 위에 스트리밍을 흉내 내야 해. 조심해서. 배치 모델은 뒤를 더 들으면서 앞 단어에 대한 생각을 계속 바꾸니까.
LocalAgreement
비결은 엔진 위에 앉는 스트리밍 컨트롤러야. 롤링 버퍼를 유지하고, 오디오가 커지면서 배치 모델을 반복 돌리고, 각 새 가설을 이전 것과 비교해. 연달아 돌린 두 패스가 앞부분에서 일치하면, 그 앞부분을 커밋해. 최종으로 보여줘도 될 만큼 안정됐다는 뜻이니까. 아직 안 맞는 꼬리는 프리뷰로만 보여 주고 절대 최종으로 취급 안 해. 그게 LocalAgreement 아이디어야. 연달아 돌린 패스가 일치한 다음에만 텍스트를 확정하고, 아직 확정 안 된 꼬리는 보여만 주고, 안전할 때 문장 경계에서 버퍼를 다듬는 거지.
패스 N: "보고서를 보내"
패스 N+1: "보고서를 화요일에 보내" 앞부분 일치 ->
^^^^^^^^ 커밋됨 "보고서를"
^^^^^^^^^^ 아직 꼬리 -> 프리뷰만
# 일치한 앞부분만 커밋. 흔들리는 꼬리는 절대 삽입 안 함.
MVP 규율
말하는 동안 라이브로 타이핑하는 게 어려운 버전이고, 거기서 시작하는 건 함정이야. 솔직한 MVP 는 부분 전사를 오버레이에 프리뷰로 보여 주다가 키를 놓을 때 한 번만 삽입해. 그러면서도 MVP 안에서 '커밋됨' 과 '아직 아님' 은 내부적으로 갈라 놔. 그래야 나중에 진짜 라이브 타이핑을 붙이는 날, 기계는 이미 다 있고 커밋된 텍스트가 어디로 갈지만 바꾸면 되거든. 오버레이 대신 앱으로. 데이터 모델은 어려운 버전에 맞춰 짓고, 배포는 쉬운 버전부터 해.