Speaker Context Contract
이 문서는 OnDevice 화자 인식 결과와 Cloud 사용자 조회 결과를 섞지 않기 위한 계약이다.
1. 소유권 원칙
| 데이터 | 생성·판단 주체 | 비고 |
|---|---|---|
voice_id |
OnDevice | 로컬 등록 완료 시 발급 |
| confidence, 화자 수, overlap | OnDevice | 현재 발화의 인식 evidence |
person_id, 계정 |
Cloud | Voice ID lookup 결과 |
| display name, 개인화 동의, 권한 | Cloud | 사용자/Profile DB 기준 |
| 등록 WAV, PCM | OnDevice only | 등록 완료 후 삭제, Cloud 전송 금지 |
| Reference Embedding | OnDevice 생성 | Local 저장 + Cloud Voice Sync Registry 동기화 |
| Query Embedding | OnDevice 생성 | 로컬 매칭 입력; PPT Lookup 요청에는 포함되지만 Cloud 조회·매칭에는 미사용 |
Cloud는 embedding으로 화자를 다시 판정하지 않는다. OnDevice도 계정, 사람 ID, 동의, 권한을 주장하지 않는다. 같은 payload에 두 종류의 사실을 섞으면 spoofing과 stale profile 문제가 생긴다.
2. OnDevice 요청: speaker_context
speaker_context는 기존 voice_context에 추가하는 optional field다.
{
"voice_context": {
"recognized_text": "거실 청정하고 10분 뒤에 침실로 와",
"session_id": "sess_001",
"asr_confidence": 0.94,
"audio_locale": "ko-KR",
"speaker_context": {
"contract_version": "speaker-context-v2",
"voice_id": "vp_opaque_uuid",
"speaker_state": "identified",
"speaker_confidence": 0.72,
"speaker_count": 1,
"overlap_ratio": 0.0,
"unknown_ratio": 0.0,
"max_score": 0.72,
"model_version": "speaker-model-version",
"profile_version": 1,
"source": "ondevice_sherpa_cpu"
}
}
}
2.1 런타임 요청에서 신뢰하면 안 되는 필드
다음 값은 기기 요청에서 제거한다.
person_iddisplay_nameidentity_link_statepersonalization_allowedauthority_levelconsent_scopelinked_vital_face_ids- 외부 계정 식별자
- raw audio, local path
이 값들은 Cloud의 신뢰 가능한 사용자 정보에서 만들어야 한다. queryEmbedding은 PPT
3페이지 호환 요청에 포함될 수 있지만 Cloud Identity Resolver는 이를 lookup key나 화자
판정 근거로 사용하지 않는다.
2.2 등록 동기화와 런타임 조회를 분리
| 계약 | 전송 데이터 | Cloud 사용 |
|---|---|---|
voice-profile-sync-v1 |
Voice ID + Reference Embedding + account/profile metadata | Registry 저장, 다기기 동기화, 삭제 전파 |
voice-id-lookup-v1 |
Voice ID + optional Query Embedding + speaker evidence | Voice ID로 Account/Profile 조회; embedding 미사용 |
두 계약을 같은 endpoint와 retention 정책으로 처리하면 Query Embedding이 등록 자산처럼 쌓일 수 있다. 저장 허용 대상은 등록 동기화의 Reference Embedding뿐이다.
3. Cloud 내부 결과: person_context
Cloud는 voice_id로 사용자 mapping을 조회한 뒤 별도 context를 만든다. Cloud Registry에
Reference Embedding이 있더라도 이 lookup에서 재매칭하지 않는다.
{
"person_context": {
"person_id": "person_001",
"display_name": "나무",
"identity_link_state": "linked",
"personalization_allowed": true,
"authority_level": "normal",
"consent_scope": {
"voice_personalization": true,
"vital_history_summary": false,
"external_calendar": false
}
}
}
| lookup 결과 | 처리 |
|---|---|
| linked + active | 허용된 범위에서 개인화 |
| mapping 없음 | 익명 사용자로 처리 |
| revoked/deleted | 익명 처리, stale binding audit |
| timeout/오류 | 익명 fallback, 기존 대화 경로 유지 |
| 개인화 OFF | 사용자는 확인되더라도 개인화 memory를 사용하지 않음 |
4. speaker_state
| 값 | 의미 | Cloud 처리 |
|---|---|---|
identified |
로컬 등록 화자와 충분한 신뢰도로 매칭 | Voice ID lookup 가능 |
unknown |
등록 화자 없음 또는 threshold 미달 | lookup 생략, 익명 처리 |
ambiguous |
최고점과 차점의 차이가 부족 | 개인화 금지, 필요 시 확인 |
multi_speaker |
두 명 이상이 발화 | 개인화·민감 동작 제한 |
overlap |
겹침 발화 비율이 큼 | 재질문 또는 익명 일반 응답 |
far_speech |
거리/에너지 조건이 불량 | 재발화 안내 후보 |
unknown_timeout |
시간 안에 인식이 끝나지 않음 | 익명 fallback |
화자 미확인은 Cloud LLM 전체 실패 사유가 아니다. 기본 동작은 개인화만 끄고 현재 발화를 정상 처리하는 것이다.
5. Cloud 적용 순서
normalize voice_context
-> validate speaker_context-v2
-> identified인 경우 Voice ID lookup
-> build person_context
-> consent / authority policy
-> router, memory, RAG, TaskManager
| 위치 | 책임 |
|---|---|
| request normalizer | 허용 필드, 범위, enum, 버전 검증 |
| identity resolver | voice_id -> person/profile 조회 |
| policy layer | 개인화 동의와 민감 기능 권한 적용 |
| memory | Cloud person_id scope로 읽기·쓰기 |
| task manager | 민감 side effect에서 별도 확인 정책 적용 |
6. Session과 workflow
Cloud가 멀티턴 owner를 유지할 때 OnDevice Voice ID와 Cloud Person ID를 구분한다.
{
"session_state": {
"last_voice_id": "vp_opaque_uuid",
"workflow_owner_person_id": "person_001",
"speaker_policy": {
"personalization_applied": true,
"confirmation_required": false
}
}
}
last_voice_id: 직전 발화에서 기기가 관측한 로컬 identityworkflow_owner_person_id: Cloud가 lookup으로 확인한 사용자- 후속 발화가 unknown이면 이전 사람으로 자동 간주하지 않는다.
- 민감 동작의 권한은 Voice ID 존재만으로 부여하지 않는다.
7. 호환성과 검증
speaker_context가 없으면 기존 익명 경로로 동작한다.speaker-context-v1은 migration 기간에만 읽고 서버에서 v2로 정규화한다.- 모르는 필드는 무시하되 잘못된 enum과 범위는 unknown으로 낮춘다.
- confidence는
0.0..1.0, ratio는0.0..1.0, speaker count는 음수가 될 수 없다. - log에는 Voice ID 전체값 대신 trace용 hash 또는 마스킹 값을 사용한다.
- Reference Embedding은 sync endpoint에서만 암호화 저장하고, runtime Query Embedding은 저장하지 않는다.
- E2E 테스트는 identified, unknown, mapping miss, revoked, timeout을 모두 포함한다.
등록 계약과 저장 수명은 보이스 프로필 등록 제품 구현 기준서를 따른다.