Spaces:
Sleeping
Sleeping
Commit ·
c25fb83
1
Parent(s): a692699
Fix Phase 2 requirements: Add / endpoint for HF health checks and tasks grader definitions
Browse files- artifacts/metrics.json +2 -2
- artifacts/reward_curve.csv +2 -2
- env/graders/deterministic.py +5 -5
- env/graders/llm_judge.py +1 -1
- env/hidden_tests.py +2 -2
- env/rewards.py +1 -1
- openenv.yaml +9 -0
- server/app.py +5 -0
- tests/test_day2_engine.py +1 -1
- tests/test_judge.py +2 -2
artifacts/metrics.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
| 1 |
{
|
| 2 |
-
"average_reward": 0.
|
| 3 |
"failure_reasons": {
|
| 4 |
"max_steps_reached": 1
|
| 5 |
},
|
| 6 |
"steps": 3,
|
| 7 |
"success_rate": 0.3333,
|
| 8 |
-
"total_reward": 1.
|
| 9 |
}
|
|
|
|
| 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,4 +1,4 @@
|
|
| 1 |
step,reward
|
| 2 |
-
1,0.
|
| 3 |
-
2,0.
|
| 4 |
3,0.5700
|
|
|
|
| 1 |
step,reward
|
| 2 |
+
1,0.3020
|
| 3 |
+
2,0.3620
|
| 4 |
3,0.5700
|
env/graders/deterministic.py
CHANGED
|
@@ -46,13 +46,13 @@ class DeterministicGrader:
|
|
| 46 |
|
| 47 |
def _syntax_score(self, config_text: str) -> float:
|
| 48 |
if not (config_text or "").strip():
|
| 49 |
-
return 0.
|
| 50 |
|
| 51 |
try:
|
| 52 |
yaml.safe_load(config_text)
|
| 53 |
return 0.999
|
| 54 |
except yaml.YAMLError:
|
| 55 |
-
return 0.
|
| 56 |
|
| 57 |
def _functional_score(self, current_config: str, expected_config: str, metadata: dict[str, Any]) -> float:
|
| 58 |
expected_commands = self._extract_commands(expected_config)
|
|
@@ -82,10 +82,10 @@ class DeterministicGrader:
|
|
| 82 |
return 0.999
|
| 83 |
|
| 84 |
if broken_token and broken_token in current_normalized:
|
| 85 |
-
return 0.
|
| 86 |
|
| 87 |
if fixed_token and fixed_token not in current_normalized:
|
| 88 |
-
return 0.
|
| 89 |
|
| 90 |
return 0.999
|
| 91 |
|
|
@@ -178,7 +178,7 @@ class DeterministicGrader:
|
|
| 178 |
if not left and not right:
|
| 179 |
return 0.999
|
| 180 |
if not left or not right:
|
| 181 |
-
return 0.
|
| 182 |
|
| 183 |
return self._clamp_01(SequenceMatcher(None, left, right).ratio())
|
| 184 |
|
|
|
|
| 46 |
|
| 47 |
def _syntax_score(self, config_text: str) -> float:
|
| 48 |
if not (config_text or "").strip():
|
| 49 |
+
return 0.0010101
|
| 50 |
|
| 51 |
try:
|
| 52 |
yaml.safe_load(config_text)
|
| 53 |
return 0.999
|
| 54 |
except yaml.YAMLError:
|
| 55 |
+
return 0.0010101
|
| 56 |
|
| 57 |
def _functional_score(self, current_config: str, expected_config: str, metadata: dict[str, Any]) -> float:
|
| 58 |
expected_commands = self._extract_commands(expected_config)
|
|
|
|
| 82 |
return 0.999
|
| 83 |
|
| 84 |
if broken_token and broken_token in current_normalized:
|
| 85 |
+
return 0.0010101
|
| 86 |
|
| 87 |
if fixed_token and fixed_token not in current_normalized:
|
| 88 |
+
return 0.0010101
|
| 89 |
|
| 90 |
return 0.999
|
| 91 |
|
|
|
|
| 178 |
if not left and not right:
|
| 179 |
return 0.999
|
| 180 |
if not left or not right:
|
| 181 |
+
return 0.0010101
|
| 182 |
|
| 183 |
return self._clamp_01(SequenceMatcher(None, left, right).ratio())
|
| 184 |
|
env/graders/llm_judge.py
CHANGED
|
@@ -94,7 +94,7 @@ class LLMJudge:
|
|
| 94 |
def _extract_score(self, text: str, key: str) -> float:
|
| 95 |
match = re.search(rf"{key}\s*[:=\-]\s*([0-9]*\.?[0-9]+)", text, flags=re.IGNORECASE)
|
| 96 |
if not match:
|
| 97 |
-
return 0.
|
| 98 |
return self._clamp(match.group(1))
|
| 99 |
|
| 100 |
def _normalize_partial_scores(self, obj: dict[str, Any]) -> dict[str, float]:
|
|
|
|
| 94 |
def _extract_score(self, text: str, key: str) -> float:
|
| 95 |
match = re.search(rf"{key}\s*[:=\-]\s*([0-9]*\.?[0-9]+)", text, flags=re.IGNORECASE)
|
| 96 |
if not match:
|
| 97 |
+
return 0.0010101
|
| 98 |
return self._clamp(match.group(1))
|
| 99 |
|
| 100 |
def _normalize_partial_scores(self, obj: dict[str, Any]) -> dict[str, float]:
|
env/hidden_tests.py
CHANGED
|
@@ -36,7 +36,7 @@ class HiddenTestRunner:
|
|
| 36 |
expected = expected_config or str(task.get("expected_config", ""))
|
| 37 |
|
| 38 |
if not fixed_config.strip() or not expected.strip():
|
| 39 |
-
return 0.
|
| 40 |
|
| 41 |
total = 0
|
| 42 |
passed = 0
|
|
@@ -50,7 +50,7 @@ class HiddenTestRunner:
|
|
| 50 |
passed += 1
|
| 51 |
|
| 52 |
if total == 0:
|
| 53 |
-
return 0.
|
| 54 |
|
| 55 |
return round(passed / total, 4)
|
| 56 |
|
|
|
|
| 36 |
expected = expected_config or str(task.get("expected_config", ""))
|
| 37 |
|
| 38 |
if not fixed_config.strip() or not expected.strip():
|
| 39 |
+
return 0.0010101
|
| 40 |
|
| 41 |
total = 0
|
| 42 |
passed = 0
|
|
|
|
| 50 |
passed += 1
|
| 51 |
|
| 52 |
if total == 0:
|
| 53 |
+
return 0.0010101
|
| 54 |
|
| 55 |
return round(passed / total, 4)
|
| 56 |
|
env/rewards.py
CHANGED
|
@@ -110,7 +110,7 @@ class RewardCalculator:
|
|
| 110 |
metadata: dict[str, Any],
|
| 111 |
) -> float:
|
| 112 |
if not current_config or not expected_config:
|
| 113 |
-
return 0.
|
| 114 |
|
| 115 |
deterministic_score = result.get("deterministic_score")
|
| 116 |
if deterministic_score is None:
|
|
|
|
| 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:
|
openenv.yaml
CHANGED
|
@@ -29,27 +29,36 @@ tasks:
|
|
| 29 |
- id: "easy-command-typo"
|
| 30 |
difficulty: "easy"
|
| 31 |
failure_stage: "test"
|
|
|
|
| 32 |
- id: "easy-missing-checkout"
|
| 33 |
difficulty: "easy"
|
| 34 |
failure_stage: "build"
|
|
|
|
| 35 |
- id: "easy-yaml-indentation"
|
| 36 |
difficulty: "easy"
|
| 37 |
failure_stage: "build"
|
|
|
|
| 38 |
- id: "medium-python-version"
|
| 39 |
difficulty: "medium"
|
| 40 |
failure_stage: "build"
|
|
|
|
| 41 |
- id: "medium-cache-key"
|
| 42 |
difficulty: "medium"
|
| 43 |
failure_stage: "test"
|
|
|
|
| 44 |
- id: "medium-artifact-permissions"
|
| 45 |
difficulty: "medium"
|
| 46 |
failure_stage: "deploy"
|
|
|
|
| 47 |
- id: "hard-matrix-logic"
|
| 48 |
difficulty: "hard"
|
| 49 |
failure_stage: "test"
|
|
|
|
| 50 |
- id: "hard-conditional-deploy"
|
| 51 |
difficulty: "hard"
|
| 52 |
failure_stage: "deploy"
|
|
|
|
| 53 |
- id: "hard-needs-order"
|
| 54 |
difficulty: "hard"
|
| 55 |
failure_stage: "deploy"
|
|
|
|
|
|
| 29 |
- id: "easy-command-typo"
|
| 30 |
difficulty: "easy"
|
| 31 |
failure_stage: "test"
|
| 32 |
+
graders: ["deterministic"]
|
| 33 |
- id: "easy-missing-checkout"
|
| 34 |
difficulty: "easy"
|
| 35 |
failure_stage: "build"
|
| 36 |
+
graders: ["deterministic"]
|
| 37 |
- id: "easy-yaml-indentation"
|
| 38 |
difficulty: "easy"
|
| 39 |
failure_stage: "build"
|
| 40 |
+
graders: ["deterministic"]
|
| 41 |
- id: "medium-python-version"
|
| 42 |
difficulty: "medium"
|
| 43 |
failure_stage: "build"
|
| 44 |
+
graders: ["deterministic", "llm_judge"]
|
| 45 |
- id: "medium-cache-key"
|
| 46 |
difficulty: "medium"
|
| 47 |
failure_stage: "test"
|
| 48 |
+
graders: ["deterministic", "llm_judge"]
|
| 49 |
- id: "medium-artifact-permissions"
|
| 50 |
difficulty: "medium"
|
| 51 |
failure_stage: "deploy"
|
| 52 |
+
graders: ["deterministic", "llm_judge"]
|
| 53 |
- id: "hard-matrix-logic"
|
| 54 |
difficulty: "hard"
|
| 55 |
failure_stage: "test"
|
| 56 |
+
graders: ["deterministic", "llm_judge"]
|
| 57 |
- id: "hard-conditional-deploy"
|
| 58 |
difficulty: "hard"
|
| 59 |
failure_stage: "deploy"
|
| 60 |
+
graders: ["deterministic", "llm_judge"]
|
| 61 |
- id: "hard-needs-order"
|
| 62 |
difficulty: "hard"
|
| 63 |
failure_stage: "deploy"
|
| 64 |
+
graders: ["deterministic", "llm_judge"]
|
server/app.py
CHANGED
|
@@ -89,6 +89,11 @@ def _build_step_response(session: RuntimeSession) -> StepResponse:
|
|
| 89 |
)
|
| 90 |
|
| 91 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
@app.get("/health")
|
| 93 |
def health() -> dict[str, str]:
|
| 94 |
return {"status": "ok"}
|
|
|
|
| 89 |
)
|
| 90 |
|
| 91 |
|
| 92 |
+
@app.get("/")
|
| 93 |
+
def read_root() -> dict[str, str]:
|
| 94 |
+
return {"status": "ok", "message": "CI/CD Debugger OpenEnv Server is running"}
|
| 95 |
+
|
| 96 |
+
|
| 97 |
@app.get("/health")
|
| 98 |
def health() -> dict[str, str]:
|
| 99 |
return {"status": "ok"}
|
tests/test_day2_engine.py
CHANGED
|
@@ -71,7 +71,7 @@ class Day2EngineTests(unittest.TestCase):
|
|
| 71 |
|
| 72 |
def test_deterministic_grader_penalizes_broken_yaml(self):
|
| 73 |
score = self.grader.grade(BROKEN_YAML, EXPECTED_CONFIG)
|
| 74 |
-
self.assertLess(score, 0.
|
| 75 |
|
| 76 |
def test_deterministic_grader_is_reproducible(self):
|
| 77 |
first = self.grader.grade(WRONG_CONFIG, EXPECTED_CONFIG)
|
|
|
|
| 71 |
|
| 72 |
def test_deterministic_grader_penalizes_broken_yaml(self):
|
| 73 |
score = self.grader.grade(BROKEN_YAML, EXPECTED_CONFIG)
|
| 74 |
+
self.assertLess(score, 0.5)
|
| 75 |
|
| 76 |
def test_deterministic_grader_is_reproducible(self):
|
| 77 |
first = self.grader.grade(WRONG_CONFIG, EXPECTED_CONFIG)
|
tests/test_judge.py
CHANGED
|
@@ -37,8 +37,8 @@ class LLMJudgeTests(unittest.TestCase):
|
|
| 37 |
result = judge.evaluate_fix("a", "b", "err")
|
| 38 |
|
| 39 |
self.assertAlmostEqual(result["correctness"], 0.8)
|
| 40 |
-
self.assertAlmostEqual(result["minimalism"], 0.
|
| 41 |
-
self.assertAlmostEqual(result["quality"], 0.
|
| 42 |
|
| 43 |
def test_model_failure_returns_zeroes(self):
|
| 44 |
judge = LLMJudge(FakeModel("", raise_error=True))
|
|
|
|
| 37 |
result = judge.evaluate_fix("a", "b", "err")
|
| 38 |
|
| 39 |
self.assertAlmostEqual(result["correctness"], 0.8)
|
| 40 |
+
self.assertAlmostEqual(result["minimalism"], 0.001)
|
| 41 |
+
self.assertAlmostEqual(result["quality"], 0.001)
|
| 42 |
|
| 43 |
def test_model_failure_returns_zeroes(self):
|
| 44 |
judge = LLMJudge(FakeModel("", raise_error=True))
|