Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

QueueStorm Ticket Classifier

Stateless FastAPI microservice that classifies a digital-finance support ticket (case_type, severity, department, agent_summary, human_review_required, confidence) from a single JSON request.

Built for the bKash SUST CSE Carnival 2026 Codex Community Hackathon warmup. Rule-engine based, no GPU, no LLM, < 500 ms typical latency.


Project layout

queue-storm-classifier/
├── app/
│   ├── __init__.py
│   ├── main.py            # FastAPI app: /health and /sort-ticket
│   ├── classifier.py      # Rule-engine pipeline
│   ├── rules_config.py    # Keywords, regex, dept map (tune me here)
│   ├── safety.py          # Summary sanitizer (redaction)
│   └── schemas.py         # Pydantic request/response models
├── tests/
│   ├── test_health.py
│   └── test_classification.py
├── Dockerfile
├── .dockerignore
└── requirements.txt

API contract

GET /health

curl http://localhost:8000/health
# → {"status":"ok"}

POST /sort-ticket

curl -X POST http://localhost:8000/sort-ticket \
  -H "Content-Type: application/json" \
  -d '{
        "ticket_id": "T-001",
        "channel": "app",
        "locale": "en",
        "message": "I sent 5000 taka to a wrong number this morning, please help me get it back"
      }'
{
  "ticket_id": "T-001",
  "case_type": "wrong_transfer",
  "severity": "high",
  "department": "dispute_resolution",
  "agent_summary": "Customer reports sending 5000 BDT to a wrong recipient and requests reversal.",
  "human_review_required": true,
  "confidence": 0.9
}

channel and locale are optional. message is required but may be empty (empty → case_type: "other", severity low, department customer_support).

Local run (no Docker)

python -m venv .venv
. .venv/Scripts/activate     # Windows
# source .venv/bin/activate  # macOS / Linux
pip install -r requirements.txt
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload

Docker

docker build -t queue-storm-classifier .
docker run -p 8000:8000 queue-storm-classifier

Override port via APP_PORT (default 8000); verbosity via LOG_LEVEL (default info).

docker run -p 9000:9000 -e APP_PORT=9000 -e LOG_LEVEL=debug queue-storm-classifier

Environment variables

Variable Default Purpose
APP_PORT 8000 Uvicorn listen port
LOG_LEVEL info debug / info / warning / error

(ENABLE_LLM_FALLBACK, LLM_API_URL, LLM_API_KEY, HF_HOME, TRANSFORMERS_OFFLINE are accepted by the PRD contract but unused in the default rules-only build.)

Tests

pytest -q

The suite covers all PRD §14 acceptance criteria, including:

  • The 5 public sample payloads (cases 2–6).
  • Empty / whitespace-only messages (case 8).
  • Missing optional fields (case 9).
  • Safety redaction of OTP / PIN / card numbers (case 7).
  • Bengali (bn) and mixed locale routing.
  • Amount > 50,000 BDT boost to critical.
  • Deterministic / idempotent responses.
  • Latency guard (< 5 s per request).

Deploy to a public HTTPS endpoint

The image is a vanilla python:3.11-slim+uvicorn app and works on any container host. Tested platforms:

  • Render: create a Web Service → connect repo → “Docker” environment → set port 8000 → deploy.
  • Railway: New Project → Deploy from Docker Image (or GitHub repo).
  • Fly.io: fly launch --dockerfile, then fly deploy.

Point the platform's health check at GET /health.

How it works (one paragraph)

main.py validates the JSON via schemas.py and calls classifier.classify(message, locale). The classifier, driven by pre-compiled regexes in rules_config.py, picks the highest-priority case_type whose pattern matches (Bengali equivalents are merged into the same regex for bn and mixed), applies severity defaults + boosts (amount > 50,000 BDT, urgency keywords), routes to a department via a lookup, fills a template-based summary, runs it through safety.sanitize() to redact OTP/PIN/card-like numbers, and scores a confidence in [0, 1]. The API then sets human_review_required = (severity in {high, critical}) or (case_type == "phishing_or_social_engineering").

Tuning rules

Edit app/rules_config.py:

  • Add new case types by appending a tuple (case_type, pattern, default_severity) to the ordered list in _build_rules().
  • Add Bengali keywords to the matching BN_* list.
  • Change department routing in CASE_TYPE_TO_DEPARTMENT.
  • Change the amount threshold via CRITICAL_AMOUNT_THRESHOLD_BDT.

Releases

Packages

Contributors

Languages