SujalVaishya/dataquality-openenv
๐งน DataQuality OpenEnv
A real-world OpenEnv environment for training and evaluating AI agents on data quality triage.
Data engineers spend a significant portion of their time identifying and fixing data quality issues โ missing values, type errors, duplicate records, format violations, outliers, and referential integrity problems. This environment simulates that work as a structured, episodic agent task with partial-progress rewards and deterministic graders.
Why This Environment?
Data quality triage is a genuinely hard, high-value real-world task:
- It requires inspection (understanding what's wrong), planning (deciding what to fix first), and execution (applying the right operations in the right order)
- It has rich partial progress signals โ each fix measurably improves the dataset
- It scales in difficulty: a simple contacts CSV vs. a production healthcare dataset
- It maps cleanly to agent capabilities: tool use, state tracking, multi-step reasoning
This fills a gap in the OpenEnv ecosystem โ no existing environment models data engineering tasks.
Action Space
Agents issue JSON actions with an action_type and parameters dict:
Example action:
{
"action_type": "fix_type",
"parameters": {
"column": "revenue",
"target_type": "float",
"strip_chars": "$,"
}
}Observation Space
Each step returns an Observation with:
IssueRecord fields: issue_id, issue_type (missing/duplicate/typeerror/format/outlier), `column`, `rowindices, severity (critical/major/minor), description, resolved`
Tasks
Task 1: Basic Completeness Fix (task_easy)
Difficulty: Easy | Max steps: 15 | Target score: โฅ 0.85
A customer contacts CSV (35 rows) has:
- ~30% of
emailvalues missing โ fill withunknown@example.com - ~25% of
phonevalues missing โ fill withN/A - 5 exact duplicate rows โ remove
Grader weights: email completeness 40%, phone completeness 30%, no duplicates 30%
Optimal solution (4 actions):
[
{"action_type": "fill_missing", "parameters": {"column": "email", "fill_value": "unknown@example.com", "strategy": "constant"}},
{"action_type": "fill_missing", "parameters": {"column": "phone", "fill_value": "N/A", "strategy": "constant"}},
{"action_type": "drop_duplicates", "parameters": {}},
{"action_type": "submit", "parameters": {}}
]Task 2: Type Errors & Format Violations (task_medium)
Difficulty: Medium | Max steps: 20 | Target score: โฅ 0.80
A sales transactions dataset (40 rows) has:
revenuestored as strings with currency symbols ("$1,234.56") โ convert to floatdatecolumn in 5 mixed non-ISO formats (MM/DD/YYYY,DD-MM-YYYY,Jan 15 2024, etc.) โ normalize toYYYY-MM-DD- ~15% of
quantityvalues are negative โ drop those rows - Duplicate
transaction_idvalues โ deduplicate
Grader weights: revenue numeric 35%, dates ISO 25%, no negative qty 20%, unique transaction IDs 20%
Task 3: Multi-Issue Production Dataset (task_hard)
Difficulty: Hard | Max steps: 30 | Target score: โฅ 0.75
A healthcare appointments dataset (65 rows) with 7 simultaneous issue types:
- Missing `patient_id` (~15% of rows) โ drop those rows
- `appointment_date` format violations (~40% non-ISO) โ standardize to
YYYY-MM-DD - `created_timestamp` format violations (~35% non-ISO) โ standardize to
YYYY-MM-DDThh:mm:ss - Age outliers (negative ages, age > 130) โ drop those rows
- Invalid `status` values (
"Scheduled","cancled","no show") โ normalize to{scheduled, completed, cancelled, no_show} - Invalid `department` values (
"ORTHO","neuro","kids") โ normalize to valid set - Duplicate `appointment_id` โ remove duplicates
Grader weights: patientid 20%, apptdate 15%, created_ts 15%, age 15%, status 15%, dept 10%, uniqueness 10%
This task challenges frontier models because all 7 issues must be identified and addressed in the right order, with some interdependencies (e.g., dropping null patient_ids first reduces the duplicate count).
Reward Function
The reward at each step is a combination of:
Key properties:
- Dense signal: Every step that improves the dataset yields a positive reward
- No reward hacking:
inspect_columnactions yield exactly 0.0 reward (no state change) - Timeout penalty: Exceeding
max_stepsyields a โ0.05 penalty on the terminal reward - Efficiency incentive: Solving issues in fewer steps earns a small bonus
Setup & Usage
Local installation
git clone https://huggingface.co/spaces/your-username/dataquality-openenv
cd dataquality-openenv
pip install -r requirements.txtPython API
from dataquality_env import DataQualityEnv, Action, ActionType
env = DataQualityEnv(task_id="task_hard", seed=42)
obs = env.reset()
print(obs.task_description)
print(f"Issues: {[(i.issue_id, i.description) for i in obs.issue_registry]}")
# Fix missing patient IDs
action = Action(
action_type=ActionType.DROP_ROWS,
parameters={"column": "patient_id", "condition": "is_null"}
)
obs, reward, done, info = env.step(action)
print(f"Reward: {reward.total:+.4f}")
print(f"Result: {obs.last_action_result}")
# Get full internal state
state = env.state()
print(f"Score so far: {state.score}")HTTP API (after docker run or HF Space)
# Create a session
curl -X POST http://localhost:7860/env/reset \
-H 'Content-Type: application/json' \
-d '{"task_id": "task_medium", "seed": 42}'
# โ {"session_id": "abc-123", "observation": {...}}
# Step
curl -X POST http://localhost:7860/env/step \
-H 'Content-Type: application/json' \
-d '{
"session_id": "abc-123",
"action": {
"action_type": "fix_type",
"parameters": {"column": "revenue", "target_type": "float", "strip_chars": "$,"}
}
}'
# โ {"observation": {...}, "reward": {...}, "done": false, "info": {...}}
# Get state
curl http://localhost:7860/env/state/abc-123Docker
docker build -t dataquality-env .
docker run -p 7860:7860 dataquality-env
# Interactive docs at: http://localhost:7860/docsRun baseline agent
export OPENAI_API_KEY=your_key_here
python baseline/run_baseline.py
# Optional: use a different model
BASELINE_MODEL=gpt-4o python baseline/run_baseline.pyBaseline Scores
Reproducible scores using seed=42, model gpt-4o-mini:
Oracle scores obtained by running the deterministic optimal action sequence (verified in tests).
The gap between baseline and oracle on the hard task reflects the genuine difficulty of coordinating 7 simultaneous issue types under a step budget.
Project Structure
dataquality-env/
โโโ dataquality_env/
โ โโโ __init__.py # Package exports
โ โโโ env.py # DataQualityEnv โ step/reset/state
โ โโโ models.py # Typed Pydantic models (Action, Observation, Reward, EpisodeState)
โ โโโ tasks.py # Dataset generators + graders for all 3 tasks
โโโ baseline/
โ โโโ run_baseline.py # OpenAI-client baseline agent
โโโ tests/
โ โโโ test_env.py # 30 tests covering spec compliance, actions, graders, rewards
โโโ app.py # FastAPI server for HF Spaces / HTTP API
โโโ openenv.yaml # OpenEnv metadata
โโโ Dockerfile # Container definition
โโโ requirements.txt
โโโ setup.py
โโโ README.mdOpenEnv Spec Compliance
- โ
Typed
Action,Observation,Reward,EpisodeStatePydantic models - โ
step(action)โ(Observation, Reward, bool, Dict) - โ
reset()โObservation - โ
state()โEpisodeState - โ
openenv.yamlwith full metadata - โ 3 tasks with difficulty progression (easy โ medium โ hard)
- โ
Graders produce scores in
[0.0, 1.0], deterministic, seed-reproducible - โ Meaningful partial-progress reward function (dense, not sparse)
- โ Baseline inference script using OpenAI API client
- โ Dockerfile + HF Spaces deployment
License
MIT
