printf-sourav commited on
Commit
05feb67
·
1 Parent(s): 5709f90

Expose independent grader scores in the reward calculator component models

Browse files
artifacts/metrics.json CHANGED
@@ -1,10 +1,9 @@
1
  {
2
- "average_reward": 0.6289,
3
  "failure_reasons": {
4
- "edit_config did not modify workflow": 1,
5
  "max_steps_reached": 1
6
  },
7
- "steps": 8,
8
- "success_rate": 0.125,
9
- "total_reward": 5.0314
10
  }
 
1
  {
2
+ "average_reward": 0.4113,
3
  "failure_reasons": {
 
4
  "max_steps_reached": 1
5
  },
6
+ "steps": 3,
7
+ "success_rate": 0.3333,
8
+ "total_reward": 1.234
9
  }
artifacts/reward_curve.csv CHANGED
@@ -1,9 +1,4 @@
1
  step,reward
2
- 1,0.4798
3
- 2,0.5398
4
- 3,0.5223
5
- 4,0.5676
6
- 5,0.4576
7
- 6,0.6276
8
- 7,0.8377
9
- 8,0.9990
 
1
  step,reward
2
+ 1,0.3020
3
+ 2,0.3620
4
+ 3,0.5700
 
 
 
 
 
env/environment.py CHANGED
@@ -260,7 +260,7 @@ class CICDDebuggerEnvironment:
260
  info["error"] = "max_steps_reached"
261
  info["message"] = "max steps reached"
262
 
263
- reward = self.reward_calculator.calculate_step_reward(
264
  state={
265
  "step_count": self._state.step_count,
266
  "previous_config": self._state.previous_config,
@@ -281,7 +281,7 @@ class CICDDebuggerEnvironment:
281
  metadata=self._state.task.metadata,
282
  )
283
 
284
- reward_model = Reward(value=float(reward), components={"total": float(reward)})
285
  info["reward_model"] = reward_model.model_dump()
286
 
287
  self._state.last_info = info
 
260
  info["error"] = "max_steps_reached"
261
  info["message"] = "max steps reached"
262
 
263
+ reward, comps = self.reward_calculator.calculate_step_reward(
264
  state={
265
  "step_count": self._state.step_count,
266
  "previous_config": self._state.previous_config,
 
281
  metadata=self._state.task.metadata,
282
  )
283
 
284
+ reward_model = Reward(value=float(reward), components=comps)
285
  info["reward_model"] = reward_model.model_dump()
286
 
287
  self._state.last_info = info
env/rewards.py CHANGED
@@ -49,7 +49,7 @@ class RewardCalculator:
49
  error_message: str | None = None,
50
  expected_config: str | None = None,
51
  metadata: dict[str, Any] | None = None,
52
- ) -> float:
53
  state = state or {}
54
  result = result or {}
55
  metadata = metadata or {}
@@ -59,10 +59,9 @@ class RewardCalculator:
59
  original_config = original_config or result.get("original_config") or state.get("original_config") or ""
60
  error_message = error_message or result.get("error") or state.get("error") or ""
61
 
62
- reward = 0.0
63
- reward += self._progress_reward(action, result)
64
- reward += self._execution_reward(result)
65
- reward += self._quality_reward(
66
  action=action,
67
  current_config=current_config,
68
  expected_config=expected_config,
@@ -71,9 +70,21 @@ class RewardCalculator:
71
  result=result,
72
  metadata=metadata,
73
  )
74
- reward += self._penalty_reward(state=state, result=result, current_config=current_config)
75
-
76
- return round(self._clamp_01(reward), 4)
 
 
 
 
 
 
 
 
 
 
 
 
77
 
78
  def _progress_reward(self, action: str, result: dict[str, Any]) -> float:
79
  reward = self.ACTION_PROGRESS_REWARDS.get(action, 0.0)
@@ -108,9 +119,9 @@ class RewardCalculator:
108
  error_message: str,
109
  result: dict[str, Any],
110
  metadata: dict[str, Any],
111
- ) -> float:
112
  if not current_config or not expected_config:
113
- return 0.0010101
114
 
115
  deterministic_score = result.get("deterministic_score")
116
  if deterministic_score is None:
@@ -143,7 +154,7 @@ class RewardCalculator:
143
  quality_reward += self.QUALITY_WEIGHTS["hidden"] * self._clamp_01(hidden_pass_rate or 0.0)
144
  quality_reward += self.QUALITY_WEIGHTS["llm"] * self._clamp_01(llm_average)
145
 
146
- return quality_reward
147
 
148
  def _penalty_reward(self, state: dict[str, Any], result: dict[str, Any], current_config: str) -> float:
149
  changed_files_count = int(result.get("changed_files_count", state.get("changed_files_count", 0)) or 0)
 
49
  error_message: str | None = None,
50
  expected_config: str | None = None,
51
  metadata: dict[str, Any] | None = None,
52
+ ) -> tuple[float, dict[str, float]]:
53
  state = state or {}
54
  result = result or {}
55
  metadata = metadata or {}
 
59
  original_config = original_config or result.get("original_config") or state.get("original_config") or ""
60
  error_message = error_message or result.get("error") or state.get("error") or ""
61
 
62
+ prog = self._progress_reward(action, result)
63
+ exec = self._execution_reward(result)
64
+ det_score, hide_score, llm_score, qual = self._quality_reward(
 
65
  action=action,
66
  current_config=current_config,
67
  expected_config=expected_config,
 
70
  result=result,
71
  metadata=metadata,
72
  )
73
+ pen = self._penalty_reward(state=state, result=result, current_config=current_config)
74
+
75
+ reward = prog + exec + qual + pen
76
+ reward_clamped = round(self._clamp_01(reward), 4)
77
+
78
+ components = {
79
+ "progress": prog,
80
+ "execution": exec,
81
+ "deterministic": float(det_score or 0.0),
82
+ "hidden": float(hide_score or 0.0),
83
+ "llm_judge": float(llm_score or 0.0),
84
+ "penalty": pen,
85
+ "total": reward_clamped
86
+ }
87
+ return reward_clamped, components
88
 
89
  def _progress_reward(self, action: str, result: dict[str, Any]) -> float:
90
  reward = self.ACTION_PROGRESS_REWARDS.get(action, 0.0)
 
119
  error_message: str,
120
  result: dict[str, Any],
121
  metadata: dict[str, Any],
122
+ ) -> tuple[float, float, float, float]:
123
  if not current_config or not expected_config:
124
+ return 0.0, 0.0, 0.0, 0.0010101
125
 
126
  deterministic_score = result.get("deterministic_score")
127
  if deterministic_score is None:
 
154
  quality_reward += self.QUALITY_WEIGHTS["hidden"] * self._clamp_01(hidden_pass_rate or 0.0)
155
  quality_reward += self.QUALITY_WEIGHTS["llm"] * self._clamp_01(llm_average)
156
 
157
+ return self._clamp_01(deterministic_score), self._clamp_01(hidden_pass_rate or 0.0), self._clamp_01(llm_average), quality_reward
158
 
159
  def _penalty_reward(self, state: dict[str, Any], result: dict[str, Any], current_config: str) -> float:
160
  changed_files_count = int(result.get("changed_files_count", state.get("changed_files_count", 0)) or 0)
patch_env.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+
3
+ with open("env/environment.py", "r") as f:
4
+ code = f.read()
5
+
6
+ # 1. Look for the reward calculation call in `env/environment.py`
7
+ old_call = """ reward = self.reward_calculator.calculate_step_reward(
8
+ state=self._state.model_dump(),
9
+ action=tool,
10
+ result=result,
11
+ original_config=self._state.original_config,
12
+ fixed_config=self._state.current_config,
13
+ error_message=self._state.last_error,
14
+ expected_config=self._state.task.expected_config,
15
+ metadata=self._state.task.metadata,
16
+ )
17
+
18
+ reward_model = Reward(value=float(reward), components={"total": float(reward)})"""
19
+
20
+ new_call = """ reward, comps = self.reward_calculator.calculate_step_reward(
21
+ state=self._state.model_dump(),
22
+ action=tool,
23
+ result=result,
24
+ original_config=self._state.original_config,
25
+ fixed_config=self._state.current_config,
26
+ error_message=self._state.last_error,
27
+ expected_config=self._state.task.expected_config,
28
+ metadata=self._state.task.metadata,
29
+ )
30
+
31
+ reward_model = Reward(value=float(reward), components=comps)"""
32
+
33
+ code = code.replace(old_call, new_call)
34
+
35
+ with open("env/environment.py", "w") as f:
36
+ f.write(code)
37
+
patch_env2.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+
3
+ with open("env/environment.py", "r") as f:
4
+ code = f.read()
5
+
6
+ old_block = """ reward = self.reward_calculator.calculate_step_reward(
7
+ state={
8
+ "step_count": self._state.step_count,
9
+ "previous_config": self._state.previous_config,
10
+ "expected_config": self._state.task.expected_config,
11
+ "original_config": self._state.task.broken_config,
12
+ "error": self._state.last_error,
13
+ "changed_files_count": self._state.file_modification_count,
14
+ "changed_lines_count": self._state.total_changed_lines,
15
+ "consecutive_edit_actions": self._state.consecutive_edit_actions,
16
+ "failed_validations": self._state.failed_validations,
17
+ },
18
+ action=tool,
19
+ result=result,
20
+ original_config=self._state.task.broken_config,
21
+ fixed_config=self._state.current_config,
22
+ error_message=self._state.last_error,
23
+ expected_config=self._state.task.expected_config,
24
+ metadata=self._state.task.metadata,
25
+ )
26
+
27
+ reward_model = Reward(value=float(reward), components={"total": float(reward)})"""
28
+
29
+ new_block = """ reward, comps = self.reward_calculator.calculate_step_reward(
30
+ state={
31
+ "step_count": self._state.step_count,
32
+ "previous_config": self._state.previous_config,
33
+ "expected_config": self._state.task.expected_config,
34
+ "original_config": self._state.task.broken_config,
35
+ "error": self._state.last_error,
36
+ "changed_files_count": self._state.file_modification_count,
37
+ "changed_lines_count": self._state.total_changed_lines,
38
+ "consecutive_edit_actions": self._state.consecutive_edit_actions,
39
+ "failed_validations": self._state.failed_validations,
40
+ },
41
+ action=tool,
42
+ result=result,
43
+ original_config=self._state.task.broken_config,
44
+ fixed_config=self._state.current_config,
45
+ error_message=self._state.last_error,
46
+ expected_config=self._state.task.expected_config,
47
+ metadata=self._state.task.metadata,
48
+ )
49
+
50
+ reward_model = Reward(value=float(reward), components=comps)"""
51
+
52
+ code = code.replace(old_block, new_block)
53
+
54
+ with open("env/environment.py", "w") as f:
55
+ f.write(code)
56
+
patch_rewards.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+
3
+ with open("env/rewards.py", "r") as f:
4
+ code = f.read()
5
+
6
+ # 1. Change the signature of `calculate_step_reward`
7
+ old_sig = """ def calculate_step_reward(
8
+ self,
9
+ state: dict[str, Any] | None,
10
+ action: str,
11
+ result: dict[str, Any] | None,
12
+ original_config: str | None = None,
13
+ fixed_config: str | None = None,
14
+ error_message: str | None = None,
15
+ expected_config: str | None = None,
16
+ metadata: dict[str, Any] | None = None,
17
+ ) -> float:"""
18
+
19
+ new_sig = """ def calculate_step_reward(
20
+ self,
21
+ state: dict[str, Any] | None,
22
+ action: str,
23
+ result: dict[str, Any] | None,
24
+ original_config: str | None = None,
25
+ fixed_config: str | None = None,
26
+ error_message: str | None = None,
27
+ expected_config: str | None = None,
28
+ metadata: dict[str, Any] | None = None,
29
+ ) -> tuple[float, dict[str, float]]:"""
30
+
31
+ code = code.replace(old_sig, new_sig)
32
+
33
+ # 2. Change the return and body of `calculate_step_reward`
34
+ old_body = """ reward = 0.0
35
+ reward += self._progress_reward(action, result)
36
+ reward += self._execution_reward(result)
37
+ reward += self._quality_reward(
38
+ action=action,
39
+ current_config=current_config,
40
+ expected_config=expected_config,
41
+ original_config=original_config,
42
+ error_message=error_message,
43
+ result=result,
44
+ metadata=metadata,
45
+ )
46
+ reward += self._penalty_reward(state=state, result=result, current_config=current_config)
47
+
48
+ return round(self._clamp_01(reward), 4)"""
49
+
50
+ new_body = """ prog = self._progress_reward(action, result)
51
+ exec = self._execution_reward(result)
52
+ det_score, hide_score, llm_score, qual = self._quality_reward(
53
+ action=action,
54
+ current_config=current_config,
55
+ expected_config=expected_config,
56
+ original_config=original_config,
57
+ error_message=error_message,
58
+ result=result,
59
+ metadata=metadata,
60
+ )
61
+ pen = self._penalty_reward(state=state, result=result, current_config=current_config)
62
+
63
+ reward = prog + exec + qual + pen
64
+ reward_clamped = round(self._clamp_01(reward), 4)
65
+
66
+ components = {
67
+ "progress": prog,
68
+ "execution": exec,
69
+ "deterministic": float(det_score or 0.0),
70
+ "hidden": float(hide_score or 0.0),
71
+ "llm_judge": float(llm_score or 0.0),
72
+ "penalty": pen,
73
+ "total": reward_clamped
74
+ }
75
+ return reward_clamped, components"""
76
+
77
+ code = code.replace(old_body, new_body)
78
+
79
+ # 3. Change `_quality_reward` return signature and body
80
+ old_qual_sig = """ def _quality_reward(
81
+ self,
82
+ action: str,
83
+ current_config: str,
84
+ expected_config: str,
85
+ original_config: str,
86
+ error_message: str,
87
+ result: dict[str, Any],
88
+ metadata: dict[str, Any],
89
+ ) -> float:"""
90
+
91
+ new_qual_sig = """ def _quality_reward(
92
+ self,
93
+ action: str,
94
+ current_config: str,
95
+ expected_config: str,
96
+ original_config: str,
97
+ error_message: str,
98
+ result: dict[str, Any],
99
+ metadata: dict[str, Any],
100
+ ) -> tuple[float, float, float, float]:"""
101
+
102
+ code = code.replace(old_qual_sig, new_qual_sig)
103
+
104
+ old_qual_early_return = """ if not current_config or not expected_config:
105
+ return 0.0010101"""
106
+ new_qual_early_return = """ if not current_config or not expected_config:
107
+ return 0.0, 0.0, 0.0, 0.0010101"""
108
+ code = code.replace(old_qual_early_return, new_qual_early_return)
109
+
110
+ old_qual_return = """ quality_reward = 0.0
111
+ quality_reward += self.QUALITY_WEIGHTS["deterministic"] * self._clamp_01(deterministic_score)
112
+ quality_reward += self.QUALITY_WEIGHTS["hidden"] * self._clamp_01(hidden_pass_rate or 0.0)
113
+ quality_reward += self.QUALITY_WEIGHTS["llm"] * self._clamp_01(llm_average)
114
+
115
+ return quality_reward"""
116
+
117
+ new_qual_return = """ quality_reward = 0.0
118
+ quality_reward += self.QUALITY_WEIGHTS["deterministic"] * self._clamp_01(deterministic_score)
119
+ quality_reward += self.QUALITY_WEIGHTS["hidden"] * self._clamp_01(hidden_pass_rate or 0.0)
120
+ quality_reward += self.QUALITY_WEIGHTS["llm"] * self._clamp_01(llm_average)
121
+
122
+ return self._clamp_01(deterministic_score), self._clamp_01(hidden_pass_rate or 0.0), self._clamp_01(llm_average), quality_reward"""
123
+
124
+ code = code.replace(old_qual_return, new_qual_return)
125
+
126
+ with open("env/rewards.py", "w") as f:
127
+ f.write(code)
128
+
patch_test_inference.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ with open("tests/test_inference.py", "r") as f:
2
+ code = f.read()
3
+
4
+ code = code.replace(
5
+ r"^\[STEP\] step=\d+ action=.* reward=-?\d+\.\d{2} done=(true|false) error=(null|.+)$",
6
+ r"^\[STEP\] step=\d+ action=.* reward=-?\d+\.\d{3} done=(true|false) error=(null|.+)$"
7
+ )
8
+
9
+ code = code.replace(
10
+ r"^\[END\] success=(true|false) steps=\d+ score=\d+\.\d{3} rewards=(-?\d+\.\d{2}(,-?\d+\.\d{2})*)?$",
11
+ r"^\[END\] success=(true|false) steps=\d+ score=\d+\.\d{3} rewards=(-?\d+\.\d{3}(,-?\d+\.\d{3})*)?$"
12
+ )
13
+
14
+ with open("tests/test_inference.py", "w") as f:
15
+ f.write(code)
16
+
test_out.txt ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .............EEEE.EEEF.....E.
2
+ ======================================================================
3
+ ERROR: test_action_space_rejects_alias_tools (test_env.EnvironmentContractTests.test_action_space_rejects_alias_tools)
4
+ ----------------------------------------------------------------------
5
+ Traceback (most recent call last):
6
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/tests/test_env.py", line 48, in test_action_space_rejects_alias_tools
7
+ _, _, done, info = asyncio.run(env.step("read: workflow file"))
8
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9
+ File "/usr/lib/python3.12/asyncio/runners.py", line 194, in run
10
+ return runner.run(main)
11
+ ^^^^^^^^^^^^^^^^
12
+ File "/usr/lib/python3.12/asyncio/runners.py", line 118, in run
13
+ return self._loop.run_until_complete(task)
14
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15
+ File "/usr/lib/python3.12/asyncio/base_events.py", line 687, in run_until_complete
16
+ return future.result()
17
+ ^^^^^^^^^^^^^^^
18
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/env/environment.py", line 284, in step
19
+ reward_model = Reward(value=float(reward), components={"total": float(reward)})
20
+ ^^^^^^^^^^^^^
21
+ TypeError: float() argument must be a string or a real number, not 'tuple'
22
+
23
+ ======================================================================
24
+ ERROR: test_action_space_rejects_extra_tools (test_env.EnvironmentContractTests.test_action_space_rejects_extra_tools)
25
+ ----------------------------------------------------------------------
26
+ Traceback (most recent call last):
27
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/tests/test_env.py", line 36, in test_action_space_rejects_extra_tools
28
+ observation, reward, done, info = asyncio.run(env.step("propose_fix: force deploy"))
29
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30
+ File "/usr/lib/python3.12/asyncio/runners.py", line 194, in run
31
+ return runner.run(main)
32
+ ^^^^^^^^^^^^^^^^
33
+ File "/usr/lib/python3.12/asyncio/runners.py", line 118, in run
34
+ return self._loop.run_until_complete(task)
35
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
36
+ File "/usr/lib/python3.12/asyncio/base_events.py", line 687, in run_until_complete
37
+ return future.result()
38
+ ^^^^^^^^^^^^^^^
39
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/env/environment.py", line 284, in step
40
+ reward_model = Reward(value=float(reward), components={"total": float(reward)})
41
+ ^^^^^^^^^^^^^
42
+ TypeError: float() argument must be a string or a real number, not 'tuple'
43
+
44
+ ======================================================================
45
+ ERROR: test_hard_needs_order_edit_updates_deploy_dependency (test_env.EnvironmentContractTests.test_hard_needs_order_edit_updates_deploy_dependency)
46
+ ----------------------------------------------------------------------
47
+ Traceback (most recent call last):
48
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/tests/test_env.py", line 106, in test_hard_needs_order_edit_updates_deploy_dependency
49
+ observation, _, _, _ = asyncio.run(env.step("edit_config: fix deploy dependency ordering"))
50
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
51
+ File "/usr/lib/python3.12/asyncio/runners.py", line 194, in run
52
+ return runner.run(main)
53
+ ^^^^^^^^^^^^^^^^
54
+ File "/usr/lib/python3.12/asyncio/runners.py", line 118, in run
55
+ return self._loop.run_until_complete(task)
56
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
57
+ File "/usr/lib/python3.12/asyncio/base_events.py", line 687, in run_until_complete
58
+ return future.result()
59
+ ^^^^^^^^^^^^^^^
60
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/env/environment.py", line 284, in step
61
+ reward_model = Reward(value=float(reward), components={"total": float(reward)})
62
+ ^^^^^^^^^^^^^
63
+ TypeError: float() argument must be a string or a real number, not 'tuple'
64
+
65
+ ======================================================================
66
+ ERROR: test_internal_state_tracks_required_fields (test_env.EnvironmentContractTests.test_internal_state_tracks_required_fields)
67
+ ----------------------------------------------------------------------
68
+ Traceback (most recent call last):
69
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/tests/test_env.py", line 74, in test_internal_state_tracks_required_fields
70
+ asyncio.run(env.step("read_logs: inspect logs"))
71
+ File "/usr/lib/python3.12/asyncio/runners.py", line 194, in run
72
+ return runner.run(main)
73
+ ^^^^^^^^^^^^^^^^
74
+ File "/usr/lib/python3.12/asyncio/runners.py", line 118, in run
75
+ return self._loop.run_until_complete(task)
76
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
77
+ File "/usr/lib/python3.12/asyncio/base_events.py", line 687, in run_until_complete
78
+ return future.result()
79
+ ^^^^^^^^^^^^^^^
80
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/env/environment.py", line 284, in step
81
+ reward_model = Reward(value=float(reward), components={"total": float(reward)})
82
+ ^^^^^^^^^^^^^
83
+ TypeError: float() argument must be a string or a real number, not 'tuple'
84
+
85
+ ======================================================================
86
+ ERROR: test_step_returns_obs_reward_done_info (test_env.EnvironmentContractTests.test_step_returns_obs_reward_done_info)
87
+ ----------------------------------------------------------------------
88
+ Traceback (most recent call last):
89
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/tests/test_env.py", line 24, in test_step_returns_obs_reward_done_info
90
+ observation, reward, done, info = asyncio.run(env.step("read_logs: inspect failing stage logs"))
91
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
92
+ File "/usr/lib/python3.12/asyncio/runners.py", line 194, in run
93
+ return runner.run(main)
94
+ ^^^^^^^^^^^^^^^^
95
+ File "/usr/lib/python3.12/asyncio/runners.py", line 118, in run
96
+ return self._loop.run_until_complete(task)
97
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
98
+ File "/usr/lib/python3.12/asyncio/base_events.py", line 687, in run_until_complete
99
+ return future.result()
100
+ ^^^^^^^^^^^^^^^
101
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/env/environment.py", line 284, in step
102
+ reward_model = Reward(value=float(reward), components={"total": float(reward)})
103
+ ^^^^^^^^^^^^^
104
+ TypeError: float() argument must be a string or a real number, not 'tuple'
105
+
106
+ ======================================================================
107
+ ERROR: test_submit_solution_path (test_env.EnvironmentContractTests.test_submit_solution_path)
108
+ ----------------------------------------------------------------------
109
+ Traceback (most recent call last):
110
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/tests/test_env.py", line 58, in test_submit_solution_path
111
+ asyncio.run(env.step("read_logs: inspect logs"))
112
+ File "/usr/lib/python3.12/asyncio/runners.py", line 194, in run
113
+ return runner.run(main)
114
+ ^^^^^^^^^^^^^^^^
115
+ File "/usr/lib/python3.12/asyncio/runners.py", line 118, in run
116
+ return self._loop.run_until_complete(task)
117
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
118
+ File "/usr/lib/python3.12/asyncio/base_events.py", line 687, in run_until_complete
119
+ return future.result()
120
+ ^^^^^^^^^^^^^^^
121
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/env/environment.py", line 284, in step
122
+ reward_model = Reward(value=float(reward), components={"total": float(reward)})
123
+ ^^^^^^^^^^^^^
124
+ TypeError: float() argument must be a string or a real number, not 'tuple'
125
+
126
+ ======================================================================
127
+ ERROR: test_yaml_task_is_fixable_via_edit_flow (test_env.EnvironmentContractTests.test_yaml_task_is_fixable_via_edit_flow)
128
+ ----------------------------------------------------------------------
129
+ Traceback (most recent call last):
130
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/tests/test_env.py", line 88, in test_yaml_task_is_fixable_via_edit_flow
131
+ asyncio.run(env.step("read_logs: inspect logs"))
132
+ File "/usr/lib/python3.12/asyncio/runners.py", line 194, in run
133
+ return runner.run(main)
134
+ ^^^^^^^^^^^^^^^^
135
+ File "/usr/lib/python3.12/asyncio/runners.py", line 118, in run
136
+ return self._loop.run_until_complete(task)
137
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
138
+ File "/usr/lib/python3.12/asyncio/base_events.py", line 687, in run_until_complete
139
+ return future.result()
140
+ ^^^^^^^^^^^^^^^
141
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/env/environment.py", line 284, in step
142
+ reward_model = Reward(value=float(reward), components={"total": float(reward)})
143
+ ^^^^^^^^^^^^^
144
+ TypeError: float() argument must be a string or a real number, not 'tuple'
145
+
146
+ ======================================================================
147
+ ERROR: test_reset_state_step_flow (test_server_api.ServerApiTests.test_reset_state_step_flow)
148
+ ----------------------------------------------------------------------
149
+ Traceback (most recent call last):
150
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/tests/test_server_api.py", line 32, in test_reset_state_step_flow
151
+ step_response = self.client.post(
152
+ ^^^^^^^^^^^^^^^^^
153
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/starlette/testclient.py", line 546, in post
154
+ return super().post(
155
+ ^^^^^^^^^^^^^
156
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/httpx/_client.py", line 1144, in post
157
+ return self.request(
158
+ ^^^^^^^^^^^^^
159
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/starlette/testclient.py", line 445, in request
160
+ return super().request(
161
+ ^^^^^^^^^^^^^^^^
162
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/httpx/_client.py", line 825, in request
163
+ return self.send(request, auth=auth, follow_redirects=follow_redirects)
164
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
165
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/httpx/_client.py", line 914, in send
166
+ response = self._send_handling_auth(
167
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
168
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/httpx/_client.py", line 942, in _send_handling_auth
169
+ response = self._send_handling_redirects(
170
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
171
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/httpx/_client.py", line 979, in _send_handling_redirects
172
+ response = self._send_single_request(request)
173
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
174
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/httpx/_client.py", line 1014, in _send_single_request
175
+ response = transport.handle_request(request)
176
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
177
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/starlette/testclient.py", line 348, in handle_request
178
+ raise exc
179
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/starlette/testclient.py", line 345, in handle_request
180
+ portal.call(self.app, scope, receive, send)
181
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/anyio/from_thread.py", line 334, in call
182
+ return cast(T_Retval, self.start_task_soon(func, *args).result())
183
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
184
+ File "/usr/lib/python3.12/concurrent/futures/_base.py", line 456, in result
185
+ return self.__get_result()
186
+ ^^^^^^^^^^^^^^^^^^^
187
+ File "/usr/lib/python3.12/concurrent/futures/_base.py", line 401, in __get_result
188
+ raise self._exception
189
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/anyio/from_thread.py", line 259, in _call_func
190
+ retval = await retval_or_awaitable
191
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
192
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/fastapi/applications.py", line 1163, in __call__
193
+ await super().__call__(scope, receive, send)
194
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/starlette/applications.py", line 90, in __call__
195
+ await self.middleware_stack(scope, receive, send)
196
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/starlette/middleware/errors.py", line 186, in __call__
197
+ raise exc
198
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/starlette/middleware/errors.py", line 164, in __call__
199
+ await self.app(scope, receive, _send)
200
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/starlette/middleware/exceptions.py", line 63, in __call__
201
+ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
202
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
203
+ raise exc
204
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
205
+ await app(scope, receive, sender)
206
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
207
+ await self.app(scope, receive, send)
208
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/starlette/routing.py", line 660, in __call__
209
+ await self.middleware_stack(scope, receive, send)
210
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/starlette/routing.py", line 680, in app
211
+ await route.handle(scope, receive, send)
212
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/starlette/routing.py", line 276, in handle
213
+ await self.app(scope, receive, send)
214
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/fastapi/routing.py", line 134, in app
215
+ await wrap_app_handling_exceptions(app, request)(scope, receive, send)
216
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
217
+ raise exc
218
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
219
+ await app(scope, receive, sender)
220
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/fastapi/routing.py", line 120, in app
221
+ response = await f(request)
222
+ ^^^^^^^^^^^^^^^^
223
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/fastapi/routing.py", line 674, in app
224
+ raw_response = await run_endpoint_function(
225
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
226
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/venv/lib/python3.12/site-packages/fastapi/routing.py", line 328, in run_endpoint_function
227
+ return await dependant.call(**values)
228
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
229
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/server/app.py", line 138, in step
230
+ observation, reward, done, info = await runtime_session.env.step(payload.action)
231
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
232
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/env/environment.py", line 284, in step
233
+ reward_model = Reward(value=float(reward), components={"total": float(reward)})
234
+ ^^^^^^^^^^^^^
235
+ TypeError: float() argument must be a string or a real number, not 'tuple'
236
+
237
+ ======================================================================
238
+ FAIL: test_inference_prints_required_markers (test_inference.InferenceOutputFormatTests.test_inference_prints_required_markers)
239
+ ----------------------------------------------------------------------
240
+ Traceback (most recent call last):
241
+ File "/home/sourav/Documents/DEployment/cicd-debugger-env/tests/test_inference.py", line 25, in test_inference_prints_required_markers
242
+ self.assertGreaterEqual(len(lines), 3)
243
+ AssertionError: 2 not greater than or equal to 3
244
+
245
+ ----------------------------------------------------------------------
246
+ Ran 29 tests in 1.321s
247
+
248
+ FAILED (failures=1, errors=8)
tests/test_day2_engine.py CHANGED
@@ -152,7 +152,7 @@ jobs:
152
  "changed_lines_count": 1,
153
  }
154
 
155
- reward = self.reward_calculator.calculate_step_reward(
156
  state=state,
157
  action="validate_fix",
158
  result=result,
@@ -181,7 +181,7 @@ jobs:
181
  "changed_lines_count": 500,
182
  }
183
 
184
- reward = self.reward_calculator.calculate_step_reward(
185
  state=state,
186
  action="edit_config",
187
  result=result,
 
152
  "changed_lines_count": 1,
153
  }
154
 
155
+ reward, _ = self.reward_calculator.calculate_step_reward(
156
  state=state,
157
  action="validate_fix",
158
  result=result,
 
181
  "changed_lines_count": 500,
182
  }
183
 
184
+ reward, _ = self.reward_calculator.calculate_step_reward(
185
  state=state,
186
  action="edit_config",
187
  result=result,
tests/test_inference.py CHANGED
@@ -28,10 +28,10 @@ class InferenceOutputFormatTests(unittest.TestCase):
28
 
29
  start_pattern = re.compile(r"^\[START\] task=\S+ env=\S+ model=.+$")
30
  step_pattern = re.compile(
31
- r"^\[STEP\] step=\d+ action=.* reward=-?\d+\.\d{2} done=(true|false) error=(null|.+)$"
32
  )
33
  end_pattern = re.compile(
34
- r"^\[END\] success=(true|false) steps=\d+ score=\d+\.\d{3} rewards=(-?\d+\.\d{2}(,-?\d+\.\d{2})*)?$"
35
  )
36
 
37
  self.assertRegex(lines[0], start_pattern)
 
28
 
29
  start_pattern = re.compile(r"^\[START\] task=\S+ env=\S+ model=.+$")
30
  step_pattern = re.compile(
31
+ r"^\[STEP\] step=\d+ action=.* reward=-?\d+\.\d{3} done=(true|false) error=(null|.+)$"
32
  )
33
  end_pattern = re.compile(
34
+ r"^\[END\] success=(true|false) steps=\d+ score=\d+\.\d{3} rewards=(-?\d+\.\d{3}(,-?\d+\.\d{3})*)?$"
35
  )
36
 
37
  self.assertRegex(lines[0], start_pattern)