Spaces:
Sleeping
Sleeping
Dhruv Goyal commited on
Commit Β·
efaffe2
1
Parent(s): f0ad703
changes
Browse files- README.md +1 -1
- explainer.html +196 -0
README.md
CHANGED
|
@@ -23,7 +23,7 @@ Agents learn to fix messy tabular data β filling nulls, normalising inconsiste
|
|
| 23 |
|
| 24 |
---
|
| 25 |
|
| 26 |
-
## Why This Environment
|
| 27 |
|
| 28 |
Data cleaning is one of the most common, time-consuming tasks in real data engineering. Every company with a data pipeline does this daily. Training an RL agent on this task has immediate real-world value β unlike game-based environments.
|
| 29 |
|
|
|
|
| 23 |
|
| 24 |
---
|
| 25 |
|
| 26 |
+
## Why This Environment?
|
| 27 |
|
| 28 |
Data cleaning is one of the most common, time-consuming tasks in real data engineering. Every company with a data pipeline does this daily. Training an RL agent on this task has immediate real-world value β unlike game-based environments.
|
| 29 |
|
explainer.html
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<title>DataClean OpenEnv β Team Explainer</title>
|
| 6 |
+
<style>
|
| 7 |
+
body { font-family: Arial, sans-serif; max-width: 860px; margin: 40px auto; padding: 0 20px; color: #000; background: #fff; line-height: 1.7; }
|
| 8 |
+
h1 { font-size: 26px; border-bottom: 2px solid #000; padding-bottom: 8px; }
|
| 9 |
+
h2 { font-size: 18px; margin-top: 36px; border-bottom: 1px solid #ccc; padding-bottom: 4px; }
|
| 10 |
+
h3 { font-size: 15px; margin-top: 20px; }
|
| 11 |
+
table { width: 100%; border-collapse: collapse; margin: 16px 0; }
|
| 12 |
+
th, td { border: 1px solid #999; padding: 8px 12px; text-align: left; vertical-align: top; }
|
| 13 |
+
th { background: #f0f0f0; font-weight: bold; }
|
| 14 |
+
code { background: #f4f4f4; padding: 2px 6px; border-radius: 3px; font-family: monospace; font-size: 13px; }
|
| 15 |
+
pre { background: #f4f4f4; padding: 14px; border-radius: 4px; overflow-x: auto; font-size: 13px; line-height: 1.6; }
|
| 16 |
+
.box { border: 1px solid #999; padding: 14px 18px; margin: 16px 0; border-radius: 4px; }
|
| 17 |
+
.highlight { background: #fffbe6; border-left: 4px solid #999; padding: 10px 16px; margin: 16px 0; }
|
| 18 |
+
ul { margin: 8px 0; padding-left: 24px; }
|
| 19 |
+
li { margin-bottom: 4px; }
|
| 20 |
+
.score-row { display: flex; align-items: center; gap: 12px; margin: 6px 0; }
|
| 21 |
+
.bar-wrap { flex: 1; background: #e0e0e0; height: 14px; border-radius: 2px; }
|
| 22 |
+
.bar { height: 14px; background: #555; border-radius: 2px; }
|
| 23 |
+
small { color: #555; font-size: 12px; }
|
| 24 |
+
</style>
|
| 25 |
+
</head>
|
| 26 |
+
<body>
|
| 27 |
+
|
| 28 |
+
<h1>DataClean OpenEnv β What We Built & Why</h1>
|
| 29 |
+
<p><em>Team explainer β no jargon, plain English</em></p>
|
| 30 |
+
|
| 31 |
+
<h2>1. What is this hackathon actually asking us to build?</h2>
|
| 32 |
+
<div class="box">
|
| 33 |
+
<p>Meta and Hugging Face created a standard called <strong>OpenEnv</strong>. Think of it like a rulebook for building AI training gyms. The hackathon says: <em>"Build a gym for an AI agent to practice a real-world task in."</em></p>
|
| 34 |
+
<p>The gym must:</p>
|
| 35 |
+
<ul>
|
| 36 |
+
<li>Let an AI agent take actions step by step</li>
|
| 37 |
+
<li>Give the agent a score after each action (reward)</li>
|
| 38 |
+
<li>Have at least 3 tasks β easy, medium, hard</li>
|
| 39 |
+
<li>Run inside Docker and deploy on Hugging Face</li>
|
| 40 |
+
</ul>
|
| 41 |
+
<p><strong>We chose the task: Data Cleaning.</strong> Every company that works with data spends hours fixing messy spreadsheets. We built an environment where an AI can learn to do that automatically.</p>
|
| 42 |
+
</div>
|
| 43 |
+
|
| 44 |
+
<h2>2. What does "data cleaning" mean here?</h2>
|
| 45 |
+
<p>Imagine you receive a messy Excel file from a client. It might have:</p>
|
| 46 |
+
<ul>
|
| 47 |
+
<li>Missing values β some cells are blank or say "N/A"</li>
|
| 48 |
+
<li>Wrong data types β age stored as text "25" instead of number 25</li>
|
| 49 |
+
<li>Duplicate rows β same record appears twice</li>
|
| 50 |
+
<li>Inconsistent text β "USA", "usa", "U.S.A" all meaning the same country</li>
|
| 51 |
+
<li>Extreme outliers β amount = $500,000 when everything else is under $2,000</li>
|
| 52 |
+
<li>Multiple tables that need to be joined together</li>
|
| 53 |
+
</ul>
|
| 54 |
+
<p>Our environment presents these messy datasets to an AI agent and asks it to fix them step by step.</p>
|
| 55 |
+
|
| 56 |
+
<h2>3. How does the AI agent interact? (The Loop)</h2>
|
| 57 |
+
<div class="box">
|
| 58 |
+
<pre>
|
| 59 |
+
1. reset() β Agent receives a dirty dataset + description of what to fix
|
| 60 |
+
Score starts at 0.0
|
| 61 |
+
|
| 62 |
+
2. step() β Agent sends ONE action (e.g. "fill nulls in age column with median")
|
| 63 |
+
Environment applies it, scores the result
|
| 64 |
+
Agent receives: updated dataset + reward + current score
|
| 65 |
+
|
| 66 |
+
3. repeat β Agent keeps sending actions until it calls "submit" or runs out of steps
|
| 67 |
+
|
| 68 |
+
4. submit β Final score is recorded. Episode ends.
|
| 69 |
+
</pre>
|
| 70 |
+
</div>
|
| 71 |
+
<p>The agent never sees the "correct answer" β it only sees the current messy data and must figure out what to fix based on the feedback it gets after each action.</p>
|
| 72 |
+
|
| 73 |
+
<h2>4. Our 4 Tasks</h2>
|
| 74 |
+
<table>
|
| 75 |
+
<tr><th>Task</th><th>Difficulty</th><th>What the agent must do</th><th>Max Steps</th></tr>
|
| 76 |
+
<tr>
|
| 77 |
+
<td><strong>task1</strong><br>Null Fixer</td>
|
| 78 |
+
<td>Easy</td>
|
| 79 |
+
<td>50-row customer table. Fill missing age values with median β convert to integer. Fill missing salary values with mean.</td>
|
| 80 |
+
<td>10</td>
|
| 81 |
+
</tr>
|
| 82 |
+
<tr>
|
| 83 |
+
<td><strong>task2</strong><br>Schema Normalizer</td>
|
| 84 |
+
<td>Medium</td>
|
| 85 |
+
<td>200-row orders table. Remove ~30 duplicate rows. Fix "usa/USA/U.S.A" β all uppercase. Convert mixed date formats to proper datetime. Fill missing amounts.</td>
|
| 86 |
+
<td>20</td>
|
| 87 |
+
</tr>
|
| 88 |
+
<tr>
|
| 89 |
+
<td><strong>task3</strong><br>ETL Pipeline</td>
|
| 90 |
+
<td>Hard</td>
|
| 91 |
+
<td>Two separate tables (orders + customers). Must: join them on customer_id, remove outliers in the amount column, add a new "order_year" column derived from the date.</td>
|
| 92 |
+
<td>30</td>
|
| 93 |
+
</tr>
|
| 94 |
+
<tr>
|
| 95 |
+
<td><strong>task4</strong><br>Data Drift β</td>
|
| 96 |
+
<td>Expert (Novel)</td>
|
| 97 |
+
<td>Live streaming table. Starts with 120 dirty rows. Every 5 steps, 7 MORE dirty rows are automatically injected β simulating a real Kafka data pipeline. Agent must keep cleaning while new dirty data keeps arriving.</td>
|
| 98 |
+
<td>40</td>
|
| 99 |
+
</tr>
|
| 100 |
+
</table>
|
| 101 |
+
|
| 102 |
+
<div class="highlight">
|
| 103 |
+
<strong>Why Task 4 is our competitive edge:</strong> No existing OpenEnv environment does this. All other environments have a fixed dataset β static, unchanging. Task 4 simulates what actually happens in production data pipelines where data keeps flowing in. This is genuinely novel.
|
| 104 |
+
</div>
|
| 105 |
+
|
| 106 |
+
<h2>5. Actions β what can the AI agent do?</h2>
|
| 107 |
+
<p>The agent can only do these specific operations (one per step):</p>
|
| 108 |
+
<table>
|
| 109 |
+
<tr><th>Operation</th><th>What it does</th><th>Example</th></tr>
|
| 110 |
+
<tr><td><code>fill_nulls</code></td><td>Fill missing values in a column</td><td>Fill age nulls with median value</td></tr>
|
| 111 |
+
<tr><td><code>cast_column</code></td><td>Change data type of a column</td><td>Convert age from text to integer</td></tr>
|
| 112 |
+
<tr><td><code>remove_duplicates</code></td><td>Delete duplicate rows</td><td>Keep only the first occurrence</td></tr>
|
| 113 |
+
<tr><td><code>normalize_values</code></td><td>Standardize text values</td><td>Convert all country names to UPPERCASE</td></tr>
|
| 114 |
+
<tr><td><code>filter_outliers</code></td><td>Remove extreme values</td><td>Remove amounts outside IQRΓ1.5 range</td></tr>
|
| 115 |
+
<tr><td><code>merge_tables</code></td><td>Join two tables together</td><td>Join orders + customers on customer_id</td></tr>
|
| 116 |
+
<tr><td><code>add_derived_column</code></td><td>Create new column from existing data</td><td>Extract year from a date column</td></tr>
|
| 117 |
+
<tr><td><code>submit</code></td><td>End the episode, get final score</td><td>β</td></tr>
|
| 118 |
+
</table>
|
| 119 |
+
|
| 120 |
+
<h2>6. Scoring (Reward System)</h2>
|
| 121 |
+
<p>After every single step, the agent gets a reward:</p>
|
| 122 |
+
<pre>
|
| 123 |
+
reward = new_score - previous_score
|
| 124 |
+
</pre>
|
| 125 |
+
<p>This means:</p>
|
| 126 |
+
<ul>
|
| 127 |
+
<li>If the action improved the data β positive reward (+)</li>
|
| 128 |
+
<li>If the action made things worse β negative reward (β)</li>
|
| 129 |
+
<li>If the action failed/invalid β small penalty (β0.02)</li>
|
| 130 |
+
</ul>
|
| 131 |
+
<p>Each task has its own grader that scores specific things. For example, Task 1 grader checks:</p>
|
| 132 |
+
<ul>
|
| 133 |
+
<li>30% β is age integer type?</li>
|
| 134 |
+
<li>35% β are all age nulls filled?</li>
|
| 135 |
+
<li>15% β is salary numeric?</li>
|
| 136 |
+
<li>20% β are all salary nulls filled?</li>
|
| 137 |
+
</ul>
|
| 138 |
+
<p>This "partial credit" design means the agent always has a signal to improve β it's never just 0 or 1 with nothing in between.</p>
|
| 139 |
+
|
| 140 |
+
<h2>7. What is the "Baseline"?</h2>
|
| 141 |
+
<p>The hackathon requires us to show that an actual AI model can run against our environment and produce scores. Our baseline uses a free LLM (Groq's llama-3.3-70b) to play through all 4 tasks.</p>
|
| 142 |
+
<p><strong>Our innovation:</strong> All 4 tasks run <em>simultaneously</em> using Python threads (parallel execution). Normal submissions run tasks one by one. Ours runs all 4 at the same time β 3x faster.</p>
|
| 143 |
+
|
| 144 |
+
<h3>Baseline results (seed=42, all 4 parallel):</h3>
|
| 145 |
+
<div class="box">
|
| 146 |
+
<div class="score-row"><span style="width:200px">task1 β Null Fixer</span><div class="bar-wrap"><div class="bar" style="width:100%"></div></div><span>1.0000</span></div>
|
| 147 |
+
<div class="score-row"><span style="width:200px">task2 β Schema Normalizer</span><div class="bar-wrap"><div class="bar" style="width:100%"></div></div><span>1.0000</span></div>
|
| 148 |
+
<div class="score-row"><span style="width:200px">task3 β ETL Pipeline</span><div class="bar-wrap"><div class="bar" style="width:80%"></div></div><span>0.8000</span></div>
|
| 149 |
+
<div class="score-row"><span style="width:200px">task4 β Data Drift</span><div class="bar-wrap"><div class="bar" style="width:93%"></div></div><span>0.9297</span></div>
|
| 150 |
+
<div class="score-row"><span style="width:200px"><strong>Mean</strong></span><div class="bar-wrap"><div class="bar" style="width:93%"></div></div><span><strong>0.9324</strong></span></div>
|
| 151 |
+
<p><small>Wall clock time: 34.28 seconds (all 4 tasks ran simultaneously)</small></p>
|
| 152 |
+
</div>
|
| 153 |
+
|
| 154 |
+
<h2>8. How the code is structured</h2>
|
| 155 |
+
<table>
|
| 156 |
+
<tr><th>File</th><th>What it does (plain English)</th></tr>
|
| 157 |
+
<tr><td><code>server/dataset_factory.py</code></td><td>Generates dirty datasets. Uses a "seed" number so the same dataset is always generated the same way β ensures reproducibility. Also generates "drift batches" (new dirty rows) for Task 4.</td></tr>
|
| 158 |
+
<tr><td><code>server/graders.py</code></td><td>The scoring functions. Takes the current state of the data and returns a number between 0.0 and 1.0. Completely deterministic β same input always gives same score.</td></tr>
|
| 159 |
+
<tr><td><code>server/environment.py</code></td><td>The "game engine". Handles reset(), step(), and state(). For Task 4 it automatically injects drift rows every 5 steps.</td></tr>
|
| 160 |
+
<tr><td><code>server/app.py</code></td><td>The web server (FastAPI). Exposes all endpoints as HTTP routes so any agent can talk to it.</td></tr>
|
| 161 |
+
<tr><td><code>models.py</code></td><td>Defines exactly what an Action and Observation look like using Pydantic. This is the "contract" between agent and environment.</td></tr>
|
| 162 |
+
<tr><td><code>baseline.py</code></td><td>Runs an LLM agent against all 4 tasks simultaneously and prints scores.</td></tr>
|
| 163 |
+
<tr><td><code>Dockerfile</code></td><td>Packages everything into a container. Runs on port 7860 (required by Hugging Face Spaces).</td></tr>
|
| 164 |
+
</table>
|
| 165 |
+
|
| 166 |
+
<h2>9. Why this beats "TicTacToe" type submissions</h2>
|
| 167 |
+
<table>
|
| 168 |
+
<tr><th></th><th>Game-based (TicTacToe etc.)</th><th>Our submission</th></tr>
|
| 169 |
+
<tr><td>Real-world use</td><td>No practical application</td><td>Every data team uses this daily</td></tr>
|
| 170 |
+
<tr><td>Domain novelty</td><td>Already exists in OpenEnv</td><td>First data cleaning environment</td></tr>
|
| 171 |
+
<tr><td>Difficulty range</td><td>Usually one level</td><td>Easy β Medium β Hard β Expert</td></tr>
|
| 172 |
+
<tr><td>Grader variance</td><td>Win/loss binary</td><td>Continuous 0.0β1.0 with partial credit</td></tr>
|
| 173 |
+
<tr><td>Novel mechanics</td><td>None</td><td>Live data drift (Task 4) β genuinely new</td></tr>
|
| 174 |
+
<tr><td>Baseline</td><td>Sequential</td><td>Parallel (4 tasks simultaneously)</td></tr>
|
| 175 |
+
</table>
|
| 176 |
+
|
| 177 |
+
<h2>10. Hackathon scoring β how we expect to do</h2>
|
| 178 |
+
<table>
|
| 179 |
+
<tr><th>Criterion</th><th>Weight</th><th>Our position</th></tr>
|
| 180 |
+
<tr><td>Real-world utility</td><td>30%</td><td>Strong β data cleaning is a genuine daily task</td></tr>
|
| 181 |
+
<tr><td>Task & grader quality</td><td>25%</td><td>Strong β 4 tasks, deterministic graders, partial credit</td></tr>
|
| 182 |
+
<tr><td>Environment design</td><td>20%</td><td>Strong β dense rewards, drift injection, clean state management</td></tr>
|
| 183 |
+
<tr><td>Code quality & spec compliance</td><td>15%</td><td>Good β typed models, FastAPI, Dockerfile works</td></tr>
|
| 184 |
+
<tr><td>Creativity & novelty</td><td>10%</td><td>Strong β Task 4 is genuinely novel in OpenEnv</td></tr>
|
| 185 |
+
</table>
|
| 186 |
+
|
| 187 |
+
<h2>11. Deployment</h2>
|
| 188 |
+
<p>The environment is deployed at:</p>
|
| 189 |
+
<p><strong><a href="https://huggingface.co/spaces/agent-dg21/dataclean-env">https://huggingface.co/spaces/agent-dg21/dataclean-env</a></strong></p>
|
| 190 |
+
<p>It runs as a Docker container on Hugging Face Spaces (free CPU tier). Any agent in the world can connect to it and start training.</p>
|
| 191 |
+
|
| 192 |
+
<hr>
|
| 193 |
+
<p><small>Built for Meta Γ Hugging Face OpenEnv Hackathon Β· Team: Mishika Sardana, Vaani Prashar, Dhruv Goyal</small></p>
|
| 194 |
+
|
| 195 |
+
</body>
|
| 196 |
+
</html>
|