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
16 changes: 7 additions & 9 deletions uc-0a/agents.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
# agents.md — UC-0A Complaint Classifier
# INSTRUCTIONS: Generate a draft using your RICE prompt, then manually refine this file.
# Delete these comments before committing.

role: >
[FILL IN: Who is this agent? What is its operational boundary?]
You are a complaint classification agent responsible for analyzing citizen complaint descriptions and assigning them to predefined categories, priorities, reasons, and review flags based on exact rules. Your operational boundary is limited to processing individual complaint rows or batches from CSV files, ensuring no external data is used and outputs strictly adhere to the allowed values.

intent: >
[FILL IN: What does a correct output look like — make it verifiable]
A correct output includes: category as exactly one of the allowed strings (Pothole, Flooding, etc.), priority as Urgent if severity keywords are present otherwise Standard, reason as one sentence citing specific words from the description, and flag as NEEDS_REVIEW only when category is genuinely ambiguous or cannot be determined from the description alone.

context: >
[FILL IN: What information is the agent allowed to use? State exclusions explicitly.]
You are allowed to use only the 'description' field from the input complaint row. You must not use any external knowledge, assumptions about locations, or data beyond what's in the description. Exclusions: Do not consider city, ward, location, or any other fields; do not infer based on common knowledge.

enforcement:
- "[FILL IN: Specific testable rule 1 — e.g. Category must be exactly one of: Pothole, Flooding, ...]"
- "[FILL IN: Specific testable rule 2 — e.g. Priority must be Urgent if description contains: injury, child, school, ...]"
- "[FILL IN: Specific testable rule 3 — e.g. Every output row must include a reason field citing specific words from the description]"
- "[FILL IN: Refusal condition — e.g. If category cannot be determined from description alone, output category: Other and flag: NEEDS_REVIEW]"
- "Category must be exactly one of: Pothole, Flooding, Streetlight, Waste, Noise, Road Damage, Heritage Damage, Heat Hazard, Drain Blockage, Other — no variations or additional categories allowed."
- "Priority must be Urgent if the description contains any of these severity keywords: injury, child, school, hospital, ambulance, fire, hazard, fell, collapse; otherwise, use Standard."
- "Every output row must include a reason field as one sentence that cites specific words from the description."
- "Set flag to NEEDS_REVIEW if category cannot be determined from description alone or is genuinely ambiguous; otherwise, leave flag blank."
100 changes: 98 additions & 2 deletions uc-0a/classifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"""
import argparse
import csv
import re

def classify_complaint(row: dict) -> dict:
"""
Expand All @@ -13,7 +14,72 @@ def classify_complaint(row: dict) -> dict:
TODO: Build this using your AI tool guided by your agents.md and skills.md.
Your RICE enforcement rules must be reflected in this function's behaviour.
"""
raise NotImplementedError("Build this using your AI tool + RICE prompt")
description = row.get('description', '').lower()
complaint_id = row.get('complaint_id', '')

# Define category keywords
categories = {
'Pothole': ['pothole', 'potholes', 'tyre', 'blowout', 'accident'],
'Flooding': ['flood', 'water', 'rain', 'drain'],
'Streetlight': ['lamp', 'light', 'streetlight', 'darkness', 'tripped', 'substation'],
'Waste': ['waste', 'overflowing', 'piles'],
'Noise': ['noise', 'band', 'playing', 'amplifiers'],
'Road Damage': ['road', 'damage', 'broken', 'buckled', 'subsided', 'footpath', 'cobblestone'],
'Heritage Damage': ['heritage', 'historic', 'defaced', 'billboard'],
'Heat Hazard': ['heat', 'hazard'],
'Drain Blockage': ['drain', 'blockage'],
}

# Find matching categories
matching_categories = []
for cat, keywords in categories.items():
if any(kw in description for kw in keywords):
matching_categories.append(cat)

if len(matching_categories) == 1:
category = matching_categories[0]
flag = ''
elif len(matching_categories) > 1:
category = 'Other'
flag = 'NEEDS_REVIEW'
else:
category = 'Other'
flag = 'NEEDS_REVIEW'

# Priority
severity_keywords = ['injury', 'child', 'school', 'hospital', 'ambulance', 'fire', 'hazard', 'fell', 'collapse']
if any(kw in description for kw in severity_keywords):
priority = 'Urgent'
else:
priority = 'Standard'

# Reason
if category != 'Other':
cited_words = []
for kw in categories[category]:
if kw in description:
cited_words.append(f"'{kw}'")
reason = f"Classified as {category} because description contains {', '.join(cited_words)}."
else:
if len(matching_categories) > 1:
all_cited = set()
for cat in matching_categories:
for kw in categories[cat]:
if kw in description:
all_cited.add(f"'{kw}'")
reason = f"Classified as Other because description contains conflicting keywords {', '.join(sorted(all_cited))} matching multiple categories."
elif len(matching_categories) == 0:
reason = "Classified as Other because description does not contain keywords matching any specific category."
else:
reason = "Classified as Other based on description analysis."

return {
'complaint_id': complaint_id,
'category': category,
'priority': priority,
'reason': reason,
'flag': flag
}


def batch_classify(input_path: str, output_path: str):
Expand All @@ -23,7 +89,37 @@ def batch_classify(input_path: str, output_path: str):
TODO: Build this using your AI tool.
Must: flag nulls, not crash on bad rows, produce output even if some rows fail.
"""
raise NotImplementedError("Build this using your AI tool + RICE prompt")
results = []
try:
with open(input_path, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
try:
classified = classify_complaint(row)
results.append(classified)
except Exception as e:
# On failure, add with Other and flag
results.append({
'complaint_id': row.get('complaint_id', ''),
'category': 'Other',
'priority': 'Standard',
'reason': f'Classification failed: {str(e)}',
'flag': 'NEEDS_REVIEW'
})
except Exception as e:
print(f"Error reading input file: {e}")
return

# Write output
if results:
fieldnames = ['complaint_id', 'category', 'priority', 'reason', 'flag']
try:
with open(output_path, 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(results)
except Exception as e:
print(f"Error writing output file: {e}")


if __name__ == "__main__":
Expand Down
16 changes: 16 additions & 0 deletions uc-0a/result_ahmedabad.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
complaint_id,category,priority,reason,flag
AM-202401,Other,Standard,Classified as Other because description does not contain keywords matching any specific category.,NEEDS_REVIEW
AM-202402,Other,Standard,Classified as Other because description does not contain keywords matching any specific category.,NEEDS_REVIEW
AM-202405,Other,Standard,Classified as Other because description does not contain keywords matching any specific category.,NEEDS_REVIEW
AM-202406,Other,Standard,"Classified as Other because description contains conflicting keywords 'broken', 'heat' matching multiple categories.",NEEDS_REVIEW
AM-202407,Road Damage,Urgent,Classified as Road Damage because description contains 'broken'.,
AM-202410,Pothole,Standard,Classified as Pothole because description contains 'pothole'.,
AM-202414,Other,Standard,Classified as Other because description does not contain keywords matching any specific category.,NEEDS_REVIEW
AM-202417,Other,Standard,"Classified as Other because description contains conflicting keywords 'heritage', 'waste' matching multiple categories.",NEEDS_REVIEW
AM-202421,Other,Standard,Classified as Other because description does not contain keywords matching any specific category.,NEEDS_REVIEW
AM-202424,Road Damage,Standard,Classified as Road Damage because description contains 'road'.,
AM-202429,Other,Standard,Classified as Other because description does not contain keywords matching any specific category.,NEEDS_REVIEW
AM-202431,Other,Standard,"Classified as Other because description contains conflicting keywords 'heritage', 'road' matching multiple categories.",NEEDS_REVIEW
AM-202435,Other,Standard,"Classified as Other because description contains conflicting keywords 'heat', 'road' matching multiple categories.",NEEDS_REVIEW
AM-202444,Waste,Standard,"Classified as Waste because description contains 'waste', 'overflowing'.",
AM-202445,Road Damage,Standard,Classified as Road Damage because description contains 'broken'.,
16 changes: 16 additions & 0 deletions uc-0a/result_hyderabad.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
complaint_id,category,priority,reason,flag
GH-202401,Flooding,Urgent,"Classified as Flooding because description contains 'flood', 'rain'.",
GH-202402,Other,Standard,"Classified as Other because description contains conflicting keywords 'drain', 'flood', 'rain' matching multiple categories.",NEEDS_REVIEW
GH-202406,Other,Standard,"Classified as Other because description contains conflicting keywords 'drain', 'rain', 'water' matching multiple categories.",NEEDS_REVIEW
GH-202407,Other,Standard,"Classified as Other because description contains conflicting keywords 'drain', 'rain' matching multiple categories.",NEEDS_REVIEW
GH-202410,Other,Standard,"Classified as Other because description contains conflicting keywords 'pothole', 'potholes', 'road' matching multiple categories.",NEEDS_REVIEW
GH-202411,Pothole,Urgent,Classified as Pothole because description contains 'pothole'.,
GH-202412,Pothole,Urgent,"Classified as Pothole because description contains 'pothole', 'potholes'.",
GH-202417,Other,Standard,"Classified as Other because description contains conflicting keywords 'heritage', 'piles', 'waste' matching multiple categories.",NEEDS_REVIEW
GH-202420,Other,Standard,Classified as Other because description does not contain keywords matching any specific category.,NEEDS_REVIEW
GH-202422,Road Damage,Urgent,Classified as Road Damage because description contains 'road'.,
GH-202424,Other,Standard,"Classified as Other because description contains conflicting keywords 'band', 'flood', 'light', 'rain' matching multiple categories.",NEEDS_REVIEW
GH-202428,Waste,Standard,Classified as Waste because description contains 'waste'.,
GH-202432,Other,Standard,Classified as Other because description does not contain keywords matching any specific category.,NEEDS_REVIEW
GH-202448,Other,Standard,"Classified as Other because description contains conflicting keywords 'drain', 'flood', 'rain' matching multiple categories.",NEEDS_REVIEW
GH-202438,Other,Standard,"Classified as Other because description contains conflicting keywords 'rain', 'road', 'water' matching multiple categories.",NEEDS_REVIEW
16 changes: 16 additions & 0 deletions uc-0a/result_pune.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
complaint_id,category,priority,reason,flag
PM-202401,Other,Standard,"Classified as Other because description contains conflicting keywords 'damage', 'pothole', 'tyre' matching multiple categories.",NEEDS_REVIEW
PM-202402,Pothole,Urgent,Classified as Pothole because description contains 'pothole'.,
PM-202406,Flooding,Standard,"Classified as Flooding because description contains 'flood', 'rain'.",
PM-202408,Other,Standard,"Classified as Other because description contains conflicting keywords 'drain', 'flood', 'rain', 'water' matching multiple categories.",NEEDS_REVIEW
PM-202410,Streetlight,Standard,"Classified as Streetlight because description contains 'light', 'streetlight'.",
PM-202411,Other,Urgent,"Classified as Other because description contains conflicting keywords 'hazard', 'light', 'streetlight' matching multiple categories.",NEEDS_REVIEW
PM-202413,Waste,Standard,Classified as Waste because description contains 'overflowing'.,
PM-202418,Noise,Standard,Classified as Noise because description contains 'playing'.,
PM-202419,Road Damage,Standard,Classified as Road Damage because description contains 'road'.,
PM-202420,Other,Urgent,Classified as Other because description does not contain keywords matching any specific category.,NEEDS_REVIEW
PM-202427,Flooding,Standard,"Classified as Flooding because description contains 'flood', 'rain'.",
PM-202428,Other,Standard,Classified as Other because description does not contain keywords matching any specific category.,NEEDS_REVIEW
PM-202430,Other,Standard,"Classified as Other because description contains conflicting keywords 'heritage', 'light' matching multiple categories.",NEEDS_REVIEW
PM-202433,Other,Standard,"Classified as Other because description contains conflicting keywords 'road', 'waste' matching multiple categories.",NEEDS_REVIEW
PM-202446,Road Damage,Urgent,"Classified as Road Damage because description contains 'broken', 'footpath'.",
16 changes: 16 additions & 0 deletions uc-0a/results_kolkata.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
complaint_id,category,priority,reason,flag
KM-202401,Other,Standard,"Classified as Other because description contains conflicting keywords 'heritage', 'lamp' matching multiple categories.",NEEDS_REVIEW
KM-202402,Other,Standard,"Classified as Other because description contains conflicting keywords 'broken', 'cobblestone', 'historic', 'road' matching multiple categories.",NEEDS_REVIEW
KM-202405,Noise,Standard,"Classified as Noise because description contains 'band', 'playing'.",
KM-202409,Other,Standard,"Classified as Other because description contains conflicting keywords 'pothole', 'potholes', 'road' matching multiple categories.",NEEDS_REVIEW
KM-202410,Pothole,Standard,"Classified as Pothole because description contains 'pothole', 'tyre', 'blowout'.",
KM-202411,Other,Standard,"Classified as Other because description contains conflicting keywords 'accident', 'pothole', 'rain', 'water' matching multiple categories.",NEEDS_REVIEW
KM-202415,Other,Standard,"Classified as Other because description contains conflicting keywords 'drain', 'rain', 'road' matching multiple categories.",NEEDS_REVIEW
KM-202418,Waste,Standard,"Classified as Waste because description contains 'waste', 'overflowing', 'piles'.",
KM-202421,Road Damage,Urgent,"Classified as Road Damage because description contains 'broken', 'footpath'.",
KM-202422,Road Damage,Standard,"Classified as Road Damage because description contains 'road', 'buckled'.",
KM-202426,Heritage Damage,Standard,"Classified as Heritage Damage because description contains 'heritage', 'defaced', 'billboard'.",
KM-202430,Road Damage,Standard,"Classified as Road Damage because description contains 'road', 'subsided'.",
KM-202434,Heritage Damage,Standard,Classified as Heritage Damage because description contains 'heritage'.,
KM-202436,Streetlight,Standard,"Classified as Streetlight because description contains 'darkness', 'tripped', 'substation'.",
KM-202438,Other,Standard,"Classified as Other because description contains conflicting keywords 'amplifiers', 'heritage' matching multiple categories.",NEEDS_REVIEW
22 changes: 10 additions & 12 deletions uc-0a/skills.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
# skills.md
# INSTRUCTIONS: Generate a draft by prompting AI, then manually refine this file.
# Delete these comments before committing.

skills:
- name: [skill_name]
description: [One sentence — what does this skill do?]
input: [What does it receive? Type and format.]
output: [What does it return? Type and format.]
error_handling: [What does it do when input is invalid or ambiguous?]
- name: classify_complaint
description: Classifies a single complaint row by analyzing the description to assign category, priority, reason, and flag according to the enforcement rules.
input: A dictionary representing a complaint row, containing at least a 'description' key with the complaint text.
output: A dictionary with keys 'complaint_id', 'category', 'priority', 'reason', 'flag', where category is from the allowed list, priority is Urgent/Standard, reason cites words, and flag is NEEDS_REVIEW if ambiguous.
error_handling: If the input is invalid or description is missing/empty, output category as 'Other', priority as 'Standard', reason explaining the issue, and flag as 'NEEDS_REVIEW'.

- name: [second_skill_name]
description: [One sentence]
input: [Type and format]
output: [Type and format]
error_handling: [What does it do when input is invalid or ambiguous?]
- name: batch_classify
description: Reads a CSV file of complaints, applies classify_complaint to each row, and writes the results to a new CSV file.
input: Two string paths - input_path to the CSV file and output_path for the results CSV.
output: Writes a CSV file with columns complaint_id, category, priority, reason, flag for each row; prints a success message.
error_handling: Handles file read/write errors by printing error messages; for bad rows, applies classify_complaint's error handling and continues processing other rows without crashing.
17 changes: 8 additions & 9 deletions uc-0b/agents.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
# agents.md
# INSTRUCTIONS: Generate a draft using your RICE prompt, then manually refine this file.
# Delete these comments before committing.

role: >
[FILL IN: Who is this agent? What is its operational boundary?]
A policy summarization agent for UC-0B that reads HR leave policy documents and produces a meaning-preserving summary organized by numbered clauses.

intent: >
[FILL IN: What does a correct output look like — make it verifiable]
Generate a compliant summary of the target policy document in which every numbered clause is present, all obligations and conditions are preserved, no new information is added, and any clause requiring verbatim preservation is flagged.

context: >
[FILL IN: What information is the agent allowed to use? State exclusions explicitly.]
The agent may only use the supplied policy document and the clause inventory as its source of truth. It must not infer or introduce policy details from outside the document, nor should it generalize or soften obligations.

enforcement:
- "[FILL IN: Specific testable rule 1]"
- "[FILL IN: Specific testable rule 2]"
- "[FILL IN: Specific testable rule 3]"
- "[FILL IN: Refusal condition — when should the system refuse rather than guess?]"
- "Every numbered clause from the source document must be present in the summary."
- "When an obligation includes multiple conditions, preserve every condition exactly; do not drop or weaken any condition."
- "Do not add information that is not directly contained in the source document."
- "If a clause cannot be summarized without meaning loss, quote it verbatim and mark it as such."
- "If the input is not a valid policy text file with numbered clauses, refuse and request the correct source document rather than guessing."
Loading