SamaKool commited on
Commit
a81c92f
·
1 Parent(s): f85a371

added the run_episode function

Browse files
graders/grader_classification.py CHANGED
@@ -13,31 +13,27 @@ class MediumClassificationGrader:
13
  def __init__(self) -> None:
14
  self.last_breakdown: dict[str, Any] = {}
15
 
16
- def grade(self, state: Any, ground_truth: dict[str, Any] | None = None) -> float:
 
 
 
 
17
  tp = float(getattr(state, "total_tp", 0))
18
  tn = float(getattr(state, "total_tn", 0))
19
  fp = float(getattr(state, "total_fp", 0))
20
  fn = float(getattr(state, "total_fn", 0))
21
 
22
- total = tp + tn + fp + fn
23
-
24
- # The maximum possible score if they made zero mistakes
25
  actual_anomalies = tp + fn
26
  actual_valid = tn + fp
27
-
28
  perfect_signal = (actual_anomalies * _TP_WEIGHT) + (actual_valid * _TN_WEIGHT)
29
-
30
  if perfect_signal == 0:
31
  return 0.1
32
 
33
  positive_signal = (tp * _TP_WEIGHT) + (tn * _TN_WEIGHT)
34
  negative_signal = (fp * _FP_PENALTY) + (fn * _FN_PENALTY)
35
 
36
- # Normalize against the true perfect scenario
37
  raw_score = max(0.0, positive_signal - negative_signal) / perfect_signal
38
-
39
- # Strict hackathon boundary
40
  score = max(0.1, min(0.99, raw_score))
41
-
42
  self.last_breakdown = {"tp": int(tp), "tn": int(tn), "fp": int(fp), "fn": int(fn), "score": score}
43
  return score
 
13
  def __init__(self) -> None:
14
  self.last_breakdown: dict[str, Any] = {}
15
 
16
+ def grade(self, state: Any = None, ground_truth: dict[str, Any] | None = None) -> float:
17
+ if state is None:
18
+ self.last_breakdown = {"error": "empty_state_ping", "score": 0.1}
19
+ return 0.1
20
+
21
  tp = float(getattr(state, "total_tp", 0))
22
  tn = float(getattr(state, "total_tn", 0))
23
  fp = float(getattr(state, "total_fp", 0))
24
  fn = float(getattr(state, "total_fn", 0))
25
 
 
 
 
26
  actual_anomalies = tp + fn
27
  actual_valid = tn + fp
 
28
  perfect_signal = (actual_anomalies * _TP_WEIGHT) + (actual_valid * _TN_WEIGHT)
29
+
30
  if perfect_signal == 0:
31
  return 0.1
32
 
33
  positive_signal = (tp * _TP_WEIGHT) + (tn * _TN_WEIGHT)
34
  negative_signal = (fp * _FP_PENALTY) + (fn * _FN_PENALTY)
35
 
 
36
  raw_score = max(0.0, positive_signal - negative_signal) / perfect_signal
 
 
37
  score = max(0.1, min(0.99, raw_score))
 
38
  self.last_breakdown = {"tp": int(tp), "tn": int(tn), "fp": int(fp), "fn": int(fn), "score": score}
39
  return score
graders/grader_detection.py CHANGED
@@ -13,30 +13,27 @@ class EasyDetectionGrader:
13
  def __init__(self) -> None:
14
  self.last_breakdown: dict[str, Any] = {}
15
 
16
- def grade(self, state: Any, ground_truth: dict[str, Any] | None = None) -> float:
 
 
 
 
17
  tp = float(getattr(state, "total_tp", 0))
18
  tn = float(getattr(state, "total_tn", 0))
19
  fp = float(getattr(state, "total_fp", 0))
20
  fn = float(getattr(state, "total_fn", 0))
21
 
22
- total = tp + tn + fp + fn
23
-
24
- # The maximum possible score if they made zero mistakes
25
  actual_anomalies = tp + fn
26
  actual_valid = tn + fp
27
-
28
  perfect_signal = (actual_anomalies * _TP_WEIGHT) + (actual_valid * _TN_WEIGHT)
29
-
30
  if perfect_signal == 0:
31
  return 0.1
32
 
33
  positive_signal = (tp * _TP_WEIGHT) + (tn * _TN_WEIGHT)
34
  negative_signal = (fp * _FP_PENALTY) + (fn * _FN_PENALTY)
35
 
36
- # Normalize against the true perfect scenario
37
  raw_score = max(0.0, positive_signal - negative_signal) / perfect_signal
38
-
39
- # Strict hackathon boundary
40
  score = max(0.1, min(0.99, raw_score))
41
  self.last_breakdown = {"tp": int(tp), "tn": int(tn), "fp": int(fp), "fn": int(fn), "score": score}
42
  return score
 
13
  def __init__(self) -> None:
14
  self.last_breakdown: dict[str, Any] = {}
15
 
16
+ def grade(self, state: Any = None, ground_truth: dict[str, Any] | None = None) -> float:
17
+ if state is None:
18
+ self.last_breakdown = {"error": "empty_state_ping", "score": 0.1}
19
+ return 0.1
20
+
21
  tp = float(getattr(state, "total_tp", 0))
22
  tn = float(getattr(state, "total_tn", 0))
23
  fp = float(getattr(state, "total_fp", 0))
24
  fn = float(getattr(state, "total_fn", 0))
25
 
 
 
 
26
  actual_anomalies = tp + fn
27
  actual_valid = tn + fp
 
28
  perfect_signal = (actual_anomalies * _TP_WEIGHT) + (actual_valid * _TN_WEIGHT)
29
+
30
  if perfect_signal == 0:
31
  return 0.1
32
 
33
  positive_signal = (tp * _TP_WEIGHT) + (tn * _TN_WEIGHT)
34
  negative_signal = (fp * _FP_PENALTY) + (fn * _FN_PENALTY)
35
 
 
36
  raw_score = max(0.0, positive_signal - negative_signal) / perfect_signal
 
 
37
  score = max(0.1, min(0.99, raw_score))
38
  self.last_breakdown = {"tp": int(tp), "tn": int(tn), "fp": int(fp), "fn": int(fn), "score": score}
39
  return score
graders/grader_fix.py CHANGED
@@ -13,30 +13,27 @@ class HardFixGrader:
13
  def __init__(self) -> None:
14
  self.last_breakdown: dict[str, Any] = {}
15
 
16
- def grade(self, state: Any, ground_truth: dict[str, Any] | None = None) -> float:
 
 
 
 
17
  tp = float(getattr(state, "total_tp", 0))
18
  tn = float(getattr(state, "total_tn", 0))
19
  fp = float(getattr(state, "total_fp", 0))
20
  fn = float(getattr(state, "total_fn", 0))
21
 
22
- total = tp + tn + fp + fn
23
-
24
- # The maximum possible score if they made zero mistakes
25
  actual_anomalies = tp + fn
26
  actual_valid = tn + fp
27
-
28
  perfect_signal = (actual_anomalies * _TP_WEIGHT) + (actual_valid * _TN_WEIGHT)
29
-
30
  if perfect_signal == 0:
31
  return 0.1
32
 
33
  positive_signal = (tp * _TP_WEIGHT) + (tn * _TN_WEIGHT)
34
  negative_signal = (fp * _FP_PENALTY) + (fn * _FN_PENALTY)
35
 
36
- # Normalize against the true perfect scenario
37
  raw_score = max(0.0, positive_signal - negative_signal) / perfect_signal
38
-
39
- # Strict hackathon boundary
40
  score = max(0.1, min(0.99, raw_score))
41
  self.last_breakdown = {"tp": int(tp), "tn": int(tn), "fp": int(fp), "fn": int(fn), "score": score}
42
  return score
 
13
  def __init__(self) -> None:
14
  self.last_breakdown: dict[str, Any] = {}
15
 
16
+ def grade(self, state: Any = None, ground_truth: dict[str, Any] | None = None) -> float:
17
+ if state is None:
18
+ self.last_breakdown = {"error": "empty_state_ping", "score": 0.1}
19
+ return 0.1
20
+
21
  tp = float(getattr(state, "total_tp", 0))
22
  tn = float(getattr(state, "total_tn", 0))
23
  fp = float(getattr(state, "total_fp", 0))
24
  fn = float(getattr(state, "total_fn", 0))
25
 
 
 
 
26
  actual_anomalies = tp + fn
27
  actual_valid = tn + fp
 
28
  perfect_signal = (actual_anomalies * _TP_WEIGHT) + (actual_valid * _TN_WEIGHT)
29
+
30
  if perfect_signal == 0:
31
  return 0.1
32
 
33
  positive_signal = (tp * _TP_WEIGHT) + (tn * _TN_WEIGHT)
34
  negative_signal = (fp * _FP_PENALTY) + (fn * _FN_PENALTY)
35
 
 
36
  raw_score = max(0.0, positive_signal - negative_signal) / perfect_signal
 
 
37
  score = max(0.1, min(0.99, raw_score))
38
  self.last_breakdown = {"tp": int(tp), "tn": int(tn), "fp": int(fp), "fn": int(fn), "score": score}
39
  return score
inference.py CHANGED
@@ -190,7 +190,7 @@ def run_inference() -> None:
190
  action = AuditorAction(decisions=decisions)
191
 
192
  obs = env.step(action)
193
- step_reward = float(obs.reward) if obs.reward is not None else 0.00
194
  all_rewards.append(step_reward)
195
  steps_completed = step_num
196
 
@@ -213,13 +213,13 @@ def run_inference() -> None:
213
  finally:
214
  # 4. The Ultimate Safety Clamp
215
  if not all_rewards:
216
- all_rewards = [0.00]
217
 
218
  current_sum = sum(all_rewards)
219
 
220
- if current_sum <= 0.0:
221
- # If the script crashed or agent scored 0.0, inject absolute minimum
222
- all_rewards[-1] = 0.01
223
  elif current_sum >= 1.0:
224
  # If floating point math drifted to 1.0+, force the final entry down
225
  excess = current_sum - 0.99
 
190
  action = AuditorAction(decisions=decisions)
191
 
192
  obs = env.step(action)
193
+ step_reward = float(obs.reward) if obs.reward is not None else 0.1
194
  all_rewards.append(step_reward)
195
  steps_completed = step_num
196
 
 
213
  finally:
214
  # 4. The Ultimate Safety Clamp
215
  if not all_rewards:
216
+ all_rewards = [0.1]
217
 
218
  current_sum = sum(all_rewards)
219
 
220
+ if current_sum <= 0.1:
221
+ # If the script crashed or agent scored nothing, inject the grader floor
222
+ all_rewards[-1] = 0.1
223
  elif current_sum >= 1.0:
224
  # If floating point math drifted to 1.0+, force the final entry down
225
  excess = current_sum - 0.99
server/fin_auditor_environment.py CHANGED
@@ -137,7 +137,7 @@ class FinAuditorEnvironment(Environment):
137
  return FinAuditorObservation(
138
  features=anomalies,
139
  message=f"Fin Auditor engine ready. {len(anomalies)} trades loaded.",
140
- reward=0.0,
141
  done=False
142
  )
143
 
 
137
  return FinAuditorObservation(
138
  features=anomalies,
139
  message=f"Fin Auditor engine ready. {len(anomalies)} trades loaded.",
140
+ reward=0.1,
141
  done=False
142
  )
143
 
tasks/task1_easy.py CHANGED
@@ -33,4 +33,40 @@ def setup_env(env) -> None:
33
  env.difficulty = hft_auditor.Difficulty.EASY
34
  env._MAX_EPISODE_STEPS = MAX_STEPS
35
  except Exception as e:
36
- print(f"[task_easy] Could not set difficulty: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  env.difficulty = hft_auditor.Difficulty.EASY
34
  env._MAX_EPISODE_STEPS = MAX_STEPS
35
  except Exception as e:
36
+ print(f"[task_easy] Could not set difficulty: {e}")
37
+
38
+ def run_episode(env, agent_fn) -> dict:
39
+ """Run a single EASY anomaly-detection episode and return the graded result.
40
+
41
+ Called by the OpenEnv evaluator. agent_fn receives an observation and
42
+ returns a list of binary decisions (0 = valid, 1 = anomaly).
43
+ """
44
+ setup_env(env)
45
+ total_reward = 0.0
46
+ steps_done = 0
47
+
48
+ try:
49
+ obs = env.reset()
50
+ for _ in range(MAX_STEPS):
51
+ decisions = agent_fn(obs)
52
+ from models import AuditorAction
53
+ action = AuditorAction(decisions=decisions)
54
+ obs = env.step(action)
55
+ total_reward += float(obs.reward) if obs.reward is not None else 0.0
56
+ steps_done += 1
57
+ if obs.done:
58
+ break
59
+ except Exception as exc:
60
+ print(f"[task_easy] run_episode error at step {steps_done}: {exc}")
61
+
62
+ # Always grade — even partial data yields a valid score via perfect_signal fallback
63
+ final_score = grader.grade(env.state)
64
+
65
+ return {
66
+ "task": TASK_ID,
67
+ "difficulty": DIFFICULTY,
68
+ "steps": steps_done,
69
+ "total_reward": round(total_reward, 4),
70
+ "score": round(final_score, 4),
71
+ "grader_breakdown": grader.last_breakdown,
72
+ }
tasks/task2_medium.py CHANGED
@@ -33,4 +33,41 @@ def setup_env(env) -> None:
33
  env.difficulty = hft_auditor.Difficulty.MEDIUM
34
  env._MAX_EPISODE_STEPS = MAX_STEPS
35
  except Exception as e:
36
- print(f"[task_medium] Could not set difficulty: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  env.difficulty = hft_auditor.Difficulty.MEDIUM
34
  env._MAX_EPISODE_STEPS = MAX_STEPS
35
  except Exception as e:
36
+ print(f"[task_medium] Could not set difficulty: {e}")
37
+
38
+
39
+ def run_episode(env, agent_fn) -> dict:
40
+ """Run a single MEDIUM anomaly-detection episode and return the graded result.
41
+
42
+ Called by the OpenEnv evaluator. agent_fn receives an observation and
43
+ returns a list of binary decisions (0 = valid, 1 = anomaly).
44
+ """
45
+ setup_env(env)
46
+ total_reward = 0.0
47
+ steps_done = 0
48
+
49
+ try:
50
+ obs = env.reset()
51
+ for _ in range(MAX_STEPS):
52
+ decisions = agent_fn(obs)
53
+ from models import AuditorAction
54
+ action = AuditorAction(decisions=decisions)
55
+ obs = env.step(action)
56
+ total_reward += float(obs.reward) if obs.reward is not None else 0.0
57
+ steps_done += 1
58
+ if obs.done:
59
+ break
60
+ except Exception as exc:
61
+ print(f"[task_medium] run_episode error at step {steps_done}: {exc}")
62
+
63
+ # Always grade — even partial data yields a valid score via perfect_signal fallback
64
+ final_score = grader.grade(env.state)
65
+
66
+ return {
67
+ "task": TASK_ID,
68
+ "difficulty": DIFFICULTY,
69
+ "steps": steps_done,
70
+ "total_reward": round(total_reward, 4),
71
+ "score": round(final_score, 4),
72
+ "grader_breakdown": grader.last_breakdown,
73
+ }
tasks/task3_hard.py CHANGED
@@ -33,4 +33,41 @@ def setup_env(env) -> None:
33
  env.difficulty = hft_auditor.Difficulty.HARD
34
  env._MAX_EPISODE_STEPS = MAX_STEPS
35
  except Exception as e:
36
- print(f"[task_hard] Could not set difficulty: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  env.difficulty = hft_auditor.Difficulty.HARD
34
  env._MAX_EPISODE_STEPS = MAX_STEPS
35
  except Exception as e:
36
+ print(f"[task_hard] Could not set difficulty: {e}")
37
+
38
+
39
+ def run_episode(env, agent_fn) -> dict:
40
+ """Run a single HARD anomaly-detection episode and return the graded result.
41
+
42
+ Called by the OpenEnv evaluator. agent_fn receives an observation and
43
+ returns a list of binary decisions (0 = valid, 1 = anomaly).
44
+ """
45
+ setup_env(env)
46
+ total_reward = 0.0
47
+ steps_done = 0
48
+
49
+ try:
50
+ obs = env.reset()
51
+ for _ in range(MAX_STEPS):
52
+ decisions = agent_fn(obs)
53
+ from models import AuditorAction
54
+ action = AuditorAction(decisions=decisions)
55
+ obs = env.step(action)
56
+ total_reward += float(obs.reward) if obs.reward is not None else 0.0
57
+ steps_done += 1
58
+ if obs.done:
59
+ break
60
+ except Exception as exc:
61
+ print(f"[task_hard] run_episode error at step {steps_done}: {exc}")
62
+
63
+ # Always grade — even partial data yields a valid score via perfect_signal fallback
64
+ final_score = grader.grade(env.state)
65
+
66
+ return {
67
+ "task": TASK_ID,
68
+ "difficulty": DIFFICULTY,
69
+ "steps": steps_done,
70
+ "total_reward": round(total_reward, 4),
71
+ "score": round(final_score, 4),
72
+ "grader_breakdown": grader.last_breakdown,
73
+ }