aarjavjjain/SQL-Data-Quality-OpenEnv
๐๏ธ SQL Data Quality Environment
<div align="center">
   
A real-world OpenEnv environment where AI agents audit SQL databases for data quality issues and generate corrective SQL queries.
</div>
๐ฏ What This Environment Simulates
Data quality issues cost enterprises an estimated $12.9M per year on average (Gartner). Every data engineer and analytics team spends significant time:
- Detecting NULL values in critical columns
- Finding and deduplicating records with the same business key
- Identifying referential integrity violations (orphan foreign keys)
- Fixing type mismatches and format inconsistencies
- Correcting calculation errors in derived columns
This environment reproduces exactly these real workflows through an interactive SQLite database that agents explore using list_tables, describe_table, query, and submit_fix actions โ the same tools a real data engineer would use.
๐๏ธ Architecture
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Agent (LLM / RL) โ
โ Observes text + structured JSON data โ
โโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ HTTP (reset / step / state)
โโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ FastAPI Server (port 7860) โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ SQLDataQualityEnvironment โ โ
โ โ reset() โ fresh in-memory SQLite DB per episode โ โ
โ โ step() โ routes action, returns Observation โ โ
โ โ state โ episode metadata (step_count, score) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ EASY โ โ MEDIUM โ โ HARD โ โ
โ โ1 table โ โ2 tables โ โ3 tables โ โ
โ โnull/type โ โdedup+FK โ โmulti-table+biz rules โ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ๐ OpenEnv Spec Compliance
๐ฎ Action Space
The agent communicates through structured Action objects:
class Action(BaseModel):
action_type: ActionType # required
table_name: Optional[str] # for describe_table
sql: Optional[str] # for query (read-only SELECT)
fix_sql: Optional[str] # for submit_fix (UPDATE/DELETE)
reasoning: Optional[str] # optional chain-of-thought (not graded)Action Types
Example Actions
// Explore
{"action_type": "list_tables"}
{"action_type": "describe_table", "table_name": "customers"}
{"action_type": "query", "sql": "SELECT * FROM customers WHERE email IS NULL"}
// Fix
{"action_type": "submit_fix", "fix_sql": "UPDATE customers SET email='unknown@example.com' WHERE email IS NULL;"}
{"action_type": "finish"}๐๏ธ Observation Space
Each step returns an Observation:
class Observation(BaseModel):
done: bool # True when episode ends
reward: float # Step reward (with shaping)
observation_text: str # Human-readable description
data: Optional[Dict[str, Any]] # Structured payload (varies by action)
error: Optional[str] # Error message if action failedData Payload by Action
๐ Episode State
class State(BaseModel):
episode_id: str # unique episode identifier
task_id: str # 'easy' | 'medium' | 'hard'
step_count: int # steps taken so far
max_steps: int # budget (easy=20, medium=25, hard=35)
cumulative_reward: float # total reward accumulated
issues_found: int # issues the agent has found
fixes_applied: int # successful fix statements applied
task_description: str # full task instructions
available_tables: List[str] # tables in this episode's DB๐ Tasks
Task 1 โ EASY: Customer Table Null & Type Audit
Difficulty: Easy | Max steps: 20 | Table: customers
The customers table has 10 rows with four categories of data quality issues:
Expected agent strategy: Describe table โ query for NULLs by column โ submit UPDATE fixes โ finish
Baseline score (GPT-4o-mini): ~0.75
Task 2 โ MEDIUM: Products & Orders Integrity
Difficulty: Medium | Max steps: 25 | Tables: products, orders
Two related tables with three categories of issues:
Expected agent strategy: Detect cross-table relationships โ find duplicates with GROUP BY โ identify FK violations โ fix sequentially
Baseline score (GPT-4o-mini): ~0.60
Task 3 โ HARD: Multi-Table Schema & Business Rules
Difficulty: Hard | Max steps: 35 | Tables: employees, departments, payroll
Seven distinct issue categories across three tables:
Expected agent strategy: Deep multi-table analysis, verify self-referencing integrity, check derived column calculations, fix issues in dependency order
Baseline score (GPT-4o-mini): ~0.43
๐ Reward Function
The reward function provides dense, shaped signals throughout the episode:
step_reward = -0.005 # per-step efficiency penalty
+ 0.05 # if fix affected โฅ 1 row(s)
+ max(grader_delta, 0.0) ร 0.5 # proportional to quality improvementOn finish():
finish_reward = final_grader_score # 0.0 โ 1.0
+ 0.10 # efficiency bonus (โค half step budget)On timeout (step budget exhausted):
timeout_penalty = -0.05Design rationale:
- The per-step penalty discourages aimless exploration without preventing necessary investigation
submit_fixgives immediate feedback even before the episode ends- The grader delta component rewards meaningful fixes, not just any SQL execution
- The efficiency bonus incentivises concise, targeted agents over brute-force approaches
๐ Quick Start
Local Setup
# Clone / download the project
cd scaler/
# Install dependencies
pip install -r requirements.txt
# Start the server
uvicorn server.app:app --host 0.0.0.0 --port 7860
# Open http://localhost:7860 in your browser for the web UI
# OpenAPI docs at http://localhost:7860/docsDocker
docker build -t sql-data-quality-env .
docker run -p 7860:7860 sql-data-quality-env
# Health check
curl http://localhost:7860/healthPython Client
from client import SQLDataQualityClient
from models import Action, ActionType
with SQLDataQualityClient("http://localhost:7860") as client:
# Start easy task
obs = client.reset(task_id="easy")
print(obs.observation_text)
# Explore
result = client.step(Action(action_type=ActionType.LIST_TABLES))
result = client.step(Action(action_type=ActionType.DESCRIBE_TABLE, table_name="customers"))
# Fix
result = client.step(Action(
action_type=ActionType.SUBMIT_FIX,
fix_sql="UPDATE customers SET email='unknown@example.com' WHERE email IS NULL;"
))
print(result.observation.data["validation"])
# Finish
result = client.step(Action(action_type=ActionType.FINISH))
print(f"Final score: {result.observation.data['final_score']}")๐ค Baseline Inference Script
The baseline script runs a GPT-4o-mini agent through all three tasks:
# Required environment variables
export HF_TOKEN="your-api-key"
export API_BASE_URL="https://api.openai.com/v1" # or your custom endpoint
export MODEL_NAME="gpt-4o-mini" # or your model
# Run all tasks (server must be running)
python inference.py --url http://localhost:7860
# Run specific tasks
python inference.py --tasks easy medium
# Quiet mode (just scores)
python inference.py --quietBaseline Scores (Reproducible)
๐งช Running Tests
pytest tests/ -v
# Expected output:
# test_reset_easy_returns_observation PASSED
# test_reset_sets_state PASSED
# ...
# 22 passed in X.XX seconds๐ณ Deploying to Hugging Face Spaces
- Create a new HF Space with Docker SDK
- Push this repository to the Space
- The Space will automatically build and start on port 7860
- Tag your Space with
openenvfor discoverability
The web UI at / provides a no-code interface for manual interaction.
๐ Project Structure
scaler/
โโโ openenv.yaml # OpenEnv manifest
โโโ models.py # Pydantic models (Action, Observation, State, StepResult)
โโโ tasks.py # Task definitions, schemas, seed data, graders
โโโ environment.py # Core environment logic (reset/step/state)
โโโ client.py # Synchronous HTTP client
โโโ inference.py # Baseline inference script (OpenAI client)
โโโ requirements.txt # Python dependencies
โโโ pyproject.toml # Package metadata
โโโ Dockerfile # Container definition
โโโ server/
โ โโโ app.py # FastAPI application
โโโ tests/
โโโ test_environment.py # Test suite (pytest)๐ง Environment Variables
๐ Acknowledgments
Built for the OpenEnv Community Challenge by Meta PyTorch ร Hugging Face.
The SQL schema designs are inspired by real data quality issues encountered in production data warehouses.
