Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 165 additions & 0 deletions code/ReadMe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
Multi-Domain Support Triage Agent

This project implements a deterministic support triage agent for the HackerRank Orchestrate challenge. It processes support tickets across three domains:

- Claude (Anthropic)
- HackerRank
- Visa

The system classifies tickets, retrieves relevant documentation, decides whether to reply or escalate, and generates grounded responses.

--------------------------------------------------

System Overview

The agent follows a Retrieval-Augmented Decision Pipeline:

Input Ticket → Classification → Retrieval (TF-IDF) → Decision Engine → Response / Escalation

--------------------------------------------------

Architecture

1. Knowledge Base (kb.py)
- Loads Markdown files from the data/ directory
- Splits documents into fixed-size chunks
- Tags each chunk with its domain (claude / hackerrank / visa)

2. Retriever (retriever.py)
- Uses TF-IDF vectorization with cosine similarity
- Filters by company before scoring
- Returns top relevant chunks

3. Classifier (classifier.py)
Rule-based classification into:
- product_issue
- bug
- feature_request
- invalid

Designed to remain deterministic and avoid overfitting.

4. Decision Engine (decision.py)
Determines:
- status (replied / escalated)
- justification

Uses strict rules for:
- Financial and billing issues
- Security and fraud cases
- Vulnerabilities
- Admin actions (remove user, reschedule, etc.)
- Subscription control (pause/cancel)
- Compliance requests
- Low-confidence retrieval

5. Response Generation (main.py)
- Uses retrieved context only
- No hallucinated content
- If confidence is low → escalates instead of replying

--------------------------------------------------

Key Design Decisions

- Deterministic system
Same input always produces the same output.

- No external APIs
Fully offline; uses only the provided corpus.

- Rule-based escalation
Ensures safe handling of high-risk queries.

- Corpus grounding
All responses are derived from retrieved documentation only.

--------------------------------------------------

Escalation Policy

The system escalates in the following cases:

- Visa financial issues (billing, fraud, urgent money requests)
- Security issues (unauthorized access, stolen card, vulnerabilities)
- Admin actions (remove employee/user, account modifications)
- Subscription control (pause, cancel, stop)
- Compliance / infosec-related queries
- Low retrieval confidence
- Unsupported or unsafe queries

--------------------------------------------------

Project Structure

code/
main.py # Entry point (runs full pipeline)
kb.py # Loads and chunks support documents
retriever.py # TF-IDF retrieval with cosine similarity
classifier.py # Rule-based request classification
decision.py # Escalation and decision logic

data/ # Support knowledge base (Markdown files)

support_tickets/
support_tickets.csv # Input tickets
output.csv # Generated output

requirements.txt # Python dependencies
README.txt # Project documentation
log.txt # Development log

--------------------------------------------------

How to Run

1. Install dependencies:
pip install -r requirements.txt

2. Run the pipeline:
python code/main.py

3. Output file will be generated at:
support_tickets/output.csv

--------------------------------------------------

Output Format

issue,subject,company,response,product_area,status,request_type,justification

--------------------------------------------------

Output Guarantees

- No hallucinated responses
- Deterministic behavior
- Strict escalation for sensitive cases
- Fully grounded in provided documentation

--------------------------------------------------

Limitations

- Keyword-based rules may miss rare paraphrases
- TF-IDF retrieval may return less optimal results for ambiguous queries

--------------------------------------------------

Future Improvements

- Semantic retrieval using embeddings
- Hybrid ranking (BM25 + vector search)
- Improved intent classification
- Smarter document chunking

--------------------------------------------------

Summary

This system prioritizes:
- Safety over automation
- Determinism over complexity
- Grounded responses over generative output

It is designed to be robust, explainable, and evaluation-ready.
33 changes: 33 additions & 0 deletions code/classifier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
def classify(text):
t = text.lower()

# 🔴 Billing / money issues
if any(k in t for k in ["bill", "charge", "payment", "refund", "money"]):
return "product_issue", "billing"

# 🔐 Account / login issues (refined)
elif any(k in t for k in ["login", "password", "sign in"]):
return "product_issue", "account"

elif "access" in t:
return "product_issue", "account"

# ⚙️ Technical bugs
elif any(k in t for k in ["error", "bug", "not working", "failed", "issue", "problem", "down", "failing"]):
return "bug", "technical"

# 💡 Feature requests
elif any(k in t for k in ["feature", "request", "add", "improve"]):
return "feature_request", "general"

# 🚨 Security / fraud
elif any(k in t for k in ["stolen", "fraud", "unauthorized", "hacked"]):
return "product_issue", "security"

# ❌ Truly invalid
elif any(k in t for k in ["delete all files", "give me code to hack"]):
return "invalid", "other"

# ✅ Default
else:
return "product_issue", "general"
131 changes: 131 additions & 0 deletions code/decision.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
def contains_phrase(query, phrases):
return any(p in query for p in phrases)

def contains_word_pattern(query, patterns):
words = set(query.split())
return any(all(w in words for w in group) for group in patterns)


def decide(results, request_type, company, query):
query = query.lower()

if not results:
return "escalated", "No relevant documentation found in support corpus"

top_result = results[0]
top_score = results[0]["score"]
text = top_result["text"].lower()

# 🔴 Keyword groups
security_keywords = ["stolen", "fraud", "unauthorized", "hacked", "identity"]
billing_keywords = ["refund", "charge", "payment", "billing", "money"]

control_keywords = [
"increase my score", "change result", "review my answers",
"move me to next round", "reschedule", "extend",
"approve", "ban", "restore access"
]

permission_keywords = ["access removed", "lost access", "no permission"]
compliance_keywords = ["infosec", "compliance", "forms"]
informational_keywords = ["how long", "what is", "why", "explain"]

# 🔴 Admin detection
admin_phrase_patterns = [
"remove employee", "remove user", "delete user",
"remove interviewer", "remove from account"
]

admin_word_patterns = [
["employee", "remove"],
["user", "remove"],
["account", "remove"],
["employee", "left"]
]

is_admin_action = (
contains_phrase(query, admin_phrase_patterns) or
contains_word_pattern(query, admin_word_patterns)
)

# 🔴 Subscription detection
is_subscription = (
"subscription" in query and any(w in query for w in ["pause", "cancel", "stop"])
)

# 🔴 Extra detection
is_vulnerability = any(k in query for k in ["vulnerability", "security issue", "security bug"])
is_cash = any(k in query for k in ["cash", "need money", "urgent money"])

combined_text = query + " " + text

is_security = any(k in combined_text for k in security_keywords)
is_billing = any(k in query for k in billing_keywords)
is_control = any(k in query for k in control_keywords)
is_permission = any(k in query for k in permission_keywords)
is_compliance = any(k in query for k in compliance_keywords)
is_informational = any(k in query for k in informational_keywords)

# =========================
# 🔴 HARD ESCALATION
# =========================

# Visa strict handling
if company == "visa" and (is_security or is_billing):
return "escalated", f"Sensitive financial/security issue (score {top_score:.2f})"

# Visa financial urgency
if company == "visa" and is_cash:
return "escalated", f"Financial assistance request requires support (score {top_score:.2f})"

# Security vulnerability
if is_vulnerability:
return "escalated", f"Security vulnerability requires escalation (score {top_score:.2f})"

# Subscription control
if is_subscription:
return "escalated", f"Subscription control requires support (score {top_score:.2f})"

# Admin actions
if is_admin_action:
return "escalated", f"Admin action requires intervention (score {top_score:.2f})"

# Permission issues
if is_permission:
return "escalated", f"Permission issue requires support (score {top_score:.2f})"

# Security issues
if is_security:
return "escalated", f"Security issue requires support (score {top_score:.2f})"

# Billing issues
if is_billing:
return "escalated", f"Billing issue requires support (score {top_score:.2f})"

# Compliance issues
if is_compliance:
return "escalated", f"Compliance-related request (score {top_score:.2f})"

# Control requests
if is_control:
return "escalated", f"Administrative request (score {top_score:.2f})"

# =========================
# ⚠️ INFORMATIONAL
# =========================

if is_informational and top_score >= 0.2:
return "replied", f"Answered using documentation (score {top_score:.2f})"

# =========================
# ⚠️ CONFIDENCE
# =========================

if top_score < 0.2:
return "escalated", f"Low confidence (score {top_score:.2f})"

if request_type == "bug" and top_score < 0.4:
return "escalated", f"Technical issue unclear (score {top_score:.2f})"

# =========================
return "replied", f"Relevant documentation match (score {top_score:.2f})"
Loading