sravaniamere commited on
Commit
1a1713a
·
1 Parent(s): 51264be

Fix server entrypoint packaging and align environment docs

Browse files
Files changed (7) hide show
  1. README.md +21 -20
  2. openenv.yaml +2 -2
  3. pyproject.toml +1 -1
  4. server.py +5 -107
  5. server/app.py +0 -8
  6. sql_env/models.py +1 -1
  7. sql_env/server.py +116 -0
README.md CHANGED
@@ -1,6 +1,6 @@
1
  ---
2
  title: SQL Correction RL Environment
3
- emoji: 🛢
4
  colorFrom: blue
5
  colorTo: indigo
6
  sdk: docker
@@ -12,15 +12,16 @@ tags:
12
  # SQL Correction RL Environment
13
 
14
  An **OpenEnv-compliant** reinforcement learning environment where an AI agent
15
- learns to fix broken SQL queries a real task that developers face every day.
16
 
17
  ---
18
 
19
  ## Description & Motivation
20
 
21
- SQL errors are one of the most common and costly mistakes in software development.
22
- This environment trains agents to identify and correct SQL syntax and logical
23
- errors, ranging from simple typos to complex multi-join query reconstruction.
 
24
 
25
  The environment provides **partial progress signals** at every step; the agent
26
  receives graded feedback even for near-correct answers, enabling meaningful
@@ -34,7 +35,7 @@ learning across the full trajectory rather than sparse end-of-episode rewards.
34
  |--------------------|-----------------|----------------------------------------------------------|
35
  | `task_id` | string | Unique identifier for the current task instance |
36
  | `broken_query` | string | The malformed SQL query the agent must fix |
37
- | `schema_context` | string or null | Table/column definitions (provided for medium/hard tasks)|
38
  | `error_hint` | string or null | Plain-language hint about the error (easy tasks only) |
39
  | `step_number` | integer | Current step within the episode |
40
  | `previous_attempt` | string or null | The agent's SQL output from the previous step |
@@ -42,9 +43,9 @@ learning across the full trajectory rather than sparse end-of-episode rewards.
42
 
43
  ## Action Space
44
 
45
- | Field | Type | Description |
46
- |--------------------|--------|------------------------------------|
47
- | `corrected_query` | string | The agent's corrected SQL query |
48
 
49
  ---
50
 
@@ -52,9 +53,9 @@ learning across the full trajectory rather than sparse end-of-episode rewards.
52
 
53
  | Name | Difficulty | Max Steps | Description |
54
  |----------|------------|-----------|-------------|
55
- | `easy` | Easy | 5 | Fix a single syntax error (e.g. `FORM` `FROM`). Hint provided. |
56
- | `medium` | Medium | 6 | Fix multiple errors including missing keywords and wrong clauses. Schema provided, no hint. |
57
- | `hard` | Hard | 8 | Fix complex multi-join queries with subtle errors and wrong clause ordering. Schema provided, no hint. |
58
 
59
  ---
60
 
@@ -64,11 +65,11 @@ learning across the full trajectory rather than sparse end-of-episode rewards.
64
  |-------|-----------|
65
  | `1.0` | Exact match after normalization (perfect fix) |
66
  | `0.7` | All correct tokens present, structure slightly off |
67
- | `0.5` | Mostly correct small errors remain |
68
- | `0.3` | Partial fix several errors remain |
69
  | `0.0` | Query still incorrect |
70
 
71
- Episodes terminate when reward = 1.0 (success) or max_steps is reached.
72
 
73
  ---
74
 
@@ -125,11 +126,11 @@ SQL_ENV_TASK=hard python inference.py
125
 
126
  ## Baseline Scores
127
 
128
- | Task | Model | Avg Score | Notes |
129
- |--------|------------------------|-----------|-------|
130
- | easy | Qwen/Qwen2.5-72B | ~0.85 | Single typo fix, hint provided |
131
- | medium | Qwen/Qwen2.5-72B | ~0.62 | Multi-error, schema-guided |
132
- | hard | Qwen/Qwen2.5-72B | ~0.38 | Complex multi-join, no hint |
133
 
134
  *Run `inference.py` against the live Space to reproduce these scores.*
135
 
 
1
  ---
2
  title: SQL Correction RL Environment
3
+ emoji: "🛠"
4
  colorFrom: blue
5
  colorTo: indigo
6
  sdk: docker
 
12
  # SQL Correction RL Environment
13
 
14
  An **OpenEnv-compliant** reinforcement learning environment where an AI agent
15
+ learns to fix broken SQL queries, a real task that developers face every day.
16
 
17
  ---
18
 
19
  ## Description & Motivation
20
 
21
+ SQL errors are one of the most common and costly mistakes in software
22
+ development. This environment trains agents to identify and correct SQL syntax
23
+ and logical errors, ranging from simple typos to complex multi-join query
24
+ reconstruction.
25
 
26
  The environment provides **partial progress signals** at every step; the agent
27
  receives graded feedback even for near-correct answers, enabling meaningful
 
35
  |--------------------|-----------------|----------------------------------------------------------|
36
  | `task_id` | string | Unique identifier for the current task instance |
37
  | `broken_query` | string | The malformed SQL query the agent must fix |
38
+ | `schema_context` | string or null | Table and column definitions when a task includes them |
39
  | `error_hint` | string or null | Plain-language hint about the error (easy tasks only) |
40
  | `step_number` | integer | Current step within the episode |
41
  | `previous_attempt` | string or null | The agent's SQL output from the previous step |
 
43
 
44
  ## Action Space
45
 
46
+ | Field | Type | Description |
47
+ |--------------------|--------|---------------------------------|
48
+ | `corrected_query` | string | The agent's corrected SQL query |
49
 
50
  ---
51
 
 
53
 
54
  | Name | Difficulty | Max Steps | Description |
55
  |----------|------------|-----------|-------------|
56
+ | `easy` | Easy | 5 | Fix a single syntax error (for example `FORM` -> `FROM`). Hint provided. |
57
+ | `medium` | Medium | 5 | Fix multiple errors including missing keywords and wrong clauses. No hint. |
58
+ | `hard` | Hard | 4 | Fix complex multi-join queries with subtle errors and wrong clause ordering. Schema provided, no hint. |
59
 
60
  ---
61
 
 
65
  |-------|-----------|
66
  | `1.0` | Exact match after normalization (perfect fix) |
67
  | `0.7` | All correct tokens present, structure slightly off |
68
+ | `0.4` | Most keywords correct and token overlap is high |
69
+ | `0.2` | Basic `SELECT ... FROM ...` structure present |
70
  | `0.0` | Query still incorrect |
71
 
72
+ Episodes terminate when reward = 1.0 (success) or max steps is reached.
73
 
74
  ---
75
 
 
126
 
127
  ## Baseline Scores
128
 
129
+ | Task | Model | Avg Score | Notes |
130
+ |--------|------------------|-----------|-------|
131
+ | easy | Qwen/Qwen2.5-72B | ~0.85 | Single typo fix, hint provided |
132
+ | medium | Qwen/Qwen2.5-72B | ~0.62 | Multi-error correction |
133
+ | hard | Qwen/Qwen2.5-72B | ~0.38 | Complex multi-join, schema-guided |
134
 
135
  *Run `inference.py` against the live Space to reproduce these scores.*
136
 
openenv.yaml CHANGED
@@ -23,7 +23,7 @@ observation_space:
23
  schema_context:
24
  type: string
25
  nullable: true
26
- description: Table and column definitions (provided on hard tasks only)
27
  error_hint:
28
  type: string
29
  nullable: true
@@ -73,4 +73,4 @@ tasks:
73
  endpoints:
74
  reset: POST /reset
75
  step: POST /step
76
- state: GET /state
 
23
  schema_context:
24
  type: string
25
  nullable: true
26
+ description: Table and column definitions when a task includes schema context
27
  error_hint:
28
  type: string
29
  nullable: true
 
73
  endpoints:
74
  reset: POST /reset
75
  step: POST /step
76
+ state: POST /state
pyproject.toml CHANGED
@@ -20,4 +20,4 @@ build-backend = "hatchling.build"
20
  packages = ["sql_env"]
21
 
22
  [project.scripts]
23
- server = "server.app:main"
 
20
  packages = ["sql_env"]
21
 
22
  [project.scripts]
23
+ server = "sql_env.server:main"
server.py CHANGED
@@ -1,111 +1,9 @@
1
- """
2
- server.py — FastAPI HTTP wrapper for SQLCorrectionEnv
3
- Exposes the OpenEnv-required endpoints: /reset, /step, /state
4
- """
5
 
6
- import os
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 SQLCorrectionEnv, SQLAction
15
 
16
-
17
- # ── Request / Response schemas ────────────────────────────────
18
-
19
- class ResetRequest(BaseModel):
20
- difficulty: Optional[str] = "easy"
21
- task_name: Optional[str] = None
22
- task_index: Optional[int] = None
23
-
24
-
25
- class StepRequest(BaseModel):
26
- corrected_query: str
27
-
28
-
29
- # ── App setup ─────────────────────────────────────────────────
30
-
31
- env: Optional[SQLCorrectionEnv] = None
32
-
33
-
34
- @asynccontextmanager
35
- async def lifespan(app: FastAPI):
36
- global env
37
- env = SQLCorrectionEnv(difficulty="easy")
38
- yield
39
- if env:
40
- await env.close()
41
-
42
-
43
- app = FastAPI(
44
- title="SQL Correction RL Environment",
45
- description="OpenEnv-compliant environment for SQL query correction tasks.",
46
- version="1.0.0",
47
- lifespan=lifespan,
48
- )
49
-
50
- app.add_middleware(
51
- CORSMiddleware,
52
- allow_origins=["*"],
53
- allow_methods=["*"],
54
- allow_headers=["*"],
55
- )
56
-
57
-
58
- # ── Endpoints ─────────────────────────────────────────────────
59
-
60
- @app.post("/reset")
61
- async def reset(request: ResetRequest = ResetRequest()):
62
- """Reset the environment. Returns initial observation."""
63
- global env
64
- difficulty = request.task_name or request.difficulty or "easy"
65
- if difficulty not in ("easy", "medium", "hard"):
66
- raise HTTPException(status_code=400, detail="difficulty must be easy, medium, or hard")
67
-
68
- env = SQLCorrectionEnv(
69
- difficulty=difficulty,
70
- task_index=request.task_index,
71
- )
72
- obs = await env.reset()
73
- return obs.model_dump()
74
-
75
-
76
- @app.post("/step")
77
- async def step(request: StepRequest):
78
- """Take one step. Returns observation, reward, done, info."""
79
- global env
80
- if env is None:
81
- raise HTTPException(status_code=400, detail="Call /reset first.")
82
- try:
83
- action = SQLAction(corrected_query=request.corrected_query)
84
- result = await env.step(action)
85
- return result.model_dump()
86
- except RuntimeError as e:
87
- raise HTTPException(status_code=400, detail=str(e))
88
-
89
-
90
- @app.post("/state")
91
- async def state():
92
- """Return current environment state."""
93
- global env
94
- if env is None:
95
- return {"status": "not_initialized"}
96
- return await env.state()
97
-
98
-
99
- @app.get("/health")
100
- async def health():
101
- return {"status": "ok", "service": "sql-correction-env"}
102
-
103
-
104
- @app.get("/")
105
- async def root():
106
- return {
107
- "name": "SQL Correction RL Environment",
108
- "version": "1.0.0",
109
- "endpoints": ["/reset", "/step", "/state", "/health"],
110
- "tasks": ["easy", "medium", "hard"],
111
- }
 
1
+ """Compatibility wrapper for local `python server.py` runs."""
 
 
 
2
 
3
+ from sql_env.server import app, main
 
 
4
 
5
+ __all__ = ["app", "main"]
 
 
6
 
 
7
 
8
+ if __name__ == "__main__":
9
+ main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
server/app.py DELETED
@@ -1,8 +0,0 @@
1
- from server import app
2
- import uvicorn
3
-
4
- def main():
5
- uvicorn.run(app, host="0.0.0.0", port=7860)
6
-
7
- if __name__ == "__main__":
8
- main()
 
 
 
 
 
 
 
 
 
sql_env/models.py CHANGED
@@ -35,4 +35,4 @@ class StepResult(BaseModel):
35
  observation: SQLObservation
36
  reward: float
37
  done: bool
38
- info: Dict[str, Any] = {}
 
35
  observation: SQLObservation
36
  reward: float
37
  done: bool
38
+ info: Dict[str, Any] = Field(default_factory=dict)
sql_env/server.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ FastAPI HTTP wrapper for SQLCorrectionEnv.
3
+
4
+ Exposes the OpenEnv-required endpoints: /reset, /step, /state.
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
+
16
+
17
+ class ResetRequest(BaseModel):
18
+ difficulty: Optional[str] = "easy"
19
+ task_name: Optional[str] = None
20
+ task_index: Optional[int] = None
21
+
22
+
23
+ class StepRequest(BaseModel):
24
+ corrected_query: str
25
+
26
+
27
+ env: Optional[SQLCorrectionEnv] = None
28
+
29
+
30
+ @asynccontextmanager
31
+ async def lifespan(_: FastAPI):
32
+ global env
33
+ env = SQLCorrectionEnv(difficulty="easy")
34
+ yield
35
+ if env is not None:
36
+ await env.close()
37
+
38
+
39
+ app = FastAPI(
40
+ title="SQL Correction RL Environment",
41
+ description="OpenEnv-compliant environment for SQL query correction tasks.",
42
+ version="1.0.0",
43
+ lifespan=lifespan,
44
+ )
45
+
46
+ app.add_middleware(
47
+ CORSMiddleware,
48
+ allow_origins=["*"],
49
+ allow_methods=["*"],
50
+ allow_headers=["*"],
51
+ )
52
+
53
+
54
+ @app.post("/reset")
55
+ async def reset(request: ResetRequest = ResetRequest()):
56
+ """Reset the environment and return the initial observation."""
57
+ global env
58
+ difficulty = request.task_name or request.difficulty or "easy"
59
+ if difficulty not in {"easy", "medium", "hard"}:
60
+ raise HTTPException(status_code=400, detail="difficulty must be easy, medium, or hard")
61
+
62
+ env = SQLCorrectionEnv(
63
+ difficulty=difficulty,
64
+ task_index=request.task_index,
65
+ )
66
+ obs = await env.reset()
67
+ return obs.model_dump()
68
+
69
+
70
+ @app.post("/step")
71
+ async def step(request: StepRequest):
72
+ """Take one step and return the new observation, reward, done flag, and info."""
73
+ global env
74
+ if env is None:
75
+ raise HTTPException(status_code=400, detail="Call /reset first.")
76
+
77
+ try:
78
+ action = SQLAction(corrected_query=request.corrected_query)
79
+ result = await env.step(action)
80
+ return result.model_dump()
81
+ except RuntimeError as exc:
82
+ raise HTTPException(status_code=400, detail=str(exc)) from exc
83
+
84
+
85
+ @app.post("/state")
86
+ async def state():
87
+ """Return current environment state."""
88
+ global env
89
+ if env is None:
90
+ return {"status": "not_initialized"}
91
+ return await env.state()
92
+
93
+
94
+ @app.get("/health")
95
+ async def health():
96
+ return {"status": "ok", "service": "sql-correction-env"}
97
+
98
+
99
+ @app.get("/")
100
+ async def root():
101
+ return {
102
+ "name": "SQL Correction RL Environment",
103
+ "version": "1.0.0",
104
+ "endpoints": ["/reset", "/step", "/state", "/health"],
105
+ "tasks": ["easy", "medium", "hard"],
106
+ }
107
+
108
+
109
+ def main():
110
+ import uvicorn
111
+
112
+ uvicorn.run(app, host="0.0.0.0", port=7860)
113
+
114
+
115
+ if __name__ == "__main__":
116
+ main()