CoolFace
Apppublic

aarjavjjain/SQL-Data-Quality-OpenEnv

sourceHugging Faceupdated 5mo agoView on Hugging Face
0likes
App README

๐Ÿ—„๏ธ SQL Data Quality Environment

<div align="center">

![OpenEnv](https://github.com/meta-pytorch/OpenEnv) ![HF Spaces](https://huggingface.co/spaces) ![Python](https://python.org) ![License](LICENSE)

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

RequirementStatus
Typed Action Pydantic modelโœ…
Typed Observation Pydantic modelโœ…
Typed State Pydantic modelโœ…
POST /reset endpointโœ…
POST /step endpointโœ…
GET /state endpointโœ…
openenv.yaml manifestโœ…
3+ tasks with graders (0.0โ€“1.0)โœ…
Graders are deterministicโœ…
Baseline inference scriptโœ…
Working Dockerfileโœ…
HF Spaces deployableโœ…

๐ŸŽฎ Action Space

The agent communicates through structured Action objects:

python
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

`action_type`DescriptionRequired Fields
list_tablesList all tables in the databaseโ€”
describe_tableSchema + sample rows for a tabletable_name
queryExecute a read-only SELECT/WITHsql
submit_fixApply UPDATE/DELETE/ALTER fix statementsfix_sql
finishEnd the episode, receive final scoreโ€”

Example Actions

json
// 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:

python
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 failed

Data Payload by Action

Action`data` structure
list_tables{tables: [str]}
describe_table{columns: [{name, type, nullable}], sample_rows: [dict], total_rows: int}
query{columns: [str], rows: [[...]], row_count: int}
submit_fix{affected_rows: int, validation: {score_before, score_after, delta, errors}}
finish{final_score: float, steps_used: int, efficiency_bonus: float, breakdown: dict}

๐Ÿ“Š Episode State

python
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:

CategoryIssuePoints
A3 rows missing email25%
B2 rows missing phone25%
C2 rows missing city or country25%
D3 rows with non-numeric age values ('abc', '', 'N/A')25%

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:

CategoryIssuePoints
A2 duplicate SKUs (SKU-001, SKU-002) โ€” keep lower product_id33%
B2 orphan orders referencing non-existent products33%
C2 orders with quantity โ‰ค 0 (0 and -1)34%

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:

#CategoryTableIssue
1Date formatemployeesRow 4: hire_date='15/06/2018' โ†’ ISO 8601
2Invalid FKemployeesRow 6: department 'Logistics' not in departments
3Self-ref integrityemployeesRow 7: manager_id=99 doesn't exist
4Business ruleemployeesRow 8: negative salary=-5000
5NULL constraintemployeesRow 11: NULL department
6Calculation errorpayrollRows 2, 5: net_pay โ‰  gross_pay - deductions
7Orphan recordpayrollRow 9: emp_id=99 doesn't exist in employees

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 improvement

On 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.05

Design rationale:

  • โ€”The per-step penalty discourages aimless exploration without preventing necessary investigation
  • โ€”submit_fix gives 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

bash
# 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/docs

Docker

bash
docker build -t sql-data-quality-env .
docker run -p 7860:7860 sql-data-quality-env

# Health check
curl http://localhost:7860/health

Python Client

python
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:

bash
# 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 --quiet

Baseline Scores (Reproducible)

TaskGPT-4o-miniNotes
Easy~0.75Misses some edge cases in age validation
Medium~0.60Struggles with ordering of operations (must delete dupes before orphan check)
Hard~0.43Date format conversion and multi-table coordination are challenging
Average~0.59Room for significant improvement

๐Ÿงช Running Tests

bash
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

  1. 1.Create a new HF Space with Docker SDK
  2. 2.Push this repository to the Space
  3. 3.The Space will automatically build and start on port 7860
  4. 4.Tag your Space with openenv for 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

VariableDescriptionDefault
API_BASE_URLLLM API endpointhttps://api.openai.com/v1
MODEL_NAMEModel identifier for inferencegpt-4o-mini
HF_TOKENAPI key (used as OpenAI api_key)(required)

๐Ÿ™ 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.