Dhruv Goyal commited on
Commit
efaffe2
Β·
1 Parent(s): f0ad703
Files changed (2) hide show
  1. README.md +1 -1
  2. 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>