hpce-dev / scripts /build_bundle_scenario.py
matalee's picture
[FIX] κ²°ν•© ν™•μž₯ μ˜λ„ β€” 보유 μ„œλΉ„μŠ€ 기반 게이트 (has_internet/has_iptv)
f8a23d4
Raw
History Blame Contribute Delete
26.3 kB
#!/usr/bin/env python3
"""
κ²°ν•©(bundle-v3) μ‹œλ‚˜λ¦¬μ˜€ μΉ΄νƒˆλ‘œκ·Έ 생성기.
단일 TAXONOMY μ •μ˜(μ†ŒμŠ€ 였브 트루슀)λ‘œλΆ€ν„°
- intents.json : L3 Intent μΉ΄νƒˆλ‘œκ·Έ (id/name/L1/L2/inference_type/features)
- actions.json : Intent별 3채널(push / call_center / agent) ν™œμš© μ˜ˆμ‹œ
- behavior_intents.json : behaviors.json entity β†’ 직접 μ‹ ν˜Έ Intent λ§€ν•‘
μ„Έ νŒŒμΌμ„ μΌκ΄€λ˜κ²Œ μƒμ„±ν•œλ‹€.
μ‹œλ‚˜λ¦¬μ˜€_κ²°ν•©:
1.1 κ²°ν•© Domain Intent Taxonomy / 1.2 Metadata / 4.2 ν™œμš© λ°©μ•ˆ.
μ‹€ν–‰:
cd roadshow-server-v3
python scripts/build_bundle_scenario.py
"""
from __future__ import annotations
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
from scripts._scenario_common import emit_layers # noqa: E402
SCENARIO_ID = "bundle-v3"
OUT_DIR = Path(__file__).parent.parent / "scenarios" / SCENARIO_ID
# ── L1 / L2 메타 ─────────────────────────────────────────────
L1 = {
"1": ("INT-B1000", "κ°€μž… ν™•λŒ€"),
"2": ("INT-B2000", "할인 μ΅œμ ν™”"),
"3": ("INT-B3000", "νšŒμ„ /μ„œλΉ„μŠ€ ν™•μž₯"),
"4": ("INT-B4000", "μœ μ§€/락인"),
"5": ("INT-B5000", "μ΄νƒˆ κ²€ν† "),
}
L2 = {
"11": ("INT-B1100", "κ²°ν•© κ°€λŠ₯ μ—¬λΆ€ 탐색"),
"12": ("INT-B1200", "κ²°ν•© μƒν’ˆ 탐색"),
"13": ("INT-B1300", "κ°€μž… ν˜œνƒ 탐색"),
"14": ("INT-B1400", "κ°€μž… μ‹€ν–‰ κ²€ν† "),
"21": ("INT-B2100", "ν˜„μž¬ ν˜œνƒ 점검"),
"22": ("INT-B2200", "μΆ”κ°€ ν˜œνƒ 탐색"),
"23": ("INT-B2300", "ν˜œνƒ ν™œμš© μ΅œμ ν™”"),
"31": ("INT-B3100", "κ²°ν•© λ²”μœ„ ν™•λŒ€"),
"32": ("INT-B3200", "λ””λ°”μ΄μŠ€/IoT ν™•μž₯"),
"33": ("INT-B3300", "κ²°ν•© ꡬ쑰 μž¬κ΅¬μ„±"),
"41": ("INT-B4100", "μž¬μ•½μ • κ²€ν† "),
"42": ("INT-B4200", "μž₯κΈ° 고객 ν˜œνƒ 확인"),
"43": ("INT-B4300", "κ²°ν•© μœ μ§€ 영ν–₯ 확인"),
"51": ("INT-B5100", "κ²½μŸμ‚¬ 비ꡐ"),
"52": ("INT-B5200", "ν˜œνƒ/λΉ„μš© 뢈만"),
"53": ("INT-B5300", "ν’ˆμ§ˆ 뢈만"),
"54": ("INT-B5400", "ν•΄μ§€ κ²€ν† "),
}
# ── L3 Intent μ •μ˜ ───────────────────────────────────────────
# 각 ν•­λͺ©:
# key : L3 μ½”λ“œ 3자리 (μ•ž 2μžλ¦¬κ°€ L2)
# name : Intent ν•œκΈ€λͺ…
# type : Rule | Model
# features : μΆ”λ‘  핡심 batch feature λͺ… (Index/Score)
# entities : 이 Intent둜 직접 μ‹ ν˜Έλ₯Ό μ£ΌλŠ” behavior entity (behavior_intents)
# push : μ•± Push 문ꡬ
# cc : (상황, μ•ˆλ‚΄) 상담사 μ»¨ν…μŠ€νŠΈ
# agent : AI Agent λ°œν™”
TAX: list[dict] = [
# ── L1=1 κ°€μž… ν™•λŒ€ ───────────────────────────────────────
dict(key="111", name="κ°€μ‘± κ²°ν•© κ°€λŠ₯ μ—¬λΆ€ 확인", type="Rule",
features=["family_line_count", "Bundle Opportunity Index"],
entities=["bundle_eligibility", "family_bundle"],
push="κ°€μ‘± κ²°ν•© μ‹œ 받을 수 μžˆλŠ” 할인 ν˜œνƒμ„ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("κ°€μ‘± κ²°ν•© κ°€λŠ₯ μ—¬λΆ€ 탐색", "κ°€μ‘± κ²°ν•© κ°€λŠ₯ 여뢀와 μ˜ˆμƒ 할인 κΈˆμ•‘μ„ μ•ˆλ‚΄"),
agent="κ°€μ‘± νšŒμ„ μ„ κ²°ν•©ν•˜λ©΄ μ–Όλ§ˆλ‚˜ μ ˆμ•½λ˜λŠ”μ§€ κ³„μ‚°ν•΄λ³ΌκΉŒμš”?"),
dict(key="112", name="인터넷/IPTV κ²°ν•© κ°€λŠ₯ μ—¬λΆ€ 확인", type="Rule",
features=["service_coverage_ratio", "Bundle Opportunity Index"],
entities=["internet_iptv_bundle"],
push="인터넷·TV κ²°ν•© μ‹œ μΆ”κ°€ ν˜œνƒμ„ 받을 수 μžˆμ–΄μš”",
cc=("인터넷/IPTV κ²°ν•© κ°€λŠ₯ μ—¬λΆ€ 탐색", "ν˜„μž¬ 이용 μƒν’ˆ κΈ°μ€€ κ²°ν•© κ°€λŠ₯ μƒν’ˆμ„ μ•ˆλ‚΄"),
agent="인터넷과 TVλ₯Ό ν•¨κ»˜ μ΄μš©ν•˜λ©΄ μ–΄λ–€ ν˜œνƒμ΄ μƒκΈ°λŠ”μ§€ μ•Œμ•„λ³ΌκΉŒμš”?"),
dict(key="113", name="ν˜„μž¬ μš”κΈˆμ œ 기반 κ²°ν•© κ°€λŠ₯ μ—¬λΆ€ 확인", type="Rule",
features=["plan_tier", "Bundle Opportunity Index"],
entities=[],
push="μ§€κΈˆ μš”κΈˆμ œλ‘œ 받을 수 μžˆλŠ” κ²°ν•© ν˜œνƒμ„ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("ν˜„μž¬ μš”κΈˆμ œ 기반 κ²°ν•© κ°€λŠ₯ μ—¬λΆ€ 확인", "ν˜„μž¬ μš”κΈˆμ œ κΈ°μ€€ 적용 κ°€λŠ₯ν•œ 결합을 μ•ˆλ‚΄"),
agent="μ§€κΈˆ μ“°μ‹œλŠ” μš”κΈˆμ œλ‘œ κ²°ν•©ν•˜λ©΄ μ–΄λ–€ ν˜œνƒμ΄ μžˆλŠ”μ§€ λ³ΌκΉŒμš”?"),
dict(key="121", name="할인 쀑심 κ²°ν•© μƒν’ˆ 탐색", type="Model",
features=["non_mobile_cost_gap", "Benefit Optimization Index"],
entities=["discount_calc", "total_bundle"],
push="할인 ν˜œνƒμ΄ 큰 κ²°ν•© μƒν’ˆμ„ μΆ”μ²œν•΄λ“œλ¦½λ‹ˆλ‹€",
cc=("할인 쀑심 κ²°ν•© μƒν’ˆ 탐색", "κ³ κ°λ‹˜ 쑰건에 λ§žλŠ” κ²°ν•© μƒν’ˆμ„ μ•ˆλ‚΄"),
agent="κ°€μž₯ μœ λ¦¬ν•œ κ²°ν•© μƒν’ˆμ„ ν•¨κ»˜ μ°Ύμ•„λ³ΌκΉŒμš”?"),
dict(key="122", name="데이터 ν˜œνƒ 쀑심 κ²°ν•© μƒν’ˆ 탐색", type="Model",
features=["content_view_mode", "Benefit Engagement Index"],
entities=[],
push="데이터 ν˜œνƒμ΄ 큰 κ²°ν•© μƒν’ˆμ„ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("데이터 ν˜œνƒ 쀑심 κ²°ν•© μƒν’ˆ 탐색", "데이터 ν™œμš©μ΄ λ§Žμ€ 고객 λŒ€μƒ 결합을 μ•ˆλ‚΄"),
agent="데이터λ₯Ό 더 λ„‰λ„‰νžˆ μ“Έ 수 μžˆλŠ” 결합을 μ°Ύμ•„λ³ΌκΉŒμš”?"),
dict(key="123", name="프리미엄 ν˜œνƒ 쀑심 κ²°ν•© μƒν’ˆ 탐색", type="Model",
features=["plan_tier", "Benefit Engagement Index"],
entities=[],
push="프리미엄 ν˜œνƒ 쀑심 κ²°ν•© μƒν’ˆμ„ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("프리미엄 ν˜œνƒ 쀑심 κ²°ν•© μƒν’ˆ 탐색", "μƒμœ„ μš”κΈˆμ œ 기반 프리미엄 결합을 μ•ˆλ‚΄"),
agent="프리미엄 ν˜œνƒκΉŒμ§€ ν¬ν•¨λœ 결합을 μ‚΄νŽ΄λ³ΌκΉŒμš”?"),
dict(key="131", name="μ‹ κ·œ κ²°ν•© κ°€μž… ν˜œνƒ 확인", type="Model",
features=["Bundle Opportunity Index", "Benefit Optimization Index"],
entities=["internet_signup_benefit"],
push="μ‹ κ·œ κ°€μž… 고객 μ „μš© ν˜œνƒμ„ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("μ‹ κ·œ κ°€μž… ν˜œνƒ 탐색", "ν˜„μž¬ κ°€μž… κ°€λŠ₯ν•œ ν˜œνƒμ„ μ•ˆλ‚΄"),
agent="κ°€μž… μ‹œ 받을 수 μžˆλŠ” ν˜œνƒμ„ μ •λ¦¬ν•΄λ³ΌκΉŒμš”?"),
dict(key="141", name="온라인 κ²°ν•© κ°€μž… κ²€ν† ", type="Rule",
features=["Bundle Opportunity Index", "Acquisition Score"],
entities=["bundle_apply"],
push="온라인으둜 κ°„νŽΈν•˜κ²Œ κ°€μž…ν•΄λ³΄μ„Έμš”",
cc=("온라인 κ°€μž… κ²€ν† ", "온라인 κ°€μž… 절차λ₯Ό μ•ˆλ‚΄"),
agent="κ°€μž…κΉŒμ§€ ν•„μš”ν•œ 단계λ₯Ό μ•ˆλ‚΄ν•΄λ“œλ¦΄κΉŒμš”?"),
dict(key="142", name="상담 기반 κ²°ν•© κ°€μž… κ²€ν† ", type="Rule",
features=["Bundle Opportunity Index", "Acquisition Score"],
entities=["support_consult", "bundle_apply"],
push="상담사와 ν•¨κ»˜ κ°€μž…μ„ μ§„ν–‰ν•΄λ³΄μ„Έμš”",
cc=("상담 기반 κ°€μž… κ²€ν†  (상담 μΈμž…)", "고객 쑰건 확인 ν›„ 맞좀 κ²°ν•© κ°€μž…μ„ μ•ˆλ‚΄"),
agent="상담사 μ—°κ²° 전에 ν•„μš”ν•œ 정보λ₯Ό 미리 μ •λ¦¬ν•΄λ“œλ¦΄κΉŒμš”?"),
dict(key="143", name="λ§€μž₯ λ°©λ¬Έ κ²°ν•© κ°€μž… κ²€ν† ", type="Model",
features=["Bundle Opportunity Index", "Acquisition Score"],
entities=[],
push="κ°€κΉŒμš΄ λ§€μž₯μ—μ„œ κ°€μž… 상담을 λ°›μ•„λ³΄μ„Έμš”",
cc=("λ§€μž₯ λ°©λ¬Έ κ°€μž… κ²€ν† ", "λ°©λ¬Έ κ°€λŠ₯ λ§€μž₯κ³Ό μ€€λΉ„ μ„œλ₯˜λ₯Ό μ•ˆλ‚΄"),
agent="λ°©λ¬Έ κ°€μž… μ‹œ ν•„μš”ν•œ 쀀비물을 μ•ˆλ‚΄ν•΄λ“œλ¦΄κΉŒμš”?"),
# ── L1=2 할인 μ΅œμ ν™” ─────────────────────────────────────
dict(key="211", name="ν˜„μž¬ κ²°ν•© ν˜œνƒ 확인", type="Rule",
features=["Benefit Engagement Index", "benefit_utilization"],
entities=["current_bundle_benefit"],
push="ν˜„μž¬ λ°›κ³  μžˆλŠ” 할인·결합 ν˜œνƒμ„ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("ν˜„μž¬ 적용 ν˜œνƒ 확인", "ν˜„μž¬ 적용 쀑인 할인 내역을 μ•ˆλ‚΄"),
agent="μ§€κΈˆ λ°›κ³  μžˆλŠ” ν˜œνƒμ„ ν•œ λ²ˆμ— μ •λ¦¬ν•΄λ“œλ¦΄κΉŒμš”?"),
dict(key="221", name="μΆ”κ°€ κ²°ν•© 할인 κ°€λŠ₯ μ—¬λΆ€ 확인", type="Rule",
features=["Benefit Optimization Index", "non_mobile_cost_gap"],
entities=["discount_calc"],
push="μΆ”κ°€λ‘œ 받을 수 μžˆλŠ” 할인 ν˜œνƒμ΄ μžˆλŠ”μ§€ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("μΆ”κ°€ ν˜œνƒ 탐색", "적용 κ°€λŠ₯ν•œ 할인 ν•­λͺ©μ„ μ•ˆλ‚΄"),
agent="ν˜„μž¬ μ‘°κ±΄μ—μ„œ μΆ”κ°€ 할인이 κ°€λŠ₯ν•œμ§€ ν™•μΈν•΄λ³ΌκΉŒμš”?"),
dict(key="231", name="데이터 ν˜œνƒ ν™œμš© κ²€ν† ", type="Model",
features=["Benefit Engagement Index", "content_view_mode"],
entities=[],
push="아직 ν™œμš©ν•˜μ§€ μ•Šμ€ 데이터 ν˜œνƒμ„ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("데이터 ν˜œνƒ ν™œμš© κ²€ν† ", "λ―Έν™œμš© 데이터 ν˜œνƒμ„ μ•ˆλ‚΄"),
agent="λ†“μΉ˜κ³  μžˆλŠ” 데이터 ν˜œνƒμ΄ μžˆλŠ”μ§€ ν•¨κ»˜ λ³ΌκΉŒμš”?"),
dict(key="234", name="λ―Έμ‚¬μš© κ²°ν•© ν˜œνƒ 확인", type="Rule",
features=["Benefit Engagement Index", "benefit_utilization"],
entities=["unused_benefit"],
push="아직 μ‚¬μš©ν•˜μ§€ μ•Šμ€ ν˜œνƒμ΄ μžˆμŠ΅λ‹ˆλ‹€",
cc=("λ―Έμ‚¬μš© ν˜œνƒ 확인", "λ―Έμ‚¬μš© ν˜œνƒμ„ 정리해 μ•ˆλ‚΄"),
agent="λ†“μΉ˜κ³  μžˆλŠ” ν˜œνƒμ΄ μžˆλŠ”μ§€ ν•¨κ»˜ ν™•μΈν•΄λ³ΌκΉŒμš”?"),
# ── L1=3 νšŒμ„ /μ„œλΉ„μŠ€ ν™•μž₯ ────────────────────────────────
dict(key="311", name="κ°€μ‘± νšŒμ„  μΆ”κ°€ κ²€ν† ", type="Rule",
features=["family_line_count", "Bundle Opportunity Index"],
entities=["family_bundle"],
push="κ°€μ‘± νšŒμ„ μ„ μΆ”κ°€ν•˜λ©΄ 할인 ν˜œνƒμ΄ 더 컀질 수 μžˆμ–΄μš”",
cc=("κ°€μ‘± νšŒμ„  μΆ”κ°€ κ²€ν† ", "κ°€μ‘± νšŒμ„  μΆ”κ°€ μ‹œ μ˜ˆμƒ ν˜œνƒμ„ μ•ˆλ‚΄"),
agent="κ°€μ‘± νšŒμ„ μ„ μΆ”κ°€ν•˜λ©΄ μ–Όλ§ˆλ‚˜ μ ˆμ•½λ˜λŠ”μ§€ κ³„μ‚°ν•΄λ³ΌκΉŒμš”?"),
dict(key="312", name="인터넷 κ²°ν•© μΆ”κ°€ κ²€ν† ", type="Rule",
features=["Home Service Expansion Index", "service_coverage_ratio"],
entities=["internet"],
push="인터넷 κ²°ν•© μ‹œ μΆ”κ°€ ν˜œνƒμ„ 받을 수 μžˆμ–΄μš”",
cc=("인터넷 κ²°ν•© μΆ”κ°€ κ²€ν† ", "인터넷 κ²°ν•© μƒν’ˆμ„ μ•ˆλ‚΄"),
agent="인터넷을 ν•¨κ»˜ μ΄μš©ν•˜λ©΄ μ–Όλ§ˆλ‚˜ μ ˆμ•½λ˜λŠ”μ§€ μ•Œμ•„λ³ΌκΉŒμš”?"),
dict(key="313", name="IPTV κ²°ν•© μΆ”κ°€ κ²€ν† ", type="Rule",
features=["Home Service Expansion Index", "content_view_mode"],
entities=["iptv"],
push="IPTV κ²°ν•© μ‹œ μ½˜ν…μΈ  ν˜œνƒμ„ 받을 수 μžˆμ–΄μš”",
cc=("IPTV κ²°ν•© μΆ”κ°€ κ²€ν† ", "IPTV κ²°ν•© μƒν’ˆκ³Ό μ½˜ν…μΈ  ν˜œνƒμ„ μ•ˆλ‚΄"),
agent="TVκΉŒμ§€ κ²°ν•©ν•˜λ©΄ μ–΄λ–€ μ½˜ν…μΈ  ν˜œνƒμ΄ μƒκΈ°λŠ”μ§€ λ³ΌκΉŒμš”?"),
dict(key="314", name="인터넷+IPTV 톡합 이용 κ²€ν† ", type="Rule",
features=["Home Service Expansion Index", "service_coverage_ratio"],
entities=["internet_iptv_bundle"],
push="인터넷+TV 톡합 κ²°ν•© ν˜œνƒμ„ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("인터넷+IPTV 톡합 이용 κ²€ν† ", "톡합 κ²°ν•© μ‹œ ν˜œνƒμ„ μ•ˆλ‚΄"),
agent="인터넷과 TVλ₯Ό 묢으면 μ–Όλ§ˆλ‚˜ μœ λ¦¬ν•œμ§€ λΉ„κ΅ν•΄λ³ΌκΉŒμš”?"),
dict(key="315", name="ν™ˆ WiFi μΆ”κ°€ κ²€ν† ", type="Rule",
features=["Home Service Expansion Index", "household_change"],
entities=["wifi"],
push="ν™ˆ WiFi μΆ”κ°€ μ‹œ 더 νŽΈλ¦¬ν•˜κ²Œ μ΄μš©ν•  수 μžˆμ–΄μš”",
cc=("ν™ˆ WiFi μΆ”κ°€ κ²€ν† ", "ν™ˆ WiFi κ²°ν•© ν˜œνƒμ„ μ•ˆλ‚΄"),
agent="ν™ˆ WiFiλ₯Ό μΆ”κ°€ν•˜λ©΄ μ–΄λ–€ 점이 μ’‹μ•„μ§€λŠ”μ§€ μ•Œλ €λ“œλ¦΄κΉŒμš”?"),
dict(key="321", name="μ›ŒμΉ˜ νšŒμ„  μΆ”κ°€ κ²€ν† ", type="Model",
features=["plan_tier", "Service Expansion Score"],
entities=[],
push="μ›ŒμΉ˜ μ „μš© νšŒμ„  ν˜œνƒμ„ μ•ˆλ‚΄ν•΄λ“œλ¦΄κ²Œμš”",
cc=("μ›ŒμΉ˜ νšŒμ„  μΆ”κ°€ κ²€ν† ", "μ›ŒμΉ˜ μ „μš© νšŒμ„  ν˜œνƒμ„ μ•ˆλ‚΄"),
agent="μŠ€λ§ˆνŠΈμ›ŒμΉ˜ μ—°κ²° μ‹œ 이용 κ°€λŠ₯ν•œ ν˜œνƒμ„ ν™•μΈν•΄λ³ΌκΉŒμš”?"),
dict(key="322", name="νƒœλΈ”λ¦Ώ κ²°ν•© μΆ”κ°€ κ²€ν† ", type="Model",
features=["plan_tier", "Service Expansion Score"],
entities=[],
push="νƒœλΈ”λ¦Ώ κ²°ν•© ν˜œνƒμ„ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("νƒœλΈ”λ¦Ώ κ²°ν•© μΆ”κ°€ κ²€ν† ", "νƒœλΈ”λ¦Ώ κ²°ν•© νšŒμ„  ν˜œνƒμ„ μ•ˆλ‚΄"),
agent="νƒœλΈ”λ¦Ώμ„ κ²°ν•©ν•˜λ©΄ μ–΄λ–€ ν˜œνƒμ΄ μžˆλŠ”μ§€ λ³ΌκΉŒμš”?"),
dict(key="323", name="μ„Έμ»¨λ“œ λ””λ°”μ΄μŠ€ μ—°κ²° κ²€ν† ", type="Model",
features=["plan_tier", "Service Expansion Score"],
entities=[],
push="μ„Έμ»¨λ“œ λ””λ°”μ΄μŠ€ μ—°κ²° ν˜œνƒμ„ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("μ„Έμ»¨λ“œ λ””λ°”μ΄μŠ€ μ—°κ²° κ²€ν† ", "μΆ”κ°€ λ””λ°”μ΄μŠ€ μ—°κ²° ν˜œνƒμ„ μ•ˆλ‚΄"),
agent="μΆ”κ°€ λ””λ°”μ΄μŠ€λ₯Ό μ—°κ²°ν•˜λ©΄ μ–΄λ–€ ν˜œνƒμ΄ μžˆλŠ”μ§€ μ•Œμ•„λ³ΌκΉŒμš”?"),
dict(key="331", name="κ°€μ‘± νšŒμ„  톡합 κ²€ν† ", type="Model",
features=["family_line_count", "Bundle Opportunity Index"],
entities=[],
push="κ°€μ‘± νšŒμ„ μ„ ν†΅ν•©ν•˜λ©΄ 더 μœ λ¦¬ν•œ 결합을 받을 수 μžˆμ–΄μš”",
cc=("κ°€μ‘± νšŒμ„  톡합 κ²€ν† ", "κ°€μ‘± νšŒμ„  톡합 μ‹œ κ²°ν•© ꡬ성을 μ•ˆλ‚΄"),
agent="κ°€μ‘± νšŒμ„ μ„ ν†΅ν•©ν•˜λ©΄ μ–΄λ–€ ν˜œνƒμ΄ μƒκΈ°λŠ”μ§€ λΉ„κ΅ν•΄λ³ΌκΉŒμš”?"),
dict(key="332", name="κ°€μ‘± νšŒμ„  뢄리 κ²€ν† ", type="Model",
features=["family_line_count", "household_change"],
entities=[],
push="κ°€μ‘± νšŒμ„  뢄리 μ‹œ λ³€λ™λ˜λŠ” ν˜œνƒμ„ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("κ°€μ‘± νšŒμ„  뢄리 κ²€ν† ", "νšŒμ„  뢄리 μ‹œ ν˜œνƒ 변동을 μ•ˆλ‚΄"),
agent="νšŒμ„ μ„ λΆ„λ¦¬ν•˜λ©΄ ν˜œνƒμ΄ μ–΄λ–»κ²Œ λ‹¬λΌμ§€λŠ”μ§€ ν™•μΈν•΄λ³ΌκΉŒμš”?"),
dict(key="333", name="λͺ…μ˜ λ³€κ²½ κ²€ν† ", type="Rule",
features=["household_change", "family_line_count"],
entities=[],
push="κ²°ν•© ꡬ쑰λ₯Ό λ³€κ²½ν•˜λ©΄ 더 μœ λ¦¬ν•œ ν˜œνƒμ„ 받을 수 μžˆμŠ΅λ‹ˆλ‹€",
cc=("λͺ…μ˜ λ³€κ²½ κ²€ν† ", "λͺ…μ˜ λ³€κ²½ κ°€λŠ₯ν•œ κ²°ν•© ꡬ성을 μ•ˆλ‚΄"),
agent="ν˜„μž¬ 상황에 맞게 결합을 λ‹€μ‹œ κ΅¬μ„±ν•΄λ³ΌκΉŒμš”?"),
dict(key="334", name="λŒ€ν‘œ νšŒμ„  λ³€κ²½ κ²€ν† ", type="Rule",
features=["household_change", "family_line_count"],
entities=[],
push="λŒ€ν‘œ νšŒμ„  λ³€κ²½ μ‹œ κ²°ν•© ν˜œνƒμ„ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("λŒ€ν‘œ νšŒμ„  λ³€κ²½ κ²€ν† ", "λŒ€ν‘œ νšŒμ„  λ³€κ²½ μ‹œ ν˜œνƒ 변동을 μ•ˆλ‚΄"),
agent="λŒ€ν‘œ νšŒμ„ μ„ λ°”κΎΈλ©΄ κ²°ν•© ν˜œνƒμ΄ μ–΄λ–»κ²Œ λ‹¬λΌμ§€λŠ”μ§€ λ³ΌκΉŒμš”?"),
dict(key="335", name="νšŒμ„  이동 κ²€ν† ", type="Model",
features=["household_change", "family_line_count"],
entities=[],
push="νšŒμ„  이동 μ‹œ κ²°ν•© ꡬ성을 ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("νšŒμ„  이동 κ²€ν† ", "νšŒμ„  이동 μ‹œ κ²°ν•© ꡬ성을 μ•ˆλ‚΄"),
agent="νšŒμ„ μ„ μ΄λ™ν•˜λ©΄ 결합이 μ–΄λ–»κ²Œ λ°”λ€ŒλŠ”μ§€ ν™•μΈν•΄λ³ΌκΉŒμš”?"),
# ── L1=4 μœ μ§€/락인 ───────────────────────────────────────
dict(key="411", name="κ²°ν•© μ•½μ • μƒνƒœΒ·μ—°μž₯ ν˜œνƒ 확인", type="Rule",
features=["contract_status", "Retention Readiness Index"],
entities=["contract_status"],
push="μ•½μ • μƒνƒœμ™€ μ—°μž₯ μ‹œ 받을 수 μžˆλŠ” ν˜œνƒμ„ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("μ•½μ • μƒνƒœ 및 μ—°μž₯ ν˜œνƒ 확인", "ν˜„μž¬ μ•½μ • μƒνƒœμ™€ μ—°μž₯ ν˜œνƒμ„ μ•ˆλ‚΄"),
agent="μ•½μ • μ—°μž₯ μ‹œ 받을 수 μžˆλŠ” ν˜œνƒμ„ μ •λ¦¬ν•΄λ“œλ¦΄κΉŒμš”?"),
dict(key="412", name="κ²°ν•© μž¬μ•½μ • ν˜œνƒ 비ꡐ", type="Model",
features=["Retention Readiness Index", "Benefit Engagement Index"],
entities=["renewal_benefit", "renewal_consult"],
push="μž¬μ•½μ • μ‹œ 받을 수 μžˆλŠ” ν˜œνƒμ„ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("μž¬μ•½μ • κ²€ν†  (상담 μΈμž…)", "ν˜„μž¬ μž¬μ•½μ • κ°€λŠ₯ ν˜œνƒμ„ 비ꡐ μ•ˆλ‚΄"),
agent="μž¬μ•½μ •κ³Ό ν˜„μž¬ 쑰건을 λΉ„κ΅ν•΄λ³ΌκΉŒμš”?"),
dict(key="421", name="κ²°ν•© μž₯κΈ° 고객 ν˜œνƒ 확인", type="Rule",
features=["tenure_group", "Retention Readiness Index"],
entities=["long_term_benefit"],
push="μž₯κΈ° 고객 μ „μš© ν˜œνƒμ„ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("μž₯κΈ° 고객 ν˜œνƒ 확인", "고객이 받을 수 μžˆλŠ” μž₯κΈ° ν˜œνƒμ„ μ•ˆλ‚΄"),
agent="μž₯κΈ° 이용 고객 ν˜œνƒμ„ μ •λ¦¬ν•΄λ“œλ¦΄κΉŒμš”?"),
dict(key="431", name="μš”κΈˆμ œ λ³€κ²½ μ‹œ κ²°ν•© 영ν–₯ 확인", type="Model",
features=["non_mobile_cost_gap", "Retention Readiness Index"],
entities=[],
push="μš”κΈˆμ œ λ³€κ²½ μ‹œ κ²°ν•© ν˜œνƒ 변동을 ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("μš”κΈˆμ œ λ³€κ²½ 영ν–₯ 확인", "μš”κΈˆμ œ λ³€κ²½ μ‹œ κ²°ν•© ν˜œνƒ 변동을 μ•ˆλ‚΄"),
agent="μš”κΈˆμ œλ₯Ό λ°”κΎΈλ©΄ κ²°ν•© ν˜œνƒμ— μ–΄λ–€ 영ν–₯이 μžˆλŠ”μ§€ λ³ΌκΉŒμš”?"),
dict(key="432", name="κ²°ν•© ν•΄μ§€ 영ν–₯ 확인", type="Rule",
features=["Retention Readiness Index", "Churn Risk Index"],
entities=["penalty"],
push="κ²°ν•© ν•΄μ§€ μ‹œ λ³€κ²½λ˜λŠ” ν˜œνƒμ„ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("κ²°ν•© μœ μ§€ 영ν–₯ 확인", "κ²°ν•© ν•΄μ§€ μ‹œ λ³€λ™λ˜λŠ” 할인 ν˜œνƒμ„ μ•ˆλ‚΄"),
agent="결합을 ν•΄μ§€ν•˜λ©΄ μ–΄λ–€ 영ν–₯이 μžˆλŠ”μ§€ λΉ„κ΅ν•΄λ³ΌκΉŒμš”?"),
# ── L1=5 μ΄νƒˆ κ²€ν†  ───────────────────────────────────────
dict(key="511", name="타사 κ²°ν•© ν˜œνƒ/가격 비ꡐ", type="Model",
features=["Churn Risk Index", "non_mobile_cost_gap"],
entities=["competitor_compare"],
push="ν˜„μž¬ ν˜œνƒκ³Ό 타사 ν˜œνƒμ„ λΉ„κ΅ν•΄λ³΄μ„Έμš”",
cc=("κ²½μŸμ‚¬ 비ꡐ", "κ²½μŸμ‚¬ μƒν’ˆκ³Ό 비ꡐ μ•ˆλ‚΄"),
agent="ν˜„μž¬ ν˜œνƒκ³Ό 타사 ν˜œνƒμ„ λ‚˜λž€νžˆ λΉ„κ΅ν•΄λ³ΌκΉŒμš”?"),
dict(key="512", name="λ²ˆν˜Έμ΄λ™ 기반 ν˜œνƒ 비ꡐ", type="Rule",
features=["Churn Risk Index", "contract_status"],
entities=[],
push="λ²ˆν˜Έμ΄λ™ μ‹œ 받을 수 μžˆλŠ” ν˜œνƒμ„ λΉ„κ΅ν•΄λ³΄μ„Έμš”",
cc=("λ²ˆν˜Έμ΄λ™ 기반 ν˜œνƒ 비ꡐ", "λ²ˆν˜Έμ΄λ™ μ‹œ ν˜œνƒμ„ 비ꡐ μ•ˆλ‚΄"),
agent="λ²ˆν˜Έμ΄λ™ μ‹œ ν˜œνƒμ„ ν˜„μž¬μ™€ λΉ„κ΅ν•΄λ³ΌκΉŒμš”?"),
dict(key="521", name="κ²°ν•© ν˜œνƒ λΆ€μ‘± 체감", type="Model",
features=["dissatisfaction_factor", "Benefit Optimization Index"],
entities=[],
push="더 받을 수 μžˆλŠ” ν˜œνƒμ΄ μžˆλŠ”μ§€ ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("ν˜œνƒ λΆ€μ‘± 체감", "μΆ”κ°€ 적용 κ°€λŠ₯ν•œ ν˜œνƒμ„ μ•ˆλ‚΄"),
agent="μ§€κΈˆ 받을 수 μžˆλŠ” ν˜œνƒμ„ ν•œ λ²ˆμ— μ •λ¦¬ν•΄λ“œλ¦΄κΉŒμš”?"),
dict(key="522", name="κ²°ν•© μœ μ§€ κ°€μΉ˜ ν•˜λ½", type="Model",
features=["dissatisfaction_factor", "Retention Readiness Index"],
entities=[],
push="κ²°ν•© μœ μ§€ μ‹œ 받을 수 μžˆλŠ” κ°€μΉ˜λ₯Ό ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("κ²°ν•© μœ μ§€ κ°€μΉ˜ ν•˜λ½", "κ²°ν•© μœ μ§€ κ°€μΉ˜λ₯Ό μž¬μ•ˆλ‚΄"),
agent="결합을 μœ μ§€ν•˜λ©΄ μ–΄λ–€ 점이 μœ λ¦¬ν•œμ§€ λ‹€μ‹œ μ •λ¦¬ν•΄λ“œλ¦΄κΉŒμš”?"),
dict(key="523", name="κ²°ν•© 톡신비 λΆ€λ‹΄ 증가", type="Model",
features=["non_mobile_cost_gap", "dissatisfaction_factor"],
entities=[],
push="톡신비λ₯Ό 쀄일 수 μžˆλŠ” 방법을 ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("톡신비 λΆ€λ‹΄ 증가", "λΉ„μš© 뢀담을 쀄일 수 μžˆλŠ” μƒν’ˆμ„ μ•ˆλ‚΄"),
agent="μ§€κΈˆλ³΄λ‹€ 톡신비λ₯Ό μ ˆμ•½ν•  수 μžˆλŠ” 방법을 μ°Ύμ•„λ³ΌκΉŒμš”?"),
dict(key="531", name="인터넷 ν’ˆμ§ˆ 뢈만", type="Rule",
features=["dissatisfaction_factor", "Churn Risk Index"],
entities=[],
push="인터넷 ν’ˆμ§ˆ κ°œμ„  방법을 ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("인터넷 ν’ˆμ§ˆ 뢈만", "ν˜„μž¬ 인터넷 ν’ˆμ§ˆ μƒνƒœλ₯Ό 점검 μ•ˆλ‚΄"),
agent="인터넷 이용 ν™˜κ²½μ„ ν•¨κ»˜ μ κ²€ν•΄λ³ΌκΉŒμš”?"),
dict(key="532", name="IPTV ν’ˆμ§ˆ 뢈만", type="Rule",
features=["dissatisfaction_factor", "Churn Risk Index"],
entities=[],
push="IPTV ν’ˆμ§ˆ κ°œμ„  방법을 ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("IPTV ν’ˆμ§ˆ 뢈만", "IPTV ν’ˆμ§ˆ μƒνƒœλ₯Ό 점검 μ•ˆλ‚΄"),
agent="TV 이용 ν™˜κ²½μ„ ν•¨κ»˜ μ κ²€ν•΄λ³ΌκΉŒμš”?"),
dict(key="533", name="λͺ¨λ°”일 데이터 ν’ˆμ§ˆ 뢈만", type="Model",
features=["dissatisfaction_factor", "Churn Risk Index"],
entities=[],
push="λͺ¨λ°”일 데이터 ν’ˆμ§ˆ κ°œμ„  방법을 ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("λͺ¨λ°”일 데이터 ν’ˆμ§ˆ 뢈만", "데이터 ν’ˆμ§ˆ μƒνƒœλ₯Ό 점검 μ•ˆλ‚΄"),
agent="데이터 이용 ν™˜κ²½μ„ ν•¨κ»˜ μ κ²€ν•΄λ³ΌκΉŒμš”?"),
dict(key="541", name="κ²°ν•© ν•΄μ§€ 절차 확인", type="Rule",
features=["Churn Risk Index", "Retention Readiness Index"],
entities=["cancel_process", "penalty"],
push="ν•΄μ§€ μ „ μ ˆμ°¨μ™€ 변동 ν˜œνƒμ„ 미리 ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("ν•΄μ§€ κ²€ν† ", "ν•΄μ§€ μ ˆμ°¨μ™€ ν•΄μ§€ μ‹œ 변동 사항을 μ•ˆλ‚΄"),
agent="ν•΄μ§€ μ‹œ λ³€κ²½λ˜λŠ” 뢀뢄을 미리 μ •λ¦¬ν•΄λ“œλ¦΄κΉŒμš”?"),
dict(key="542", name="κ²°ν•© ν•΄μ§€ μœ„μ•½κΈˆ 확인", type="Rule",
features=["Churn Risk Index", "contract_status"],
entities=["penalty"],
push="ν•΄μ§€ μ „ μœ„μ•½κΈˆ 정보λ₯Ό 미리 ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("μœ„μ•½κΈˆ 확인", "ν•΄μ§€ μ‹œ λ°œμƒ κ°€λŠ₯ν•œ μœ„μ•½κΈˆμ„ μ•ˆλ‚΄"),
agent="μ§€κΈˆ ν•΄μ§€ν•˜λ©΄ μœ„μ•½κΈˆμ΄ μ–Όλ§ˆλ‚˜ λ°œμƒν•˜λŠ”μ§€ ν™•μΈν•΄λ³ΌκΉŒμš”?"),
dict(key="543", name="κ²°ν•© ν•΄μ§€ μ‹œ μž”μ—¬ νšŒμ„  영ν–₯ 확인", type="Rule",
features=["Churn Risk Index", "Retention Readiness Index"],
entities=[],
push="ν•΄μ§€ μ‹œ λ³€λ™λ˜λŠ” ν˜œνƒκ³Ό 영ν–₯을 ν™•μΈν•΄λ³΄μ„Έμš”",
cc=("ν•΄μ§€ 영ν–₯ 확인", "ν•΄μ§€ μ‹œ λ³€λ™λ˜λŠ” κ²°ν•© ν˜œνƒμ„ μ•ˆλ‚΄"),
agent="ν•΄μ§€ν•˜λ©΄ μ–΄λ–€ ν˜œνƒμ΄ μ‚¬λΌμ§€λŠ”μ§€ λΉ„κ΅ν•΄λ³ΌκΉŒμš”?"),
]
def _l1_of(key: str) -> str:
return key[0]
def _l2_of(key: str) -> str:
return key[:2]
def build_intents() -> dict:
intents = []
for t in TAX:
key = t["key"]
l1_id, l1_name = L1[_l1_of(key)]
l2_id, l2_name = L2[_l2_of(key)]
intents.append({
"id": f"INT-B{key}0",
"name": t["name"],
"L1_id": l1_id,
"L1_name": l1_name,
"L2_id": l2_id,
"L2_name": l2_name,
"inference_type": t["type"],
"features": t["features"],
})
return {
"scenario_id": SCENARIO_ID,
"version": "0.1.0",
"description": "κ²°ν•© μƒν’ˆ ν™œμ„±ν™” μ‹œλ‚˜λ¦¬μ˜€ Intent Taxonomy",
"intents": intents,
}
CHANNELS = [
{"id": "push", "name": "μ•± Push", "icon": "πŸ“±",
"characteristic": "κ³ κ°μ—κ²Œ 직접 λ…ΈμΆœλ˜λŠ” μ•Œλ¦Ό λ©”μ‹œμ§€ β€” 행동 μœ λ„Β·ν˜œνƒ μ•ˆλ‚΄"},
{"id": "call_center", "name": "고객센터 상담사 μ»¨ν…μŠ€νŠΈ", "icon": "πŸ“ž",
"characteristic": "μ½œΒ·μ±„νŒ… μΈμž… μ‹œ 상담사 ν™”λ©΄ μ»¨ν…μŠ€νŠΈ β€” 상황 + μ•ˆλ‚΄ κ°€μ΄λ“œ(고객 λŒ€μƒ λ¬Έμž₯ μ•„λ‹˜)"},
{"id": "agent", "name": "AI Agent", "icon": "πŸ€–",
"characteristic": "AI Agentκ°€ κ³ κ°μ—κ²Œ λ˜μ§€λŠ” κ°œμΈν™” μ œμ•ˆΒ·λΉ„κ΅Β·λΆ„μ„ λ°œν™”"},
]
def build_actions() -> dict:
actions = {}
for t in TAX:
iid = f"INT-B{t['key']}0"
situation, guidance = t["cc"]
actions[iid] = {
"push": t["push"],
"call_center": {"situation": situation, "guidance": guidance},
"agent": t["agent"],
}
return {
"scenario_id": SCENARIO_ID,
"version": "0.1.0",
"description": "κ²°ν•© μ‹œλ‚˜λ¦¬μ˜€ Intent별 3채널 ν™œμš© μ˜ˆμ‹œ",
"channels": CHANNELS,
"actions": actions,
}
# Step1(λͺ©μ ν˜•) behavior entity β†’ λŒ€ν‘œ L3 Intent κ·Έλ£Ή.
# Step1 클릭도 μ˜λ„λ₯Ό λŒμ–΄μ˜¬λ¦¬λ„λ‘(behaviors.json step1 entity 컀버).
STEP1_ENTITY_INTENTS = {
"benefit_check": ["INT-B2110", "INT-B2210", "INT-B2340"],
"bundle_discount_check": ["INT-B1110", "INT-B1210", "INT-B3110"],
"home_service_explore": ["INT-B1120", "INT-B3120", "INT-B3130", "INT-B3140"],
"contract_benefit_check": ["INT-B4110", "INT-B4120", "INT-B4210"],
"competitor_explore": ["INT-B5110", "INT-B5410", "INT-B5420"],
}
def build_behavior_intents() -> dict:
entity_intents: dict[str, list[str]] = {}
for t in TAX:
iid = f"INT-B{t['key']}0"
for ent in t["entities"]:
entity_intents.setdefault(ent, []).append(iid)
# Step1 λͺ©μ ν˜• entity λ§€ν•‘ 병합
for ent, iids in STEP1_ENTITY_INTENTS.items():
entity_intents.setdefault(ent, [])
for iid in iids:
if iid not in entity_intents[ent]:
entity_intents[ent].append(iid)
# behaviors.json 곡톡(BACK/EXIT) entityλŠ” 무효과
entity_intents.setdefault("back_to_step1", [])
entity_intents.setdefault("session_end", [])
return {
"scenario_id": SCENARIO_ID,
"version": "0.1.0",
"description": "κ²°ν•© behaviors.json entity β†’ 직접 μ‹ ν˜Έ Intent λ§€ν•‘",
"entity_intents": entity_intents,
}
def main() -> None:
emit_layers(
OUT_DIR / "engine",
taxonomy=build_intents(),
context_library=build_actions(),
behavior_signals=build_behavior_intents()["entity_intents"],
)
# μš”μ•½
intents = build_intents()["intents"]
from collections import Counter
print("\n── L1 뢄포 ──")
for (lid, lname), c in sorted(Counter((i["L1_id"], i["L1_name"]) for i in intents).items()):
print(f" {lid} {lname}: {c}")
print("── inference_type ──")
print(" ", Counter(i["inference_type"] for i in intents))
bi = build_behavior_intents()["entity_intents"]
print(f"── behavior entities mapped: {len([k for k,v in bi.items() if v])} ──")
if __name__ == "__main__":
main()