jankip20 commited on
Commit
5d911cb
·
verified ·
1 Parent(s): 39419fc

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. server/sql_env_environment.py +7 -27
  2. tasks.py +34 -2
server/sql_env_environment.py CHANGED
@@ -95,60 +95,40 @@ class SqlEnvironment(Environment):
95
  }
96
 
97
  def _reward(self, result: dict, query: str) -> float:
98
- """
99
- Reward based on query quality:
100
- - Error: 0.0
101
- - Runs successfully: +0.3
102
- - Returns rows: +0.2
103
- - Uses JOIN: +0.2
104
- - Uses aggregation: +0.2
105
- - Uses WHERE: +0.1
106
- - Columns match task expected: +0.2 bonus
107
- Max possible: 1.0
108
- """
109
  if result["error"]:
110
  return 0.0
111
 
112
  score = 0.0
113
  q = query.lower()
114
 
115
- # Base score for running successfully
116
  score += 0.3
117
 
118
- # Returned actual data
119
  if result["rowcount"] > 0:
120
  score += 0.2
121
 
122
- # Bonus for JOIN
123
  if "join" in q:
124
  score += 0.2
125
 
126
- # Bonus for aggregation
127
  if any(fn in q for fn in ["count(", "sum(", "avg(", "max(", "min("]):
128
  score += 0.2
129
 
130
- # Bonus for WHERE filter
131
  if "where" in q:
132
  score += 0.1
133
 
134
- # Bonus for matching expected columns from task
135
  if self._task and result["columns"]:
136
  matched = sum(
137
  1 for c in self._task.expected_columns
138
- if any(
139
- c in col.lower() or col.lower() in c # ← bidirectional match
140
- for col in result["columns"]
141
- )
142
  )
143
  score += 0.2 * (matched / len(self._task.expected_columns))
144
 
145
- return min(score, 1.0)
 
 
 
146
 
147
- def _pick_task(self) -> Task:
148
- """Pick a task based on TASK_DIFFICULTY env var, or random if unset."""
149
- if TASK_DIFFICULTY in ("easy", "medium", "hard"):
150
- return get_task_by_difficulty(TASK_DIFFICULTY)
151
- return get_random_task()
152
 
153
  # ------------------------------------------------------------------
154
  # Environment interface
 
95
  }
96
 
97
  def _reward(self, result: dict, query: str) -> float:
 
 
 
 
 
 
 
 
 
 
 
98
  if result["error"]:
99
  return 0.0
100
 
101
  score = 0.0
102
  q = query.lower()
103
 
 
104
  score += 0.3
105
 
 
106
  if result["rowcount"] > 0:
107
  score += 0.2
108
 
 
109
  if "join" in q:
110
  score += 0.2
111
 
 
112
  if any(fn in q for fn in ["count(", "sum(", "avg(", "max(", "min("]):
113
  score += 0.2
114
 
 
115
  if "where" in q:
116
  score += 0.1
117
 
 
118
  if self._task and result["columns"]:
119
  matched = sum(
120
  1 for c in self._task.expected_columns
121
+ if any(c in col.lower() or col.lower() in c
122
+ for col in result["columns"])
 
 
123
  )
124
  score += 0.2 * (matched / len(self._task.expected_columns))
125
 
126
+ # ← run grader if available
127
+ if self._task and self._task.grader and result["rows"]:
128
+ grader_score = self._task.grader(result["rows"])
129
+ score = min(score + (grader_score * 0.2), 1.0)
130
 
131
+ return min(score, 1.0)
 
 
 
 
132
 
133
  # ------------------------------------------------------------------
134
  # Environment interface
tasks.py CHANGED
@@ -1,5 +1,5 @@
1
- from dataclasses import dataclass
2
- from typing import List
3
  import random
4
 
5
  @dataclass
@@ -9,6 +9,35 @@ class Task:
9
  expected_columns: List[str]
10
  validation_query: str
11
  difficulty: str
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
  TASKS = [
14
  Task(
@@ -17,6 +46,7 @@ TASKS = [
17
  expected_columns=["name", "salary"],
18
  validation_query="SELECT name, salary FROM employees WHERE salary > 50000",
19
  difficulty="easy",
 
20
  ),
21
  Task(
22
  id="task_02",
@@ -24,6 +54,7 @@ TASKS = [
24
  expected_columns=["name", "department"],
25
  validation_query="SELECT e.name, d.name AS department FROM employees e JOIN departments d ON e.department = d.id",
26
  difficulty="medium",
 
27
  ),
28
  Task(
29
  id="task_03",
@@ -31,6 +62,7 @@ TASKS = [
31
  expected_columns=["name", "avg_salary"],
32
  validation_query="SELECT d.name, AVG(e.salary) AS avg_salary FROM employees e JOIN departments d ON e.department = d.id GROUP BY d.id",
33
  difficulty="hard",
 
34
  ),
35
  ]
36
 
 
1
+ from dataclasses import dataclass, field
2
+ from typing import List, Callable, Any
3
  import random
4
 
5
  @dataclass
 
9
  expected_columns: List[str]
10
  validation_query: str
11
  difficulty: str
12
+ grader: Callable[[List[Any]], float] = None # ← add this
13
+
14
+
15
+ def grader_salary_above_50000(rows: List[Any]) -> float:
16
+ """All returned rows must have salary > 50000."""
17
+ if not rows:
18
+ return 0.0
19
+ correct = all(row[1] > 50000 for row in rows)
20
+ return 1.0 if correct else 0.0
21
+
22
+
23
+ def grader_employee_department_join(rows: List[Any]) -> float:
24
+ """Must return rows with at least 2 columns (name + department)."""
25
+ if not rows:
26
+ return 0.0
27
+ correct = all(len(row) >= 2 for row in rows)
28
+ return 1.0 if correct else 0.0
29
+
30
+
31
+ def grader_avg_salary_per_department(rows: List[Any]) -> float:
32
+ """Must return rows with department name and a numeric avg salary."""
33
+ if not rows:
34
+ return 0.0
35
+ try:
36
+ correct = all(isinstance(row[1], (int, float)) for row in rows)
37
+ return 1.0 if correct else 0.0
38
+ except (IndexError, TypeError):
39
+ return 0.0
40
+
41
 
42
  TASKS = [
43
  Task(
 
46
  expected_columns=["name", "salary"],
47
  validation_query="SELECT name, salary FROM employees WHERE salary > 50000",
48
  difficulty="easy",
49
+ grader=grader_salary_above_50000,
50
  ),
51
  Task(
52
  id="task_02",
 
54
  expected_columns=["name", "department"],
55
  validation_query="SELECT e.name, d.name AS department FROM employees e JOIN departments d ON e.department = d.id",
56
  difficulty="medium",
57
+ grader=grader_employee_department_join,
58
  ),
59
  Task(
60
  id="task_03",
 
62
  expected_columns=["name", "avg_salary"],
63
  validation_query="SELECT d.name, AVG(e.salary) AS avg_salary FROM employees e JOIN departments d ON e.department = d.id GROUP BY d.id",
64
  difficulty="hard",
65
+ grader=grader_avg_salary_per_department,
66
  ),
67
  ]
68