카드 발급 신청 Node Graph¶
dm/scenario/card_issuance.json 기준의 정적 graph와 runtime routing입니다.
기본 흐름¶
Node schema¶
| Node | Terminal | 주요 params | collect_slots | 기본 이동 |
|---|---|---|---|---|
welcome |
false |
max_turns=2 |
— | collect_personal_info |
collect_personal_info |
false |
max_turns=4 |
이름, 생년월일 | select_card_type |
select_card_type |
false |
max_turns=3 |
카드 종류 | income_verification |
income_verification |
false |
max_turns=5 |
소득, 직장, 근무기간 | address_collection |
address_collection |
false |
max_turns=6 |
우편번호, 주소, 상세주소, 배송 | final_confirmation |
final_confirmation |
false |
max_turns=4 |
약관 동의 | process_application |
process_application |
false |
max_turns=2 |
최종 신청 확인 | 조건 분기 |
completion_approved |
true |
fallback 0 | — | 완료 |
completion_rejected |
true |
fallback 0 | — | 완료 |
application_cancelled |
true |
fallback 0 | — | 완료 |
정적 graph¶
flowchart LR
W["welcome"] --> P["collect_personal_info"]
P --> C["select_card_type"]
C --> I["income_verification"]
I --> A["address_collection"]
A --> F["final_confirmation"]
F --> X["process_application"]
F --> CANCEL["application_cancelled"]
X --> APPROVED["completion_approved"]
X --> REJECTED["completion_rejected"]
X --> CANCEL
정적 edge:
| Source | Target | 선언 |
|---|---|---|
welcome |
collect_personal_info |
default_next |
collect_personal_info |
select_card_type |
default_next |
select_card_type |
income_verification |
default_next |
income_verification |
address_collection |
default_next |
address_collection |
final_confirmation |
default_next |
final_confirmation |
process_application |
default_next |
final_confirmation |
application_cancelled |
조건부 target |
process_application |
completion_approved |
카드별 조건부 target 3개 |
process_application |
completion_rejected |
조건부 target |
process_application |
application_cancelled |
조건부 target |
NetworkX는 DiGraph이므로 process_application → completion_approved를 만드는 세 카드별 선언은 정적 graph에서 하나의 edge로 표현됩니다. Runtime은 원본 next_nodes 배열의 세 조건을 순서대로 각각 평가합니다.
welcome.next_nodes[].action=stay와 global transition은 정적 edge를 만들지 않습니다.
Runtime routing 우선순위¶
이 시나리오에서 중요한 순서:
Action END
→ global transition
→ Action STAY/GOTO
→ off-topic slot-node stay guard
→ node next_nodes condition
→ default_next
→ terminal 판정
→ graph successor fallback
→ 현재 node 유지
Global 취소·종료·fallback 소진 전이가 required slot 미수집으로 발생한
STAY_CURRENT보다 먼저 적용됩니다.
Welcome¶
flowchart TD
START([Session start]) --> W["welcome"]
W --> T{"system.node_turns = 1?"}
T -- "예" --> STAY["action: stay"]
STAY --> W
T -- "아니오" --> PERSONAL["collect_personal_info"]
첫 빈 입력 턴에는 welcome에 머물러 인사를 제공합니다. 다음 사용자 응답 이후 collect_personal_info로 이동합니다.
선형 수집 구간¶
collect_personal_info
required: name, birth_date
↓ all required filled
select_card_type
required: card_type
↓
income_verification
required: annual_income, workplace, employment_months
↓
address_collection
required: postal_code, address, detailed_address, delivery_option
↓
final_confirmation
각 Task node에서 required slot이 남아 있으면 executor가 STAY_CURRENT를 요청합니다. 모두 채워졌을 때만 default_next가 적용됩니다.
낮은 소득 처리¶
소득 기준 판정은 income_verification에서 하지 않습니다.
flowchart TD
INPUT["annual_income 입력"] --> COLLECT{"workplace와<br/>employment_months도 채웠는가?"}
COLLECT -- "아니오" --> STAY["income_verification 유지"]
COLLECT -- "예" --> ADDRESS["address_collection"]
ADDRESS --> TERMS["final_confirmation"]
TERMS --> PROCESS["process_application"]
PROCESS --> RESULT{"카드별 기준 판정"}
예를 들어 일반카드를 선택하고 연소득 1,000만원을 입력해도 직장명과 근무기간 수집을 계속합니다. 거절은 최종 신청 확인 이후에만 결정됩니다.
약관 동의¶
flowchart TD
FINAL["final_confirmation"] --> CONSENT{"terms_agreed"}
CONSENT -- "no" --> CANCEL["application_cancelled"]
CONSENT -- "yes" --> PROCESS["process_application"]
CONSENT -- "미수집" --> FINAL
| Condition | 결과 |
|---|---|
slots.terms_agreed == no |
취소 |
user_wants_to_cancel |
global 또는 node-local 취소 |
user_wants_to_end |
global 또는 node-local 취소 |
| required slot 완료, 취소 조건 없음 | process_application |
최종 신청 확인과 심사¶
flowchart TD
PROCESS["process_application"] --> CONFIRM{"application_confirmed"}
CONFIRM -- "no" --> CANCEL["application_cancelled"]
CONFIRM -- "yes" --> CARD{"card_type"}
CARD -- "standard" --> S{"income > 1999<br/>months > 5"}
CARD -- "gold" --> G{"income > 3499<br/>months > 5"}
CARD -- "platinum" --> P{"income > 7999<br/>months > 5"}
S -- "예" --> OK["completion_approved"]
G -- "예" --> OK
P -- "예" --> OK
S -- "아니오" --> NO["completion_rejected"]
G -- "아니오" --> NO
P -- "아니오" --> NO
Runtime의 승인 조건:
| 순서 | Condition | Target |
|---|---|---|
| 1 | application_confirmed == no |
취소 |
| 2 | standard AND income > 1999 AND months > 5 | 승인 |
| 3 | gold AND income > 3499 AND months > 5 | 승인 |
| 4 | platinum AND income > 7999 AND months > 5 | 승인 |
| 5 | months < 6 OR 카드별 income 미달 | 거절 |
application_confirmed=yes는 Task node의 required slot을 완료시키는 값입니다. 승인 조건에는 반복하지 않고 이미 수집 완료된 사실을 전제로 합니다.
Global transition¶
| 이름 | Condition | Target |
|---|---|---|
user_wants_to_cancel |
nlu.intent == user_wants_to_cancel |
application_cancelled |
user_wants_to_end |
nlu.intent == user_wants_to_end |
application_cancelled |
fallback_exhausted |
context.fallback_exhausted is not empty |
application_cancelled |
Global transition은 모든 node에서 평가됩니다. 이미 application_cancelled에 있을 때 target이 현재 node와 같으면 self-target을 무시하고 terminal 판정으로 내려갑니다.
Terminal 처리¶
세 결과 node 모두 terminal: true입니다.
flowchart LR
APPROVED["completion_approved"] --> DONE([Session complete])
REJECTED["completion_rejected"] --> DONE
CANCELLED["application_cancelled"] --> DONE
Terminal node는 executor가 해당 node의 응답을 만든 뒤 명시적 전이가 없으면 TransitionEngine이 session_complete=true로 설정합니다.
응답과 node 이동 시점¶
한 턴은 이동 전 node에서 응답을 만든 뒤 transition을 적용합니다.
따라서 detailed 출력의 node A › B에서 같은 턴의 응답은 일반적으로 A의 설정으로 생성됩니다. B의 terminal 안내는 B가 현재 node인 다음 처리 시점에 적용됩니다.