sravaniamere commited on
Commit
0e2347e
·
1 Parent(s): 14fb228

use openenv core base classes

Browse files
Files changed (1) hide show
  1. sql_env/server.py +109 -137
sql_env/server.py CHANGED
@@ -1,142 +1,114 @@
1
  """
2
- FastAPI HTTP wrapper for SQLCorrectionEnv.
3
-
4
- Exposes the OpenEnv-required endpoints: /reset, /step, /state + /tasks for validator.
5
  """
6
-
7
- from contextlib import asynccontextmanager
8
- from typing import Optional
9
-
10
- from fastapi import FastAPI, HTTPException
11
- from fastapi.middleware.cors import CORSMiddleware
12
- from pydantic import BaseModel
13
-
14
- from sql_env import SQLAction, SQLCorrectionEnv
15
- from sql_env.tasks import ALL_TASKS
16
-
17
-
18
- class ResetRequest(BaseModel):
19
- difficulty: Optional[str] = "easy"
20
- task_name: Optional[str] = None
21
- task_index: Optional[int] = None
22
-
23
-
24
- class StepRequest(BaseModel):
25
- corrected_query: str
26
-
27
-
28
- env: Optional[SQLCorrectionEnv] = None
29
-
30
-
31
- @asynccontextmanager
32
- async def lifespan(_: FastAPI):
33
- global env
34
- env = SQLCorrectionEnv(difficulty="easy")
35
- yield
36
- if env is not None:
37
- await env.close()
38
-
39
-
40
- app = FastAPI(
41
- title="SQL Correction RL Environment",
42
- description="OpenEnv-compliant environment for SQL query correction tasks.",
43
- version="1.0.0",
44
- lifespan=lifespan,
45
- )
46
-
47
- app.add_middleware(
48
- CORSMiddleware,
49
- allow_origins=["*"],
50
- allow_methods=["*"],
51
- allow_headers=["*"],
52
- )
53
-
54
-
55
- @app.post("/reset")
56
- async def reset(request: ResetRequest = ResetRequest()):
57
- """Reset the environment and return the initial observation."""
58
- global env
59
- difficulty = request.task_name or request.difficulty or "easy"
60
- if difficulty not in {"easy", "medium", "hard"}:
61
- raise HTTPException(status_code=400, detail="difficulty must be easy, medium, or hard")
62
-
63
- env = SQLCorrectionEnv(
64
- difficulty=difficulty,
65
- task_index=request.task_index,
66
- )
67
- obs = await env.reset()
68
- return obs.model_dump()
69
-
70
-
71
- @app.post("/step")
72
- async def step(request: StepRequest):
73
- """Take one step and return the new observation, reward, done flag, and info."""
74
- global env
75
- if env is None:
76
- raise HTTPException(status_code=400, detail="Call /reset first.")
77
-
78
- try:
79
- action = SQLAction(corrected_query=request.corrected_query)
80
- result = await env.step(action)
81
- return result.model_dump()
82
- except RuntimeError as exc:
83
- raise HTTPException(status_code=400, detail=str(exc)) from exc
84
-
85
-
86
- @app.post("/state")
87
- async def state():
88
- """Return current environment state."""
89
- global env
90
- if env is None:
91
- return {"status": "not_initialized"}
92
- return await env.state()
93
-
94
-
95
- @app.get("/health")
96
- async def health():
97
- return {"status": "ok", "service": "sql-correction-env"}
98
-
99
-
100
- @app.get("/tasks")
101
- async def list_tasks():
102
- return {
103
- "tasks": [
104
- {
105
- "name": "easy",
106
- "difficulty": "easy",
107
- "description": "Fix a single syntax error. Error hint provided.",
108
- "max_steps": 5,
109
- "has_grader": True,
110
- "grader": "sql_env.grader.grade",
111
- },
112
- {
113
- "name": "medium",
114
- "difficulty": "medium",
115
- "description": "Fix multiple errors. No hint.",
116
- "max_steps": 5,
117
- "has_grader": True,
118
- "grader": "sql_env.grader.grade",
119
- },
120
- {
121
- "name": "hard",
122
- "difficulty": "hard",
123
- "description": "Fix complex multi-join queries. Schema provided.",
124
- "max_steps": 4,
125
- "has_grader": True,
126
- "grader": "sql_env.grader.grade",
127
- },
128
- ]
129
- }
130
-
131
-
132
- @app.get("/")
133
- async def root():
134
- return {
135
- "name": "SQL Correction RL Environment",
136
- "version": "1.0.0",
137
- "endpoints": ["/reset", "/step", "/state", "/health", "/tasks"],
138
- "tasks": ["easy", "medium", "hard"],
139
- }
140
 
141
 
142
  def main():
 
1
  """
2
+ FastAPI HTTP wrapper for SQLCorrectionEnv using openenv.core base classes.
 
 
3
  """
4
+ from openenv.core.env_server import create_fastapi_app
5
+ from openenv.core.env_server.interfaces import Environment
6
+ from openenv.core.env_server.types import State
7
+ from sql_env.models import SQLAction, SQLObservation
8
+ from sql_env.tasks import ALL_TASKS, TASK_SETS
9
+ from sql_env.grader import grade, generate_feedback
10
+ import random
11
+
12
+
13
+ class SQLCorrectionEnvironment(Environment):
14
+
15
+ def __init__(self):
16
+ super().__init__()
17
+ self._difficulty = "easy"
18
+ self._current_task = None
19
+ self._step_count = 0
20
+ self._done = False
21
+ self._last_reward = 0.0
22
+ self._previous_attempt = None
23
+ self._feedback = None
24
+ self._rewards_history = []
25
+
26
+ def reset(self, difficulty: str = "easy") -> SQLObservation:
27
+ self._difficulty = difficulty
28
+ tasks = TASK_SETS.get(difficulty, TASK_SETS["easy"])
29
+ self._current_task = random.choice(tasks)
30
+ self._step_count = 0
31
+ self._done = False
32
+ self._last_reward = 0.0
33
+ self._previous_attempt = None
34
+ self._feedback = None
35
+ self._rewards_history = []
36
+ return SQLObservation(
37
+ task_id=self._current_task.task_id,
38
+ broken_query=self._current_task.broken_query,
39
+ schema_context=self._current_task.schema_context,
40
+ error_hint=self._current_task.error_hint,
41
+ step_number=0,
42
+ previous_attempt=None,
43
+ feedback=None,
44
+ )
45
+
46
+ def step(self, action: SQLAction) -> SQLObservation:
47
+ self._step_count += 1
48
+ reward_obj = grade(action, self._current_task)
49
+ reward = reward_obj.value
50
+ self._last_reward = reward
51
+ self._previous_attempt = action.corrected_query
52
+ self._feedback = generate_feedback(action, self._current_task, reward_obj)
53
+ self._rewards_history.append(reward)
54
+ done = (reward >= 0.95) or (self._step_count >= self._current_task.max_steps)
55
+ self._done = done
56
+ return SQLObservation(
57
+ task_id=self._current_task.task_id,
58
+ broken_query=self._current_task.broken_query,
59
+ schema_context=self._current_task.schema_context,
60
+ error_hint=self._current_task.error_hint,
61
+ step_number=self._step_count,
62
+ previous_attempt=self._previous_attempt,
63
+ feedback=self._feedback,
64
+ )
65
+
66
+ @property
67
+ def state(self) -> dict:
68
+ if self._current_task is None:
69
+ return {"status": "not_initialized"}
70
+ return {
71
+ "task_id": self._current_task.task_id,
72
+ "difficulty": self._difficulty,
73
+ "step_count": self._step_count,
74
+ "done": self._done,
75
+ "last_reward": self._last_reward,
76
+ "rewards_history": self._rewards_history,
77
+ }
78
+
79
+ def get_tasks(self):
80
+ return {
81
+ "tasks": [
82
+ {
83
+ "name": "easy",
84
+ "difficulty": "easy",
85
+ "description": "Fix a single syntax error. Error hint provided.",
86
+ "max_steps": 5,
87
+ "has_grader": True,
88
+ "grader": "sql_env.grader.grade",
89
+ },
90
+ {
91
+ "name": "medium",
92
+ "difficulty": "medium",
93
+ "description": "Fix multiple errors. No hint.",
94
+ "max_steps": 5,
95
+ "has_grader": True,
96
+ "grader": "sql_env.grader.grade",
97
+ },
98
+ {
99
+ "name": "hard",
100
+ "difficulty": "hard",
101
+ "description": "Fix complex multi-join queries. Schema provided.",
102
+ "max_steps": 4,
103
+ "has_grader": True,
104
+ "grader": "sql_env.grader.grade",
105
+ },
106
+ ]
107
+ }
108
+
109
+
110
+ env = SQLCorrectionEnvironment()
111
+ app = create_fastapi_app(env, SQLAction, SQLObservation)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
 
114
  def main():