Dhanushkumarps
fix: utf-8 emoji encoding in yaml frontmatter
fcc9900
|
Raw
History Blame Contribute Delete
11.6 kB
---
title: Customer Support OpenEnv
emoji: πŸ‘½
colorFrom: blue
colorTo: green
sdk: docker
pinned: false
---
# 🎧 Customer Support OpenEnv
[![Python 3.10+](https://img.shields.io/badge/Python-3.10%2B-blue?logo=python&logoColor=white)](https://www.python.org/)
[![OpenEnv](https://img.shields.io/badge/OpenEnv-compatible-brightgreen)](https://github.com/openenv)
[![Hugging Face Spaces](https://img.shields.io/badge/%F0%9F%A4%97-HuggingFace%20Spaces-orange)](https://huggingface.co/spaces)
[![FastAPI](https://img.shields.io/badge/FastAPI-0.100%2B-009688?logo=fastapi&logoColor=white)](https://fastapi.tiangolo.com/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow)](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> πŸš€ &nbsp;|&nbsp; Customer support AI benchmark that fills a real gap.
</p>