자유 대화 Node Graph¶
dm/scenario/general_conversation.json 기준의 node 흐름입니다.
기본 흐름¶
Node schema¶
| Node | Terminal | 주요 params | next_nodes |
|---|---|---|---|
greeting |
false |
max_turns=3 |
첫 턴 stay, 이후 conversation |
conversation |
false |
turn_limit_enabled=false |
종료 시 closure, 그 외 stay |
conversation_closure |
true |
max_turns=2 |
없음 |
정적 graph¶
NetworkX에 생성되는 node 간 edge:
flowchart LR
GREET["greeting"] --> TALK["conversation"]
TALK --> CLOSE["conversation_closure"]
정적 edge가 되는 선언:
| 선언 | 정적 edge |
|---|---|
greeting.default_next = conversation |
greeting → conversation |
next_nodes[].target = conversation_closure |
conversation → conversation_closure |
next_nodes[].action = stay |
생성하지 않음 |
global_transitions[].target |
생성하지 않음 |
action: stay를 자기 자신을 향한 target으로 바꾸면 self-loop가 생겨 start node 계산과 DAG 검증을 방해할 수 있습니다.
Runtime routing 우선순위¶
현재 scenario에서 실제로 관련된 순서:
Action END
→ global transition
→ Action STAY/GOTO
→ node next_nodes condition
→ terminal 판정
→ graph successor fallback
→ 현재 node 유지
conversation의 일반 executor는 보통 명시적인 Action transition을 만들지 않습니다. 따라서 global transition 또는 node의 condition이 흐름을 결정합니다.
Global transition¶
| 이름 | Condition | Target |
|---|---|---|
user_wants_to_end |
nlu.intent == user_wants_to_end |
conversation_closure |
flowchart TD
INPUT["현재 턴"] --> END_INTENT{"nlu.intent =<br/>user_wants_to_end?"}
END_INTENT -- "예" --> CLOSE["conversation_closure"]
END_INTENT -- "아니오" --> LOCAL["conversation node-local routing"]
Global transition은 모든 node에서 평가합니다. 이미 conversation_closure에 있을 때 target이 현재 node와 같으면 runtime이 self-targeting transition을 무시하고 terminal 판정으로 내려갑니다.
conversation routing¶
flowchart TD
TALK["conversation"] --> END_INTENT{"intent = user_wants_to_end?"}
END_INTENT -- "예" --> CLOSE["conversation_closure"]
END_INTENT -- "아니오" --> STAY["action: stay"]
STAY --> TALK
| Condition | Action |
|---|---|
nlu.intent == user_wants_to_end |
conversation_closure 이동 |
nlu.intent != user_wants_to_end |
현재 node 유지 |
None, unknown, inform 등 종료 intent가 아닌 값은 not_equals 조건에 해당합니다.
conversation_closure routing¶
flowchart TD
CLOSE["conversation_closure<br/>terminal: true"] --> GLOBAL{"global 종료 target이<br/>현재 node인가?"}
GLOBAL -- "예" --> IGNORE["self-target 무시"]
GLOBAL -- "아니오/불일치" --> TERMINAL["terminal 판정"]
IGNORE --> TERMINAL
TERMINAL --> COMPLETE([Session complete])
Closure에는 next_nodes와 default_next가 없습니다. 따라서 재개 경로 없이 terminal node로 완료됩니다.
종료 응답과 node 이동¶
Transition은 현재 node의 응답 생성 뒤에 적용됩니다.
sequenceDiagram
participant U as User
participant C as conversation
participant T as TransitionEngine
participant X as conversation_closure
U->>C: 종료 발화
C-->>U: conversation 기준 응답
C->>T: NLU + Action + State
T->>X: global transition
Note over X: 다음 처리 시점의 current_node
current_node=conversation_closure가 된 것과 같은 턴의 응답을 closure가 생성한 것으로 해석하면 안 됩니다. Detailed 출력에서는 details.transition.from/to를 함께 확인합니다.
정적 graph와 runtime graph의 차이¶
| 경로 | 정적 edge | Runtime 조건 |
|---|---|---|
| greeting → conversation | 있음 | default_next (첫 턴은 stay) |
| conversation → closure | 있음 | 종료 intent |
| conversation → conversation | 없음 | action: stay |
| closure → complete | 없음 | terminal: true 판정 |