File size: 9,689 Bytes
86b817d
1779f34
 
 
 
86b817d
 
1779f34
 
 
 
 
 
 
 
86b817d
 
1779f34
 
 
 
16038fc
 
1779f34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16038fc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1779f34
 
 
 
 
 
 
 
 
 
16038fc
1779f34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16038fc
 
 
 
 
 
 
 
 
 
 
 
1779f34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16038fc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1779f34
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
---
title: FSDS Cleaning Environment
emoji: 🧼
colorFrom: indigo
colorTo: green
sdk: docker
pinned: false
app_port: 8000
base_path: /web
tags:
  - openenv
  - rl
  - data-science
  - cleaning
  - fsds
---

# FSDS Cleaning Environment

An HF-ready OpenEnv environment for the **cleaning / Silver-layer** of Full-Stack Data Science.

> **New here?** Read **[AGENT_GUIDE.md](AGENT_GUIDE.md)** β€” tool reference, reward formulas, episode walkthrough, common mistakes, and the full training pipeline.

## What this environment tests

The agent must turn a messy business table into a trustworthy Silver table by:

1. profiling the dataset,
2. identifying duplicates / invalid tokens / schema issues,
3. applying cleaning operations,
4. passing quality gates,
5. submitting the cleaned result.

The environment is inspired by:
- **FSDS**: Bronze β†’ Silver β†’ Gold, with a DS Agent plus QA gates.
- **VDSAgents**: Explore-Agent + PCS-style unit tests and perturbation-minded validation.
- **Data Interpreter**: progressive, tool-driven, multi-step execution instead of one-shot code.

## Tasks included

- `ecommerce_mobile` β€” clean a mobile conversion table.
- `subscription_churn` β€” clean a subscriber churn table.
- `delivery_eta` β€” clean a last-mile delivery table for ETA modeling.

## Quick start

```bash
# 1. Start the server
pip install -e .
uvicorn fsds_cleaning_env.server.app:app --port 8000

# 2. Run the minimal agent example (in another shell)
python examples/minimal_agent.py

# 3. Run the evaluation harness
python -m fsds_cleaning_env.evaluate_agent --agent heuristic

# 4. Run a curriculum training experiment
python -m fsds_cleaning_env.training.run_experiment --config configs/curriculum_rl.json
```

See [AGENT_GUIDE.md](AGENT_GUIDE.md) for the full reference.

## Dataset generation (maximize RL learning)

Tables are generated **per episode** by default (500 rows, medium noise) so the agent sees diverse data each run. This improves generalization.

- **Training**: `env.reset(task_id="ecommerce_mobile", seed=None)` β€” fresh random table each episode.
- **Evaluation**: `env.reset(task_id="ecommerce_mobile", seed=42)` β€” fixed seed for reproducible held-out data.
- **Debug**: `env.reset(task_id="ecommerce_mobile", dataset_mode="debug")` β€” original tiny static table (12 rows).

Optional kwargs: `dataset_n_rows` (override size), `dataset_mode="debug"` (use static data). See `dataset_generators.py` for `NoiseProfile`, `SIZE_*`, and `get_eval_dataset()`.

## Tools

- `list_tasks()`
- `get_task_brief()`
- `preview_data(n=5)`
- `profile_data()`
- `get_operation_history()`
- `apply_cleaning_operation(operation, column=None, strategy="median")`
- `run_quality_gates()`
- `submit_solution()`
- `render_episode(n_preview_rows=5)` β€” human-friendly snapshot with step count, total reward, and a small preview.

## Reward design

Each cleaning action receives a small dense reward based on **quality score improvement**:

- positive reward when the table gets cleaner,
- small step cost to discourage unnecessary actions,
- gate bonus for passing quality checks,
- final reward combining table quality, gate pass/fail, and coverage of required cleaning operations.

This satisfies the hackathon preference for coherent rewards and observable improvement.

## Quality gates

The built-in QA / PCS layer checks:

- no unresolved missing values outside the target,
- no duplicate rows,
- target column preserved,
- row retention above threshold,
- dtype alignment,
- simple stability probe via repeated downstream model scoring.

## What a β€œgood” agent looks like

At evaluation time, we care less about sounding smart and more about concrete, testable behavior. In practice, a good agent for this environment has:

- **High task success**: consistently passes the quality gate on held-out episodes.
- **Strong returns**: high cumulative reward per episode (from dense step rewards + gate + final reward).
- **Low invalid action rate**: few or no tool calls that trigger `error` responses.
- **Good efficiency**: solves tasks in relatively few steps without unnecessary operations.
- **Healthy retention and stability**: preserves enough rows, aligns dtypes, and passes the stability probe.

These metrics can be computed from trajectories using the `metrics` module and evaluated on the scenarios in `evaluation_tasks.py`.

## Local development

```bash
pip install -e .
uvicorn server.app:app --host 0.0.0.0 --port 8000
```

In another shell:

```bash
python examples/local_agent_demo.py
```

## Deploy to Hugging Face

```bash
openenv push
```

## Use from a client

```python
from fsds_cleaning_env import FSDSCleaningEnv

with FSDSCleaningEnv(base_url="https://YOUR-SPACE.hf.space").sync() as env:
    env.reset(task_id="ecommerce_mobile")
    print(env.call_tool("get_task_brief"))
    print(env.call_tool("profile_data"))
    print(env.call_tool("apply_cleaning_operation", operation="drop_duplicates"))
    print(env.call_tool("run_quality_gates"))
    print(env.call_tool("submit_solution"))
```

## Evaluation harness

Run baseline agents on the held-out evaluation set:

```bash
# Local environment (start server first: uvicorn server.app:app --port 8000)
python -m fsds_cleaning_env.evaluate_agent --agent heuristic --base-url http://localhost:8000
python -m fsds_cleaning_env.evaluate_agent --agent random -o results.json

# HF-hosted environment
python -m fsds_cleaning_env.evaluate_agent --agent heuristic --base-url https://YOUR-SPACE.hf.space
```

Agents: `RandomAgent` (uniform random over tools), `HeuristicAgent` (rule-based canonical policy). Output: success rate, avg return, avg steps, invalid actions; optional JSON file.

## Training harness

Run config-driven training experiments:

```bash
# Start server first: uvicorn fsds_cleaning_env.server.app:app --port 8000
python -m fsds_cleaning_env.training.run_experiment --config configs/basic_rl.json
# Or with YAML (requires: pip install pyyaml)
python -m fsds_cleaning_env.training.run_experiment --config configs/basic_rl.yaml
```

Config: `task_id`, `n_episodes`, `agent` (random | heuristic), `base_url`, `max_steps_per_episode`, `log_dir`, `log_interval`, `seed`, `output_dir`. Results are logged to `log_dir/` and saved as JSON in `output_dir/`. For full GRPO/TRL training with LLMs, see `training_colab.py`.

## Curriculum training

The `CurriculumScheduler` in `curriculum.py` drives progressive difficulty across three stages:

| Stage  | Noise   | Rows | Steps | Promote at              |
|--------|---------|------|-------|-------------------------|
| easy   | light   | 100  | 22    | β‰₯70% success / 10 eps   |
| medium | medium  | 500  | 18    | β‰₯65% success / 15 eps   |
| hard   | heavy   | 1000 | 15    | terminal level          |

**Quick start** β€” run the curriculum experiment config:

```bash
# Start server first
python -m fsds_cleaning_env.training.run_experiment --config configs/curriculum_rl.json
```

**Demo (no server required):**

```bash
python examples/curriculum_demo.py --n-episodes 60
# Live run (requires server):
python examples/curriculum_demo.py --live --base-url http://localhost:8000 --n-episodes 30
```

**Programmatic usage:**

```python
from fsds_cleaning_env.curriculum import CurriculumScheduler

scheduler = CurriculumScheduler(
    task_ids=["ecommerce_mobile", "subscription_churn", "delivery_eta"],
    mode="round_robin",   # or "random"
    start_level="easy",
)

for ep in range(n_episodes):
    cur = scheduler.next_task(seed=ep)
    trajectory = agent.run_episode(env, **cur.reset_kwargs(), max_steps=cur.max_steps)
    promoted = scheduler.record_episode(success=trajectory_success(trajectory))
    if promoted:
        print(f"Promoted to {scheduler.level_name}!")
```

`scheduler.summary()` returns a JSON-serialisable dict with the current level, rolling success rate, and full promotion history β€” automatically saved in run results when using the training harness.

## SFT-first, RL-second (Phase 7)

Expert trajectories from the `HeuristicAgent` are used to SFT-warm-start the model before GRPO reinforcement learning.  A warm-start model already knows the JSON action format and the correct *inspect β†’ clean β†’ validate* methodology, so GRPO converges much faster.

**Step 1 β€” Collect demonstrations and train SFT model (Colab)**

Open `training_sft.py` in Colab and run all cells.  It will:
1. Connect to the HF Space and collect expert trajectories.
2. Build a Hugging Face Dataset of step-level `(prompt, completion)` pairs.
3. Fine-tune via `trl.SFTTrainer` and save the adapter to `./data-cleaning-sft-final/`.

**Step 2 β€” Use the SFT checkpoint as the RL warm-start**

In `training_colab.py`, change one line:

```python
# Before (trains from scratch):
MODEL_NAME = "unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit"

# After (warm-start from SFT):
MODEL_NAME = "./data-cleaning-sft-final"
```

**Programmatic demo collection (no Colab)**

```python
from fsds_cleaning_env.demonstrations import DemonstrationCollector, build_sft_dataset, save_demonstrations
from fsds_cleaning_env import FSDSCleaningEnv

with FSDSCleaningEnv(base_url="http://localhost:8000").sync() as env:
    demos = DemonstrationCollector(env).collect(
        task_ids=["ecommerce_mobile", "subscription_churn", "delivery_eta"],
        n_per_task=20,
    )

save_demonstrations(demos, "demos/expert_demos.json")
dataset = build_sft_dataset(demos, mode="step", successful_only=True)
print(f"{len(dataset)} SFT training examples")
```

Config reference: `configs/sft_config.json`.

## Minimal TRL integration

See `examples/trl_rollout_stub.py` for a compact `rollout_func` pattern that forwards `env_reward` into a TRL reward function.