|
| 1 | +--- |
| 2 | +title: SQL Query Optimization Environment |
| 3 | +emoji: 🗄️ |
| 4 | +colorFrom: indigo |
| 5 | +colorTo: blue |
| 6 | +sdk: docker |
| 7 | +pinned: false |
| 8 | +app_port: 8000 |
| 9 | +base_path: /web |
| 10 | +tags: |
| 11 | + - openenv |
| 12 | + - sql |
| 13 | + - duckdb |
| 14 | + - optimization |
| 15 | +--- |
| 16 | + |
| 17 | +# SQL Query Optimization Environment |
| 18 | + |
| 19 | +An **execution-grounded** environment for training agents to write fast SQL. The |
| 20 | +agent is given a slow query plus its schema and must return a rewrite. Reward is |
| 21 | +**not** a keyword heuristic: the environment runs both the original and the |
| 22 | +optimized query against a real in-memory **DuckDB** database seeded with |
| 23 | +realistic synthetic data (10k users, 500k orders, 1k products, 1M events), then |
| 24 | +scores the agent on measured speedup and result-correctness. |
| 25 | + |
| 26 | +Five tasks scale from basic anti-patterns to expert window-function audits. |
| 27 | + |
| 28 | +## Quick Start |
| 29 | + |
| 30 | +```python |
| 31 | +from sql_optim_env import SQLOptimAction, SQLOptimEnv |
| 32 | + |
| 33 | +with SQLOptimEnv(base_url="http://localhost:8000").sync() as env: |
| 34 | + obs = env.reset(task_id="task_1_basic_antipatterns").observation |
| 35 | + print(obs.sql_query) # the slow query to fix |
| 36 | + print(obs.schema_info) # tables, row counts |
| 37 | + |
| 38 | + result = env.step( |
| 39 | + SQLOptimAction( |
| 40 | + suggestions=[ |
| 41 | + {"issue_type": "select_star", "line": 1, |
| 42 | + "description": "SELECT * reads every column", "severity": "high", |
| 43 | + "fix": "project only the needed columns"}, |
| 44 | + ], |
| 45 | + optimized_query="SELECT id FROM orders WHERE customer_id = 5000", |
| 46 | + summary="Dropped SELECT * and the non-sargable CAST.", |
| 47 | + estimated_improvement="~10x faster", |
| 48 | + approved=False, |
| 49 | + ) |
| 50 | + ) |
| 51 | + print(result.reward, result.done) |
| 52 | + print(result.metadata["reward_breakdown"]) |
| 53 | + print(result.metadata["execution"]["speedup"]) # real DuckDB speedup |
| 54 | +``` |
| 55 | + |
| 56 | +Async usage mirrors the other environments: |
| 57 | + |
| 58 | +```python |
| 59 | +async with SQLOptimEnv(base_url="http://localhost:8000") as env: |
| 60 | + result = await env.reset(task_id="task_1_basic_antipatterns") |
| 61 | +``` |
| 62 | + |
| 63 | +## Action |
| 64 | + |
| 65 | +| Field | Type | Meaning | |
| 66 | +|-------|------|---------| |
| 67 | +| `suggestions` | `list[dict]` | Issues found: `issue_type`, `line`, `description`, `severity`, `fix` | |
| 68 | +| `optimized_query` | `str` | The rewritten SQL — executed for real | |
| 69 | +| `summary` | `str` | Overall analysis | |
| 70 | +| `estimated_improvement` | `str` | Agent's own speedup estimate | |
| 71 | +| `approved` | `bool` | `True` if the query is already optimal | |
| 72 | + |
| 73 | +## Observation |
| 74 | + |
| 75 | +`sql_query`, `schema_info`, `task_description`, `difficulty`, `step_count`, |
| 76 | +`max_steps`, `issues_found_so_far`, and `last_execution` (the previous step's |
| 77 | +real timing comparison, so the agent can refine its rewrite). The step reward is |
| 78 | +on `reward`; the composite `reward_breakdown`, `feedback`, and full `execution` |
| 79 | +comparison are under `metadata`. |
| 80 | + |
| 81 | +## Reward |
| 82 | + |
| 83 | +Composite score in `[0, 1]`, computed inside the environment: |
| 84 | + |
| 85 | +| Component | Weight | Source | |
| 86 | +|-----------|--------|--------| |
| 87 | +| Execution speedup | 35% | real DuckDB timing ratio | |
| 88 | +| Result correctness | 20% | do both queries return identical rows? | |
| 89 | +| Issue detection | 25% | flagged issues vs. ground truth | |
| 90 | +| Approval correctness | 8% | correctly judged the query bad/good | |
| 91 | +| Summary quality | 7% | thoroughness of the written analysis | |
| 92 | +| Severity labels | 5% | severities present | |
| 93 | + |
| 94 | +## Tasks |
| 95 | + |
| 96 | +Five tasks (`task_1_basic_antipatterns` … `task_5_*`) covering `SELECT *`, |
| 97 | +non-sargable predicates, functions on filter columns, join ordering, and window |
| 98 | +functions, spanning `easy` → `expert`. |
| 99 | + |
| 100 | +## Run the server locally |
| 101 | + |
| 102 | +```bash |
| 103 | +uvicorn server.app:app --host 0.0.0.0 --port 8000 |
| 104 | +``` |
| 105 | + |
| 106 | +## Tests |
| 107 | + |
| 108 | +```bash |
| 109 | +PYTHONPATH=src:envs uv run pytest tests/envs/test_sql_optim_environment.py -v |
| 110 | +``` |
0 commit comments