Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
.git
.github
.venv
.env
__pycache__
*.pyc
*.egg-info
.pytest_cache
.ruff_cache
.DS_Store
31 changes: 31 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: CI

on:
push:
branches: [main]
pull_request:

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.12"]
steps:
- uses: actions/checkout@v4

- uses: astral-sh/setup-uv@v6
with:
python-version: ${{ matrix.python-version }}

- name: Install
run: uv sync --locked --extra dev

- name: Lint
run: uv run ruff check .

- name: Test
run: uv run pytest -q

- name: Validate OpenEnv layout
run: uv run openenv validate .
21 changes: 18 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
.venv/
# Python
__pycache__/
*.py[cod]
*.egg-info/
*.pyc
build/
dist/

# Environments
.venv/
.env

# Tooling
.pytest_cache/
.ruff_cache/
.coverage
htmlcov/

# OS / editors
.DS_Store
uv.lock
.idea/
.vscode/
79 changes: 35 additions & 44 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,66 +1,57 @@
# Development Notes
# Contributing

Thanks for checking out the codebase! I built this specifically for the Meta OpenEnv Hackathon 2026. If you want to run my local testing suite or add more SQL tasks later, here is my setup process.
Issues and pull requests are welcome. This guide covers local setup, the test suite, and how to add a task.

## Setup

Requires Python 3.10+ and [uv](https://docs.astral.sh/uv/).

```bash
# clone and install
git clone <repo-url>
git clone https://github.com/rajdeepchatale/sql_query_env.git
cd sql_query_env
uv sync
uv sync --extra dev
```

## Running locally
## Run the server

```bash
# start the server
uv run server

# test with curl
uv run server # http://localhost:8000
curl http://localhost:8000/health
```

## Adding a new task

1. Add the database seed data (if new domain) to `server/tasks.py`
2. Create a `Task` object with:
- Ground truth SQL query
- Expected output columns
- Difficulty level and hints
3. Add task ID to the appropriate list in `tasks.py`
4. Add task entry in `openenv.yaml`
5. Add task ID to `TASK_IDS` in `inference.py` (for baseline testing)
6. Test: start server, call `/reset` with the new task ID, verify grading
## Checks

## Testing grading
CI runs the same three commands on every push and pull request:

We have a quick sanity check you can run:
```bash
uv run ruff check .
uv run pytest -q
uv run openenv validate .
```

```python
import sqlite3
from server.tasks import create_database, TASK_MAP
from server.graders import grade_query
The test suite checks:

conn = create_database("company")
task = TASK_MAP["company_easy_1"]
- every reference query runs and is graded as correct
- the manifest, the task registry, and the baseline script list the same tasks
- the database rejects writes, `PRAGMA`, and `ATTACH`
- runaway queries are cut off
- known ways to game the reward stay closed

# should score ~0.95+
result = grade_query(conn, task.ground_truth_query, task, [])
print(f"Ground truth score: {result.total_score}")
## Adding a task

# should score ~0.10 (syntax only)
result = grade_query(conn, "SELECT 1", task, [])
print(f"Bad query score: {result.total_score}")
```
1. If the task needs a new domain, add its schema, seed data, and schema description to `server/tasks.py` and register it in `SCHEMAS`.
2. Add a `Task` to the matching list in `server/tasks.py` with:
- a `question` that states every filter the reference query applies. Hidden conditions make a task unfair, not harder.
- `ground_truth_query` and `expected_columns`, which must match the query's output column names.
- `difficulty`, `hints` (ordered from general to specific), and `max_steps`.
3. Add the task to `openenv.yaml`.
4. Add the task ID to `TASK_IDS` in `inference.py`.
5. Run `uv run pytest -q`. The consistency tests fail if you skipped step 3 or 4.

## Common issues
When the reference query sorts on a key that can tie, keep in mind that any tie order counts as correct. Row order is not part of the correctness check.

- **SQLite threading**: We use `check_same_thread=False` because FastAPI
is async. The in-memory databases are per-episode so there's no real
contention, but be aware of this if you change the session model.
## Things to know

- **Import errors**: The server can be run multiple ways (`uv run server`,
`python -m sql_query_env.server.app`, `uvicorn server.app:app`) and
each has a different package layout. That's why there are try/except
import blocks. Don't remove them.
- **Import fallbacks.** The server runs in several layouts (`uv run server`, `uvicorn server.app:app`, `python -m sql_query_env.server.app`), and each one resolves imports differently. That's why several modules have `try`/`except ImportError` import blocks. Keep them.
- **SQLite threading.** Connections use `check_same_thread=False` because the server calls the environment from a thread pool. Each episode has its own in-memory database, so there is no shared state. Revisit this if you change the session model.
- **Read-only database.** `create_database()` installs an SQLite authorizer after seeding. If a new task needs a feature the authorizer blocks, allow the specific action code rather than removing the authorizer.
14 changes: 6 additions & 8 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# Multi-stage build using openenv-base
# This Dockerfile is flexible and works for both:
# - In-repo environments (with local OpenEnv sources)
# - Standalone environments (with openenv from PyPI/Git)
# The build script (openenv build) handles context detection and sets appropriate build args.
# Multi-stage build on the OpenEnv base image.
# Used by Hugging Face Spaces (Docker SDK), `docker build .`, and `openenv build`
# (which passes BUILD_MODE / ENV_NAME as build args).

ARG BASE_IMAGE=ghcr.io/meta-pytorch/openenv-base:latest
FROM ${BASE_IMAGE} AS builder
Expand Down Expand Up @@ -31,9 +29,9 @@ RUN if ! command -v uv >/dev/null 2>&1; then \
mv /root/.local/bin/uv /usr/local/bin/uv && \
mv /root/.local/bin/uvx /usr/local/bin/uvx; \
fi
# Install dependencies using uv sync
# If uv.lock exists, use it; otherwise resolve on the fly

# Install dependencies from the committed lockfile (falls back to resolving
# on the fly if uv.lock is absent)
RUN --mount=type=cache,target=/root/.cache/uv \
if [ -f uv.lock ]; then \
uv sync --frozen --no-install-project --no-editable; \
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
BSD 3-Clause License

Copyright (c) 2025, sql_query_env contributors
Copyright (c) 2026, Rajdeep Chatale
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
Loading
Loading