-
Notifications
You must be signed in to change notification settings - Fork 0
PERSONA_SCENARIO_MODEL
⚠️ 이 문서는 논의·검토용 자료입니다. 아직 확정된 설계 결정이 아니며, 7개 deliverable의 불변식을 바꾸지 않습니다. 2차 체험 시나리오(Figma3061-1142,3120-1161) 검토 과정에서 합의된 체험 구동 방식의 전환을 정리한 메모로, 팀 확정 시 SYSTEM_DESIGN §16에 2차 매핑 절로 흡수한다.작성일: 2026-05-25
2차 시나리오(하루 여정 / 장보기 기억 연속성)는 표면상 음성 인식, 냉장고 재고 비전, 반려동물 상태 인식, 업무량 감지, rPPG(remote PhotoPlethysmoGraphy, 원격 광용적맥파 측정) 등 다수의 실시간 인식(perception) 기능을 요구하는 것처럼 보인다. 그러나 전시 운영상 이들 대부분은 실제 동작이 아니라 연출(staging) 또는 사전 가정된 고정 상황으로 처리할 예정이다.
이 전제를 설계 모델로 형식화한 것이 본 문서다:
체험자는 입장 전에 캐릭터(페르소나)를 선택하고, 각 장소에는 사전 작성된 상황(situation) 카드가 페르소나 가중치로 추첨되어 상태 저장소에 주입된다. 이후 이벤트(zone 진입·명령 등)가 발생하면 AI(LLM)는 그 지정 상황 위에서 적절히 반응한다.
랜덤성은 상황 카드 추첨에만 두고, AI는 고정된 상황 위에서 대사·옵션·로봇 동작을 변주한다 → 매 체험이 다르게 느껴지되 서사·안전은 통제된다.
| 2차 시나리오 요구 | 종전 판정 | 본 모델 적용 후 |
|---|---|---|
| 음성 혼잣말 인식 + 위치 태깅 | ❌ ASR(Automatic Speech Recognition, 자동 음성 인식) 신규 도메인 | 상황 카드 텍스트로 대체 — ASR 불요 (음성은 선택적 연출) |
| 냉장고/세제/계란 재고 비전 | ❌ 사물 CV(Computer Vision, 컴퓨터 비전) 신규 | 카드 텍스트 ("우유가 3일 뒤 떨어진다") |
| 반려동물 상태(구토/활동) | 🎭 연출 | 카드 텍스트 |
| 업무량 감지·선제 경고 | 🔶 외부 데이터 소스 | 카드 텍스트 |
| 수면/피로/rPPG | 🔶 wearable 미결 | 카드 또는 페르소나 개인사정 필드 |
비전의 역할은 "누가 어느 zone에 있는가"(person enter/exit)로 축소된다 — 현 Frigate 설계(SYSTEM_DESIGN §3.2)가 정확히 그 기능을 하도록 만들어져 있어, 사물·동물·표정 인식이 전부 불필요해진다.
SYSTEM_DESIGN §4.1의 UserContext에 두 필드를 추가한다. 신규 MQTT(Message Queuing Telemetry Transport, 메시지 큐 텔레메트리 전송 프로토콜) 토픽은 0개 — 기존 context/user/<id>/update로 주입하고 Home Assistant가 SoT(Source of Truth, 단일 진실 공급원)로 보관한다.
// 추상 모델 확장 (실제 저장은 HA sensor.session_<id>_* 로 매핑)
interface UserContext {
// ... 기존 필드 ...
persona: {
job: string; // 예: "개발자", "간호사" — config/personas.yaml enum
personality: string; // 예: "내향적", "활기참"
circumstance: string; // 예: "야근이 잦음", "반려동물과 산다"
};
active_situation: {
zone_id: ZoneId;
card_id: string; // config/situations.yaml의 카드 id
drawn_at: ISO8601;
} | null;
}- HA 엔티티:
sensor.session_<id>_persona,sensor.session_<id>_active_situation. -
SCRUB 정합: 두 필드 모두 SYSTEM_DESIGN §11.3의
session/end핸들러에서 기존 임베딩 폐기와 함께 폐기한다.
zones.yaml·robots.yaml과 동일하게 single-source 설정 파일로 관리한다. 카드 hint는 반드시 capability 화이트리스트(SYSTEM_DESIGN §9.2) 안에서 작성 — 어떤 카드가 추첨돼도 가드레일(JSON schema → whitelist → zone clamp → velocity clamp)을 통과하도록 보장한다.
# config/situations.yaml (illustrative)
situations:
home:
- id: home_cat_hairball
desc: "반려묘가 헤어볼을 토함. 활동 상태는 정상."
persona_weight: { circumstance: { "반려동물과 산다": 3 } } # 가중치
hint:
media_key: cat_resting # 창문 디스플레이 사전 제작 영상 key
playbook_sub: evening_care
- id: home_milk_low
desc: "냉장고 우유가 3일 내 소진 예상."
persona_weight: {}
hint: { tablet_options: ["주문할까요?"] }
park:
- id: park_rain_incoming
desc: "30분 뒤 비 예보. 우산 없음."
persona_weight: { personality: { "활기참": 2 } }추첨 주체는 orchestrator 내 모듈로 둔다(신규 서비스 없음). 결과는 context/user/<id>/update로 publish하여 HA에 기록 → "HA는 상태 저장소"(SYSTEM_DESIGN §3.1) 불변식 유지.
선택 방식: 페르소나 가중 + 비복원 추출(weighted draw without replacement).
-
vision/zone/enter수신 → 해당 zone의 카드 풀 로드. - 이미 이번 세션에서 뽑힌 카드 제외(비복원) → 같은 사람이 같은 카드를 반복 경험하지 않음.
- 페르소나 필드와
persona_weight를 곱해 가중 확률 산출 → 직업/성격/사정에 맞는 카드가 더 자주 등장 → 캐릭터 선택이 체험에 의미를 가짐. - 1장 추첨 →
active_situationpatch publish → HA 갱신. - 이후 동일 session_id 처리는 SYSTEM_DESIGN §7.3.C의 session lock으로 직렬화.
# services/llm-orchestrator (illustrative)
def draw_situation(zone_id, persona, drawn_history):
pool = [c for c in DECK[zone_id] if c.id not in drawn_history]
weights = [base_weight(c) * persona_factor(c, persona) for c in pool]
return weighted_choice(pool, weights)운영자 오버라이드: VIP·시연 재현 시 특정 카드를 강제할 수 있도록, operator 콘솔에서 active_situation을 직접 set하는 경로를 둔다(기존 operator 우선순위 정책 재사용).
기존 SYSTEM_DESIGN §5.1 패턴에 페르소나·상황을 합성하는 단계만 얹는다.
입장 전: 태블릿 페르소나 선택 → context/user/<id>/update (persona)
│
zone 진입: vision/zone/enter ─► orchestrator
│ ① draw_situation() → active_situation publish
│ ② assemble: system_prompt + persona
│ + active_situation + zone_playbook
│ + robot_state
│ ③ Claude tool use (가드레일 통과)
▼
MCP 도구 호출: robot_command / show_options / show_message
"지정 상황에 맞춰 AI가 적절히 반응" = ②③ 단계. 가드레일·MCP(Model Context Protocol, 모델 컨텍스트 프로토콜) 디스패치는 무변경.
- intro playbook(SYSTEM_DESIGN §16.2 1단계)에서
show_options로 직업/성격/사정을 순차 선택. -
MQTT_SCHEMA §3.5의
tablet.intentintent_type에persona_select추가(기존intro_theme옆) — 신규 토픽 아님, enum 1개 추가. - 선택 완료 시 orchestrator가
personapatch를 publish → 세션 컨텍스트 확정.
| 불변식 | 상태 |
|---|---|
| MQTT가 유일한 이벤트 백본 / 신규 토픽 최소화 | ✅ 신규 토픽 0, intent_type enum 2개 추가만 |
| Home Assistant가 상태 저장소 | ✅ persona·active_situation 모두 HA entity |
| 가드레일 필수 | ✅ 카드 hint를 whitelist 내에서 작성, 추첨 결과도 동일 가드 통과 |
| 별도 context-server·서비스 금지 | ✅ 추첨은 orchestrator 내 모듈 |
| session/end = SCRUB | ✅ persona·active_situation 동일 폐기 |
캐릭터(페르소나) 선택 → zone별 상황 카드 추첨 → 이벤트 발생 시 LLM이 호출하는 AI tools(MCP 도구 + HA 서비스 호출)의 매칭표다. 카드는 hint로 후보 도구를 제시하지만, 실제 호출·인자·대사는 LLM이 결정한다(매번 변주). 모든 호출은 가드레일을 통과한다.
도구 약칭 (legend)
| 약칭 | 도구 | 설명 |
|---|---|---|
RC |
robot_command(robot_id, capability, params) |
로봇 동작 (capability: goto/follow/stop/sit/stand/gesture/look_at, †bring, ‡lock) |
SO |
show_options(tablet_id, options[]) |
태블릿/디스플레이 선택지 push |
SM |
show_message(tablet_id, text, media) |
메시지·미디어 push (창문 디스플레이 포함) |
CU |
context_update(session_id, patch) |
세션 컨텍스트 갱신 (orchestrator publish) |
HA:* |
HA 서비스 호출 |
light.turn_on·climate.set_temperature·media_player.play_media·lock.lock 등 |
† bring·‡lock은 미결 capability — KAIST 결정/§11.3.3 정책 적용 후 추가. lock은 LLM 자율 발행 금지, HA rule 경로 전용.
| 단계 | 트리거 | 매칭 tools | 산출 |
|---|---|---|---|
| 직업/성격/사정 선택 |
vision/zone/enter (신규 페어링) |
SO (3회 순차) → CU(persona)
|
sensor.session_<id>_persona 확정 |
| zone | 카드 id | 상황 (desc) | 페르소나 가중 | 트리거 | 매칭 AI tools |
|---|---|---|---|---|---|
| home (기) | home_oversleep |
수면 부족, 힘든 기상 | circumstance:야근잦음 ×3 | zone enter |
HA:light.turn_on(warm) · RC(kaist: gesture) · HA:media_player(잔잔한 음악) · SM(부드러운 기상) |
| home (기) | home_milk_low |
우유 3일 내 소진 | — | zone enter |
SM("주문 안내") · SO("주문할까요?") → intent → CU(shopping_list+=milk) |
| home (기) | home_cat_hairball |
반려묘 헤어볼 토함, 정상 | circumstance:반려동물 ×3 | zone enter |
SM(상태 리포트) · HA:media_player(창문: cat_resting) · RC(kaist: look_at) |
| vehicle (승) | vehicle_busy_day |
업무량 많음, 야근 예상 | job:개발자 ×2 | zone enter |
SM("오늘 늦을 수도") · SO(스트레칭/일정조정) |
| vehicle (승) | vehicle_traffic |
정체, 최적경로 연출 | — | zone enter |
SM(차량 디스플레이) · HA:media_player
|
| park (전) | park_running |
러닝 동행 | personality:활기참 ×2 | zone enter |
RC(spot: follow, params.pace) · SM(페이스 코칭) |
| park (전) | park_rain |
30분 뒤 비 예보 | — | zone enter |
SM(우산 안내) · RC(spot: follow) |
| park (전) | park_fatigue |
피로 누적, 휴식 권유 | circumstance:야근잦음 ×2 | zone enter |
RC(spot: follow 저속) · SM(휴식 제안) |
| home (결) | home_evening_return |
귀가, 회복 분위기 | — | zone re-enter (prev≠home) |
HA:light.turn_on(dim warm) · HA:climate.set_temperature · RC(kaist: gesture 인사) · HA:media_player(창문: 평온한 밤) |
| home (결) | home_sleep |
수면 유도 | — | context update (가정 심박저하) |
HA:light(점진 디밍) · HA:media_player(volume↓ + 수면음악) · SM(굿나잇) |
| 돌발 (병행) | home_unknown_visitor |
가전기사 조기 방문 | — | Frigate 미등록 person detect |
HA:lock.lock‡ (rule 경로) · SM(알림) — LLM 자율 금지
|
| 트리거 | 매칭 tools | 산출 |
|---|---|---|
session/end |
LLM 텍스트 요약 생성 → HA:text.set_value(diary) · SM(하루 요약) |
sensor.session_<id>_diary (§11.3.2, 최대 7일) → 이후 SCRUB |
매트릭스의 모든 tool은 현 capability 화이트리스트 내(또는 §16.5에 예약된
bring·lock)이며, 신규 MQTT 토픽을 만들지 않는다. 카드별hint는 후보일 뿐, 실제 조합·대사·인자는 LLM이 페르소나·zone playbook과 함께 결정한다.
| 항목 | 영향 위치 | 비고 |
|---|---|---|
config/personas.yaml, config/situations.yaml 신설 + 작성 컨벤션 |
config, SERVICES §5 | 카드 hint는 capability whitelist 내 |
UserContext.persona·active_situation 스키마 |
SYSTEM_DESIGN §4.1 | |
draw_situation 모듈 (페르소나 가중·비복원) |
SERVICES §5 (orchestrator) | |
intent_type: persona_select |
MQTT_SCHEMA §3.5 | |
| 운영자 상황 오버라이드 경로 | OPERATIONS, dashboard | VIP·재현용 |
| 페르소나 효과 범위 확정 | — | 현 제안: 카드 풀 가중치 + LLM 대사 톤. playbook 분기까지 확장할지 미결 |
| 순차 pinned 비트 필요 여부 | situations.yaml | 기·승·전·결 핵심 비트를 zone별 고정할지 — 본 안은 순수 가중 추첨, 서사 보강 필요 시 재논의 |
| 창문 디스플레이: 사전 제작 영상 vs 생성형 | 별도 검토 | 카드 media_key로 사전 제작 영상 선택이 현실적(연출 정합) |