File size: 8,733 Bytes
75ba9ee
 
 
 
1259390
75ba9ee
 
aa97969
7ff4071
1ce77b3
75ba9ee
 
 
 
 
 
7ff4071
 
75ba9ee
 
aa97969
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
753b5ee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
---
title: Email Triage RL Environment
emoji: πŸ“§
colorFrom: blue
colorTo: indigo
sdk: docker
app_port: 7860
pinned: false
license: apache-2.0
short_description: RL env to classify, route and reply to emails
tags:
  - openenv
  - email-triage
  - rl
  - real-world
  - nlp
  - reinforcement-learning
  - environment
---

# πŸ“§ Email Triage Environment

> **Meta Γ— PyTorch OpenEnv Hackathon β€” Round 1**
> An RL environment where an AI agent learns to triage real-world emails.

## 🎯 What Is This?

This environment simulates an **email triage system** β€” a task every business performs daily. An agent receives a queue of emails and must:

1. **Classify** the email (spam / billing / technical / hr / general)
2. **Assign a priority** (low / medium / high / urgent)
3. **Route** to the correct department (support / finance / engineering / hr / management)
4. **Draft a professional reply** (required for medium and hard tasks)

Rewards are **continuous and partial** β€” agents earn credit for getting each dimension right, incentivising learning even when the full answer isn't perfect.

---

## πŸ—‚οΈ Action Space

| Field        | Type   | Values                                              |
|--------------|--------|-----------------------------------------------------|
| `category`   | string | `spam` Β· `billing` Β· `technical` Β· `hr` Β· `general` |
| `priority`   | string | `low` Β· `medium` Β· `high` Β· `urgent`                |
| `department` | string | `support` Β· `finance` Β· `engineering` Β· `hr` Β· `management` |
| `reply`      | string | Free-text reply draft (empty string for easy tasks) |

---

## πŸ‘οΈ Observation Space

| Field             | Type   | Description                                  |
|-------------------|--------|----------------------------------------------|
| `email_id`        | string | Unique email identifier                      |
| `subject`         | string | Email subject line                           |
| `body`            | string | Full email body                              |
| `sender`          | string | Sender's email address                       |
| `task_level`      | string | `easy` Β· `medium` Β· `hard`                  |
| `feedback`        | string | Natural-language grader feedback             |
| `score`           | float  | Cumulative average score (0.0–1.0)           |
| `emails_remaining`| int    | Number of emails left in the episode         |
| `done`            | bool   | Episode complete flag                        |
| `reward`          | float  | Per-step reward (0.0–1.0)                    |

---

## πŸ“Š Task Descriptions

### 🟒 Easy β€” Classification Only
- **5 emails** per episode (spam, billing, technical, HR, general)
- Agent must correctly classify category, priority, and department
- No reply required
- Score: `category(0.4) + priority(0.3) + department(0.3)`

### 🟑 Medium β€” Classification + Short Reply
- **3 emails** per episode (billing urgency, technical incident, HR complaint)
- Agent must classify AND write a professional 2-4 sentence reply
- Score: `classification(0.5) + reply_quality(0.5)`
- Reply graded on: professional tone, keyword coverage

### πŸ”΄ Hard β€” Classification + Detailed Accurate Reply
- **3 emails** per episode (enterprise escalations, security incidents, board complaints)
- Agent must classify AND write a detailed, accurate reply covering specific required points
- Score: `classification(0.4) + reply_depth(0.6)`
- Reply graded on: length, tone, keyword coverage (9 required keywords per email)

---

## πŸ† Reward Function

Rewards are **partial and continuous** β€” agents earn credit at every step:

| Condition                                 | Reward        |
|-------------------------------------------|---------------|
| Correct category                          | +0.15 – +0.40 |
| Correct priority                          | +0.13 – +0.30 |
| Correct department                        | +0.12 – +0.30 |
| Reply provided (non-trivial)              | +0.05 – +0.10 |
| Professional tone in reply                | +0.05 – +0.10 |
| Each required keyword matched             | proportional  |
| Missing reply on medium/hard             | βˆ’0.10 penalty |

---

## πŸš€ Quick Start

### 1. Install dependencies
```bash
git clone https://huggingface.co/spaces/Shivacode/rl-hackathon
cd rl-hackathon
pip install -e email_triage_rl_hackathon/
```

### 2. Run the server locally
```bash
# Easy task (default)
uvicorn email_triage_rl_hackathon.server.app:app --host 0.0.0.0 --port 8000 --reload

# Medium task
TASK_LEVEL=medium uvicorn email_triage_rl_hackathon.server.app:app --port 8000

# Hard task
TASK_LEVEL=hard uvicorn email_triage_rl_hackathon.server.app:app --port 8000
```

### 3. Interact with the environment (Python)
```python
import asyncio
from email_triage_rl_hackathon import EmailTriageEnv, TriageAction

async def main():
    env = EmailTriageEnv(base_url="http://localhost:8000")
    obs = await env.reset(seed=42, task_level="easy")
    print(obs.subject)

    result = await env.step(TriageAction(
        category="billing", priority="urgent",
        department="finance",
        reply="Dear customer, we apologize and will investigate within 24 hours."
    ))
    print(result.reward, result.observation.feedback)
    await env.close()

asyncio.run(main())
```

### 4. Run with Docker
```bash
docker build -t email-triage-env .
docker run -p 7860:7860 -e TASK_LEVEL=easy email-triage-env
```

### 5. Run inference against this Space
```bash
HF_TOKEN=hf_your_token_here \
ENV_BASE_URL=https://Shivacode-rl-hackathon.hf.space \
TASK_LEVEL=easy \
python inference.py
```

---

## πŸ“ˆ Scores (Qwen/Qwen2.5-72B-Instruct via HF Router)

| Task Level | Steps | Score  |
|------------|-------|--------|
| Easy       | 5     | 0.880  |
| Medium     | 3     | 0.830  |
| Hard       | 3     | 0.800  |
| **Overall**|       | **0.837** |

---

## πŸ—ƒοΈ Project Structure

```
rl-hackathon/
β”œβ”€β”€ Dockerfile                    # HF Spaces Docker deployment (port 7860)
β”œβ”€β”€ inference.py                  # Run agent against this environment
β”œβ”€β”€ baseline.py                   # Baseline script (OpenAI models)
└── email_triage_rl_hackathon/
    β”œβ”€β”€ __init__.py               # Public exports
    β”œβ”€β”€ models.py                 # TriageAction, TriageObservation
    β”œβ”€β”€ client.py                 # EmailTriageEnv (EnvClient)
    β”œβ”€β”€ openenv.yaml              # Environment manifest
    β”œβ”€β”€ pyproject.toml            # Package config + scripts entry point
    β”œβ”€β”€ uv.lock                   # Locked dependencies
    └── server/
        β”œβ”€β”€ app.py                # FastAPI app (uvicorn entry point)
        β”œβ”€β”€ my_environment.py     # EmailTriageEnvironment (reset/step/state)
        β”œβ”€β”€ email_data.py         # 11 curated emails across 3 levels
        β”œβ”€β”€ graders.py            # Deterministic graders (easy/medium/hard)
        └── requirements.txt
```

---

## πŸ”‘ Environment Variables

| Variable        | Default                    | Description                          |
|-----------------|----------------------------|--------------------------------------|
| `TASK_LEVEL`    | `easy`                     | Task difficulty: easy / medium / hard |
| `PORT`          | `7860`                     | Server port                          |
| `HF_TOKEN`      | β€”                          | Required for inference.py (HF router)|
| `MODEL_NAME`    | `Qwen/Qwen2.5-72B-Instruct`| Model for inference                  |
| `ENV_BASE_URL`  | `http://localhost:8000`    | Environment server URL               |


## Structure

```
hackathon-sst/
β”œβ”€β”€ email_triage_rl_hackathon/              
β”‚   β”œβ”€β”€ models.py        ← Action / Observation / State
β”‚   β”œβ”€β”€ client.py        ← EnvClient
β”‚   β”œβ”€β”€ server/
β”‚   β”‚   β”œβ”€β”€ my_environment.py          ← reset(), step(), state()
β”‚   β”‚   └── app.py             ← FastAPI server
β”‚   β”œβ”€β”€ Dockerfile
β”‚   └── openenv.yaml
β”œβ”€β”€ pyproject.toml
└── .venv/               ← Python virtual environment
```

## Getting Started

```bash
# Activate venv
source .venv/bin/activate

# Install dependencies
pip install openenv-core fastapi uvicorn pydantic

# Run the server
uvicorn email_triage_rl_hackathon.server.app:app --reload --port 8000
```

## Useful Links

- [OpenEnv GitHub](https://github.com/meta-pytorch/OpenEnv)
- [OpenEnv Course](https://github.com/huggingface/openenv-course)
- [OpenEnv Docs](https://meta-pytorch.org/OpenEnv/)
- [Hackathon Dashboard](https://www.scaler.com/school-of-technology/meta-pytorch-hackathon/)