data-cleaning-env / README.md
vedastra's picture
Upload folder using huggingface_hub
7af055a verified
|
Raw
History Blame Contribute Delete
6.53 kB
---
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": "<string>",
"column": "<string | null>"
}
```
| 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