Spaces:
Sleeping
Sleeping
| title: Customer Support OpenEnv | |
| emoji: π½ | |
| colorFrom: blue | |
| colorTo: green | |
| sdk: docker | |
| pinned: false | |
| # π§ Customer Support OpenEnv | |
| [](https://www.python.org/) | |
| [](https://github.com/openenv) | |
| [](https://huggingface.co/spaces) | |
| [](https://fastapi.tiangolo.com/) | |
| [](LICENSE) | |
| > **OpenEnv Hackathon submission** β a production-grade customer support simulation environment for training and evaluating LLM-based support agents. | |
| --- | |
| ## π Why This Environment? | |
| Customer support is one of the most common enterprise AI use cases, yet no standard RL/agent benchmark exists for it. | |
| This environment fills that gap: it provides a **realistic, multi-difficulty, fully graded** benchmark where agents must: | |
| - π·οΈ **Classify** support tickets into the correct category | |
| - βοΈ **Respond** empathetically and accurately to customer issues | |
| - π£οΈ **Hold multi-turn conversations** β clarify, resolve, and close tickets | |
| All graded automatically with clear, deterministic rubrics (0.0β1.0) and meaningful **partial rewards** on every turn. | |
| --- | |
| ## βοΈ How It Works β Workflow | |
| ``` | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β AGENT LOOP β | |
| β β | |
| β ββββββββββββ POST /reset βββββββββββββββββββββββββββββββββββ β | |
| β β β βββββββββββββββΊ β FastAPI Server β β | |
| β β Agent β β (server/app.py) β β | |
| β β (client) β βββββββββββββββ β β β | |
| β β β Observation β ββββββββββββββββββββββββββββ β β | |
| β β β β β SupportEnvironment β β β | |
| β β β POST /step β β (environment.py) β β β | |
| β β β βββββββββββββββΊ β β β β β | |
| β β β obs+reward β β 15 scenarios Γ 5 types β β β | |
| β β β βββββββββββββββ β β 3 graders (easy/med/hrd)β β β | |
| β ββββββββββββ β β Cumulative reward logic β β β | |
| β β ββββββββββββββββββββββββββββ β β | |
| β GET /state βββββββββββββββΊ β β β | |
| β POST /grader ββββββββββββββΊ β Score + turn breakdown β β | |
| β GET /tasks βββββββββββββββΊ β Task list + action schemas β β | |
| β POST /baseline ββββββββββββΊ β Built-in oracle agent scores β β | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ-ββ | |
| ``` | |
| **Episode lifecycle:** | |
| 1. Agent calls `POST /reset` β gets the opening customer message | |
| 2. Agent sends replies via `POST /step` β gets observation + reward each turn | |
| 3. Agent calls `POST /grader` β gets full score breakdown with `turn_scores` | |
| 4. Episode ends when `done: true` in the observation | |
| --- | |
| ## ποΈ Environment Description | |
| Simulates a customer support system across **5 issue categories** with **15 unique scenarios** (3 per category): | |
| | Category | Sample Scenarios | | |
| |---|---| | |
| | **Refund** | Missing delivery refund, damaged product return, cancelled-order refund delay | | |
| | **Technical** | App crash after update, Slack webhook error, PDF export blank | | |
| | **Shipping** | 3-week missing order, wrong-door delivery, split shipment partial arrival | | |
| | **Billing** | Duplicate subscription charge, unauthorized upgrade charge, invoice ghost charge | | |
| | **Account** | Password reset email missing, account suspended, email address transfer | | |
| --- | |
| ## π₯ Action Space | |
| Each agent step submits a `SupportAction`: | |
| | Field | Type | Required | Description | | |
| |---|---|---|---| | |
| | `message` | `str` | β | The agent's text reply to the customer | | |
| | `intent` | `str` | β | Declared intent: `"classify"`, `"respond"`, `"clarify"`, `"escalate"`, or `"close"` | | |
| --- | |
| ## π€ Observation Space | |
| The environment returns a `SupportObservation` after each step: | |
| | Field | Type | Description | | |
| |---|---|---| | |
| | `conversation` | `List[str]` | Full message history (alternating customer / agent) | | |
| | `customer_query` | `str` | The latest customer message the agent must address | | |
| | `task_name` | `str` | Difficulty tier: `"easy"`, `"medium"`, or `"hard"` | | |
| | `done` | `bool` | Whether the episode has ended | | |
| | `reward` | `float \| None` | Step-level reward (0.0β1.0); `None` on opening observation | | |
| | `cumulative_reward` | `float` | Running average reward across all turns so far | | |
| | `turn_scores` | `List[float]` | Per-turn reward breakdown (useful for analysis) | | |
| | `info` | `str \| None` | Optional context or hints for the agent | | |
| --- | |
| ## π Tasks | |
| ### π’ Easy β Ticket Classification | |
| **Objective:** Output the correct issue category for a customer message. | |
| **Scoring:** | |
| - β `1.0` β Exact category in reply (`refund`, `billing`, etc.) | |
| - π‘ `0.5` β Partial keyword match | |
| - β `0.0` β Wrong or missing category | |
| - Max steps: **1** | |
| --- | |
| ### π‘ Medium β Single-Turn Response | |
| **Objective:** Write a complete, empathetic reply resolving the customer's issue. | |
| **Scoring rubric:** | |
| | Component | Reward | | |
| |---|---| | |
| | +0.20 per matching keyword (max 4) | 0.00β0.80 | | |
| | Empathy detected (apologize/sorry/understand) | +0.10 | | |
| | Reply length > 80 chars | +0.10 | | |
| | Unnecessary escalation penalty | β0.20 | | |
| All scores clamped to `[0.0, 1.0]`. Max steps: **1** | |
| --- | |
| ### π΄ Hard β Multi-Turn Conversation | |
| **Objective:** Handle a 3-turn dialogue: clarify β resolve β close. | |
| | Turn | Behaviour | Max Reward | | |
| |---|---|---| | |
| | 1 (clarify) | Ask a `?` question (bonus if on-topic) | +0.40 | | |
| | 2 (resolve) | Keyword + empathy + detail | +0.50 | | |
| | 3 (close) | Polite closing phrase | +0.30 | | |
| `cumulative_reward = mean(turn_scores)`, clamped to `[0.0, 1.0]`. Max steps: **10** | |
| --- | |
| ## π― Reward Function Design | |
| | Signal | When | Magnitude | | |
| |---|---|---| | |
| | Correct classification | Easy, step 1 | +1.0 / +0.5 / 0.0 | | |
| | Keyword coverage | Medium & Hard turn 2 | +0.20 per keyword | | |
| | Empathy language | Medium & Hard turn 2 | +0.10β+0.12 | | |
| | Response detail (length) | Medium & Hard turn 2 | +0.08β+0.10 | | |
| | Clarifying question | Hard turn 1 | +0.30 (+0.10 bonus) | | |
| | Polite close | Hard turn 3 | +0.30 | | |
| | Unnecessary escalation | Medium | β0.20 | | |
| | Exceeding max steps | All tasks | Episode terminates | | |
| **Key property:** Every turn gives a partial signal β agents never wait until the end to learn if they did well. | |
| --- | |
| ## π API Endpoints | |
| | Method | Endpoint | Description | | |
| |---|---|---| | |
| | `GET` | `/` | Health check | | |
| | `POST` | `/reset` | Start a new episode | | |
| | `POST` | `/step` | Submit an agent action | | |
| | `GET` | `/state` | Current session internal state | | |
| | `GET` | `/tasks` | Task list with typed action schemas | | |
| | `POST` | `/grader` | Score + turn breakdown for completed episode | | |
| | `POST` | `/baseline` | Run built-in oracle agent, return average scores | | |
| --- | |
| ## π Setup & Usage | |
| ### 1. Clone | |
| ```bash | |
| git clone https://huggingface.co/spaces/sanathkumarps/customer_support_env | |
| cd customer_support_env | |
| ``` | |
| ### 2. Install | |
| ```bash | |
| pip install -r requirements.txt | |
| ``` | |
| ### 3. Run locally | |
| ```bash | |
| uvicorn server.app:app --host 0.0.0.0 --port 7860 --reload | |
| ``` | |
| Visit `http://localhost:7860/docs` for interactive Swagger docs. | |
| ### 4. Run with Docker | |
| ```bash | |
| docker build -t customer_support_env . | |
| docker run -p 7860:7860 customer_support_env | |
| ``` | |
| ### 5. Run the baseline evaluation | |
| ```bash | |
| export GROQ_API_KEY="gsk-..." # required | |
| export ENV_BASE_URL="http://localhost:7860" # optional | |
| export GROQ_MODEL="llama-3.1-8b-instant" # optional, default: llama-3.1-8b-instant | |
| python run_baseline.py | |
| ``` | |
| Results print to console and save to `baseline_scores.json`. | |
| ### 6. Quick API test | |
| ```bash | |
| # Health check | |
| curl http://localhost:7860/ | |
| # Start easy episode | |
| curl -X POST http://localhost:7860/reset \ | |
| -H "Content-Type: application/json" \ | |
| -d '{"task_name":"easy","seed":42}' | |
| # Submit action (replace SESSION_ID) | |
| curl -X POST http://localhost:7860/step \ | |
| -H "Content-Type: application/json" \ | |
| -d '{"session_id":"SESSION_ID","message":"refund","intent":"classify"}' | |
| # Get grader score | |
| curl -X POST http://localhost:7860/grader \ | |
| -H "Content-Type: application/json" \ | |
| -d '{"session_id":"SESSION_ID"}' | |
| ``` | |
| --- | |
| ## π Baseline Scores | |
| | Task | Avg Score | Model | Episodes | | |
| |---|---|---|---| | |
| | Easy | 0.90 | llama-3.1-8b-instant | 5 | | |
| | Medium | 0.55 | llama-3.1-8b-instant | 5 | | |
| | Hard | 0.40 | llama-3.1-8b-instant | 5 | | |
| > Run `python run_baseline.py` after starting the server to generate fresh scores. | |
| --- | |
| ## π Project Structure | |
| ``` | |
| customer_support_env/ | |
| βββ models.py # Pydantic models: SupportAction, SupportObservation, SupportState | |
| βββ client.py # OpenEnv typed client library | |
| βββ openenv.yaml # OpenEnv metadata manifest | |
| βββ requirements.txt # Python dependencies (groq, fastapi, uvicornβ¦) | |
| βββ run_baseline.py # llama-3.1-8b-instant baseline evaluation script | |
| βββ README.md # This file | |
| βββ Dockerfile # Container config for Hugging Face Spaces | |
| βββ .dockerignore # Excludes venv, __pycache__, .env from image | |
| βββ baseline_scores.json # Auto-generated baseline results | |
| βββ server/ | |
| βββ __init__.py # Package marker | |
| βββ app.py # FastAPI server β all 7 endpoints | |
| βββ environment.py # Core env: 15 scenarios, 3 graders, reward logic | |
| ``` | |
| --- | |
| ## ποΈ Architecture | |
| ``` | |
| models.py β Pydantic contracts (Action / Observation / State) | |
| β | |
| βββ server/environment.py β Episode logic, 15 scenarios, 3 graders | |
| β β | |
| β βββ Reward signals: per-turn partial rewards + cumulative score | |
| β | |
| βββ server/app.py β FastAPI: /reset /step /state /tasks /grader /baseline | |
| β | |
| βββ client.py β Typed client for external scripts | |
| ``` | |
| --- | |
| ## π License | |
| MIT β see [LICENSE](LICENSE). | |
| --- | |
| <p align="center"> | |
| Built for the <strong>OpenEnv Hackathon</strong> π | Customer support AI benchmark that fills a real gap. | |
| </p> | |