Spaces:
Sleeping
Sleeping
File size: 7,355 Bytes
9d28948 8aa8df1 9d28948 8aa8df1 9d28948 14de67e 9496a0e 14de67e 9496a0e 9d28948 9496a0e 14de67e 9d28948 9496a0e 14de67e 9496a0e 14de67e 9496a0e 14de67e 9496a0e 14de67e 38819be 9d28948 14de67e 9d28948 14de67e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | ---
title: SQL-RL (OpenEnv)
emoji: 📊
colorFrom: blue
colorTo: green
sdk: docker
app_port: 7860
pinned: false
tags:
- openenv
---
# SQL-RL (OpenEnv)
## Environment Description and Motivation
This environment simulates a real business workflow: a data analyst converting stakeholder requests into executable SQL over an internal company warehouse.
Why this is real-world:
- HR and finance teams routinely need ad-hoc SQL analysis.
- Models must handle schema understanding, joins, aggregation, and constraints.
- Evaluation is done against deterministic graders over actual query results (not string matching).
The environment implements the OpenEnv lifecycle (`reset()`, `step()`, `state()`) and is deployable on Hugging Face Spaces as a containerized service.
## Action Space
`SqlAction`
- `query: str` - a SQL query to execute against the provided SQLite schema.
## Observation Space
`SqlObservation`
- `current_task_instruction: str` - current objective text.
- `schema_info: str` - schema description.
- `task_id: str` - stable task identifier.
- `difficulty: str` - `easy | medium | hard`.
- `execution_result: Optional[str]` - previous query result rows as JSON.
- `execution_error: Optional[str]` - previous execution or safety error.
- `task_score: float` - grader output in `[0.0, 1.0]`.
- `grader_feedback: Optional[str]` - deterministic grader feedback.
## State
`SqlState`
- Tracks episode id, step count, current task index, accumulated reward, per-task scores, and attempts.
- Exposed via `state()` for inspection and reproducibility.
## Tasks and Difficulty Progression
1. **Easy - `employee_payroll_overview`**
List employee names and salaries in descending salary order.
2. **Medium - `department_budget_summary`**
Compute average salary per department with required output schema.
3. **Hard - `senior_engineering_comp_review`**
Multi-table logic to identify engineering employees meeting senior salary thresholds.
All tasks have deterministic graders producing scores from `0.0` to `1.0`.
## Reward Function
Reward is shaped for trajectory-level signal (not binary terminal only):
- `+0.1` valid SQL execution bonus
- `+0.9 * task_score` progress toward correctness
- `-0.02` per step (discourages loops)
- `-0.5` invalid query penalty
- `-1.0` safety penalty for destructive SQL (`DROP/DELETE/TRUNCATE/ALTER/UPDATE/INSERT`)
Task completion threshold is `task_score >= 0.95`.
Episode ends when all tasks are solved or max attempts for a task are exhausted.
## Setup and Usage
1. Install dependencies:
```bash
pip install -r requirements.txt
```
2. Set **hackathon-required** variables (OpenAI-compatible client):
```bash
export HF_TOKEN="your-api-key"
export API_BASE_URL="https://api.openai.com/v1"
export MODEL_NAME="gpt-4o-mini"
```
`HF_TOKEN` is preferred; `OPENAI_API_KEY` or `API_KEY` are accepted as fallbacks.
3. Run baseline (root `inference.py`):
```bash
python inference.py
```
The baseline uses the **OpenAI Python client** (`openai.OpenAI`) with `base_url=API_BASE_URL` and `api_key=HF_TOKEN` (or fallback). For reproducibility on the official OpenAI API, `temperature=0.0` and `seed=OPENAI_SEED` (default `42`) are used when `API_BASE_URL` points at OpenAI.
### Mandatory stdout format (for automated judging)
`inference.py` prints **only** these structured lines to **stdout** (debug goes to **stderr**):
- `[START] task=<name> env=<benchmark> model=<model>`
- `[STEP] step=<n> action=<sql> reward=<0.00> done=<true|false> error=<msg|null>`
- `[END] success=<true|false> steps=<n> score=<0.000> rewards=<r1,r2,...>`
`[END] score` is the mean of best grader scores seen for the three tasks (each in `[0, 1]`). `success` is `true` when the episode ends with `done` and that mean score is ≥ `0.95`.
## Pre-submission validation
Before submitting, run:
```bash
python hf/pre-validation-script.py
```
This checks files, the stdout contract in `inference.py`, syntax, and `openenv validate` (if the CLI is installed).
## Baseline Score Reporting
Structured `[END]` line carries the aggregate score and per-step rewards; use stderr `[DEBUG]` lines only for local troubleshooting.
## Deploy to Hugging Face Spaces (spec checklist)
1. **Create a Space** → **Docker** template, or link this GitHub repo to a Space.
2. **README frontmatter** (top of this file) must stay valid YAML:
- `sdk: docker`
- `app_port: 7860` (must match `openenv.yaml` `port` and the container listen port)
- `tags:` includes `openenv`
3. **Build**: HF runs `docker build` on the repo root; entrypoint is `Dockerfile` `CMD` → Uvicorn on `0.0.0.0:$PORT` (default **7860**).
4. **Health**: platform probes your app; this repo exposes **`GET /health`** and OpenEnv **`POST /reset`** for automated checks.
5. **Push** the same commit you validated locally (`openenv validate`, `python hf/pre-validation-script.py`).
Local smoke test (matches CI-style build):
```bash
docker build -t sql-agent-env .
docker run --rm -p 7860:7860 -e PORT=7860 sql-agent-env
# Then open http://localhost:7860/health and http://localhost:7860/
```
## Docker and Hugging Face Space
- `Dockerfile` runs `uvicorn server.app:app` with **`PORT`** from the environment (default **7860**).
- `.dockerignore` excludes `.env` and build junk so secrets are not copied into the image.
- Space metadata is configured in this `README.md` frontmatter with `sdk: docker`.
- Health endpoint: `/health`
- **Web playground:** open the Space URL (`/`). Click **Connect session** to open a WebSocket to `/ws`, then **Start episode (reset)** and **Run query (step)**. OpenEnv’s HTTP `POST /reset` and `POST /step` each use a fresh environment instance (stateless); the WebSocket session keeps one episode alive for the UI.
Local container run:
```bash
docker build -t sql-agent-env .
docker run -p 7860:7860 sql-agent-env
```
## OpenEnv Metadata
OpenEnv runtime metadata is declared in `openenv.yaml`.
Validation command:
```bash
openenv validate
```
```mermaid
flowchart TD
Start([Episode Start]) --> EnvInit[Environment loads Task 1]
EnvInit --> Obs[Generate Observation]
Obs -.-> |1. Send Schema and Instruction| Agent((LLM Agent))
Agent -.-> |2. Predicts SQL Query| Step[Environment step function]
Step --> Exec{Execute SQL on SQLite Engine}
Exec -->|SQL Syntax Error| Pen[Return Negative Reward]
Exec -->|Valid SQL| Grader[Evaluate Pandas DataFrame]
Grader --> Match{Compare Expected DataFrame}
Match -->|Perfect Match| Rew1[Reward 1.0 Advance Level]
Match -->|Unordered Match| RewPartial[Reward 0.8]
Match -->|Incorrect Data| Rew0[Reward 0.0]
Pen --> StateUpdate
Rew1 --> StateUpdate
RewPartial --> StateUpdate
Rew0 --> StateUpdate
StateUpdate[Log History and Update Episode state] --> CheckDone{All Tasks Completed Yes or No}
CheckDone -->|No| Obs
CheckDone -->|Yes| Finish([Episode End])
```
## Internal Engine Design
To read more about exactly how the logic is handled under the hood, access the OOP components inside the root directory:
- `server/environment.py`: The orchestrator handling the OpenEnv lifecycle.
- `database/sqlite_manager.py`: Creates ephemeral SQLite sandboxes per session.
- `core/grader.py`: Deterministic result grader with partial credit and detailed feedback.
|