padmapriyagosakan commited on
Commit
50e4165
·
1 Parent(s): e4e1fe4

fix: make graders fully self-contained, embed correct_action and partial_credit directly

Browse files
Files changed (1) hide show
  1. server/graders.py +134 -57
server/graders.py CHANGED
@@ -1,85 +1,162 @@
1
  """
2
  Grader callables for PayOps OpenEnv tasks.
3
 
4
- Each class is referenced from openenv.yaml as:
5
- server.graders:EASY001Grader
6
 
7
- The platform imports the class and calls it with an action string.
8
- Return type is {"score": float, "feedback": str} as required by the platform validator.
 
 
 
9
  """
10
  from __future__ import annotations
11
 
12
 
13
  class _BaseGrader:
14
- """Base grader: returns {"score": float, "feedback": str} as required by the platform validator."""
15
-
16
- task_id: str = ""
17
 
18
- def grade(self, action: str, **kwargs):
19
- from payops_env.tasks import TASKS_BY_ID # lazy import avoids circular deps
 
 
20
 
21
- t = TASKS_BY_ID.get(self.task_id)
22
- if t is None:
23
- return {"score": 0.0, "feedback": "Task not found"}
24
 
25
- if action == t.correct_action:
 
26
  return {"score": 1.0, "feedback": "Correct action"}
27
-
28
- partial = float(
29
- dict(getattr(t, "partial_credit_actions", {})).get(action, 0.0)
30
- )
31
  return {
32
- "score": partial,
33
- "feedback": "Partial credit" if partial > 0 else "Incorrect action",
34
  }
35
 
36
  def __call__(self, action: str, **kwargs):
37
  return self.grade(action, **kwargs)
38
 
39
 
40
- def _make(task_id: str) -> type:
41
- """Factory: create a named grader class for the given task_id."""
42
- return type(
43
- task_id.replace("-", "") + "Grader",
44
- (_BaseGrader,),
45
- {"task_id": task_id},
46
- )
 
47
 
 
 
 
48
 
49
- # ── Easy ─────────────────────────────────────────────────────────────────────
50
- EASY001Grader = _make("EASY-001") # approve
51
- EASY002Grader = _make("EASY-002") # reject
52
- EASY003Grader = _make("EASY-003") # approve
53
- EASY004Grader = _make("EASY-004") # flag
54
- EASY005Grader = _make("EASY-005") # approve
55
- EASY006Grader = _make("EASY-006") # flag
 
 
 
 
56
 
57
  # ── Medium ────────────────────────────────────────────────────────────────────
58
- MED001Grader = _make("MED-001") # escalate
59
- MED002Grader = _make("MED-002") # hold
60
- MED003Grader = _make("MED-003") # flag
61
- MED004Grader = _make("MED-004") # flag
62
- MED005Grader = _make("MED-005") # hold
63
- MED006Grader = _make("MED-006") # escalate
64
- MED007Grader = _make("MED-007") # hold
65
- MED008Grader = _make("MED-008") # flag
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
  # ─��� Hard ──────────────────────────────────────────────────────────────────────
68
- HARD001Grader = _make("HARD-001") # escalate
69
- HARD002Grader = _make("HARD-002") # reject
70
- HARD003Grader = _make("HARD-003") # reject
71
- HARD004Grader = _make("HARD-004") # approve
72
- HARD005Grader = _make("HARD-005") # escalate
73
- HARD006Grader = _make("HARD-006") # flag
74
- HARD007Grader = _make("HARD-007") # reject
75
- HARD008Grader = _make("HARD-008") # reject
76
- HARD009Grader = _make("HARD-009") # escalate
77
- HARD010Grader = _make("HARD-010") # reject
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
  # ── Critical ──────────────────────────────────────────────────────────────────
80
- CRIT001Grader = _make("CRIT-001") # approve
81
- CRIT002Grader = _make("CRIT-002") # reject
82
- CRIT003Grader = _make("CRIT-003") # escalate
83
- CRIT004Grader = _make("CRIT-004") # reject
84
- CRIT005Grader = _make("CRIT-005") # reject
85
- CRIT006Grader = _make("CRIT-006") # escalate
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  """
2
  Grader callables for PayOps OpenEnv tasks.
3
 
4
+ Referenced from openenv.yaml as: server.graders:EASY001Grader
 
5
 
6
+ Each grader is fully self-contained (zero external imports) so the platform
7
+ validator can import and call them in any isolated environment.
8
+
9
+ Returns {"score": float, "feedback": str} as required by the platform.
10
+ Scores are always in [0.0, 1.0].
11
  """
12
  from __future__ import annotations
13
 
14
 
15
  class _BaseGrader:
16
+ """
17
+ Self-contained base grader.
 
18
 
19
+ Subclasses set:
20
+ correct_action : str
21
+ partial_credit : dict[str, float] (action -> score, all in (0, 1))
22
+ """
23
 
24
+ correct_action: str = ""
25
+ partial_credit: dict = {}
 
26
 
27
+ def grade(self, action: str, **kwargs):
28
+ if action == self.correct_action:
29
  return {"score": 1.0, "feedback": "Correct action"}
30
+ score = float(self.partial_credit.get(action, 0.0))
 
 
 
31
  return {
32
+ "score": score,
33
+ "feedback": "Partial credit" if score > 0 else "Incorrect action",
34
  }
35
 
36
  def __call__(self, action: str, **kwargs):
37
  return self.grade(action, **kwargs)
38
 
39
 
40
+ # ── Easy ─────────────────────────────────────────────────────────────────────
41
+ class EASY001Grader(_BaseGrader):
42
+ correct_action = "approve"
43
+ partial_credit = {}
44
+
45
+ class EASY002Grader(_BaseGrader):
46
+ correct_action = "reject"
47
+ partial_credit = {"escalate": 0.4}
48
 
49
+ class EASY003Grader(_BaseGrader):
50
+ correct_action = "approve"
51
+ partial_credit = {}
52
 
53
+ class EASY004Grader(_BaseGrader):
54
+ correct_action = "flag"
55
+ partial_credit = {"escalate": 0.6, "hold": 0.5}
56
+
57
+ class EASY005Grader(_BaseGrader):
58
+ correct_action = "approve"
59
+ partial_credit = {}
60
+
61
+ class EASY006Grader(_BaseGrader):
62
+ correct_action = "flag"
63
+ partial_credit = {"hold": 0.6}
64
 
65
  # ── Medium ────────────────────────────────────────────────────────────────────
66
+ class MED001Grader(_BaseGrader):
67
+ correct_action = "escalate"
68
+ partial_credit = {"flag": 0.5, "hold": 0.4}
69
+
70
+ class MED002Grader(_BaseGrader):
71
+ correct_action = "hold"
72
+ partial_credit = {"escalate": 0.6, "flag": 0.4}
73
+
74
+ class MED003Grader(_BaseGrader):
75
+ correct_action = "flag"
76
+ partial_credit = {"hold": 0.5, "escalate": 0.3}
77
+
78
+ class MED004Grader(_BaseGrader):
79
+ correct_action = "flag"
80
+ partial_credit = {"escalate": 0.5, "hold": 0.4}
81
+
82
+ class MED005Grader(_BaseGrader):
83
+ correct_action = "hold"
84
+ partial_credit = {"flag": 0.5, "escalate": 0.4}
85
+
86
+ class MED006Grader(_BaseGrader):
87
+ correct_action = "escalate"
88
+ partial_credit = {"flag": 0.4, "hold": 0.5}
89
+
90
+ class MED007Grader(_BaseGrader):
91
+ correct_action = "hold"
92
+ partial_credit = {"escalate": 0.6, "flag": 0.4}
93
+
94
+ class MED008Grader(_BaseGrader):
95
+ correct_action = "flag"
96
+ partial_credit = {"hold": 0.6, "escalate": 0.4}
97
 
98
  # ─��� Hard ──────────────────────────────────────────────────────────────────────
99
+ class HARD001Grader(_BaseGrader):
100
+ correct_action = "escalate"
101
+ partial_credit = {"flag": 0.6, "hold": 0.5, "reject": 0.3}
102
+
103
+ class HARD002Grader(_BaseGrader):
104
+ correct_action = "reject"
105
+ partial_credit = {"escalate": 0.6, "hold": 0.5, "flag": 0.3}
106
+
107
+ class HARD003Grader(_BaseGrader):
108
+ correct_action = "reject"
109
+ partial_credit = {"escalate": 0.5, "flag": 0.2}
110
+
111
+ class HARD004Grader(_BaseGrader):
112
+ correct_action = "approve"
113
+ partial_credit = {"escalate": 0.5, "hold": 0.4, "flag": 0.3}
114
+
115
+ class HARD005Grader(_BaseGrader):
116
+ correct_action = "escalate"
117
+ partial_credit = {"flag": 0.5, "hold": 0.4, "reject": 0.3}
118
+
119
+ class HARD006Grader(_BaseGrader):
120
+ correct_action = "flag"
121
+ partial_credit = {"hold": 0.6, "escalate": 0.5}
122
+
123
+ class HARD007Grader(_BaseGrader):
124
+ correct_action = "reject"
125
+ partial_credit = {"hold": 0.5, "escalate": 0.4, "flag": 0.3}
126
+
127
+ class HARD008Grader(_BaseGrader):
128
+ correct_action = "reject"
129
+ partial_credit = {"hold": 0.5, "escalate": 0.4, "flag": 0.3}
130
+
131
+ class HARD009Grader(_BaseGrader):
132
+ correct_action = "escalate"
133
+ partial_credit = {"hold": 0.5, "flag": 0.4, "reject": 0.3}
134
+
135
+ class HARD010Grader(_BaseGrader):
136
+ correct_action = "reject"
137
+ partial_credit = {"hold": 0.5, "escalate": 0.4, "flag": 0.3}
138
 
139
  # ── Critical ──────────────────────────────────────────────────────────────────
140
+ class CRIT001Grader(_BaseGrader):
141
+ correct_action = "approve"
142
+ partial_credit = {"escalate": 0.5, "hold": 0.4, "flag": 0.3}
143
+
144
+ class CRIT002Grader(_BaseGrader):
145
+ correct_action = "reject"
146
+ partial_credit = {"escalate": 0.4, "flag": 0.2}
147
+
148
+ class CRIT003Grader(_BaseGrader):
149
+ correct_action = "escalate"
150
+ partial_credit = {"flag": 0.4, "hold": 0.35, "reject": 0.3}
151
+
152
+ class CRIT004Grader(_BaseGrader):
153
+ correct_action = "reject"
154
+ partial_credit = {"escalate": 0.5, "hold": 0.4}
155
+
156
+ class CRIT005Grader(_BaseGrader):
157
+ correct_action = "reject"
158
+ partial_credit = {"escalate": 0.5, "hold": 0.4}
159
+
160
+ class CRIT006Grader(_BaseGrader):
161
+ correct_action = "escalate"
162
+ partial_credit = {"hold": 0.5, "reject": 0.4}