File size: 5,410 Bytes
52204de | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | from __future__ import annotations
"""
κ²°ν©(bundle-v3) off-persona κ°κ±΄μ± κ²μ¦.
νλ₯΄μλμ λ§€μ΄μ§ μμ 무μμ/μμ μ€λ¬Έ μλ΅μμλ
A. μ΄κΈ° λΆν¬κ° μλ΅(νλ‘ν)μ ν©λ¦¬μ μΌλ‘ λ°μνλκ°
B. κ° νλμ΄ κ·Έ νλμ κ΄λ ¨ intentλ₯Ό λμ΄μ¬λ¦¬λκ° (μλ λ³νμ ν΄μκ°λ₯μ±)
λ₯Ό μ λΒ·μ μ±μΌλ‘ νμΈνλ€.
μ€ν: python scripts/sim_offpersona.py
"""
import random
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
from core.engines import config, get_engine # noqa: E402
from core.extractor import get_extractor # noqa: E402
from core.inference import infer_batch, infer_with_behavior # noqa: E402
from scripts.sim_bundle import _behavior_map, _intent_names, _rank_of, SID # noqa: E402
def _random_answers(rng: random.Random) -> dict[str, str]:
"""λͺ¨λ λ¬Ένμ μ΅μ
μ€ κ· λ± λ¬΄μμλ‘ (νλ₯΄μλ 무κ΄)."""
survey = config.get_survey(SID)
out = {}
for q in survey["questions"]:
out[q["id"]] = rng.choice([o["code"] for o in q["options"]])
return out
def _rank(scores, iid: str) -> int:
return _rank_of(scores, iid)
# ββ B. νλ μλ΅μ±: 무μμ νλ‘ν à 무μμ λ¨μΌ νλ βββββββββββββ
def behavior_responsiveness(k: int = 300, seed: int = 11) -> None:
rng = random.Random(seed)
bmap = _behavior_map()
sig = config.get_behavior_signals(SID)
# μ νΈλ₯Ό κ°μ§ entityλ§ (back/exit μ μΈ)
actable = [(bid, et, en) for bid, (et, en) in bmap.items()
if sig.get(en) and et not in ("navigate_back", "app_exit")]
ext = get_extractor()
rose, in_top5, total = 0, 0, 0
for i in range(k):
ans = _random_answers(rng)
bid, et, en = rng.choice(actable)
targets = sig[en]
sess = f"__off_{i}"
ext.reset(sess)
ext.add_event(sess, et, en)
_, scores = infer_with_behavior(ans, sess, SID)
ext.reset(sess)
smap = {s.intent_id: s for s in scores}
for t in targets:
s = smap.get(t)
if s is None:
continue
total += 1
if s.rank_change > 0: # baseline λλΉ μμ μμΉ
rose += 1
if s.rank <= 5:
in_top5 += 1
print("ββ B. νλ μλ΅μ± (무μμ νλ‘ν à 무μμ νλ, k=%d) ββ" % k)
print(f" ν΄λ¦ν νλμ κ΄λ ¨ intentκ° baseline λλΉ μμ μμΉ: {rose/total*100:.1f}%")
print(f" ν΄λ¦ ν κ·Έ intentκ° Top-5 μ§μ
: {in_top5/total*100:.1f}%")
# ββ A. μ΄κΈ° λΆν¬μ νλ‘ν λ°μ (λμ‘° νλ‘ν) ββββββββββββββββββββ
def initial_reflects_profile() -> None:
names = _intent_names()
eng = get_engine(SID)
# μλμ μΌλ‘ λμ‘°λλ μμ νλ‘ν (νλ₯΄μλ μ μ μλ)
profiles = {
"μ½μ λ§λ£+νμ§λΆλ§(μ΄νμ§ν)": {"Q1":"A","Q2":"D","Q3":"C","Q4":"A","Q5":"C","Q6":"A","Q7":"C","Q8":"C","Q9":"D","Q10":"A","Q11":"C","Q12":"A"},
"κ²°ν©λ―Έλ³΄μ +κ°μ‘±ε€(νμ₯μ¬μ§)": {"Q1":"B","Q2":"B","Q3":"C","Q4":"C","Q5":"A","Q6":"C","Q7":"A","Q8":"A","Q9":"B","Q10":"B","Q11":"F","Q12":"C"},
"ννμ νΈ+ν리미μ(VIP)": {"Q1":"A","Q2":"C","Q3":"D","Q4":"B","Q5":"C","Q6":"A","Q7":"C","Q8":"B","Q9":"D","Q10":"C","Q11":"F","Q12":"C"},
"μ κ°+λΉμ©λ―Όκ°": {"Q1":"B","Q2":"B","Q3":"A","Q4":"A","Q5":"A","Q6":"A","Q7":"B","Q8":"A","Q9":"A","Q10":"A","Q11":"A","Q12":"D"},
}
print("\nββ A. μ΄κΈ° λΆν¬μ νλ‘ν λ°μ (μμ λμ‘° νλ‘ν) ββ")
for label, ans in profiles.items():
_, scores = infer_batch(ans, SID)
top = sorted(scores, key=lambda s: s.final_score, reverse=True)[:5]
print(f" [{label}] Top-5: " + ", ".join(f"{s.intent_id} {names[s.intent_id][:12]}" for s in top))
# ββ B2. λ¨μΌ μμ νλ‘νμ νλλ³ λ³ν walkthrough ββββββββββββββ
def walkthrough() -> None:
names = _intent_names()
bmap = _behavior_map()
sig = config.get_behavior_signals(SID)
ext = get_extractor()
ans = {"Q1":"A","Q2":"C","Q3":"C","Q4":"B","Q5":"B","Q6":"A","Q7":"B","Q8":"B","Q9":"C","Q10":"B","Q11":"F","Q12":"C"} # μ€λ¦½μ μμ
seq = ["1-B", "2-B1", "1-C", "2-C2", "1-D", "2-D3"] # κ²°ν©μ‘°νβκ°μ‘±κ²°ν©βννμβIPTVβμ½μ βμ¬μ½μ νν
print("\nββ B2. μμ νλ‘ν νλ walkthrough (νλλ§λ€ μμΉ intent) ββ")
_, base = infer_batch(ans, SID)
base_rank = {s.intent_id: s.rank for s in base}
sess = "__walk"; ext.reset(sess)
for bid in seq:
et, en = bmap.get(bid, (None, None))
if not et:
continue
ext.add_event(sess, et, en)
_, sc = infer_with_behavior(ans, sess, SID)
risers = sorted(sc, key=lambda s: s.rank_change, reverse=True)[:3]
tgt = sig.get(en, [])
print(f" click {bid}({en}) β μ νΈ={tgt}")
print(" μ΅λ μμΉ: " + ", ".join(f"{s.intent_id} {names[s.intent_id][:10]}(β{s.rank_change},#{s.rank})" for s in risers))
ext.reset(sess)
if __name__ == "__main__":
behavior_responsiveness()
initial_reflects_profile()
walkthrough()
|