File size: 3,176 Bytes
590e3b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from __future__ import annotations
"""
์ง์žฅ์ธ(worker-v3) Intent ๋ถ„ํฌ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ (๋กœ์ง ๊ณ ๋„ํ™”์šฉ).

ํŽ˜๋ฅด์†Œ๋‚˜๊ฐ€ ์„ค๋ฌธ ์‘๋‹ตยท์•ฑ ์„ ํƒ(๋‹จ์ผ์„ ํƒ, app_open)์„ ํ–ˆ์„ ๋•Œ ๊ธฐ๋Œ€ intent(expected_intents)๊ฐ€
์ƒ์œ„ ๋ถ„ํฌ์— ๋œจ๋Š”์ง€ ์ ์ˆ˜ํ™”. intent๊ฐ€ 9๊ฐœ๋ฟ์ด๋ผ cov@3/cov@5 + avg_rank(/9) ์‚ฌ์šฉ.

์‹คํ–‰: python scripts/sim_worker.py [--behavior]
"""
import argparse
import random
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parent.parent))

from core.engines import config                              # noqa: E402
from core.extractor import get_extractor                     # noqa: E402
from core.inference import infer_batch, infer_with_behavior  # noqa: E402
from scripts.build_worker_dataset import PERSONAS            # noqa: E402

SID = "worker-v3"
N_INTENTS = len(config.get_taxonomy(SID)["intents"])


def _sample_answers(answer_dist: dict, rng: random.Random) -> dict[str, str]:
    return {qid: rng.choices(list(d), weights=list(d.values()), k=1)[0] for qid, d in answer_dist.items()}


def _rank_of(scores: list, intent_id: str) -> int:
    for s in scores:
        if s.intent_id == intent_id:
            return s.rank
    return 999


def run(use_behavior: bool, k: int = 40, seed: int = 7) -> None:
    """ํŽ˜๋ฅด์†Œ๋‚˜๋งˆ๋‹ค k๋ช… ์ƒ˜ํ”Œ๋ง โ†’ cov@3/cov@5ยทavg_rank(/9) ํ‰๊ท ."""
    ext = get_extractor()
    rng = random.Random(seed)
    p3, p5, rank_all = [], [], []
    for p in PERSONAS:
        expected = p["expected_intents"]
        c3s, c5s, rks = [], [], []
        for j in range(k):
            answers = _sample_answers(p["answer_dist"], rng)
            if use_behavior:
                seq = rng.choice(p["app_seqs"])             # ๋‹จ์ผ์„ ํƒ ์•ฑ entity ์‹œํ€€์Šค
                sess = f"__w__{p['id']}_{j}"
                ext.reset(sess)
                for ent in seq:
                    ext.add_event(sess, "app_open", ent)
                _, scores = infer_with_behavior(answers, sess, SID)
                ext.reset(sess)
            else:
                _, scores = infer_batch(answers, SID)
            top = [s.intent_id for s in sorted(scores, key=lambda s: s.final_score, reverse=True)]
            t3, t5 = set(top[:3]), set(top[:5])
            c3s.append(sum(1 for e in expected if e in t3) / len(expected))
            c5s.append(sum(1 for e in expected if e in t5) / len(expected))
            rks.extend(_rank_of(scores, e) for e in expected)
        cov3, cov5 = sum(c3s) / k, sum(c5s) / k
        p3.append(cov3); p5.append(cov5); rank_all.extend(rks)
        print(f"   {p['id']} {p['name'][:24]:24} cov@3={cov3:.2f} cov@5={cov5:.2f} "
              f"avg_rank={sum(rks)/len(rks):4.1f} (exp={expected})")
    n = len(PERSONAS)
    print("=" * 70)
    print(f"  ์ „์ฒด ํ‰๊ท   cov@3={sum(p3)/n:.3f}  cov@5={sum(p5)/n:.3f}  "
          f"avg_rank={sum(rank_all)/len(rank_all):.2f}/{N_INTENTS}  "
          f"({'ํ–‰๋™๋ฐ˜์˜' if use_behavior else '์„ค๋ฌธ๋งŒ'}, k={k})")
    print("=" * 70)


if __name__ == "__main__":
    ap = argparse.ArgumentParser()
    ap.add_argument("--behavior", action="store_true")
    args = ap.parse_args()
    run(args.behavior)