A full-stack support ticket management system with AI-powered ticket classification using LLMs.
- Backend: Django 4.2 + Django REST Framework + PostgreSQL
- Frontend: React 18
- LLM Integration: Anthropic Claude (configurable)
- Infrastructure: Docker + Docker Compose
- ✅ Create, read, update support tickets
- ✅ Filter tickets by category, priority, status
- ✅ Search tickets by title and description
- ✅ Real-time statistics dashboard
- ✅ Database-level aggregations (no Python loops)
- ✅ Automatic category and priority suggestions using LLM
- ✅ Real-time classification as user types description or title
- ✅ Intelligent keyword-based fallback when LLM unavailable
- ✅ User can accept or override LLM suggestions
- ✅ Smart pattern matching for technical, billing, and account issues
The system intelligently classifies tickets based on keywords:
Critical Priority:
- "Server is down" → Technical / Critical
- "Unable to access" → Account / Critical
- "System outage" → Technical / Critical
- "Data loss" → Technical / Critical
High Priority:
- "Payment not working" → Billing / High
- "Error 500" → Technical / High
- "Can't login" → Account / High
Technical Issues:
- Keywords: server, error, bug, crash, API, performance, slow, timeout
- Category: Technical
Billing Issues:
- Keywords: charge, payment, invoice, refund, subscription, price
- Category: Billing
Account Issues:
- Keywords: login, password, access, permission, profile, reset
- Category: Account
Selected: Anthropic Claude Sonnet 4 with Intelligent Fallback
- Superior Reasoning: Claude excels at nuanced classification tasks, understanding context and severity better than alternatives
- Reliable JSON Output: Consistent structured responses critical for production systems
- Speed-Accuracy Balance: Sonnet 4 provides enterprise-grade accuracy while maintaining low latency
- Safety: Built-in safety features reduce risk of inappropriate classifications
- API Simplicity: Clean, well-documented API with excellent error handling
The system uses a two-tier classification strategy:
-
Primary: LLM Classification (when API key available)
- Uses Claude Sonnet 4 with enhanced prompt
- Analyzes both title and description
- Considers urgency, impact, and nature of issue
- Returns accurate category and priority
-
Fallback: Keyword-Based Classification (always available)
- Works without API key
- Uses regex pattern matching
- Identifies critical keywords (down, crash, outage, error, etc.)
- Scores category relevance
- Ensures system always provides intelligent suggestions
Priority Determination:
- Critical: server down, system outage, data loss, security breach, can't access
- High: significant issues, bugs, errors, blocked work
- Medium: help requests, questions, performance issues
- Low: minor issues, cosmetic problems
Category Determination:
- Technical: server, error, bug, crash, API, integration, performance, timeout
- Billing: charge, payment, invoice, refund, subscription, price
- Account: login, password, access, permission, profile, reset
- General: fallback for unmatched content
The LLM classification prompt is designed to:
- Clearly define categories with examples
- Establish priority levels based on business impact
- Request structured JSON output for reliability
- Handle edge cases gracefully
support-ticket-system/
├── backend/
│ ├── config/ # Django project settings
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ ├── tickets/ # Tickets Django app
│ │ ├── models.py # Ticket data model
│ │ ├── serializers.py # DRF serializers
│ │ ├── views.py # API views
│ │ ├── urls.py # URL routing
│ │ ├── llm_service.py # LLM classification service
│ │ └── admin.py # Django admin config
│ ├── Dockerfile
│ ├── requirements.txt
│ ├── entrypoint.sh
│ └── manage.py
├── frontend/
│ ├── public/
│ │ └── index.html
│ ├── src/
│ │ ├── components/
│ │ │ ├── TicketForm.js # Ticket submission form
│ │ │ ├── TicketList.js # Ticket list with filters
│ │ │ ├── TicketCard.js # Individual ticket display
│ │ │ └── Stats.js # Statistics dashboard
│ │ ├── App.js
│ │ ├── App.css
│ │ ├── index.js
│ │ └── index.css
│ ├── Dockerfile
│ └── package.json
├── docker-compose.yml
├── .gitignore
└── README.md
- Docker and Docker Compose installed
- Anthropic API key (get one at https://console.anthropic.com/)
-
Clone the repository (or extract the zip file)
-
Set your API key (optional but recommended for LLM features)
export LLM_API_KEY="your-anthropic-api-key-here"
-
Build and run the entire application
docker-compose up --build
-
Access the application
- Frontend: http://localhost:3000
- Backend API: http://localhost:8000/api
- Django Admin: http://localhost:8000/admin
The application will:
- Start PostgreSQL database
- Run Django migrations automatically
- Build and serve the React frontend
- Everything works together seamlessly
Set these in your shell or in a .env file:
LLM_API_KEY- Your Anthropic API key (required for LLM classification)LLM_PROVIDER- LLM provider (default: "anthropic")DEBUG- Django debug mode (default: "True")POSTGRES_DB- Database name (default: "ticketdb")POSTGRES_USER- Database user (default: "ticketuser")POSTGRES_PASSWORD- Database password (default: "ticketpass")
If you need to run without Docker:
Backend:
cd backend
pip install -r requirements.txt
python manage.py migrate
python manage.py runserverFrontend:
cd frontend
npm install
npm startDatabase: You'll need to set up PostgreSQL manually and update the connection settings.
POST /api/tickets/- Create a new ticket (returns 201)GET /api/tickets/- List all tickets (newest first)- Query params:
?category=,?priority=,?status=,?search=
- Query params:
PATCH /api/tickets/<id>/- Update a ticketGET /api/tickets/stats/- Get aggregated statisticsPOST /api/tickets/classify/- Classify a description
{
"total_tickets": 124,
"open_tickets": 67,
"avg_tickets_per_day": 8.3,
"priority_breakdown": {
"low": 30,
"medium": 52,
"high": 31,
"critical": 11
},
"category_breakdown": {
"billing": 28,
"technical": 55,
"account": 22,
"general": 19
}
}| Field | Type | Constraints |
|---|---|---|
| id | AutoField | Primary Key |
| title | CharField | max_length=200, required |
| description | TextField | required |
| category | CharField | choices: billing, technical, account, general |
| priority | CharField | choices: low, medium, high, critical |
| status | CharField | choices: open, in_progress, resolved, closed; default=open |
| created_at | DateTimeField | auto_now_add=True |
All constraints are enforced at the database level through Django migrations.
- ViewSets over APIView: Used DRF ViewSets for clean, RESTful API design
- Database-level aggregation: Stats endpoint uses Django ORM's
aggregate()andannotate()for efficiency - Graceful LLM failure: System continues working even if LLM is unavailable
- Singleton LLM client: Reuses Anthropic client instance for efficiency
- Component separation: Clear separation between Form, List, Card, and Stats
- Real-time updates: Stats dashboard refreshes after ticket creation/update
- Progressive enhancement: Form works without LLM, enhanced when available
- User control: Users can always override LLM suggestions
- On-blur classification: Triggers after user finishes typing description
- Structured prompting: Clear instructions for consistent JSON responses
- Validation: Server-side validation of LLM responses
- Error handling: Logs errors, returns defaults on failure
docker-compose exec backend python manage.py makemigrations
docker-compose exec backend python manage.py migratedocker-compose exec backend python manage.py shelldocker-compose logs -f backend
docker-compose logs -f frontend# Backend
docker-compose exec backend python manage.py test
# Frontend
docker-compose exec frontend npm testFor production deployment:
- Set
DEBUG=Falsein Django settings - Configure
ALLOWED_HOSTSproperly - Use environment-specific secrets management
- Set up HTTPS/SSL
- Use production-grade web server (Gunicorn/uWSGI)
- Configure CORS properly for your domain
- Set up database backups
- Monitor LLM API usage and costs
- Implement rate limiting
- Add authentication/authorization
Title: "Server is down" Description: "Production server not responding" Expected: Technical / Critical
Title: "Payment failed" Description: "Credit card charge not working" Expected: Billing / High
Title: "Can't login" Description: "Password reset not working" Expected: Account / High
Title: "How to export data?" Description: "I need to download my reports" Expected: General / Medium
Database connection issues:
- Ensure PostgreSQL container is healthy:
docker-compose ps - Check database logs:
docker-compose logs db
LLM classification not working:
- Verify
LLM_API_KEYis set correctly - Check backend logs for API errors
- System will fall back to defaults if LLM fails
Frontend can't reach backend:
- Ensure both services are running
- Check CORS configuration in Django settings
- Verify API_BASE URL in frontend
This project is created as a technical assessment.
Built with attention to code quality, proper architecture, and production-ready practices.