자유 대화 시나리오¶
이 폴더는 dm/scenario/general_conversation.json의 현재 설계를 설명합니다. JSON이 실행 기준이며, 문서는 구조와 runtime 동작을 읽기 쉽게 정리합니다.
문서¶
- Node Graph: 정적 graph와 runtime routing
- Slot: 슬롯을 선언·수집하지 않는 구조
- Intent: 종료 intent와 공통 runtime intent
- Dialog act: 발화 행위별 공통 정책과 종료 영향
목적¶
이 시나리오는 정해진 업무나 정보 수집 없이 사용자와 자유롭게 대화합니다.
| 항목 | 현재 값 |
|---|---|
| Scenario slug | general_conversation |
| 언어 | ko |
| 버전 | 1.1.0 |
| Bot first | true |
| Entry node | greeting |
| Slot registry | 없음 |
| Slot 수집 | 없음 |
| 명시적 종료 신호 | nlu.intent == user_wants_to_end |
| Terminal node | conversation_closure |
전체 흐름¶
세션은 greeting에서 봇이 먼저 인사한 뒤 conversation으로 들어갑니다. conversation은 사용자가 명시적으로 종료하기 전까지 현재 노드에 머뭅니다. conversation_closure는 terminal: true이며 outgoing edge가 없습니다.
Node 요약¶
| Node | 역할 | Executor | 수집 슬롯 | Turn limit |
|---|---|---|---|---|
greeting |
짧게 인사한 뒤 오늘 이야기를 연다 | GeneralResponseExecutor |
없음 | max_turns 3 |
conversation |
사용자 입력에 이어가는 자유 대화 | GeneralResponseExecutor |
없음 | 비활성화 |
conversation_closure |
종료 의사를 짧게 받아들이고 마무리 | GeneralResponseExecutor |
없음 | max_turns 2 |
세 노드 모두 collect_slots가 없으므로 GeneralResponseExecutor가 선택됩니다.
자유 대화 설정¶
| Param | 타입 | 값 | 효과 |
|---|---|---|---|
turn_limit_enabled |
boolean |
false |
executor turn limit과 NLG turn-budget 안내 비활성화 |
turn_limit_enabled=false는 conversation에만 선언되어 있습니다. 따라서 대화 횟수만으로 closure로 이동하지 않습니다.
Prompt¶
현재 scenario prompt:
| 경로 | 선언 여부 | 내용과 역할 |
|---|---|---|
prompts.bot |
선언 | 지금 말에 답하고 앞 사실도 이어가기. 직전 봇 말이 질문이면 이번은 평서문으로만 끝냄 |
prompts.nlu |
선언 | 짧은 말은 직전 봇 말로 해석. 질문의 부정 답은 종료가 아님. 주제 접기와 대화 종료를 구분 |
prompts.bot이 빈 값이 아니므로 공통 NLG 시스템 prompt를 완전히 제거하는 구조는 아닙니다. 공통 prompt에 scenario의 bot 지침을 추가하여 사용합니다.
greeting만 responses.default를 둡니다. bot-first 첫 발화에서는 이 문장을 그대로
사용하고, 이후 일반 응답에서는 NLG 기준이자 LLM 실패 fallback이 될 수 있습니다.
conversation과 conversation_closure에는 responses가 없으므로 공통 fallback
메시지가 사용될 수 있습니다.
종료 routing¶
종료 조건은 global transition과 conversation.next_nodes에 같은 형태로 선언되어 있습니다.
| 위치 | 조건 | 결과 |
|---|---|---|
graph.global_transitions[0] |
nlu.intent == user_wants_to_end |
conversation_closure로 이동 |
conversation.next_nodes[0] |
nlu.intent == user_wants_to_end |
conversation_closure로 이동 |
conversation.next_nodes[1] |
nlu.intent != user_wants_to_end |
현재 노드 유지 |
Runtime에서는 global transition이 node-local transition보다 먼저 평가되므로 정상 종료 턴에는 global transition이 우선합니다. Node-local closure target은 정적 graph에 conversation → conversation_closure edge를 만들고 graph 구조를 명확하게 유지하는 역할도 합니다.
종료 턴의 실행 시점¶
한 턴은 현재 노드가 응답을 만든 뒤 transition을 적용합니다.
conversation에서 사용자 종료 발화 처리
→ conversation 응답 생성
→ global transition 결정
→ current_node = conversation_closure
따라서 closure로 이동한 턴의 응답은 이동 전 conversation이 생성합니다. conversation_closure의 description은 closure가 현재 노드인 다음 처리 턴에 적용됩니다.
Closure는 outgoing edge가 없고 terminal: true이므로 해당 노드에서 명시적 전이가 없으면 TransitionEngine이 세션을 완료합니다.
SeniMate와 다른 점¶
| 항목 | 자유 대화 | SeniMate |
|---|---|---|
| 목적 대화 | 없음 | 일상·식사·건강 확인 |
| Slot registry | 없음 | 6개 optional slot |
| Node 수 | 3 (greeting 포함) |
6 |
| 연속 무응답 종료 | 선언 없음 | silent_close global transition |
| Closure 재개 edge | 없음 | 미수집 단계 또는 자유 대화로 복귀 |
| Closure params | max_turns 2 |
turn/fallback 제한 선언 |
현재 conversation_closure에는 재개 transition이 없습니다. Closure에서 사용자가 새 이야기를 시작하더라도 SeniMate처럼 conversation으로 돌아가지 않고 terminal 판정으로 완료됩니다.
현재 주의점¶
- 명시적 종료 transition은
nlu.intent만 확인합니다. - Scenario가 종료 transition을 직접 선언하므로 runtime의 기본
goodbye·nlu.end_signal조건은 자동 보충되지 않습니다. - 종료 intent 분류는 공통 NLU 지침에
prompts.nlu의 부정·주제 접기 규칙을 더합니다. - Slot registry와
collect_slots가 모두 없어 task policy와 slot commit 경로를 사용하지 않습니다. - 연속 무응답을 closure로 보내는
silent_close규칙이 없습니다. - Closure에서 대화를 재개하는 outgoing edge가 없습니다.
conversation의 turn limit은 비활성화됩니다. closure는max_turns2입니다.
검증¶
python -m cli.chatbot \
--scenario dm/scenario/general_conversation.json \
--validate-only
python -m cli.chatbot \
--scenario dm/scenario/general_conversation.json \
--output-level detailed
python -m cli.chatbot \
--scenario dm/scenario/general_conversation.json \
--node conversation_closure \
--output-level detailed
필수 회귀:
- 일반 입력에서
conversation유지 - 답변 뒤에 습관적인 추가 질문이나 도움 제안을 붙이지 않음
- 여러 턴 대화 후에도 turn limit으로 종료하지 않음
- 명시적
user_wants_to_end에서 closure 이동 - closure가
terminal_node로 완료 - Slot update와 task outcome이 생성되지 않음
- closure에서 새 발화를 해도 현재 설계상 대화가 재개되지 않음