Spaces:
Sleeping
Sleeping
| title: EmailTriage Environment Server | |
| emoji: π¬ | |
| colorFrom: blue | |
| colorTo: green | |
| sdk: docker | |
| pinned: false | |
| app_port: 8000 | |
| base_path: /web | |
| tags: | |
| - openenv | |
| - rl | |
| - email-triage | |
| - multi-agent | |
| # π¬ EmailTriage: An OpenEnv Reinforcement Learning Environment | |
| A dynamic, multi-turn **OpenEnv** environment designed for strict, realistic email triage orchestration. This environment acts as a standard `step()`, `reset()`, and `state()` API that grades AI agents on how efficiently they can navigate a turbulent inbox. | |
| This project was built explicitly to fulfill the **OpenEnv Hackathon Challenge**. It passes all `openenv validate` pre-submission testing checks and is deployed universally via a Dockerfile container on Hugging Face. | |
| --- | |
| ## π― Core Problem Statement & Environment Logic | |
| ### What does this test? | |
| Unlike standard mini-games, this environment tests complex NLP reasoning and chronological tool-use. The agent must: | |
| - Detect text context to differentiate between `Spam/Marketing` vs `Escalated P1 Outages`. | |
| - Accurately trigger `archive` methods to clean the inbox loop without sacrificing important messages. | |
| - Dynamically `read` emails, followed by executing a `query_calendar` sync, and finishing with an accurate `draft_email` containing a matched date-time string logic. | |
| ### β‘ Huge Scenario Pool! | |
| The internal environment has a massive deterministic dictionary of **over 50 unique real-world emails** ranging from: | |
| - Angry CEOs making demands | |
| - Fraudulent Nigerian Princes | |
| - Legitimate B2B Vendor negotiations | |
| - DataDog Server crashing alerts | |
| --- | |
| ## π The Three Task Difficulties | |
| | ID | Name | Initial Inbox Size | Max Steps | Dynamic Events (Mid-Episode) | | |
| |----|------|--------|-----------|----------------| | |
| | `easy` | Quick Sort | Exactly 3 | 6 Iterations| β | | |
| | `medium` | Priority Triage | Exactly 5 | 10 Iterations| β | | |
| | `hard` | Dynamic Crisis | 7 to 10 | 12 Iterations| β (See Below) | | |
| ### πͺοΈ Hard Mode Dynamic Events | |
| If the AI engages in Hard Mode, the environment is programmed to actively combat the agent mid-episode: | |
| 1. **Interrupts:** Exactly on Step 3, a brand new `High Priority` email from the CEO is forcefully appended to the unread inbox queue. | |
| 2. **Calendar Shifts:** Mid-episode, an available meeting slot might spontaneously disappear, forcing the AI to re-scan its options before generating a draft scheduling email. | |
| --- | |
| ## π Action & Observation Schema Specifications | |
| ### The Agent's Action Hook (`EmailtriageAction`) | |
| The AI must reply in strictly validated JSON matching these arguments over the WebSocket: | |
| - `action_type`: Strictly mapped to `read`, `archive`, `query_calendar`, or `draft_email`. | |
| - `target_email_id`: Matches an Integer directly mapped to the dynamically changing Inbox observation. (Use `-1` for generic commands like querying). | |
| - `draft_content`: Minimum 40-character String. Scored heuristically on politeness ("thank you"), subject matching, and structural completion periods. | |
| - `proposed_slot`: String matching a Date-Time object scraped from the calendar. | |
| ### The Observation Space (`EmailtriageObservation`) | |
| In order to prevent LLM hallucination cheating, the `Observation` payload strictly returns `[:5]` of the array (Only showing the first 5 unread items on "Screen 1"). **The email Body is heavily redacted** until the AI spends a turn executing the `read` action! | |
| - `inbox_preview`: Summaries of up to 5 unread emails | |
| - `returned_emails`: Contains the full string body unlocked by manual `read` actions | |
| - `calendar_slots`: Array of currently available dates | |
| - `last_action_result`: The immediate Grader string feedback returned to the AI | |
| - `reward`: Floating integer normalized between `[0.0, 1.0]` | |
| --- | |
| ## βοΈ The Grader & Reward Logic | |
| Continuous `[0, 1]` rewards granting partial credit based on deterministic logic matching: | |
| - **Archiving Logic**: `+0.62` to `+0.80` for accurately archiving Spam and Newsletters. Massive negative penalty for archiving High Priority client emails. | |
| - **Reading Logic**: `+0.09` to `+0.25` for pulling data into focus (High Priority messages score higher). | |
| - **Drafting Workflow**: Heavy reward weighting `+0.55+` if the AI perfectly maps `read -> query_calendar -> draft_email` seamlessly. Partial deductions for proposing unavailable chronological slots or missing urgent keywords ("today"). | |
| --- | |
| ## π οΈ Quick Start & Setup Instructions | |
| ### 1. Run inference locally via Uvicorn Server | |
| Because this project utilizes modern `OpenEnv >= 0.2.2`, all environment interactions are fully asynchronous. | |
| Boot the backend HTTP server: | |
| ```bash | |
| uvicorn server.app:app --host 0.0.0.0 --port 8000 --reload | |
| ``` | |
| Trigger the OpenEnv SDK baseline: | |
| ```python | |
| import asyncio | |
| from openai import OpenAI | |
| from server.EmailTriage_environment import EmailtriageEnv | |
| async def main(): | |
| llm = OpenAI(base_url="https://router.huggingface.co/v1") | |
| # Native connection without Docker bug risks locally | |
| env = EmailtriageEnv(base_url="http://127.0.0.1:8000") | |
| await env.connect() | |
| # Let the LLM play the environment | |
| await env.reset(options={"task_id": "hard"}) | |
| asyncio.run(main()) | |
| ``` | |
| ### 2. Evaluating for Hackathon Judges | |
| This repository natively supports `openenv validate` from the root structure and natively passes the `validate-submission.sh` Hugging Face pipeline test. | |
| To compile the environment into the evaluation Docker instance: | |
| ```bash | |
| docker build -t emailtriage-env:latest -f Dockerfile . | |
| ``` | |
| To sync changes actively up to Hugging Face: | |
| ```bash | |
| openenv push --repo-id YOUR_USERNAME/EmailTriage | |
| ``` | |