-
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과 함께 결정한다.
§5에서 결정한 모델은 페르소나가 ① 카드 풀 가중치 + ② LLM 대사 톤에만 작용한다(Tier 1). 본 절은 이를 ③ zone playbook 분기까지 넓히는 확장안(Tier 2)을 정리한다. 두 단계는 배타적이 아니라 누적(superset) — Tier 2는 Tier 1 위에 얹는다.
| 단계 | 페르소나 영향 | 메커니즘 | 차별화 강도 |
|---|---|---|---|
| Tier 0 | 없음 (표시용) | — | 없음 |
| Tier 1 (현 결정) | 카드 풀 가중 + 대사 톤 | persona를 컨텍스트로 주입, LLM 재량 | 약(soft) |
| Tier 2 (본 확장안) | + playbook 분기 | zone playbook에 페르소나 조건 블록을 조립 | 강(명시) |
풀 변형 파일(home.개발자.md …)은 직업 × 성격 × 사정 × zone으로 조합 폭발한다. 이를 피하려고 차원별 작은 fragment를 가산한다.
prompts/playbooks/
home.md # base (zone) — 안정적, 캐시 대상
park.md
persona/
job/개발자.md # "야근·코드 비유로 공감", 도메인 예시
personality/내향적.md # "간결·차분한 톤"
circumstance/반려동물.md # "반려동물 케어를 우선 언급"
orchestrator의 assemble 단계 조립 순서:
system_prompt + <zone>.md ⟦cache breakpoint⟧
+ job/* + personality/* + circumstance/* # 가산 fragment
+ active_situation + robot_state
차원별 역할 가이드:
| 페르소나 차원 | playbook 분기가 바꾸는 것 |
|---|---|
job |
대사 도메인·비유·예시 |
personality |
톤·길이·능동성 |
circumstance |
케어 우선순위·강조점 |
SYSTEM_DESIGN §9.1·§3.4는 system prompt + zone playbook이 stable하다는 전제로 Anthropic prompt caching(프롬프트 캐싱)을 적용해 비용·지연을 줄인다. playbook이 persona로 분기하면 이 캐시가 깨질 수 있다.
해결: cache breakpoint(캐시 분기점)를 system_prompt + base zone playbook 뒤에 둔다 → 이 prefix는 모든 세션 공통이라 캐시 적중이 유지된다. persona fragment·situation은 breakpoint 뒤에 append(세션마다 다르나 짧아서 미적용분이 작다). 가산 조립이 곧 캐시 친화 구조인 이유다.
| 항목 | Tier 1 (현 결정) | Tier 2 (확장) |
|---|---|---|
| 페르소나 차별화 | 약 — LLM 재량 | 강 — 명시 블록 |
| 결정성·재현성 | 낮음 | 높음 |
| 작성·유지 부담 | 최소 | 차원별 fragment 관리 (가산이라 선형, 곱 아님) |
| 프롬프트 캐시 | 영향 없음 | breakpoint 설계 시 유지 (§10.3) |
| 테스트 | 적음 | fragment × zone 조합 검증 필요 |
| 신규 토픽·코드 | 없음 | 없음 (파일 추가 + assemble 로직만) |
- 페르소나가 체험의 핵심 차별 축이면 Tier 2, 분위기 양념이면 Tier 1로 충분.
- 단계적 도입 권장: Tier 1로 출시 → 페르소나별 차별이 부족하면 가산 fragment를 zone 단위로 점진 추가(파일 추가만, 코드·토픽 무변경 → §10.4 마지막 행).
- 어느 단계든 카드 풀 가중(§5, 이미 결정)은 유지 — playbook 분기는 "카드가 주어졌을 때의 반응"을 조절하는 별도 레버다.
§9.2의 "매칭 tools"는 Tier와 무관하다 — 도구 집합은 capability 화이트리스트로 고정. 바뀌는 것은 같은 카드·같은 도구라도 페르소나에 따라 LLM이 만드는 대사·인자·옵션 구성이며, Tier 2에서 그 차이가 더 또렷하고 재현 가능해진다.
| 항목 | 영향 위치 | 비고 |
|---|---|---|
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·재현용 |
| 페르소나 효과 범위 확정 | — | Tier 1(카드 가중 + 대사 톤, 현 결정) vs Tier 2(playbook 분기, §10) 선택 미결. 단계적 도입(§10.5) 권장 |
| 순차 pinned 비트 필요 여부 | situations.yaml | 기·승·전·결 핵심 비트를 zone별 고정할지 — 본 안은 순수 가중 추첨, 서사 보강 필요 시 재논의 |
| 창문 디스플레이: 사전 제작 영상 vs 생성형 | 별도 검토 | 카드 media_key로 사전 제작 영상 선택이 현실적(연출 정합) |