Files

94 lines
2.5 KiB
Python

# Rule-based triage classifier for support inquiries.
#
# Deterministic keyword scorer: every category carries a list of case-insensitive
# substrings (single words and multi-word phrases). classify() returns the
# category with the most matching keywords; ties are resolved by a fixed priority
# order. Texts with zero keyword hits fall back to "other".
#
# This is a dictionary-exact router (triage lane). Real-world accuracy is
# measured, not assumed: the gold set in gold.json and the assertion in
# test_triage.py pin the expected behaviour, and run_audit.py reports precision /
# recall / f1 per category.
CATEGORY_ORDER = [
"account",
"billing",
"technical_support",
"feature_request",
"other",
]
CATEGORY_META = {
"account": "Account access & identity",
"billing": "Billing & payments",
"technical_support": "Technical support",
"feature_request": "Feature request",
"other": "Other / general",
}
# Multi-word keywords are matched as substrings too, so "log in" matches
# "cannot log in" (which is purely account-side speech).
KEYWORDS = {
"account": [
"log in",
"password",
"2fa",
"sign up",
"signup",
"cannot log in",
"verification code",
"not received my code",
],
"billing": [
"invoice",
"charged",
"refund",
"subscription",
"credit card",
"payment method",
"amount due",
"billing statement",
],
"technical_support": [
"crash",
"500",
"slow",
"deploy",
"cannot connect",
"connection refused",
"database unreachable",
"page not found",
"timeout",
"install",
"uptime check",
"api error",
"experienced an error",
],
"feature_request": [
"feature",
"suggest",
"enhancement",
"request",
"would like",
"new feature",
"add ability",
],
}
def classify(text):
"""Return (category, scores_dict) for a single inquiry string."""
low = text.lower()
scores = {"other": 0}
scores.update({cat: sum(1 for k in kws if k in low) for cat, kws in KEYWORDS.items()})
best = max(scores.values())
if best == 0:
return "other", scores
winners = [c for c in CATEGORY_ORDER if scores[c] == best]
return winners[0], scores
def batch_classify(texts):
"""Classify a list of texts; result mirrors (text, category)."""
return [classify(t) for t in texts]