Omkar1806 commited on
Commit
ddcd2b0
·
verified ·
1 Parent(s): ed290d7

Update inference.py

Browse files
Files changed (1) hide show
  1. inference.py +46 -177
inference.py CHANGED
@@ -1,189 +1,58 @@
1
- """
2
- inference.py — OpenEnv Baseline Inference Script
3
- =================================================
4
- Runs the rule-based classifier against all three tasks defined in
5
- openenv.yaml and reports per-task scores in the 0.0 → 1.0 range.
6
-
7
- This script proves reproducibility for the hackathon submission.
8
- Run it with:
9
- python inference.py
10
-
11
- Expected output:
12
- Task 1 [EASY] — Spam Detection : 1.000 ✅
13
- Task 2 [MEDIUM] — Support Routing : 0.950 ✅
14
- Task 3 [HARD] — Phishing / Security : 0.900 ✅
15
- Overall Score : 0.950
16
- """
17
-
18
  import numpy as np
19
- from env import (
20
- EmailTriageEnv,
21
- EmailAction,
22
- TASK_SPLITS,
23
- URGENCY_LABELS,
24
- ROUTING_LABELS,
25
- RESOLUTION_LABELS,
26
- )
27
-
28
- # ── Rule-based classifier (your 95%-accuracy agent) ───────────────────────────
29
-
30
- _LEGAL_SECURITY_KW = {"lawsuit", "attorney", "sue", "ransomware", "extortion"}
31
- _BILLING_ESCALATE_KW = {"refund"}
32
 
33
-
34
- def _classify(email: dict) -> np.ndarray:
35
- """
36
- Deterministic rule-based classifier.
37
- Returns np.ndarray([urgency, routing, resolution]).
38
- """
39
- kw = set(email.get("keywords", []))
40
  context = email.get("context", "").lower()
41
-
42
- if context == "legal" or kw & {"lawsuit", "attorney", "sue"}:
 
43
  return np.array([2, 2, 2], dtype=np.int64)
44
-
45
  if context == "security":
46
- if kw & _LEGAL_SECURITY_KW or ("hacked" in kw and "breach" in kw):
47
- return np.array([2, 2, 2], dtype=np.int64)
48
  return np.array([2, 1, 2], dtype=np.int64)
49
-
50
  if context == "billing":
51
- if kw & _BILLING_ESCALATE_KW:
52
- return np.array([1, 2, 2], dtype=np.int64)
53
  return np.array([1, 0, 1], dtype=np.int64)
54
-
55
- if context == "tech" or kw & {"crash", "error", "bug", "slow"}:
56
- return np.array([0, 1, 1], dtype=np.int64)
57
-
58
  return np.array([0, 0, 0], dtype=np.int64)
59
 
60
-
61
- # ── Per-task runner ───────────────────────────────────────────────────────────
62
-
63
- def run_task(task: str, verbose: bool = False) -> float:
64
- """
65
- Run one full episode on the given task using the rule-based classifier.
66
- Returns the normalised cumulative score in [0.0, 1.0].
67
- """
68
- env = EmailTriageEnv(task=task, shuffle=False)
69
- obs, info = env.reset(seed=42)
70
-
71
- email_queue = list(env._queue) # snapshot before any steps
72
- cumulative_score = 0.0
73
- step = 0
74
- terminated = False
75
-
76
- task_labels = {
77
- "easy": "Task 1 [EASY] — Spam Detection ",
78
- "medium": "Task 2 [MEDIUM] Support Routing ",
79
- "hard": "Task 3 [HARD] — Phishing / Security ",
80
- }
81
-
82
- if verbose:
83
- print(f"\n {'─' * 58}")
84
- print(f" {task_labels.get(task, task.upper())}")
85
- print(f" {'─' * 58}")
86
-
87
- while not terminated:
88
- current_email = email_queue[step]
89
- action = _classify(current_email)
90
-
91
- obs, norm_reward, terminated, _, info = env.step(action)
92
- cumulative_score += norm_reward
93
-
94
- if verbose:
95
- ca = info["correct_actions"]
96
- raw = info["raw_reward"]
97
-
98
- pred_str = (f"{URGENCY_LABELS[action[0]]} | "
99
- f"{ROUTING_LABELS[action[1]]} | "
100
- f"{RESOLUTION_LABELS[action[2]]}")
101
- corr_str = (f"{URGENCY_LABELS[ca[0]]} | "
102
- f"{ROUTING_LABELS[ca[1]]} | "
103
- f"{RESOLUTION_LABELS[ca[2]]}")
104
-
105
- if raw >= 1.0:
106
- verdict = "✅ EXACT"
107
- elif raw > 0:
108
- verdict = "🔶 PARTIAL"
109
- elif raw < 0:
110
- verdict = "🚨 SECURITY MISS"
111
- else:
112
- verdict = "❌ WRONG"
113
-
114
- print(f" #{step+1:02d} [{current_email['difficulty'].upper():<6}] "
115
- f"{current_email['description'][:35]:<35} "
116
- f"reward={raw:+.1f} {verdict}")
117
- if raw < 1.0:
118
- print(f" Predicted : {pred_str}")
119
- print(f" Correct : {corr_str}")
120
-
121
- step += 1
122
-
123
- # Clamp to [0.0, 1.0] — penalties can push below 0
124
- final_score = max(0.0, min(1.0, cumulative_score))
125
-
126
- env_state = env.state()
127
- assert env_state.terminated, "Episode should be terminated after all steps"
128
-
129
- return final_score
130
-
131
-
132
- # ── Main ──────────────────────────────────────────────────────────────────────
133
-
134
- def main():
135
- print(f"\n{'═' * 62}")
136
- print(" EMAIL GATEKEEPER — OpenEnv Baseline Inference")
137
- print(" Meta x PyTorch Hackathon | Reproducibility Report")
138
- print(f"{'═' * 62}")
139
-
140
- tasks = [
141
- ("easy", "Task 1 [EASY] — Spam Detection "),
142
- ("medium", "Task 2 [MEDIUM] — Support Routing "),
143
- ("hard", "Task 3 [HARD] — Phishing / Security "),
144
- ]
145
-
146
- scores = {}
147
- all_correct = 0
148
- all_total = 0
149
-
150
- for task_id, label in tasks:
151
- score = run_task(task_id, verbose=True)
152
- scores[task_id] = score
153
-
154
- n = len(TASK_SPLITS[task_id])
155
- all_total += n
156
-
157
- icon = "✅" if score >= 0.8 else ("⚠️ " if score >= 0.5 else "❌")
158
- print(f"\n {label}: {score:.3f} {icon}")
159
-
160
- # Overall score = weighted average by number of emails per task
161
- weights = {t: len(TASK_SPLITS[t]) for t in scores}
162
- total_weight = sum(weights.values())
163
- overall = sum(scores[t] * weights[t] / total_weight for t in scores)
164
-
165
- print(f"\n{'─' * 62}")
166
- print(f" {'Overall Score (weighted avg)':<42}: {overall:.3f}")
167
- print(f" {'Total Emails Evaluated':<42}: {total_weight}")
168
-
169
- # Per-task summary table
170
- print(f"\n {'Task':<10} {'Emails':>7} {'Score':>8} {'Status':>10}")
171
- print(f" {'─'*10} {'─'*7} {'─'*8} {'─'*10}")
172
- for task_id, label in tasks:
173
- n = len(TASK_SPLITS[task_id])
174
- s = scores[task_id]
175
- status = "PASS ✅" if s >= 0.8 else ("WARN ⚠️ " if s >= 0.5 else "FAIL ❌")
176
- print(f" {task_id:<10} {n:>7} {s:>8.3f} {status:>10}")
177
-
178
- print(f"\n{'═' * 62}\n")
179
-
180
- # Return scores dict for programmatic use (e.g. CI pipelines)
181
- return {
182
- "task_scores": scores,
183
- "overall": round(overall, 4),
184
- "total_emails": total_weight,
185
- }
186
-
187
 
188
  if __name__ == "__main__":
189
- results = main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import numpy as np
2
+ import sys
3
+ from env import EmailTriageEnv
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ # Classification logic (Wahi jo app.py mein hai)
6
+ def classify_email(email):
7
+ kw = set(email.get("keywords", []))
 
 
 
 
8
  context = email.get("context", "").lower()
9
+
10
+ # Simple logic to match your agent
11
+ if context == "legal" or any(k in kw for k in ["lawsuit", "attorney", "sue"]):
12
  return np.array([2, 2, 2], dtype=np.int64)
 
13
  if context == "security":
 
 
14
  return np.array([2, 1, 2], dtype=np.int64)
 
15
  if context == "billing":
 
 
16
  return np.array([1, 0, 1], dtype=np.int64)
 
 
 
 
17
  return np.array([0, 0, 0], dtype=np.int64)
18
 
19
+ def run_inference():
20
+ # Meta usually tests all tasks: easy, medium, hard
21
+ tasks = ["easy", "medium", "hard"]
22
+
23
+ for task_name in tasks:
24
+ env = EmailTriageEnv(task=task_name, shuffle=False)
25
+ obs, info = env.reset(seed=42)
26
+
27
+ # --- [START] TAG ---
28
+ print(f"[START] task={task_name}", flush=True)
29
+
30
+ terminated = False
31
+ step_count = 0
32
+ total_reward = 0.0
33
+
34
+ # Queue se emails uthao
35
+ emails = list(env._queue)
36
+
37
+ while not terminated and step_count < len(emails):
38
+ email = emails[step_count]
39
+ action = classify_email(email)
40
+
41
+ # Env step
42
+ obs, reward, terminated, truncated, info = env.step(action)
43
+ total_reward += reward
44
+
45
+ # --- [STEP] TAG ---
46
+ # Grader ko har step ka hisaab chahiye
47
+ print(f"[STEP] step={step_count+1} reward={reward:.2f}", flush=True)
48
+
49
+ step_count += 1
50
+
51
+ # Final Score (Normalized)
52
+ final_score = max(0.0, min(1.0, total_reward))
53
+
54
+ # --- [END] TAG ---
55
+ print(f"[END] task={task_name} score={final_score:.3f} steps={step_count}", flush=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
  if __name__ == "__main__":
58
+ run_inference()