일반 SOHRI 턴¶
정상 음성 턴은 EPD의 confirmed activity가 STT 텍스트를 포함한 END로 끝날 때 시작됩니다.
EPD 자체가 STT를 수행하므로 별도 STT 왕복은 없습니다.
sequenceDiagram
participant C as Client/Gateway
participant S as Socket Backend
participant E as EPD + STT
participant G as DM Guard / Input Gate
participant DB as PostgreSQL
participant D as Graph Builder
participant T as TTS Provider
participant A as Immediate Analysis
C->>S: Binary PCM
S->>E: PCM + tts_playback 상태
E-->>S: candidate(activityId)
S-->>C: speech_candidate
C->>S: tts_duck_applied
S->>E: duck control
E-->>S: confirmed(activityId)
S-->>C: speech_started
E-->>S: END + STT + confidence + WAV 경로
S->>S: 발화 세대·텍스트·처리권 검증
S->>G: USER lease 획득
S->>S: response generation 시작
S->>G: AudioInputGate.pause(token)
Note over S,G: 이 시점부터 새 PCM 폐기
par EPD 기록
S->>DB: dialog_epd 저장
and 턴 처리(가상 스레드)
S->>DB: USER dialog_message 저장
S-->>C: stt_result
S-->>C: dm_processing
opt 지연 분석 모드
S->>S: WAV 분석 항목 누적
end
S->>D: /message(STT 관측값)
D-->>S: DM 응답
S->>DB: BOT 메시지·DM 응답 저장
S->>T: 응답 텍스트 합성
T-->>S: WAV 또는 PCM 스트림
S-->>C: TTS 오디오
S-->>C: dialog_response
end
S->>G: AudioInputGate.resume(token)
S->>G: USER lease 반환
opt 즉시 분석 모드
S->>A: USER WAV 분석
A->>DB: 감정·치매·우울·바이오마커 저장
A-->>C: 분석 결과 이벤트
end
END 수락 조건¶
입력 gate는 모든 END에서 닫히지 않습니다. 다음 검사를 모두 통과한 첫 END만 사용자 턴으로 수락합니다.
- activity가 현재 발화 세대에 속함
END에 STT 결과가 있고 텍스트가 비어 있지 않음- 한 글자라면
응,왜,뭐중 하나 - 다른 USER 턴이 처리 중이 아니며 USER lease를 확보함
- 비동기 실행 직전에도 발화 세대가 여전히 현재임
검사에서 탈락한 END는 gate를 닫지 않고, 보류했던 무응답 관찰을 재개합니다. 보조 처리권
(REQUERY, PERSIST)이 먼저 잡혀 있으면 정해진 정책에 따라 기다린 뒤 USER lease로 승격합니다.
저장과 출력 순서¶
- USER 메시지와 STT confidence를 저장합니다.
stt_result,dm_processing을 보냅니다.- 지연 분석 모드면 WAV 참조를 누적합니다.
- DM을 호출합니다. DM API 왕복과 BOT/DM 응답 저장은 한 단계로 취급합니다.
- 현재 response generation이면 TTS를 먼저 보내고 그 뒤
dialog_response를 보냅니다. finally에서 gate token과 USER lease를 반납합니다.- 즉시 분석 모드라면 gate가 열린 뒤 분석을 실행합니다.
따라서 분석 지연이 다음 발화 입력을 막지 않습니다. 반대로 DM/TTS/dialog_response가 끝나기
전에는 다음 PCM이 EPD로 전달되지 않습니다.
실패와 재시도¶
DM 호출은 최대 3회 시도하며 실패 사이에 1초, 2초 대기합니다. 모든 시도가 실패하면 현재
generation에만 dialog_error를 보내고 턴을 종료합니다. TTS 실패는 tts_error로 soft-fail하며
저장된 대화 턴은 유지합니다. 어떤 분기에서도 gate와 lease는 finally에서 반납됩니다.