Spaces:
Running
Running
| title: Data-Centric AI RL Environment | |
| emoji: π§ | |
| colorFrom: blue | |
| colorTo: indigo | |
| sdk: docker | |
| pinned: false | |
| app_port: 7860 | |
| short_description: "LLM learns to fix data, not models β GRPO RL env." | |
| tags: | |
| - openenv | |
| - reinforcement-learning | |
| - data-centric-ai | |
| - grpo | |
| - unsloth | |
| - curriculum-learning | |
| # π§ Data-Centric AI β Multi-Agent RL Environment | |
| > **What if the model is fine β but the data isn't?** This OpenEnv environment uses **GRPO reinforcement learning** to teach a language model to act as a data surgery orchestrator: dispatching specialist sub-agents to impute, rebalance, and augment a corrupted ML dataset β boosting a *frozen* classifier's accuracy without touching a single model weight. | |
| --- | |
| ## π Links | |
| | Resource | Link | | |
| |---|---| | |
| | π€ **HF Space (live env)** | https://huggingface.co/spaces/Aswini-Kumar/data-centric-env | | |
| | π **Training Notebook** | [](https://colab.research.google.com/github/CelestialWorthyOfHeavenAndEarth/data-centric-env/blob/main/train_colab.ipynb) | | |
| | π **Blog Post** | [BLOG.md](./BLOG.md) | | |
| | π» **GitHub** | https://github.com/CelestialWorthyOfHeavenAndEarth/data-centric-env | | |
| | π·οΈ **Theme** | #3.1 β World Modeling / Professional Tasks | | |
| --- | |
| ## π Training Evidence | |
| Real plots and logs from a verified 50-step GRPO run on Google Colab (T4 GPU): | |
| | Artifact | Link | | |
| |---|---| | |
| | π **Reward Curve** | [partial_run_reward_curve.png](./plots/partial_run_reward_curve.png) | | |
| | π― **Accuracy Gain** | [partial_run_accuracy_gain.png](./plots/partial_run_accuracy_gain.png) | | |
| | ποΈ **Curriculum Trace** | [partial_run_curriculum.png](./plots/partial_run_curriculum.png) | | |
| | π **Training Dashboard** | [partial_run_training_dashboard.png](./plots/partial_run_training_dashboard.png) | | |
| | π **Raw Training Log** | [partial_run_training.jsonl](./logs/partial_run_training.jsonl) | | |
| | π **Baseline Comparison** | [partial_run_baseline_comparison.png](./plots/partial_run_baseline_comparison.png) | | |
| > **Run summary:** SFT warmup (350 steps, ~14 min) β GRPO (50 steps, ~25 min). Reward climbed from **β0.23 β +1.00** peak, with format compliance improving **18% β 67%** over training. Extended run plots are in [`plots/full_run_*`](./plots/) and [`logs/full_run_training.jsonl`](./logs/full_run_training.jsonl). | |
| --- | |
| ## π― The Problem | |
| ML practitioners spend 80% of their time on data quality β yet almost no RL infrastructure exists to train LLMs to do this work automatically. | |
| [Andrew Ng's Data-Centric AI](https://datacentricai.org/) movement shows that **fixing the data consistently beats improving the model architecture**. We built a reinforcement learning environment to train an agent to master exactly that skill. | |
| The agent must improve a **frozen classifier** β it cannot change the model at all. Its only lever is the data. | |
| --- | |
| ## π What the Agent Sees, Does, and Gets Rewarded For | |
| ### The Setup | |
| Each episode: a noisy tabular dataset + frozen Random Forest classifier. The agent must push classifier accuracy above a target threshold within a step budget. | |
| ### Action Space (12 commands) | |
| | Command | Effect | | |
| |---------|--------| | |
| | `inspect_dataset` | View shape, missing values, class distribution | | |
| | `inspect_model` | View RF + LR accuracy, F1, per-class metrics | | |
| | `query_analyst` | Holistic diagnosis + prioritised fix plan (costs 2 budget) | | |
| | `query_cleaner` | Missing-value / outlier recommendations with skewness analysis | | |
| | `query_augmenter [class]` | Synthetic row generation for underrepresented classes | | |
| | `query_balancer` | Class rebalancing (oversample / undersample) recommendations | | |
| | `query_validator` | Rule violation detection (costs 2 budget) | | |
| | `apply <N>` | Apply recommendation N | | |
| | `reject <N>` | Reject a recommendation | | |
| | `undo` | Revert last apply (max 3 levels deep) | | |
| | `validate` | Retrain classifier and score (cooldown enforced) | | |
| | `submit` | Finalise episode β triggers terminal reward | | |
| ### Observation Space | |
| ```python | |
| DataCentricObservation( | |
| response="...", # Specialist agent text output | |
| current_accuracy=0.71, # Last validated RF accuracy | |
| baseline_accuracy=0.62, # Accuracy before any fixes | |
| target_accuracy=0.73, # Threshold to beat | |
| estimated_quality=0.84, # Lightweight quality score [0,1] | |
| rows_preserved_pct=0.97, # Fraction of original rows remaining | |
| budget_remaining=22, # Steps left before forced submit | |
| validate_calls_remaining=2, # Free validates remaining | |
| done=False, | |
| ) | |
| ``` | |
| ### Reward Function β OpenEnv Composable Rubrics | |
| **Key design principle: reward must discriminate.** An agent that trivially achieves 100% success on easy tasks with any strategy is not learning β it's saturating. Every rubric is tuned to punish inefficiency and reward surgical accuracy improvement. | |
| | Rubric | Signal | Range | | |
| |--------|--------|-------| | |
| | **AccuracyRubric** | ΞaccΓ2.5 mid-episode; at submit: base + efficiencyΓbudget_fraction + stretch bonus | [-1.0, +0.80] | | |
| | **ProcessRubric** | Correct queryβapplyβvalidate workflow (blind apply = β0.08, submit w/o validate = β0.15) | [-0.20, +0.13] | | |
| | **PreservationRubric** | Must keep β₯92% of rows (prevents delete-to-win cheating) | [-0.50, +0.05] | | |
| | **EfficiencyRubric** | At submit: gain/budget_used Γ 3.0 β hitting target in 5 steps beats 25 steps by 3Γ | [-0.10, +0.25] | | |
| | **StepRubric** | Dense per-apply proxy using lightweight quality score β no classifier retraining | [-0.30, +0.15] | | |
| Total clamped to **[-1.0, 1.0]** by `DataCentricRubric.forward()`. Reward range is real β bad episodes regularly hit β0.4, good ones hit +0.8. | |
| ### Anti-Exploit Hardening (9 protections) | |
| - Ground truth immutability asserted after **every** `apply` | |
| - `validate` cooldown β must take 2 actions between validates | |
| - Duplicate apply detection + session apply limit (max 3 per query) | |
| - Recommendation staleness β re-query required after each session | |
| - Catastrophic data loss (<50% rows) β immediate episode termination | |
| - Episode wall-clock timeout (5 min β forced submit with penalty) | |
| - Input truncation (>200 chars β truncate + β0.01 penalty) | |
| - Repeated same query without apply β β0.05 penalty | |
| - Redundant validate (two in a row) β β0.08 penalty | |
| --- | |
| ## π Task Curriculum (4 Levels) | |
| | Task | Rows | Issues | Baseline | Target | Budget | | |
| |------|------|--------|----------|--------|--------| | |
| | `task_0_tutorial` | 100 | Missing values only (20%) | ~0.62 | 0.73 | 30 | | |
| | `task_1_easy` | 200 | Missing + class imbalance | ~0.63 | 0.79 | 25 | | |
| | `task_2_medium` | 500 | Missing + duplicates + imbalance + type errors | ~0.58 | 0.74 | 40 | | |
| | `task_3_hard` | 900 | 6 issues: above + outliers + cross-column logic errors | ~0.54 | 0.71 | 60 | | |
| Curriculum advances automatically when success rate β₯ 70% over a 20-episode rolling window. | |
| --- | |
| ## ποΈ Architecture | |
| ``` | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β LLM Agent (Qwen2.5-1.5B-Instruct) β | |
| β SFT warmup β GRPO live-environment training β | |
| βββββββββββββββ¬ββββββββββββββββββββββββββββββββββββ¬ββββββββββββββββ | |
| β text commands β structured obs | |
| βΌ β² | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β DataCentricEnvironment (OpenEnv) β | |
| β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββββββ β | |
| β β Cleaner β βAugmenter β β Balancer β β Analyst β β | |
| β β Agent β β Agent β β Agent β β Agent β β | |
| β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββββββ β | |
| β Working Copy (mutable) β | |
| β ββββ Snapshot stack Γ3 (undo support) β | |
| β βββΊ ModelEvaluator (RF + LR, cached, fast_mode) β | |
| β βββΊ Ground Truth (frozen, immutability-asserted) β | |
| β β | |
| β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β | |
| β β DataCentricRubric (OpenEnv composable rubric system) β β | |
| β β βββ AccuracyRubric βββ ProcessRubric β β | |
| β β βββ PreservationRubric βββ EfficiencyRubric β β | |
| β β βββ StepRubric (dense per-step proxy) β β | |
| β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| ``` | |
| --- | |
| ## π Results | |
| ### Training Curves | |
| The following plots are generated by `plot_rewards.py` from the GRPO training log. Run `train_colab.ipynb` to reproduce. | |
| **Reward over training (150 episodes, GRPO with curriculum):** | |
|  | |
| *Rolling mean (blue) rises from β0.1 at episode 0 to +0.65 by episode 150. Vertical dashed lines mark automatic curriculum advancement as the agent masters each level.* | |
| **Full training dashboard (success rate per level, accuracy gain, curriculum progression):** | |
|  | |
| *Top-left: success rate per curriculum level β Easy masters first, Medium and Hard improve progressively. Top-right: accuracy gain above baseline rises from ~0.04 to ~0.12 per episode. Bottom-left: curriculum level advances through 3 levels across 150 episodes.* | |
| ### Trained Agent vs Baselines | |
| **Same tasks, same seeds, 10 episodes per task:** | |
|  | |
| | Agent | Tutorial | Easy | Medium | Hard | **Overall** | | |
| |---|---|---|---|---|---| | |
| | **Random Agent** | 30% | 20% | 10% | 5% | **16%** | | |
| | **Heuristic Baseline** | 100% | 80% | 60% | 40% | **70%** | | |
| | **Trained Agent (GRPO)** | 100% | 95% | 80% | 55% | **83%** | | |
| > The trained agent outperforms the heuristic on every task except tutorial (both 100%). On hard tasks it's +15% absolute improvement. The heuristic always uses the same fixed sequence regardless of data; the trained agent **adapts its strategy to the actual data issues**. | |
| ### Qualitative Comparison | |
| **Random agent** (before training): | |
| ``` | |
| inspect_dataset | |
| apply 3 β blind apply (no query) | |
| validate | |
| validate β redundant validate (cooldown triggers) | |
| submit β submits without hitting target | |
| ``` | |
| **Trained agent** (after GRPO): | |
| ``` | |
| query_analyst β starts with diagnosis | |
| inspect_dataset β orients to data shape | |
| query_cleaner β targets identified issue | |
| apply 1 β applies top recommendation | |
| validate β checks improvement | |
| query_balancer β addresses secondary issue | |
| apply 1 | |
| submit β submits after hitting target | |
| ``` | |
| The trained agent learns the correct workflow sequence β **not** because it was hardcoded, but because the reward function penalises blind applies (β0.08) and rewards the queryβapplyβvalidate loop (+0.09 total). | |
| --- | |
| ## π€ Training Pipeline | |
| **Model:** `Qwen/Qwen2.5-1.5B-Instruct` (4-bit QLoRA via Unsloth, r=8) | |
| **Algorithm:** SFT warmup (1 epoch, ~9,480 examples) β GRPO (TRL GRPOTrainer) | |
| **Tracking:** TensorBoard (`logs/sft/` and `logs/grpo/`) | |
| **Hardware:** Any CUDA GPU (tested on T4/A100) | |
| ### Run Training | |
| ```bash | |
| # Full training (Colab recommended) | |
| # Open train_colab.ipynb β runs SFT + GRPO, auto-resumes on disconnect | |
| ``` | |
| [](https://colab.research.google.com/github/CelestialWorthyOfHeavenAndEarth/data-centric-env/blob/main/train_colab.ipynb) | |
| --- | |
| ## π Quick Start β Use the Live Environment | |
| ```python | |
| pip install openenv-core requests | |
| from client import DataCentricEnv | |
| from models import DataCentricAction | |
| with DataCentricEnv(base_url="https://aswini-kumar-data-centric-env.hf.space").sync() as env: | |
| result = env.reset(task="task_1_easy", seed=42) | |
| obs = result.observation | |
| print(f"Baseline: {obs.baseline_accuracy:.2f} Target: {obs.target_accuracy:.2f}") | |
| # Query the analyst for a prioritised fix plan | |
| result = env.step(DataCentricAction(message="query_analyst")) | |
| print(result.observation.response) | |
| # Apply the top recommendation | |
| result = env.step(DataCentricAction(message="apply 1")) | |
| result = env.step(DataCentricAction(message="validate")) | |
| print(f"Accuracy: {result.observation.current_accuracy:.2f}") | |
| ``` | |
| --- | |
| ## π§ͺ Tests | |
| ```bash | |
| pytest tests/ -v # 35 tests: grader + environment safety invariants | |
| pytest tests/test_grader.py -v # 22 reward component tests | |
| pytest tests/test_environment.py -v # 13 anti-exploit + budget tests | |
| python audit.py # Full connectivity audit (imports + live env cycle) | |
| ``` | |
| --- | |
| ## π Project Structure | |
| ``` | |
| data_centric_env/ | |
| βββ openenv.yaml # OpenEnv manifest | |
| βββ client.py # WebSocket client (never imports server internals) | |
| βββ models.py # DataCentricAction + DataCentricObservation | |
| βββ agent_utils.py # SYSTEM_PROMPT, build_user_prompt, server helpers | |
| βββ train_data_centric.py # SFT β GRPO training pipeline | |
| βββ train_colab.ipynb # Training notebook (11 steps, auto-resume) | |
| βββ eval_data_centric.py # Trained vs random vs heuristic evaluation | |
| βββ plot_rewards.py # 4 reward curve plots | |
| βββ sft_generator.py # Generates ~9,480 SFT warmup trajectories | |
| βββ inference.py # Heuristic baseline agent | |
| βββ audit.py # Full connectivity audit script | |
| βββ plots/ # β Committed training plots | |
| β βββ reward_curve.png | |
| β βββ baseline_comparison.png | |
| β βββ training_dashboard.png | |
| βββ BLOG.md # Detailed writeup | |
| βββ tests/ | |
| β βββ test_grader.py # 22 reward rubric tests | |
| β βββ test_environment.py # 13 environment safety tests | |
| βββ server/ | |
| βββ app.py # FastAPI server | |
| βββ data_centric_environment.py | |
| βββ grader.py # DataCentricRubric + 5 composable child rubrics | |
| βββ specialist_agents.py # Cleaner, Augmenter, Balancer, Validator, Analyst | |
| βββ anti_exploit.py # 9 reward-hacking protections | |
| βββ model_evaluator.py # RF + LR with hash-based caching | |
| βββ dataset_generator.py # 4-task synthetic dataset generation | |
| ``` | |
| --- | |
| ## π‘ Why It Matters | |
| Data-Centric AI is the underexplored frontier of LLM training. Most RL environments train on fixed reasoning tasks (math, code). This environment trains **adaptive judgment under uncertainty** β exactly what distinguishes a senior data engineer. | |
| A model trained here can, given a messy dataset: diagnose the issues, apply targeted fixes in order of impact, verify improvement, and back out bad decisions β autonomously. | |
| **This capability does not exist in pretrained LLMs today.** This environment is the training ground for it. | |
| --- | |
| **Theme:** #3.1 β World Modeling / Professional Tasks | |
| **Stack:** OpenEnv Β· Unsloth Β· TRL (GRPO) Β· FastAPI Β· scikit-learn Β· TensorBoard | |