카드 발급 신청 시나리오¶
이 폴더는 dm/scenario/card_issuance.json의 현재 설계를 설명합니다. JSON이 실행 기준이며, 문서는 카드 신청 흐름과 runtime 동작을 읽기 쉽게 정리합니다.
문서¶
- Node Graph: 선형 수집 흐름과 승인·거절·취소 routing
- Slot: 12개 required slot과 값 정규화
- Intent: 취소·종료 intent와 심사 routing의 구분
- Dialog act: 긍정·부정·정정·질문 처리
목적¶
카드 종류를 선택하고 신청자·소득·배송 정보를 수집한 뒤, 약관 동의와 최종 확인을 거쳐 간이 사전 심사 결과를 안내합니다.
| 항목 | 현재 값 |
|---|---|
| Scenario slug | card_issuance |
| 언어 | ko |
| 버전 | 2.0.0 |
| Entry node | welcome |
| Node 수 | 10 |
| Slot 수 | 12 |
| Slot policy | 모두 required |
| Terminal node | completion_approved, completion_rejected, application_cancelled |
이 시나리오의 승인 결과는 실제 신용평가가 아니라 입력한 연소득과 근무기간을 사용한 간이 사전 심사입니다.
기본 흐름¶
welcome
→ collect_personal_info
→ select_card_type
→ income_verification
→ address_collection
→ final_confirmation
→ process_application
→ completion_approved | completion_rejected
사용자가 신청을 취소하거나 대화를 끝내면 어느 단계에서든 application_cancelled로
이동합니다. fallback 재시도를 소진해 context.fallback_exhausted가 생겨도 같은
node로 이동합니다. 약관 또는 최종 신청 확인에 no라고 답한 경우도 같습니다.
Node 요약¶
| Node | 역할 | Executor | 수집 슬롯 | 정상 경로 |
|---|---|---|---|---|
welcome |
서비스 소개와 진행 의사 확인 | General | — | 개인정보 수집 |
collect_personal_info |
이름과 생년월일 수집 | Task | name, birth_date |
카드 선택 |
select_card_type |
신청 카드 선택 | Task | card_type |
소득 확인 |
income_verification |
소득과 근무 정보 수집 | Task | annual_income, workplace, employment_months |
배송지 수집 |
address_collection |
주소와 배송 방식 수집 | Task | postal_code, address, detailed_address, delivery_option |
약관 동의 |
final_confirmation |
신청 요약과 약관 동의 | Task | terms_agreed |
최종 신청 확인 |
process_application |
최종 신청 확인과 간이 사전 심사 | Task | application_confirmed |
승인 또는 거절 |
completion_approved |
사전 심사 기준 충족 안내 | General | — | 종료 |
completion_rejected |
사전 심사 기준 미충족 안내 | General | — | 종료 |
application_cancelled |
신청 취소 안내 | General | — | 종료 |
collect_slots가 있는 6개 node는 TaskOrientedExecutor, 나머지 4개 node는 GeneralResponseExecutor가 실행합니다.
카드 상품¶
| card_type | 표시명 | 연회비 | 시나리오에 선언된 혜택 | 간이 소득 기준 |
|---|---|---|---|---|
standard |
일반카드 | 0원 | 국내 가맹점 0.3% 적립 | 연 2,000만원 이상 |
gold |
골드카드 | 5만원 | 국내 0.5%, 해외 1%, 공항 라운지 | 연 3,500만원 이상 |
platinum |
플래티넘카드 | 20만원 | 국내외 1%, 컨시어지 | 연 8,000만원 이상 |
세 카드 모두 근무기간 6개월 이상이 승인 분기의 공통 조건입니다.
간이 사전 심사¶
process_application.next_nodes가 누적 slot을 숫자로 비교합니다.
| 카드 | 승인 조건 | 그 외 |
|---|---|---|
| 일반카드 | annual_income > 1999 AND employment_months > 5 |
거절 |
| 골드카드 | annual_income > 3499 AND employment_months > 5 |
거절 |
| 플래티넘카드 | annual_income > 7999 AND employment_months > 5 |
거절 |
greater_than과 less_than은 내부에서 값을 float로 변환하므로 NLU가 "5000"처럼 숫자 문자열을 반환해도 조건을 평가할 수 있습니다.
낮은 소득을 입력해도 income_verification에서 즉시 거절하지 않습니다. 직장명, 근무기간, 배송지, 약관 동의와 최종 신청 확인을 마친 뒤 process_application이 결과를 결정합니다.
취소와 종료¶
| 신호 | 평가 위치 | Target |
|---|---|---|
nlu.intent == user_wants_to_cancel |
Global transition | application_cancelled |
nlu.intent == user_wants_to_end |
Global transition | application_cancelled |
context.fallback_exhausted가 비어 있지 않음 |
Global transition | application_cancelled |
slots.terms_agreed == no |
final_confirmation |
application_cancelled |
slots.application_confirmed == no |
process_application |
application_cancelled |
Global transition은 Task executor의 현재 node 유지 요청보다 우선합니다. NLU는 단순한 정보 정정을 취소 intent로 분류하지 않아야 합니다.
개인정보 처리 원칙¶
Scenario prompt는 다음을 명시합니다.
| 원칙 | 동작 |
|---|---|
| 최소 수집 | 주민등록번호 대신 생년월일만 수집 |
| 금지 정보 | 계좌·카드 비밀번호, CVC, 인증번호를 요청하지 않음 |
| 응답 노출 제한 | 생년월일과 전체 상세 주소를 불필요하게 반복하지 않음 |
| 생성 금지 | 신청번호, 승인일, 배송일을 임의로 만들지 않음 |
| 결과 한계 | 실제 승인·신용평가가 아닌 간이 사전 심사임을 알림 |
이 지침은 NLG prompt 제약입니다. 별도의 암호화, 마스킹, 접근 제어 또는 법적 동의 저장 기능을 Scenario JSON이 제공하는 것은 아닙니다.
Prompt 역할¶
| Prompt | 역할 |
|---|---|
prompts.bot |
말투, 개인정보 보호, 상품 정보 범위, 실제 승인 오인 방지 |
prompts.nlu |
카드·배송 enum 정규화, 금액·기간 변환, 동의·취소 해석 |
NLU 정규화 예:
| 사용자 표현 | 저장 값 |
|---|---|
| 일반카드, 일반, 1번 | card_type=standard |
| 5천만원 | annual_income="5000" |
| 2년 3개월 | employment_months="27" |
| 무료배송, 일반배송 | delivery_option=standard |
| 약관에 동의해요 | terms_agreed=yes |
Runtime상 중요한 제약¶
value_type과values는 NLU prompt metadata이며 state 저장 시 강제 검증하지 않습니다.- 생년월일은
YYYY-MM-DD정규화를 지시하지만 실제 달력 날짜 검증은 없습니다. - 숫자
0은 falsey 값이라 slot update에서 누락될 수 있어 NLU가 문자열"0"으로 반환하도록 지시합니다. - 모든 slot이 required이므로
max_turns까지 수집하지 못하면required_slot_not_collected로 세션이 종료될 수 있습니다. - Transition은 현재 node의 응답 생성 후 적용되므로 이동한 node와 응답을 만든 node가 다를 수 있습니다.
검증¶
python -m cli.chatbot \
--scenario dm/scenario/card_issuance.json \
--validate-only
python -m cli.chatbot \
--scenario dm/scenario/card_issuance.json \
--llm-choice gpt-4o \
--nlu-llm-choice gpt-4o-mini \
--output-level detailed
필수 회귀:
- 첫 인사 후 개인정보 수집으로 진행
- 생년월일을 주민등록번호 없이 수집
- 카드 표현을 세 enum 값으로 정규화
- 낮은 소득만으로 소득 수집 중 즉시 종료하지 않음
- 소득·근무기간 조건에 따라 승인·거절 분기
- 약관 또는 신청 진행 거부 시 취소
- 어느 node에서든 명시적 취소·종료 intent 처리
- terminal node에서 세션 완료