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
18 changes: 11 additions & 7 deletions uc-0a/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@
# Delete these comments before committing.

role: >
[FILL IN: Who is this agent? What is its operational boundary?]
You are a complaint classifier for citizen complaints in a city management system. Your role is to analyze complaint descriptions and assign them to predefined categories, determine priority levels, provide justification, and flag ambiguous cases.

intent: >
[FILL IN: What does a correct output look like — make it verifiable]
For each complaint, produce an output with exactly four fields: category (exact string from allowed list), priority (Urgent/Standard/Low), reason (one sentence citing specific words from the description), and flag (NEEDS_REVIEW or blank). The output must be accurate, consistent, and free from hallucinations or assumptions not present in the description.

context: >
[FILL IN: What information is the agent allowed to use? State exclusions explicitly.]
You have access only to the complaint description provided. Do not use external knowledge, general practices, or assumptions about city operations. Base classifications solely on the words in the description.

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 sub-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, assess as Standard or Low based on the description."
- "Every output must include a reason field: one sentence that cites specific words from the description justifying the category and priority."
- "Set flag to NEEDS_REVIEW if the category is genuinely ambiguous based on the description alone; otherwise, leave flag blank."
- "Avoid taxonomy drift: do not vary category names or create new ones not in the allowed list."
- "Avoid severity blindness: ensure injury/child/school-related complaints are marked Urgent."
- "Avoid missing justification: always provide a reason citing specific words."
- "Avoid false confidence: flag ambiguous complaints instead of guessing."
127 changes: 121 additions & 6 deletions uc-0a/classifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,135 @@ def classify_complaint(row: dict) -> dict:
Classify a single complaint row.
Returns: dict with keys: complaint_id, category, priority, reason, flag

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.
Enforcement rules:
- Category must be exactly one of: Pothole, Flooding, Streetlight, Waste, Noise, Road Damage, Heritage Damage, Heat Hazard, Drain Blockage, Other
- Priority is Urgent if description contains: injury, child, school, hospital, ambulance, fire, hazard, fell, collapse
- Reason must be one sentence citing specific words from the description
- Flag is NEEDS_REVIEW if category is ambiguous, otherwise empty string
"""
raise NotImplementedError("Build this using your AI tool + RICE prompt")
ALLOWED_CATEGORIES = {
"Pothole", "Flooding", "Streetlight", "Waste", "Noise",
"Road Damage", "Heritage Damage", "Heat Hazard", "Drain Blockage", "Other"
}
SEVERITY_KEYWORDS = {"injury", "child", "school", "hospital", "ambulance", "fire", "hazard", "fell", "collapse"}

description = row.get("description", "").lower()

# Determine if priority should be Urgent based on severity keywords
is_urgent = any(keyword in description for keyword in SEVERITY_KEYWORDS)
priority = "Urgent" if is_urgent else "Standard"

# Classify complaint into category based on keywords found in description
category = "Other"
reason = ""
flag = ""

description_lower = description.lower()

# Simple keyword-based classification (to be enhanced with AI)
if any(word in description_lower for word in ["pothole", "potholed", "hole", "road hole"]):
category = "Pothole"
reason = "Description contains keywords related to potholes."
elif any(word in description_lower for word in ["flood", "flooding", "water", "waterlogged", "submerged"]):
category = "Flooding"
reason = "Description contains keywords related to flooding."
elif any(word in description_lower for word in ["streetlight", "lamp", "light post", "street lamp", "broken light"]):
category = "Streetlight"
reason = "Description contains keywords related to streetlights."
elif any(word in description_lower for word in ["waste", "garbage", "trash", "litter", "rubbish"]):
category = "Waste"
reason = "Description contains keywords related to waste."
elif any(word in description_lower for word in ["noise", "sound", "loud", "loudness"]):
category = "Noise"
reason = "Description contains keywords related to noise."
elif any(word in description_lower for word in ["road damage", "damaged road", "road crack", "cracked"]):
category = "Road Damage"
reason = "Description contains keywords related to road damage."
elif any(word in description_lower for word in ["heritage", "historic", "monument", "historical"]):
category = "Heritage Damage"
reason = "Description contains keywords related to heritage sites."
elif any(word in description_lower for word in ["heat", "heat hazard", "extreme heat", "temperature"]):
category = "Heat Hazard"
reason = "Description contains keywords related to heat hazards."
elif any(word in description_lower for word in ["drain", "drainage", "blocked drain", "blockage"]):
category = "Drain Blockage"
reason = "Description contains keywords related to drain blockage."
else:
category = "Other"
flag = "NEEDS_REVIEW"
reason = "Category could not be confidently determined from the description."

if reason and category != "Other":
reason = f"{reason} Contains: {', '.join(word for word in description.split() if any(c.isalpha() for c in word))[:50]}..."

return {
"complaint_id": row.get("complaint_id", ""),
"category": category,
"priority": priority,
"reason": reason,
"flag": flag
}


def batch_classify(input_path: str, output_path: str):
"""
Read input CSV, classify each row, write results CSV.

TODO: Build this using your AI tool.
Must: flag nulls, not crash on bad rows, produce output even if some rows fail.
Features:
- Reads all rows from input CSV
- Applies classify_complaint to each row
- Handles errors gracefully without crashing
- Writes output CSV with classification results
"""
raise NotImplementedError("Build this using your AI tool + RICE prompt")
try:
with open(input_path, 'r', encoding='utf-8') as infile:
reader = csv.DictReader(infile)

if reader.fieldnames is None or 'description' not in reader.fieldnames:
print(f"Error: Input CSV must contain a 'description' column.")
return

rows = list(reader)

# Classify all rows
classified_rows = []
for idx, row in enumerate(rows):
try:
if not row.get('description', '').strip():
print(f"Warning: Row {idx + 1} has empty description, flagging for review.")
classified = {
"complaint_id": row.get("complaint_id", ""),
"category": "Other",
"priority": "Standard",
"reason": "Empty description provided.",
"flag": "NEEDS_REVIEW"
}
else:
classified = classify_complaint(row)
classified_rows.append(classified)
except Exception as e:
print(f"Error classifying row {idx + 1}: {str(e)}")
classified_rows.append({
"complaint_id": row.get("complaint_id", ""),
"category": "Other",
"priority": "Standard",
"reason": f"Error during classification: {str(e)}",
"flag": "NEEDS_REVIEW"
})

# Write output CSV
output_fieldnames = ["complaint_id", "category", "priority", "reason", "flag"]
with open(output_path, 'w', newline='', encoding='utf-8') as outfile:
writer = csv.DictWriter(outfile, fieldnames=output_fieldnames)
writer.writeheader()
writer.writerows(classified_rows)

print(f"Successfully classified {len(classified_rows)} complaints.")

except FileNotFoundError:
print(f"Error: Input file '{input_path}' not found.")
except Exception as e:
print(f"Error during batch classification: {str(e)}")


if __name__ == "__main__":
Expand Down
16 changes: 16 additions & 0 deletions uc-0a/results_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,Category could not be confidently determined from the description.,NEEDS_REVIEW
AM-202402,Heat Hazard,Standard,"Description contains keywords related to heat hazards. Contains: metal, bus, shelter, reaching, dangerous, temperat...",
AM-202405,Other,Standard,Category could not be confidently determined from the description.,NEEDS_REVIEW
AM-202406,Heat Hazard,Standard,"Description contains keywords related to heat hazards. Contains: irrigation, system, broken., grass, dying, in, hea...",
AM-202407,Other,Urgent,Category could not be confidently determined from the description.,NEEDS_REVIEW
AM-202410,Pothole,Standard,"Description contains keywords related to potholes. Contains: pothole, on, main, highway, causing, morning, rush...",
AM-202414,Other,Standard,Category could not be confidently determined from the description.,NEEDS_REVIEW
AM-202417,Waste,Standard,"Description contains keywords related to waste. Contains: night, market, waste, not, cleared, before, mornin...",
AM-202421,Other,Standard,Category could not be confidently determined from the description.,NEEDS_REVIEW
AM-202424,Other,Standard,Category could not be confidently determined from the description.,NEEDS_REVIEW
AM-202429,Heat Hazard,Standard,"Description contains keywords related to heat hazards. Contains: river, walk, surface, temperature, unbearable., in...",
AM-202431,Heritage Damage,Standard,"Description contains keywords related to heritage sites. Contains: old, city, road, subsidence, near, ancient, step, ...",
AM-202435,Heat Hazard,Standard,"Description contains keywords related to heat hazards. Contains: black, metal, road, dividers, storing, heat., moto...",
AM-202444,Waste,Standard,"Description contains keywords related to waste. Contains: restaurant, waste, bins, overflowing, on, sunday, ...",
AM-202445,Other,Standard,Category could not be confidently determined from the description.,NEEDS_REVIEW
16 changes: 16 additions & 0 deletions uc-0a/results_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,"Description contains keywords related to flooding. Contains: underpass, flooded, after, 1hr, rain., ambulance, ...",
GH-202402,Flooding,Standard,"Description contains keywords related to flooding. Contains: market, area, flooded., traders, suffering, losses...",
GH-202406,Flooding,Standard,"Description contains keywords related to flooding. Contains: main, stormwater, drain, blocked, with, constructi...",
GH-202407,Drain Blockage,Standard,"Description contains keywords related to drain blockage. Contains: drain, blocked, and, mosquito, breeding., dengue, ...",
GH-202410,Pothole,Standard,"Description contains keywords related to potholes. Contains: potholes, causing, vehicles, to, slow, to, 20kmph,...",
GH-202411,Pothole,Urgent,"Description contains keywords related to potholes. Contains: pothole, swallowed, entire, motorcycle, wheel., ri...",
GH-202412,Pothole,Urgent,"Description contains keywords related to potholes. Contains: school, bus, struggling, to, navigate, potholes, i...",
GH-202417,Waste,Standard,"Description contains keywords related to waste. Contains: heritage, zone, garbage, overflow., tourist, photo...",
GH-202420,Other,Standard,Category could not be confidently determined from the description.,NEEDS_REVIEW
GH-202422,Other,Urgent,Category could not be confidently determined from the description.,NEEDS_REVIEW
GH-202424,Flooding,Standard,"Description contains keywords related to flooding. Contains: underpass, floods, in, light, rain., cars, regular...",
GH-202428,Waste,Standard,"Description contains keywords related to waste. Contains: post-market, waste, not, cleared., area, unusable,...",
GH-202432,Other,Standard,Category could not be confidently determined from the description.,NEEDS_REVIEW
GH-202448,Flooding,Standard,"Description contains keywords related to flooding. Contains: main, drain, blocked, entire, locality, at, floodi...",
GH-202438,Flooding,Standard,"Description contains keywords related to flooding. Contains: colony, surrounded, by, fields, that, channel, rai...",
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,Streetlight,Standard,"Description contains keywords related to streetlights. Contains: heritage, lamp, post, knocked, over, by, delivery,...",
KM-202402,Heritage Damage,Standard,"Description contains keywords related to heritage sites. Contains: historic, tram, road, cobblestones, broken, up, by...",
KM-202405,Other,Standard,Category could not be confidently determined from the description.,NEEDS_REVIEW
KM-202409,Pothole,Standard,"Description contains keywords related to potholes. Contains: airport, access, road, full, of, potholes., diplom...",
KM-202410,Pothole,Standard,"Description contains keywords related to potholes. Contains: pothole, causing, tyre, blowouts., three, incident...",
KM-202411,Pothole,Standard,"Description contains keywords related to potholes. Contains: deep, pothole, filling, with, rainwater., depth, i...",
KM-202415,Drain Blockage,Standard,"Description contains keywords related to drain blockage. Contains: new, residential, complex, draining, directly, ont...",
KM-202418,Waste,Standard,"Description contains keywords related to waste. Contains: tourist, zone, waste, overflowing., foreign, visit...",
KM-202421,Other,Urgent,Category could not be confidently determined from the description.,NEEDS_REVIEW
KM-202422,Other,Standard,Category could not be confidently determined from the description.,NEEDS_REVIEW
KM-202426,Heritage Damage,Standard,"Description contains keywords related to heritage sites. Contains: heritage, residential, building, exterior, defaced...",
KM-202430,Other,Standard,Category could not be confidently determined from the description.,NEEDS_REVIEW
KM-202434,Heritage Damage,Standard,"Description contains keywords related to heritage sites. Contains: street, paving, removed, for, utility, work, herit...",
KM-202436,Other,Standard,Category could not be confidently determined from the description.,NEEDS_REVIEW
KM-202438,Heritage Damage,Standard,"Description contains keywords related to heritage sites. Contains: street, vendors, using, amplifiers, illegally, in,...",
16 changes: 16 additions & 0 deletions uc-0a/results_pune.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
complaint_id,category,priority,reason,flag
PM-202401,Pothole,Standard,"Description contains keywords related to potholes. Contains: large, pothole, 60cm, wide, causing, tyre, damage....",
PM-202402,Pothole,Urgent,"Description contains keywords related to potholes. Contains: deep, pothole, near, bus, stop., school, children,...",
PM-202406,Flooding,Standard,"Description contains keywords related to flooding. Contains: underpass, flooded, knee-deep, after, 2hrs, rain.,...",
PM-202408,Flooding,Standard,"Description contains keywords related to flooding. Contains: bus, stand, flooded., passengers, standing, in, wa...",
PM-202410,Streetlight,Standard,"Description contains keywords related to streetlights. Contains: three, consecutive, streetlights, out, for, days.,...",
PM-202411,Streetlight,Urgent,"Description contains keywords related to streetlights. Contains: streetlight, flickering, and, sparking., electrica...",
PM-202413,Waste,Standard,"Description contains keywords related to waste. Contains: overflowing, garbage, bins, near, vegetable, marke...",
PM-202418,Other,Standard,Category could not be confidently determined from the description.,NEEDS_REVIEW
PM-202419,Road Damage,Standard,"Description contains keywords related to road damage. Contains: road, surface, cracked, and, sinking, near, utilit...",
PM-202420,Pothole,Urgent,"Description contains keywords related to potholes. Contains: manhole, cover, missing., risk, of, serious, injur...",
PM-202427,Flooding,Standard,"Description contains keywords related to flooding. Contains: bridge, approach, floods, in, 30mins, of, rain., b...",
PM-202428,Other,Standard,Category could not be confidently determined from the description.,NEEDS_REVIEW
PM-202430,Heritage Damage,Standard,"Description contains keywords related to heritage sites. Contains: heritage, street,, lights, out., safety, concern, ...",
PM-202433,Waste,Standard,"Description contains keywords related to waste. Contains: bulk, waste, from, apartment, renovation, dumped, ...",
PM-202446,Other,Urgent,Category could not be confidently determined from the description.,NEEDS_REVIEW
20 changes: 10 additions & 10 deletions uc-0a/skills.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
# 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 citizen complaint into a predefined category, determines priority level, provides a justification reason, and flags if review is needed.
input: A dictionary representing a complaint row, containing at least a 'description' field with the complaint text.
output: A dictionary with keys 'category' (string from allowed list), 'priority' (Urgent/Standard/Low), 'reason' (one sentence citing specific words), 'flag' (NEEDS_REVIEW or empty string).
error_handling: If the category cannot be determined unambiguously from the description, set category to 'Other' and flag to 'NEEDS_REVIEW'. Ensure priority is Urgent if severity keywords are present.

- 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 classified results to an output CSV file.
input: Path to the input CSV file (string), where each row has a 'description' column.
output: Path to the output CSV file (string); writes a CSV with additional columns for category, priority, reason, and flag.
error_handling: Skips rows with missing or invalid descriptions, logging errors; ensures all outputs adhere to the classification schema and enforcement rules.
Loading