04. 프롬프트 변경¶
NLU 프롬프트¶
dm/core/llm/prompts/prompts_nlu.py
왜 바꿨나¶
GreetingExecutor 를 제거하면서 하드코딩 인사말 목록(_GATE_SOCIAL_GREETINGS)도 함께 사라졌다. 그 목록은 NLU 가 인사말을 제대로 분류하지 못하는 문제를 코드에서 덮고 있었다.
기존 테스트 stub 이 "안녕"에 대해 dialogue_act: "null" 을 반환하고 있던 것이 이를 보여준다. null 은 "의미를 파악할 수 없음"이므로, 그대로 두면 인사에 "제가 잘 못 알아들었어요"라고 되묻게 된다.
근본 해결 지점은 코드의 키워드 목록이 아니라 NLU 프롬프트다.
변경¶
- "- 발화가 비어있으면: intent를 'empty'로, confidence를 0.1로 설정하세요. 봇이 다시 질문해야 합니다.\n"
+ "- 발화가 비어있으면: intent를 'empty'로, dialogue_act를 'silence'로, confidence를 0.1로 설정하세요.\n"
+ "- dialogue_act 'null'은 **발화의 의미를 정말로 파악할 수 없을 때만** 사용하세요. 오타·비문·말이 끊긴
+ 경우가 여기에 해당합니다. 인사말('안녕', '안녕하세요', '반가워요'), 짧은 감상('좋네', '심심해'),
+ 거절·회피('바빠', '나중에')는 모두 의미가 파악되는 발화이므로 'null'이 아니라
+ 'inform'/'affirm'/'deny' 중 맞는 값을 쓰세요.\n"
두 가지를 명시했다.
- 빈 발화의
dialogue_act는silence.FallbackPolicy가 이 값으로 무응답을 판정한다. 이전에는intent만 지정하고 act 를 정하지 않아 기본값inform이 될 수 있었다. null의 사용 범위를 좁혔다. 의미가 파악되는 발화는null이 아니다.
왜 중요한가¶
FallbackPolicy 와 TopicGuardPolicy 가 모두 dialog act 로 판단하므로, act 가 틀리면 정책이 통째로 오작동한다.
| act 오분류 | 결과 |
|---|---|
인사말 → null |
인사에 "못 알아들었어요"로 되묻는다 |
실질 발화 → null |
대화 중인데 fallback 이 걸린다 |
빈 입력 → inform |
무응답인데 정상 응답을 시도한다 |
이 부분은 실제 LLM 으로 검증하지 않았다. 프롬프트 지시와 LLM 준수는 별개이며, --output-level detailed 로 dialogue_act 실측이 필요하다.
NLG 도메인 규칙¶
dm/core/llm/prompts/domain_rules.py
경청 지침 (모든 턴 공통)¶
[경청] 사용자가 말한 내용에서 **구체적인 한 조각을 집어서** 먼저 반응하세요.
'그러셨군요', '좋네요'처럼 어디에나 쓸 수 있는 말로 시작하지 마세요.
사용자가 '날씨가 좋다'고 하면 날씨를, '심심하다'고 하면 무료함을 언급하세요.
질문은 한 번에 하나만 하고, 하지 않아도 자연스러운 턴이면 질문 없이 마쳐도 됩니다.
build_domain_rules() 맨 앞에 무조건 추가되므로 모든 노드·모든 턴에 적용된다.
마지막 문장이 의도적이다. 기존 프롬프트는 매 턴 질문을 유도해 "취조당하는 느낌"을 만들었다. 질문하지 않아도 되는 턴을 허용한다.
fallback 화법¶
intent_data.fallback_kind 를 보고 두 갈래로 나눈다.
| kind | 화법 |
|---|---|
no_input |
재촉·비난 금지. 못 들었을 수 있다는 전제. 직전 질문을 글자 그대로 반복하지 말고 더 짧고 쉽게 |
not_understood |
사용자를 탓하지 않고 "제가 못 알아들었다"로 표현. 알아들은 부분이 있으면 그것부터 확인 |
두 경우 모두 suppress_turn_notes = True 로 두어 턴 상한 안내 등 다른 지침이 겹치지 않게 한다. 재시도 회차(fallback_retry_index)를 함께 전달해 같은 문장을 반복하지 않도록 한다.
시나리오 봇 프롬프트¶
dm/scenario/senimate.json 의 prompts.bot
노드 description 에 있던 말투 규칙을 19번 항목으로 옮겼다.
말투는 페르소나이지 노드 목적이 아니다. 한 노드의 description 에 두면 다른 노드에서 지켜지지 않는다.
정리: 어느 레이어에 무엇을 두는가¶
| 내용 | 위치 |
|---|---|
| dialog act / intent / entity 판정 기준 | prompts_nlu.py (공통) + 시나리오 prompts.nlu (도메인) |
| 상태별 말하기 제약 (금지·필수 화법) | domain_rules.py |
| 페르소나·말투 | 시나리오 prompts.bot |
| 노드 목적과 하지 말 것 | 노드 description |
| 상황별 기준 문장 | 노드 responses |