Dishaaa25 commited on
Commit
c22bf49
·
verified ·
1 Parent(s): dce68a7

Upload folder using huggingface_hub

Browse files
Files changed (8) hide show
  1. README.md +2 -1
  2. env/graders.py +7 -1
  3. env/quality.py +3 -2
  4. env/rewards.py +8 -2
  5. inference.py +8 -8
  6. openenv.yaml +1 -1
  7. server/app.py +16 -0
  8. test_env.py +2 -2
README.md CHANGED
@@ -54,7 +54,7 @@ openenv-data-cleaning/
54
  | `normalize_category` | Categorical column | `{}` | Only valid when case-only category inconsistencies remain. |
55
  | `create_feature` | Registered feature name | `{"feature_name": "<name>"}` | Feature must be required by the task and its source column must already be clean enough to use. |
56
 
57
- Invalid actions leave the dataset unchanged, emit `{"error": "invalid_action"}` in `info`, consume a step, and return reward `-0.05`.
58
 
59
  ## Observation and State Space
60
 
@@ -89,6 +89,7 @@ Step reward:
89
  ```text
90
  reward = (new_quality - old_quality) + ordering_bonus - 0.01
91
  ordering_bonus = 0.05 if dependencies were already satisfied else 0.0
 
92
  ```
93
 
94
  Dataset quality score combines:
 
54
  | `normalize_category` | Categorical column | `{}` | Only valid when case-only category inconsistencies remain. |
55
  | `create_feature` | Registered feature name | `{"feature_name": "<name>"}` | Feature must be required by the task and its source column must already be clean enough to use. |
56
 
57
+ Invalid actions leave the dataset unchanged, emit `{"error": "invalid_action"}` in `info`, consume a step, and return a low reward `0.01`.
58
 
59
  ## Observation and State Space
60
 
 
89
  ```text
90
  reward = (new_quality - old_quality) + ordering_bonus - 0.01
91
  ordering_bonus = 0.05 if dependencies were already satisfied else 0.0
92
+ reward is then clamped to `(0.01, 0.99)`
93
  ```
94
 
95
  Dataset quality score combines:
env/graders.py CHANGED
@@ -10,4 +10,10 @@ class DataCleaningGrader:
10
  penalty = wrong_actions * 0.05
11
 
12
  score = 0.8 * correctness + 0.2 * efficiency - penalty
13
- return round(max(0.0, min(1.0, score)), 2)
 
 
 
 
 
 
 
10
  penalty = wrong_actions * 0.05
11
 
12
  score = 0.8 * correctness + 0.2 * efficiency - penalty
13
+ # Phase 2 requires task scores to stay strictly inside (0, 1).
14
+ rounded_score= round(max(0.01, min(0.99, score)), 2)
15
+ if rounded_score <= 0.0:
16
+ return 0.01
17
+ if rounded_score >= 1.0:
18
+ return 0.99
19
+ return rounded_score
env/quality.py CHANGED
@@ -51,7 +51,7 @@ def _compute_consistency(dataset: list[dict], column_infos: list) -> float:
51
 
52
  def compute_quality_score(dataset: list[dict], column_infos: list, original_issues_count: int) -> float:
53
  if original_issues_count == 0:
54
- return 1.0
55
 
56
  total_cells = len(dataset) * len(dataset[0]) if dataset else 1
57
  missing_cells = sum(
@@ -65,4 +65,5 @@ def compute_quality_score(dataset: list[dict], column_infos: list, original_issu
65
 
66
  consistency = _compute_consistency(dataset, column_infos)
67
 
68
- return round(0.4 * completeness + 0.3 * uniqueness + 0.3 * consistency, 4)
 
 
51
 
52
  def compute_quality_score(dataset: list[dict], column_infos: list, original_issues_count: int) -> float:
53
  if original_issues_count == 0:
54
+ return 0.99
55
 
56
  total_cells = len(dataset) * len(dataset[0]) if dataset else 1
57
  missing_cells = sum(
 
65
 
66
  consistency = _compute_consistency(dataset, column_infos)
67
 
68
+ score = 0.4 * completeness + 0.3 * uniqueness + 0.3 * consistency
69
+ return round(max(0.01, min(0.99, score)), 4)
env/rewards.py CHANGED
@@ -5,10 +5,16 @@ def compute_reward(
5
  resolved_dependency_correctly: bool,
6
  ) -> float:
7
  if not action_valid:
8
- return -0.05
9
 
10
  progress = new_quality - old_quality
11
  ordering_bonus = 0.05 if resolved_dependency_correctly else 0.0
12
  step_cost = -0.01
13
 
14
- return round(progress + ordering_bonus + step_cost, 4)
 
 
 
 
 
 
 
5
  resolved_dependency_correctly: bool,
6
  ) -> float:
7
  if not action_valid:
8
+ return 0.01
9
 
10
  progress = new_quality - old_quality
11
  ordering_bonus = 0.05 if resolved_dependency_correctly else 0.0
12
  step_cost = -0.01
13
 
14
+ reward = progress + ordering_bonus + step_cost
15
+ rounded_score= round(max(0.01, min(0.99, score)), 2)
16
+ if rounded_score <= 0.0:
17
+ return 0.01
18
+ if rounded_score >= 1.0:
19
+ return 0.99
20
+ return rounded_score
inference.py CHANGED
@@ -15,8 +15,8 @@ from env.graders import DataCleaningGrader
15
  from env.models import Action
16
 
17
  HF_TOKEN = os.getenv("HF_TOKEN")
18
- API_BASE_URL = os.getenv("API_BASE_URL")
19
- MODEL_NAME = os.getenv("MODEL_NAME")
20
  BENCHMARK = "data_cleaning_env"
21
 
22
  TASKS = ["basic_cleaning", "moderate_cleaning", "full_pipeline"]
@@ -91,10 +91,10 @@ def log_step(step, action_str, reward, done, error):
91
  )
92
 
93
 
94
- def log_end(success, steps, score, rewards):
95
  rewards_str = ",".join(f"{reward:.2f}" for reward in rewards)
96
  success_val = str(success).lower()
97
- print(f"[END] success={success_val} steps={steps} score={score:.2f} rewards={rewards_str}", flush=True)
98
 
99
 
100
  def run_task(task_name: str):
@@ -126,7 +126,7 @@ def run_task(task_name: str):
126
  response = client.chat.completions.create(
127
  model=require_env("MODEL_NAME", MODEL_NAME),
128
  messages=messages,
129
- temperature=0.3,
130
  max_tokens=200,
131
  )
132
  response_text = response.choices[0].message.content or ""
@@ -143,8 +143,8 @@ def run_task(task_name: str):
143
 
144
  except Exception as exc:
145
  step_count += 1
146
- rewards_list.append(-0.05)
147
- log_step(step_count, "parse_error", -0.05, False, str(exc))
148
  messages.append(
149
  {
150
  "role": "user",
@@ -163,7 +163,7 @@ def run_task(task_name: str):
163
  "max_steps": max_possible_steps,
164
  },
165
  )
166
- log_end(success, step_count, task_score, rewards_list)
167
  return task_score
168
 
169
 
 
15
  from env.models import Action
16
 
17
  HF_TOKEN = os.getenv("HF_TOKEN")
18
+ API_BASE_URL = os.getenv("API_BASE_URL", "https://router.huggingface.co/v1")
19
+ MODEL_NAME = os.getenv("MODEL_NAME", "openai/gpt-oss-120b")
20
  BENCHMARK = "data_cleaning_env"
21
 
22
  TASKS = ["basic_cleaning", "moderate_cleaning", "full_pipeline"]
 
91
  )
92
 
93
 
94
+ def log_end(success, steps, rewards):
95
  rewards_str = ",".join(f"{reward:.2f}" for reward in rewards)
96
  success_val = str(success).lower()
97
+ print(f"[END] success={success_val} steps={steps} rewards={rewards_str}", flush=True)
98
 
99
 
100
  def run_task(task_name: str):
 
126
  response = client.chat.completions.create(
127
  model=require_env("MODEL_NAME", MODEL_NAME),
128
  messages=messages,
129
+ temperature=0.0,
130
  max_tokens=200,
131
  )
132
  response_text = response.choices[0].message.content or ""
 
143
 
144
  except Exception as exc:
145
  step_count += 1
146
+ rewards_list.append(0.01)
147
+ log_step(step_count, "parse_error", 0.01, False, str(exc))
148
  messages.append(
149
  {
150
  "role": "user",
 
163
  "max_steps": max_possible_steps,
164
  },
165
  )
166
+ log_end(success, step_count, rewards_list)
167
  return task_score
168
 
169
 
openenv.yaml CHANGED
@@ -15,7 +15,7 @@ action_space:
15
  type: dict
16
  description: "Action with action_type, column, and params fields"
17
 
18
- reward_range: [-0.05, 1.0]
19
 
20
  tasks:
21
  - name: basic_cleaning
 
15
  type: dict
16
  description: "Action with action_type, column, and params fields"
17
 
18
+ reward_range: [0.01, 0.99]
19
 
20
  tasks:
21
  - name: basic_cleaning
server/app.py CHANGED
@@ -5,6 +5,7 @@ from typing import Any, Literal
5
 
6
  import uvicorn
7
  from fastapi import Body, FastAPI
 
8
  from pydantic import BaseModel
9
 
10
  from models import Action, Observation
@@ -44,6 +45,21 @@ def root() -> dict[str, Any]:
44
  return payload
45
 
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  @app.get("/health")
48
  def health() -> dict[str, str]:
49
  return {"status": "healthy"}
 
5
 
6
  import uvicorn
7
  from fastapi import Body, FastAPI
8
+ from fastapi.responses import RedirectResponse, Response
9
  from pydantic import BaseModel
10
 
11
  from models import Action, Observation
 
45
  return payload
46
 
47
 
48
+ @app.get("/web", include_in_schema=False)
49
+ def web_root() -> RedirectResponse:
50
+ return RedirectResponse(url="/", status_code=307)
51
+
52
+
53
+ @app.get("/web/", include_in_schema=False)
54
+ def web_root_slash() -> RedirectResponse:
55
+ return RedirectResponse(url="/", status_code=307)
56
+
57
+
58
+ @app.get("/favicon.ico", include_in_schema=False)
59
+ def favicon() -> Response:
60
+ return Response(status_code=204)
61
+
62
+
63
  @app.get("/health")
64
  def health() -> dict[str, str]:
65
  return {"status": "healthy"}
test_env.py CHANGED
@@ -17,7 +17,7 @@ def assert_invalid_action_consumes_step() -> None:
17
  _, reward, _, info = env.step(
18
  Action(action_type="convert_dtype", column="age", params={"target_dtype": "int"})
19
  )
20
- assert reward == -0.05
21
  assert info["error"] == "invalid_action"
22
  assert env.steps_remaining == obs.steps_remaining - 1
23
 
@@ -28,7 +28,7 @@ def assert_dependency_gate() -> None:
28
  _, reward, _, info = env.step(
29
  Action(action_type="convert_dtype", column="salary", params={"target_dtype": "int"})
30
  )
31
- assert reward == -0.05
32
  assert info["error"] == "invalid_action"
33
 
34
 
 
17
  _, reward, _, info = env.step(
18
  Action(action_type="convert_dtype", column="age", params={"target_dtype": "int"})
19
  )
20
+ assert reward == 0.01
21
  assert info["error"] == "invalid_action"
22
  assert env.steps_remaining == obs.steps_remaining - 1
23
 
 
28
  _, reward, _, info = env.step(
29
  Action(action_type="convert_dtype", column="salary", params={"target_dtype": "int"})
30
  )
31
+ assert reward == 0.01
32
  assert info["error"] == "invalid_action"
33
 
34