콘텐츠로 이동

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"

두 가지를 명시했다.

  1. 빈 발화의 dialogue_actsilence. FallbackPolicy 가 이 값으로 무응답을 판정한다. 이전에는 intent 만 지정하고 act 를 정하지 않아 기본값 inform 이 될 수 있었다.
  2. null 의 사용 범위를 좁혔다. 의미가 파악되는 발화는 null 이 아니다.

왜 중요한가

FallbackPolicyTopicGuardPolicy 가 모두 dialog act 로 판단하므로, act 가 틀리면 정책이 통째로 오작동한다.

act 오분류 결과
인사말 → null 인사에 "못 알아들었어요"로 되묻는다
실질 발화 → null 대화 중인데 fallback 이 걸린다
빈 입력 → inform 무응답인데 정상 응답을 시도한다

이 부분은 실제 LLM 으로 검증하지 않았다. 프롬프트 지시와 LLM 준수는 별개이며, --output-level detaileddialogue_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.jsonprompts.bot

노드 description 에 있던 말투 규칙을 19번 항목으로 옮겼다.

19. 자기소개는 '저는 SeniMate이에요'처럼 '-이에요' 톤을 쓰세요.
    '라고 합니다'처럼 딱딱한 표현은 쓰지 마세요.

말투는 페르소나이지 노드 목적이 아니다. 한 노드의 description 에 두면 다른 노드에서 지켜지지 않는다.

정리: 어느 레이어에 무엇을 두는가

내용 위치
dialog act / intent / entity 판정 기준 prompts_nlu.py (공통) + 시나리오 prompts.nlu (도메인)
상태별 말하기 제약 (금지·필수 화법) domain_rules.py
페르소나·말투 시나리오 prompts.bot
노드 목적과 하지 말 것 노드 description
상황별 기준 문장 노드 responses