06. 슬롯 오배정¶
이 문서는 당시 오배정 문제를 추적한 기록입니다. 현재 slot registry·수집 범위·남은 위험은 SeniMate Slot을 기준으로 확인하세요.
증상¶
노드가 한 칸씩 밀려서 답이 엉뚱한 슬롯에 들어갔다.
그 결과 봇이 같은 주제를 두 번 물었다.
원인은 NLU 프롬프트 한 줄이었다¶
# dm/core/llm/prompts/prompts_nlu.py (수정 전)
"- 사용자가 현재 노드 목적과 무관한 일상대화를 하면 intent를 'off_topic'으로 설정하세요."
일상 안부를 묻는 노드에서 "일상대화면 off_topic"이라고 지시하고 있었다. daily_life_check 의 목적이 곧 일상인데 그것을 주제 이탈로 분류하라는 뜻이 된다.
여기서 연쇄가 시작된다.
"오늘 심심해" → intent = off_topic
├─ entities 비어 있음 → daily_life 안 채워짐
├─ TopicGuardPolicy 발동 → 노드에 붙잡힘
└─ 그런데 봇은 이미 다음 노드(식사) 질문을 했다
→ 사용자가 식사에 답
→ 아직 daily_life_check 이므로 daily_life 로 저장 ✗
노드가 "직전 질문의 답을 받고 다음 질문을 던지는" 구조라, 노드가 이동하지 않으면 답과 슬롯의 짝이 어긋난다.
무엇을 바꿨나¶
1. off_topic 판정 기준을 바꿨다¶
판단 기준을 "잡담인가" 에서 "이 노드가 알고 싶어 하는 것에 대한 정보가 들어 있는가" 로 바꿨다.
intent 'off_topic' 은 **현재 노드의 수집 대상 슬롯 어디에도 쓸 수 없고, 노드 목적과
명확히 무관한** 발화에만 쓰세요. 판단 기준은 '잡담인가'가 아니라 **'이 노드가 알고
싶어 하는 것에 대한 정보가 들어 있는가'** 입니다. 노드가 일상·안부를 묻는 중이라면
날씨·기분·심심함·소일거리 이야기는 off_topic 이 아니라 그 노드의 정보입니다.
애매하면 off_topic 으로 두지 마세요.
한국어·일본어 프롬프트 양쪽에 적용했다.
2. 라우팅 키를 프롬프트에서 제외했다¶
node_config 는 프롬프트에 통째로 덤프된다. 거기에 default_next: "meal_check" 가 보였다.
다음 노드를 정하는 것은 런타임의 일이지 LLM 의 일이 아니다. 이 값이 보이면 LLM 이 아직 전이하지 않은 턴에도 다음 노드 주제를 앞질러 묻는다. 전이해도 되는 턴에는 handoff 규칙이 다음 주제를 명시적으로 알려 준다.
3. daily_life_check description 을 손봤다¶
"다음 노드(meal_check)로 넘어갈 때는…"제거 — 전이 지시는 handoff 규칙이 담당한다. description 에 다음 노드 이름을 적으면 아직 전이하지 않은 턴에도 그 주제를 꺼낸다."한 걸음 더 들어가세요"예시 제거 — 이 예시가 전환 턴에서 두 번째 질문을 만들고 있었다.
결과¶
--node daily_life_check 단독 진단 (실제 LLM)
| 입력 | 이전 | 이후 |
|---|---|---|
| 오늘 심심해 | off_topic · 슬롯 없음 · 붙잡힘 |
daily_life_check · daily_life='심심해' |
| 그냥 집에 있어 | 정상 | 정상 |
| TV 봐 | off_topic · 슬롯 없음 · 붙잡힘 |
daily_life_check · daily_life='TV 봐' |
전체 흐름에서 슬롯이 제자리에 들어간다.
'오늘 심심해' → daily_life_check daily_life = '심심해'
'응 먹었지' → meal_check meal_status = 'adequate'
'건강해' → health_check health_status = 'adequate'
TopicGuardPolicy 는 손대지 않았다¶
이전 단계에서 되돌린 정책 변경(dialog act 기반 판정, 세션 종료 제거)을 다시 넣지 않았다. NLU 가 제대로 판정하니 가드가 발동할 일이 없어졌다.
off_topic_count 가 3에 도달해 세션이 끊기던 경로도 함께 사라졌다. 정책을 고치는 대신 그 정책을 잘못 트리거하던 입력을 고친 셈이다.
남은 위험¶
- NLU 판정에 의존한다. 프롬프트 지시가 지켜지지 않으면 같은 문제가 재발한다.
TopicGuardPolicy자체는 여전히 intent 기반이고 세션을 끊을 수 있다. - 구조적 취약점은 남아 있다. "노드가 다음 질문을 미리 던지는" 구조는 그대로다. 어떤 이유로든 노드가 이동하지 않으면 짝이 다시 어긋난다.