CoolFace
Apppublic

Kshtitij/ticket-triage

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
App README

Customer Support Ticket Triage Environment

An OpenEnv-compliant reinforcement-learning environment where an AI agent processes customer support tickets by classifying issues, assigning priorities, and generating appropriate customer responses.


Overview

Each episode contains 10 realistic support tickets drawn from four categories (billing, technical, account, general). The agent processes tickets one at a time; after all tickets are handled the episode ends (done=True).

The environment is fully deterministic – the same ticket corpus is used every run, ensuring reproducible scores across models.


Project Structure

project/
├── env.py            # Core environment (reset / step / state)
├── models.py         # Pydantic models: Observation, Action, Reward
├── tasks/
│   ├── easy.py       # Task 1 – category classification only
│   ├── medium.py     # Task 2 – classification + priority
│   └── hard.py       # Task 3 – classification + priority + response
├── inference.py      # Baseline inference script (OpenAI client)
├── openenv.yaml      # Environment & task metadata
├── Dockerfile        # Container definition
├── requirements.txt  # Python dependencies
└── README.md

Observation Space

FieldTypeDescription
ticket_idstrUnique ticket identifier (e.g., T001)
messagestrThe customer's support message
historylist[str]Optional prior context for this ticket
step_indexintCurrent step number (0-indexed)
total_ticketsintTotal tickets in this episode

Action Space

FieldTypeDescription
category`"billing" \"technical" \"account" \"general"`Issue category
priority`"low" \"medium" \"high"`Urgency level
responsestrCustomer-facing reply (graded in Task 3)

Reward Function

Rewards are step-wise (returned after each ticket), clamped to [0.0, 1.0].

ComponentScoring
category_score1.0 correct / 0.0 wrong
priority_score1.0 exact / 0.5 adjacent / 0.0 opposite level
response_scoreFraction of expected keywords present (≥20 chars)

Tasks

Task 1 – Easy (Category Only)

  • —Reward: 1.0 × category_score
  • —Goal: Correctly classify the ticket into one of the four categories.
  • —Expected baseline score: ~0.85

Task 2 – Medium (Category + Priority)

  • —Reward: 0.5 × category_score + 0.5 × priority_score
  • —Goal: Correctly classify and assign the appropriate urgency level.
  • —Expected baseline score: ~0.75

Task 3 – Hard (Category + Priority + Response)

  • —Reward: 0.3 × category_score + 0.3 × priority_score + 0.4 × response_score
  • —Goal: Full triage: classify, prioritize, and write a helpful response.
  • —Expected baseline score: ~0.65

Setup

Local (Python)

bash
# Clone / enter project directory
cd project/

# Install dependencies
pip install -r requirements.txt

# Set required environment variables
export OPENAI_API_KEY="sk-..."
export MODEL_NAME="gpt-4o-mini"          # optional, default: gpt-4o-mini
export API_BASE_URL="https://api.openai.com/v1"  # optional

Docker

bash
docker build -t ticket-triage .

docker run --rm \
  -e OPENAI_API_KEY="sk-..." \
  -e MODEL_NAME="gpt-4o-mini" \
  ticket-triage

Running Inference

bash
# Run all 3 tasks and print scores
python inference.py

Output follows this strict log format:

[START] task=easy model=gpt-4o-mini base_url=https://api.openai.com/v1
[STEP]  task=easy step=00 ticket=T001 category=billing priority=low reward=1.0000 ...
...
[END]   task=easy avg_reward=0.9000 steps=10 elapsed=12.34s

[START] task=medium ...
...
[END]   task=hard avg_reward=0.6500 steps=10 elapsed=18.22s

======================================================================
 FINAL RESULTS
======================================================================
  Task [easy  ]  avg_reward=0.9000  steps=10
  Task [medium]  avg_reward=0.7500  steps=10
  Task [hard  ]  avg_reward=0.6500  steps=10

  AGGREGATE SCORE : 0.7667

Results are also saved to `results.json`.


Using the Environment Directly

python
from env import TicketTriageEnv
from models import Action

env = TicketTriageEnv(task_mode="hard")
obs = env.reset()

while obs is not None:
    action = Action(
        category="billing",
        priority="high",
        response="We apologize for the duplicate charge. A full refund will be processed within 3-5 business days."
    )
    obs, reward, done, info = env.step(action)
    print(f"Reward: {reward.total:.4f}  Done: {done}")

print("Final state:", env.state())

Expected Baseline Scores

ModelEasyMediumHardAggregate
gpt-4o-mini~0.85~0.75~0.65~0.75
gpt-4o~0.95~0.85~0.75~0.85

Scores are deterministic for a given model at `temperature=0`.


Constraints

  • —Runs within 2 vCPU / 8 GB RAM
  • —No external APIs beyond OpenAI
  • —No randomness – fully reproducible