jankip20 commited on
Commit
47a9696
·
verified ·
1 Parent(s): 1a97659

Upload folder using huggingface_hub

Browse files
Dockerfile ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ # Multi-stage build using openenv-base
8
+ # This Dockerfile is flexible and works for both:
9
+ # - In-repo environments (with local OpenEnv sources)
10
+ # - Standalone environments (with openenv from PyPI/Git)
11
+ # The build script (openenv build) handles context detection and sets appropriate build args.
12
+
13
+ ARG BASE_IMAGE=ghcr.io/meta-pytorch/openenv-base:latest
14
+ FROM ${BASE_IMAGE} AS builder
15
+
16
+ WORKDIR /app
17
+
18
+ # Ensure git is available (required for installing dependencies from VCS)
19
+ RUN apt-get update && \
20
+ apt-get install -y --no-install-recommends git && \
21
+ rm -rf /var/lib/apt/lists/*
22
+
23
+ # Build argument to control whether we're building standalone or in-repo
24
+ ARG BUILD_MODE=in-repo
25
+ ARG ENV_NAME=sql_env
26
+
27
+ # Copy environment code (always at root of build context)
28
+ COPY . /app/env
29
+
30
+ # For in-repo builds, openenv is already vendored in the build context
31
+ # For standalone builds, openenv will be installed via pyproject.toml
32
+ WORKDIR /app/env
33
+
34
+ # Ensure uv is available (for local builds where base image lacks it)
35
+ RUN if ! command -v uv >/dev/null 2>&1; then \
36
+ curl -LsSf https://astral.sh/uv/install.sh | sh && \
37
+ mv /root/.local/bin/uv /usr/local/bin/uv && \
38
+ mv /root/.local/bin/uvx /usr/local/bin/uvx; \
39
+ fi
40
+
41
+ # Install dependencies using uv sync
42
+ # If uv.lock exists, use it; otherwise resolve on the fly
43
+ RUN --mount=type=cache,target=/root/.cache/uv \
44
+ if [ -f uv.lock ]; then \
45
+ uv sync --frozen --no-install-project --no-editable; \
46
+ else \
47
+ uv sync --no-install-project --no-editable; \
48
+ fi
49
+
50
+ RUN --mount=type=cache,target=/root/.cache/uv \
51
+ if [ -f uv.lock ]; then \
52
+ uv sync --frozen --no-editable; \
53
+ else \
54
+ uv sync --no-editable; \
55
+ fi
56
+
57
+ # Final runtime stage
58
+ FROM ${BASE_IMAGE}
59
+
60
+ WORKDIR /app
61
+
62
+ # Copy the virtual environment from builder
63
+ COPY --from=builder /app/env/.venv /app/.venv
64
+
65
+ # Copy the environment code
66
+ COPY --from=builder /app/env /app/env
67
+
68
+ # Set PATH to use the virtual environment
69
+ ENV PATH="/app/.venv/bin:$PATH"
70
+ ENV ENABLE_WEB_INTERFACE=true
71
+ # Set PYTHONPATH so imports work correctly
72
+ ENV PYTHONPATH="/app/env:$PYTHONPATH"
73
+
74
+ # Health check
75
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
76
+ CMD curl -f http://localhost:8000/health || exit 1
77
+
78
+ # Run the FastAPI server
79
+ # The module path is constructed to work with the /app/env structure
80
+ CMD ["sh", "-c", "cd /app/env && uvicorn server.app:app --host 0.0.0.0 --port 8000"]
README.md CHANGED
@@ -1,10 +1,261 @@
1
- ---
2
- title: Sql Env
3
- emoji: 📊
4
- colorFrom: green
5
- colorTo: pink
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: SQL Environment Server
3
+ emoji: 🤖
4
+ colorFrom: blue
5
+ colorTo: indigo
6
+ sdk: docker
7
+ pinned: false
8
+ app_port: 8000
9
+ base_path: /web
10
+ tags:
11
+ - openenv
12
+ - sql
13
+ - database
14
+ - real-world
15
+ name: sql-env
16
+ version: 0.1.0
17
+ ---
18
+
19
+ # Sql Env Environment
20
+
21
+ A real-world SQL task environment where an AI agent writes, debugs, and optimizes SQL queries against a live in-memory database, with automated graders and reward logic using the OpenEnv framework.
22
+
23
+ ## Quick Start
24
+
25
+ The simplest way to use the Sql Env environment is through the `SqlEnv` class:
26
+
27
+ ```python
28
+ from sql_env import SqlAction, SqlEnv
29
+
30
+ try:
31
+ # Create environment from Docker image
32
+ sql_envenv = SqlEnv.from_docker_image("sql_env-env:latest")
33
+
34
+ # Reset
35
+ result = sql_envenv.reset()
36
+ print(f"Reset: {result.observation.echoed_message}")
37
+
38
+ # Send multiple messages
39
+ messages = ["Hello, World!", "Testing echo", "Final message"]
40
+
41
+ for msg in messages:
42
+ result = sql_envenv.step(SqlAction(message=msg))
43
+ print(f"Sent: '{msg}'")
44
+ print(f" → Echoed: '{result.observation.echoed_message}'")
45
+ print(f" → Length: {result.observation.message_length}")
46
+ print(f" → Reward: {result.reward}")
47
+
48
+ finally:
49
+ # Always clean up
50
+ sql_envenv.close()
51
+ ```
52
+
53
+ That's it! The `SqlEnv.from_docker_image()` method handles:
54
+ - Starting the Docker container
55
+ - Waiting for the server to be ready
56
+ - Connecting to the environment
57
+ - Container cleanup when you call `close()`
58
+
59
+ ## Building the Docker Image
60
+
61
+ Before using the environment, you need to build the Docker image:
62
+
63
+ ```bash
64
+ # From project root
65
+ docker docker build -t sql-env .
66
+ ```
67
+
68
+ ## Deploying to Hugging Face Spaces
69
+
70
+ You can easily deploy your OpenEnv environment to Hugging Face Spaces using the `openenv push` command:
71
+
72
+ ```bash
73
+ # From the environment directory (where openenv.yaml is located)
74
+ openenv push
75
+
76
+ # Or specify options
77
+ openenv push --namespace my-org --private
78
+ ```
79
+
80
+ The `openenv push` command will:
81
+ 1. Validate that the directory is an OpenEnv environment (checks for `openenv.yaml`)
82
+ 2. Prepare a custom build for Hugging Face Docker space (enables web interface)
83
+ 3. Upload to Hugging Face (ensuring you're logged in)
84
+
85
+ ### Prerequisites
86
+
87
+ - Authenticate with Hugging Face: The command will prompt for login if not already authenticated
88
+
89
+ ### Options
90
+
91
+ - `--directory`, `-d`: Directory containing the OpenEnv environment (defaults to current directory)
92
+ - `--repo-id`, `-r`: Repository ID in format 'username/repo-name' (defaults to 'username/env-name' from openenv.yaml)
93
+ - `--base-image`, `-b`: Base Docker image to use (overrides Dockerfile FROM)
94
+ - `--private`: Deploy the space as private (default: public)
95
+
96
+ ### Examples
97
+
98
+ ```bash
99
+ # Push to your personal namespace (defaults to username/env-name from openenv.yaml)
100
+ openenv push
101
+
102
+ # Push to a specific repository
103
+ openenv push --repo-id my-org/my-env
104
+
105
+ # Push with a custom base image
106
+ openenv push --base-image ghcr.io/meta-pytorch/openenv-base:latest
107
+
108
+ # Push as a private space
109
+ openenv push --private
110
+
111
+ # Combine options
112
+ openenv push --repo-id my-org/my-env --base-image custom-base:latest --private
113
+ ```
114
+
115
+ After deployment, your space will be available at:
116
+ `https://huggingface.co/spaces/<repo-id>`
117
+
118
+ The deployed space includes:
119
+ - **Web Interface** at `/web` - Interactive UI for exploring the environment
120
+ - **API Documentation** at `/docs` - Full OpenAPI/Swagger interface
121
+ - **Health Check** at `/health` - Container health monitoring
122
+ - **WebSocket** at `/ws` - Persistent session endpoint for low-latency interactions
123
+
124
+ ## Environment Details
125
+
126
+ ### Action
127
+ **SqlAction**: Contains a single field
128
+ - `message` (str) - The message to echo back
129
+
130
+ ### Observation
131
+ **SqlObservation**: Contains the echo response and metadata
132
+ - `echoed_message` (str) - The message echoed back
133
+ - `message_length` (int) - Length of the message
134
+ - `reward` (float) - Reward based on message length (length × 0.1)
135
+ - `done` (bool) - Always False for echo environment
136
+ - `metadata` (dict) - Additional info like step count
137
+
138
+ ### Reward
139
+ The reward is calculated as: `message_length × 0.1`
140
+ - "Hi" → reward: 0.2
141
+ - "Hello, World!" → reward: 1.3
142
+ - Empty message → reward: 0.0
143
+
144
+ ## Advanced Usage
145
+
146
+ ### Connecting to an Existing Server
147
+
148
+ If you already have a Sql Env environment server running, you can connect directly:
149
+
150
+ ```python
151
+ from sql_env import SqlEnv
152
+
153
+ # Connect to existing server
154
+ sql_envenv = SqlEnv(base_url="<ENV_HTTP_URL_HERE>")
155
+
156
+ # Use as normal
157
+ result = sql_envenv.reset()
158
+ result = sql_envenv.step(SqlAction(message="Hello!"))
159
+ ```
160
+
161
+ Note: When connecting to an existing server, `sql_envenv.close()` will NOT stop the server.
162
+
163
+ ### Using the Context Manager
164
+
165
+ The client supports context manager usage for automatic connection management:
166
+
167
+ ```python
168
+ from sql_env import SqlAction, SqlEnv
169
+
170
+ # Connect with context manager (auto-connects and closes)
171
+ with SqlEnv(base_url="http://localhost:8000") as env:
172
+ result = env.reset()
173
+ print(f"Reset: {result.observation.echoed_message}")
174
+ # Multiple steps with low latency
175
+ for msg in ["Hello", "World", "!"]:
176
+ result = env.step(SqlAction(message=msg))
177
+ print(f"Echoed: {result.observation.echoed_message}")
178
+ ```
179
+
180
+ The client uses WebSocket connections for:
181
+ - **Lower latency**: No HTTP connection overhead per request
182
+ - **Persistent session**: Server maintains your environment state
183
+ - **Efficient for episodes**: Better for many sequential steps
184
+
185
+ ### Concurrent WebSocket Sessions
186
+
187
+ The server supports multiple concurrent WebSocket connections. To enable this,
188
+ modify `server/app.py` to use factory mode:
189
+
190
+ ```python
191
+ # In server/app.py - use factory mode for concurrent sessions
192
+ app = create_app(
193
+ SqlEnvironment, # Pass class, not instance
194
+ SqlAction,
195
+ SqlObservation,
196
+ max_concurrent_envs=4, # Allow 4 concurrent sessions
197
+ )
198
+ ```
199
+
200
+ Then multiple clients can connect simultaneously:
201
+
202
+ ```python
203
+ from sql_env import SqlAction, SqlEnv
204
+ from concurrent.futures import ThreadPoolExecutor
205
+
206
+ def run_episode(client_id: int):
207
+ with SqlEnv(base_url="http://localhost:8000") as env:
208
+ result = env.reset()
209
+ for i in range(10):
210
+ result = env.step(SqlAction(message=f"Client {client_id}, step {i}"))
211
+ return client_id, result.observation.message_length
212
+
213
+ # Run 4 episodes concurrently
214
+ with ThreadPoolExecutor(max_workers=4) as executor:
215
+ results = list(executor.map(run_episode, range(4)))
216
+ ```
217
+
218
+ ## Development & Testing
219
+
220
+ ### Direct Environment Testing
221
+
222
+ Test the environment logic directly without starting the HTTP server:
223
+
224
+ ```bash
225
+ # From the server directory
226
+ python3 server/sql_env_environment.py
227
+ ```
228
+
229
+ This verifies that:
230
+ - Environment resets correctly
231
+ - Step executes actions properly
232
+ - State tracking works
233
+ - Rewards are calculated correctly
234
+
235
+ ### Running Locally
236
+
237
+ Run the server locally for development:
238
+
239
+ ```bash
240
+ uvicorn server.app:app --reload
241
+ ```
242
+
243
+ ## Project Structure
244
+
245
+ ```
246
+ sql_env/
247
+ ├── .dockerignore # Docker build exclusions
248
+ ├── __init__.py # Module exports
249
+ ├── README.md # This file
250
+ ├── openenv.yaml # OpenEnv manifest
251
+ ├── pyproject.toml # Project metadata and dependencies
252
+ ├── uv.lock # Locked dependencies (generated)
253
+ ├── client.py # SqlEnv client
254
+ ├── models.py # Action and Observation models
255
+ └── server/
256
+ ├── __init__.py # Server module exports
257
+ ├── sql_env_environment.py # Core environment logic
258
+ ├── app.py # FastAPI application (HTTP + WebSocket endpoints)
259
+ └── Dockerfile # Container image definition
260
+ ```
261
+
__init__.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """Sql Env Environment."""
8
+
9
+ from .client import SqlEnv
10
+ from .models import SqlAction, SqlObservation
11
+
12
+ __all__ = [
13
+ "SqlAction",
14
+ "SqlObservation",
15
+ "SqlEnv",
16
+ ]
client.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """Sql Env Environment Client."""
8
+
9
+ from typing import Dict
10
+
11
+ from openenv.core import EnvClient
12
+ from openenv.core.client_types import StepResult
13
+ from openenv.core.env_server.types import State
14
+
15
+ from .models import SqlAction, SqlObservation
16
+
17
+
18
+ class SqlEnv(
19
+ EnvClient[SqlAction, SqlObservation, State]
20
+ ):
21
+ """
22
+ Client for the Sql Env Environment.
23
+
24
+ This client maintains a persistent WebSocket connection to the environment server,
25
+ enabling efficient multi-step interactions with lower latency.
26
+ Each client instance has its own dedicated environment session on the server.
27
+
28
+ Example:
29
+ >>> # Connect to a running server
30
+ >>> with SqlEnv(base_url="http://localhost:8000") as client:
31
+ ... result = client.reset()
32
+ ... print(result.observation.echoed_message)
33
+ ...
34
+ ... result = client.step(SqlAction(message="Hello!"))
35
+ ... print(result.observation.echoed_message)
36
+
37
+ Example with Docker:
38
+ >>> # Automatically start container and connect
39
+ >>> client = SqlEnv.from_docker_image("sql_env-env:latest")
40
+ >>> try:
41
+ ... result = client.reset()
42
+ ... result = client.step(SqlAction(message="Test"))
43
+ ... finally:
44
+ ... client.close()
45
+ """
46
+
47
+ def _step_payload(self, action: SqlAction) -> Dict:
48
+ """
49
+ Convert SqlAction to JSON payload for step message.
50
+
51
+ Args:
52
+ action: SqlAction instance
53
+
54
+ Returns:
55
+ Dictionary representation suitable for JSON encoding
56
+ """
57
+ return {
58
+ "query": action.query,
59
+ }
60
+
61
+ def _parse_result(self, payload: Dict) -> StepResult[SqlObservation]:
62
+ """
63
+ Parse server response into StepResult[SqlObservation].
64
+
65
+ Args:
66
+ payload: JSON response data from server
67
+
68
+ Returns:
69
+ StepResult with SqlObservation
70
+ """
71
+ obs_data = payload.get("observation", {})
72
+ observation = SqlObservation(
73
+ echoed_message=obs_data.get("echoed_message", ""),
74
+ message_length=obs_data.get("message_length", 0),
75
+ done=payload.get("done", False),
76
+ reward=payload.get("reward"),
77
+ metadata=obs_data.get("metadata", {}),
78
+ )
79
+
80
+ return StepResult(
81
+ observation=observation,
82
+ reward=payload.get("reward"),
83
+ done=payload.get("done", False),
84
+ )
85
+
86
+ def _parse_state(self, payload: Dict) -> State:
87
+ """
88
+ Parse server response into State object.
89
+
90
+ Args:
91
+ payload: JSON response from state request
92
+
93
+ Returns:
94
+ State object with episode_id and step_count
95
+ """
96
+ return State(
97
+ episode_id=payload.get("episode_id"),
98
+ step_count=payload.get("step_count", 0),
99
+ )
models.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """
8
+ Data models for the Sql Env Environment.
9
+
10
+ The sql_env environment is a simple test environment that echoes back messages.
11
+ """
12
+
13
+
14
+ from typing import Dict, Any
15
+ from openenv.core.env_server import Action, Observation, State
16
+
17
+
18
+ class SqlAction(Action):
19
+ query: str
20
+
21
+
22
+ class SqlObservation(Observation):
23
+ echoed_message: str
24
+ message_length: int
25
+ metadata: Dict[str, Any] = {}
openenv.yaml ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ title: SQL Environment Server
2
+ emoji: robot
3
+
4
+ colorFrom: blue
5
+ colorTo: cyan
6
+ sdk: docker
7
+ pinned: false
8
+ app_port: 8000
9
+ base_path: /web
10
+ tags:
11
+ - openenv
12
+ - sql
13
+ - database
14
+ - real-world
15
+ name: sql-env
16
+ version: 0.1.0
pyproject.toml ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ [build-system]
8
+ requires = ["setuptools>=45", "wheel"]
9
+ build-backend = "setuptools.build_meta"
10
+
11
+ [project]
12
+ name = "openenv-sql_env"
13
+ version = "0.1.0"
14
+ description = "Sql Env environment for OpenEnv"
15
+ requires-python = ">=3.10"
16
+ dependencies = [
17
+ # Core OpenEnv runtime (provides FastAPI server + HTTP client types)
18
+ # install from github
19
+ # "openenv-core[core] @ git+https://github.com/meta-pytorch/OpenEnv.git",
20
+ "openenv-core[core]>=0.2.2",
21
+ # Environment-specific dependencies
22
+ # Add all dependencies needed for your environment here
23
+ # Examples:
24
+ # "numpy>=1.19.0",
25
+ # "torch>=2.0.0",
26
+ # "gymnasium>=0.29.0",
27
+ # "openspiel>=1.0.0",
28
+ # "smolagents>=1.22.0,<2",
29
+ ]
30
+
31
+ [project.optional-dependencies]
32
+ dev = [
33
+ "pytest>=8.0.0",
34
+ "pytest-cov>=4.0.0",
35
+ ]
36
+
37
+ [project.scripts]
38
+ # Server entry point - enables running via: uv run --project . server
39
+ # or: python -m sql_env.server.app
40
+ server = "sql_env.server.app:main"
41
+
42
+ [tool.setuptools]
43
+ include-package-data = true
44
+ packages = ["sql_env", "sql_env.server"]
45
+ package-dir = { "sql_env" = ".", "sql_env.server" = "server" }
server/__init__.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """Sql Env environment server components."""
8
+
9
+ from .sql_env_environment import SqlEnvironment
10
+
11
+ __all__ = ["SqlEnvironment"]
server/app.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """
8
+ FastAPI application for the Sql Env Environment.
9
+
10
+ This module creates an HTTP server that exposes the SqlEnvironment
11
+ over HTTP and WebSocket endpoints, compatible with EnvClient.
12
+
13
+ Endpoints:
14
+ - POST /reset: Reset the environment
15
+ - POST /step: Execute an action
16
+ - GET /state: Get current environment state
17
+ - GET /schema: Get action/observation schemas
18
+ - WS /ws: WebSocket endpoint for persistent sessions
19
+
20
+ Usage:
21
+ # Development (with auto-reload):
22
+ uvicorn server.app:app --reload --host 0.0.0.0 --port 8000
23
+
24
+ # Production:
25
+ uvicorn server.app:app --host 0.0.0.0 --port 8000 --workers 4
26
+
27
+ # Or run directly:
28
+ python -m server.app
29
+ """
30
+
31
+ try:
32
+ from openenv.core.env_server.http_server import create_app
33
+ except Exception as e: # pragma: no cover
34
+ raise ImportError(
35
+ "openenv is required for the web interface. Install dependencies with '\n uv sync\n'"
36
+ ) from e
37
+
38
+ try:
39
+ from models import SqlAction, SqlObservation
40
+ from server.sql_env_environment import SqlEnvironment
41
+ except ModuleNotFoundError:
42
+ from env.models import SqlAction, SqlObservation
43
+ from env.server.sql_env_environment import SqlEnvironment
44
+
45
+
46
+ # Create the app with web interface and README integration
47
+ app = create_app(
48
+ SqlEnvironment,
49
+ SqlAction,
50
+ SqlObservation,
51
+ env_name="sql_env",
52
+ max_concurrent_envs=1, # increase this number to allow more concurrent WebSocket sessions
53
+ )
54
+
55
+
56
+ def main(host: str = "0.0.0.0", port: int = 8000):
57
+ """
58
+ Entry point for direct execution via uv run or python -m.
59
+
60
+ This function enables running the server without Docker:
61
+ uv run --project . server
62
+ uv run --project . server --port 8001
63
+ python -m sql_env.server.app
64
+
65
+ Args:
66
+ host: Host address to bind to (default: "0.0.0.0")
67
+ port: Port number to listen on (default: 8000)
68
+
69
+ For production deployments, consider using uvicorn directly with
70
+ multiple workers:
71
+ uvicorn sql_env.server.app:app --workers 4
72
+ """
73
+ import uvicorn
74
+
75
+ uvicorn.run(app, host=host, port=port)
76
+
77
+
78
+ if __name__ == "__main__":
79
+ import argparse
80
+
81
+ parser = argparse.ArgumentParser()
82
+ parser.add_argument("--port", type=int, default=8000)
83
+ args = parser.parse_args()
84
+ main(port=args.port)
server/requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ openenv[core]>=0.2.0
2
+ fastapi>=0.115.0
3
+ uvicorn>=0.24.0
4
+
5
+
6
+
server/sql_env_environment.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ """
8
+ Sql Env Environment Implementation.
9
+
10
+ A simple test environment that echoes back messages sent to it.
11
+ Perfect for testing HTTP server infrastructure.
12
+ """
13
+
14
+ from uuid import uuid4
15
+
16
+ from openenv.core.env_server.interfaces import Environment
17
+ from openenv.core.env_server.types import State
18
+
19
+ try:
20
+ from ..models import SqlAction, SqlObservation
21
+ except ImportError:
22
+ from models import SqlAction, SqlObservation
23
+
24
+ class SqlEnvironment(Environment):
25
+ SUPPORTS_CONCURRENT_SESSIONS: bool = True
26
+
27
+ def __init__(self):
28
+ self._state = State(episode_id=str(uuid4()), step_count=0)
29
+ self._reset_count = 0
30
+
31
+ def reset(self) -> SqlObservation:
32
+ self._state = State(episode_id=str(uuid4()), step_count=0)
33
+ self._reset_count += 1
34
+
35
+ return SqlObservation(
36
+ echoed_message="Sql Env environment ready!",
37
+ message_length=0,
38
+ metadata={}
39
+ )
40
+
41
+ def step(self, action: SqlAction) -> SqlObservation:
42
+ self._state.step_count += 1
43
+
44
+ message = action.query
45
+ length = len(message)
46
+
47
+ return SqlObservation(
48
+ echoed_message=message,
49
+ message_length=length,
50
+ metadata={}
51
+ )
52
+
53
+ @property
54
+ def state(self) -> State:
55
+ return self._state
server/tasks.py ADDED
@@ -0,0 +1 @@
 
 
1
+
uv.lock ADDED
The diff for this file is too large to render. See raw diff
 
validate-submission.sh ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+
3
+ BASE_URL=$1
4
+
5
+ if [ -z "$BASE_URL" ]; then
6
+ echo "Usage: ./validate-submission.sh <base_url>"
7
+ exit 1
8
+ fi
9
+
10
+ echo " Validating API at $BASE_URL"
11
+ echo
12
+
13
+ echo " Checking /health"
14
+ curl -s "$BASE_URL/health"
15
+ echo -e "\n"
16
+
17
+ echo " Checking /schema"
18
+ curl -s "$BASE_URL/schema"
19
+ echo -e "\n"
20
+
21
+ echo " Checking /reset"
22
+ curl -s -X POST "$BASE_URL/reset"
23
+ echo -e "\n"
24
+
25
+ echo " Checking /state"
26
+ curl -s "$BASE_URL/state"
27
+ echo -e "\n"
28
+
29
+ echo " Checking /step"
30
+ curl -s -X POST "$BASE_URL/step" \
31
+ -H "Content-Type: application/json" \
32
+ -d '{"action": {"query": "SELECT 1;"}}'
33
+ echo -e "\n"
34
+
35
+ echo "✅ Validation complete"
36
+
37
+