We are going to build a support ticket classifier that reads unstructured customer messages and returns structured JSON with a category and urgency level. This kind of tool saves hours of manual triage for support teams and fits neatly into any webhook or queue-based pipeline. Because Oxlo.ai charges a flat rate per request instead of per token, you can feed it long, messy emails without watching costs scale with word count.
What you'll need
- Python 3.10 or newer
- The OpenAI SDK:
pip install openai - An Oxlo.ai API key from https://portal.oxlo.ai
- A handful of sample support messages to test with (optional)
Step 1: Configure the Oxlo.ai client
First, initialize the OpenAI SDK pointing at Oxlo.ai. I keep my key in an environment variable, but you can paste it directly for local testing.
from openai import OpenAI
client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key="YOUR_OXLO_API_KEY"
)
# Quick connectivity check
ping = client.chat.completions.create(
model="llama-3.3-70b",
messages=[{"role": "user", "content": "Respond with OK"}]
)
print(ping.choices[0].message.content)
Step 2: Define the classification schema
Before we touch the model, lock down the labels we want back. I use a small set of categories and two urgency tiers so the model has no room to hallucinate extra values.
CATEGORIES = ["billing", "bug_report", "feature_request", "account_access", "general_inquiry"]
URGENCY_LEVELS = ["low", "high"]
SCHEMA_TEXT = f"""
Return strictly valid JSON with exactly these keys:
- category: one of {CATEGORIES}
- urgency: one of {URGENCY_LEVELS}
- reasoning: one short sentence explaining why
"""
Step 3: Write the system prompt
The system prompt is the only part of the classifier that needs frequent tuning. I keep it focused on rules and output format, not examples, so it stays cheap to evaluate on Oxlo.ai's per-request pricing.
SYSTEM_PROMPT = """
You are a support ticket classifier. Read the user's message and return strictly valid JSON with exactly these keys:
- category: one of billing, bug_report, feature_request, account_access, general_inquiry
- urgency: one of low, high
- reasoning: one short sentence explaining the choice
Rules:
1. Pick exactly one category and one urgency level.
2. Respond only with the JSON object. No markdown fences, no preamble.
3. If the message is empty or unreadable, use category "general_inquiry" and urgency "low".
Output format:
{"category": "...", "urgency": "...", "reasoning": "..."}
"""
Step 4: Build the classifier function
Now wrap the Oxlo.ai call in a small function that sends the ticket text and parses the JSON response. I use Llama 3.3 70B here because it follows structured instructions reliably, but you can swap in Qwen 3 32B if your tickets arrive in multiple languages.
import json
def classify_ticket(ticket_text: str) -> dict:
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": ticket_text},
],
temperature=0.1, # keep it deterministic
)
raw = response.choices[0].message.content.strip()
# Some models occasionally wrap JSON in fences; strip them
if raw.startswith("
```"):
raw = raw.split("\n", 1)[1].rsplit("```
", 1)[0].strip()
return json.loads(raw)
Step 5: Add batch processing and error handling
In production, tickets arrive in bursts. This loop processes a list, catches malformed JSON or network hiccups, and returns safe defaults so the pipeline never crashes.
from typing import List
def classify_batch(tickets: List[str]) -> List[dict]:
results = []
for text in tickets:
try:
result = classify_ticket(text)
# validate keys
assert "category" in result
assert "urgency" in result
results.append(result)
except Exception as e:
results.append({
"category": "general_inquiry",
"urgency": "low",
"reasoning": f"Classifier failed: {e}",
"raw_input_preview": text[:100]
})
return results
Run it
Here is a short main block with three real-ish tickets. Run the script and you should see structured output in under a second per ticket on Oxlo.ai, with no cold starts.
if __name__ == "__main__":
sample_tickets = [
"I was charged twice for my Pro subscription this month. Please refund the duplicate charge immediately.",
"Hey, could you add dark mode to the dashboard? It would really help my team during night shifts.",
"My account says locked after I tried to reset my password. I need access before the client demo in an hour."
]
classified = classify_batch(sample_tickets)
for item in classified:
print(json.dumps(item, indent=2))
Expected output:
{
"category": "billing",
"urgency": "high",
"reasoning": "Duplicate charge requires immediate refund."
}
{
"category": "feature_request",
"urgency": "low",
"reasoning": "Dark mode is a nice-to-have improvement."
}
{
"category": "account_access",
"urgency": "high",
"reasoning": "User is locked out and has a time-sensitive demo."
}
Wrap-up and next steps
This classifier is already useful as a standalone script, but the real payoff comes from wiring it into your stack. Two concrete moves: first, drop it behind a FastAPI endpoint and call it from your existing support form webhooks. Second, if your queue grows, swap to Qwen 3 32B on Oxlo.ai for multilingual tickets, or switch to DeepSeek V3.2 on the free tier while you validate volume. Because Oxlo.ai bills per request, not per token, running this on long email threads or full conversation histories stays predictable. You can see the exact pricing at https://oxlo.ai/pricing.
Top comments (0)