sravaniamere commited on
Commit
c4a66be
·
1 Parent(s): 03b2a1c

revert to working server

Browse files
Files changed (1) hide show
  1. sql_env/server.py +115 -109
sql_env/server.py CHANGED
@@ -1,114 +1,120 @@
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():
 
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 graded tasks by difficulty (RL validator format)."""
103
+ graded_tasks = {
104
+ diff: [task.__dict__ for task in tasks if task.grader is not None]
105
+ for diff, tasks in ALL_TASKS.items()
106
+ }
107
+ return graded_tasks # {"easy": [tasks], "medium": [tasks], "hard": [tasks]}
108
+
109
+
110
+ @app.get("/")
111
+ async def root():
112
+ return {
113
+ "name": "SQL Correction RL Environment",
114
+ "version": "1.0.0",
115
+ "endpoints": ["/reset", "/step", "/state", "/health", "/tasks"],
116
+ "tasks": ["easy", "medium", "hard"],
117
+ }
118
 
119
 
120
  def main():