--- title: Data Cleaning Environment emoji: ๐Ÿงน colorFrom: blue colorTo: green sdk: docker app_port: 8000 base_path: /web --- # Data Cleaning Environment A real-world OpenEnv environment where an AI agent learns to clean tabular data through the standard `step()` / `reset()` / `state()` API. The agent receives a dirty CSV-style dataset and must apply cleaning operations step-by-step to maximise a data-quality score (0.0 โ†’ 1.0). --- ## Tasks | Task ID | Difficulty | Description | Max Steps | |----------|------------|-----------------------------------------------------------------|-----------| | `easy` | Easy | Fix 3 missing values (name / age) in a 5-row table | 10 | | `medium` | Medium | Remove 2 duplicate rows **and** fix 2 type errors in `age` | 15 | | `hard` | Hard | Full pipeline: missing values + duplicates + outliers + normalise text | 25 | --- ## Action Space ```json { "operation": "", "column": "" } ``` | Operation | Task(s) | Effect | |---------------------|------------------|-----------------------------------------------------| | `impute_mean` | easy | Fill numeric `None` with column mean | | `impute_mode` | easy | Fill string `None` with column mode | | `drop_missing_rows` | easy / medium | Drop all rows containing any `None` | | `remove_duplicates` | medium | Drop exact-duplicate rows | | `fix_type_errors` | medium | Coerce non-numeric values to `float` (or `None`) | | `remove_outliers` | hard | Drop rows where `price โ‰ค 0` or `price โ‰ฅ 500` | | `normalize_text` | hard | Strip whitespace + title-case all string columns | | `fill_quantity_mean`| hard | Fill missing `quantity` with column mean | --- ## Observation Space | Field | Type | Description | |-------------------|---------|-----------------------------------------------------------| | `current_text` | `str` | Human-readable table of current rows | | `is_normalized` | `bool` | True when no missing values, duplicates, or outliers left | | `remaining_typos` | `int` | Composite issue count (missing + dupes + outliers) | | `html_found` | `bool` | Always `False` (compatibility field) | | `done` | `bool` | Episode ended (score=1.0 or step limit reached) | | `reward` | `float` | ฮ” quality score from this step (partial progress signal) | | `metadata` | `dict` | Full row data, per-field diagnostics, valid ops list | --- ## Reward Function ``` reward = (quality_score_after - quality_score_before) + 0.01 # if improvement reward = (quality_score_after - quality_score_before) - 0.01 # if no improvement ``` Each task has its own grader: - **Easy**: fraction of the 3 original missing values that are resolved - **Medium**: average of (dedup score, type-fix score) - **Hard**: average of 4 sub-scores (no missing, no dupes, no outliers, normalised text) Invalid operations incur a โˆ’0.05 penalty but do **not** end the episode. --- ## Baseline Scores Deterministic rule-based agent (reproducible, seed=42): | Task | Score | |--------|-------| | easy | 1.0 | | medium | 1.0 | | hard | 1.0 | --- ## API Endpoints | Method | Path | Description | |--------|-------------|--------------------------------------------------| | POST | `/reset` | Start new episode. Body: `{"task":"easy"}` | | POST | `/step` | Apply action. Body: `{"action":{...}}` | | GET | `/state` | Current episode state | | GET | `/schema` | Action + Observation JSON schemas | | GET | `/tasks` | Task list + action schema per difficulty | | POST | `/grader` | Score the current episode (0.0โ€“1.0) | | POST | `/baseline` | Run baseline agent on all 3 tasks | | GET | `/health` | Health check | | WS | `/ws` | WebSocket for low-latency persistent sessions | --- ## Quick Start ### 1. Reset to a task ```bash curl -X POST http://localhost:8000/reset \ -H "Content-Type: application/json" \ -d '{"task": "easy"}' ``` ### 2. Apply a cleaning operation ```bash curl -X POST http://localhost:8000/step \ -H "Content-Type: application/json" \ -d '{"action": {"operation": "impute_mean"}}' ``` ### 3. Get current state ```bash curl http://localhost:8000/state ``` ### 4. Score the episode ```bash curl -X POST http://localhost:8000/grader ``` ### 5. Run baseline on all tasks ```bash curl -X POST http://localhost:8000/baseline ``` --- ## Setup ### Run locally ```bash uv run server # or uvicorn server.app:app --reload --host 0.0.0.0 --port 8000 ``` ### Run with Docker ```bash docker build -t data-cleaning-env:latest -f server/Dockerfile . docker run -p 8000:8000 data-cleaning-env:latest ``` ### Deploy to Hugging Face Spaces ```bash openenv push --repo-id your-username/data-cleaning-env ``` --- ## Project Structure ``` data_cleaning_env/ โ”œโ”€โ”€ README.md # This file โ”œโ”€โ”€ openenv.yaml # OpenEnv manifest โ”œโ”€โ”€ pyproject.toml # Project metadata & dependencies โ”œโ”€โ”€ uv.lock # Locked dependencies โ”œโ”€โ”€ models.py # Action + Observation Pydantic models โ”œโ”€โ”€ client.py # DataCleaningEnv HTTP/WS client โ””โ”€โ”€ server/ โ”œโ”€โ”€ app.py # FastAPI app + /tasks /grader /baseline โ”œโ”€โ”€ data_cleaning_env_environment.py # Core environment logic + graders โ””โ”€โ”€ Dockerfile # Container image ``` --- ## Dependencies - `openenv-core[core] >= 0.2.2` โ€” OpenEnv runtime - Python 3.10+ - No external data dependencies โ€” all datasets are generated synthetically at runtime