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
20 changes: 11 additions & 9 deletions uc-0a/agents.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
# 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?]
A precise citizen complaint classifier for city service requests. Its operational boundary is limited to categorizing incoming complaints based on a fixed taxonomy, assessing priority based on severity keywords, and providing short justifications derived directly from the complaint text.

intent: >
[FILL IN: What does a correct output look like — make it verifiable]
A correctly classified CSV output where each row includes:
1. A `category` selected exactly from the allowed taxonomy.
2. A `priority` level (Urgent, Standard, or Low).
3. A one-sentence `reason` that cites specific words from the original description.
4. A `flag` set to 'NEEDS_REVIEW' for ambiguous cases.

context: >
[FILL IN: What information is the agent allowed to use? State exclusions explicitly.]
The agent is allowed to use only the complaint description provided in the input CSV. It must explicitly exclude any external knowledge, personal bias, or categories not present in the defined schema. It must not hallucinate sub-categories or details not present in the text.

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."
- "Priority must be 'Urgent' if the description contains any of the following severity keywords: injury, child, school, hospital, ambulance, fire, hazard, fell, collapse."
- "Every output row must include a one-sentence 'reason' field that cites specific words from the description as evidence."
- "If the category is genuinely ambiguous or cannot be determined from the description alone, the agent must set the flag to 'NEEDS_REVIEW'."
122 changes: 111 additions & 11 deletions uc-0a/classifier.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,129 @@
"""
UC-0A — Complaint Classifier
Starter file. Build this using the RICE → agents.md skills.md → CRAFT workflow.
Implementation based on agents.md and skills.md specifications.
"""
import argparse
import csv
import os

# Taxonomy and priority rules
CATEGORIES = [
"Pothole", "Flooding", "Streetlight", "Waste", "Noise",
"Road Damage", "Heritage Damage", "Heat Hazard", "Drain Blockage", "Other"
]

URGENT_KEYWORDS = [
"injury", "child", "school", "hospital", "ambulance",
"fire", "hazard", "fell", "collapse"
]

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.
Classify a single complaint row using rule-based heuristics
that strictly follow the RICE enforcement rules.
"""
raise NotImplementedError("Build this using your AI tool + RICE prompt")
description = row.get("description", "").lower()
complaint_id = row.get("complaint_id", "Unknown")

# 1. Determine Category
category = "Other"
found_words = []

if "pothole" in description:
category = "Pothole"
found_words.append("pothole")
elif "flood" in description or "rain" in description:
category = "Flooding"
found_words.append("flood" if "flood" in description else "rain")
elif "streetlight" in description or "lights out" in description:
category = "Streetlight"
found_words.append("streetlight" if "streetlight" in description else "lights out")
elif "garbage" in description or "waste" in description or "dumped" in description or "animal" in description:
category = "Waste"
if "garbage" in description: found_words.append("garbage")
if "waste" in description: found_words.append("waste")
if "dumped" in description: found_words.append("dumped")
if "animal" in description: found_words.append("dead animal")
elif "noise" in description or "music" in description:
category = "Noise"
found_words.append("noise" if "noise" in description else "music")
elif "drain" in description or "manhole" in description:
category = "Drain Blockage"
found_words.append("drain" if "drain" in description else "manhole")
elif "heritage" in description:
category = "Heritage Damage"
found_words.append("heritage")
elif "heat" in description:
category = "Heat Hazard"
found_words.append("heat")
elif "road" in description or "footpath" in description or "tiles" in description:
category = "Road Damage"
if "road" in description: found_words.append("road")
if "footpath" in description: found_words.append("footpath")
if "tiles" in description: found_words.append("tiles")
if "crack" in description: found_words.append("cracked")
if "sink" in description: found_words.append("sinking")

# 2. Determine Priority
priority = "Low"
triggered_keywords = [word for word in URGENT_KEYWORDS if word in description]

if triggered_keywords:
priority = "Urgent"
elif any(word in description for word in ["risk", "safety", "danger", "stranded"]):
priority = "Standard"
else:
priority = "Standard" # Defaulting to Standard if not Urgent but valid category

# 3. Generate Reason
if found_words:
reason = f"Classified as {category} because the description mentions '{', '.join(found_words)}'."
else:
reason = "Could not determine a specific category from the description."

# 4. Set Flag
flag = ""
if category == "Other" or not found_words:
flag = "NEEDS_REVIEW"
elif len(found_words) > 1 and category == "Other": # Genuinely ambiguous
flag = "NEEDS_REVIEW"

return {
"complaint_id": 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.
"""
raise NotImplementedError("Build this using your AI tool + RICE prompt")
if not os.path.exists(input_path):
print(f"Error: Input file {input_path} not found.")
return

results = []
try:
with open(input_path, mode='r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
classified = classify_complaint(row)
results.append(classified)
except Exception as e:
print(f"Error reading input CSV: {e}")
return

fieldnames = ["complaint_id", "category", "priority", "reason", "flag"]
try:
with open(output_path, mode='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 CSV: {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,Could not determine a specific category from the description.,NEEDS_REVIEW
AM-202402,Other,Standard,Could not determine a specific category from the description.,NEEDS_REVIEW
AM-202405,Other,Standard,Could not determine a specific category from the description.,NEEDS_REVIEW
AM-202406,Heat Hazard,Standard,Classified as Heat Hazard because the description mentions 'heat'.,
AM-202407,Other,Urgent,Could not determine a specific category from the description.,NEEDS_REVIEW
AM-202410,Pothole,Standard,Classified as Pothole because the description mentions 'pothole'.,
AM-202414,Other,Standard,Could not determine a specific category from the description.,NEEDS_REVIEW
AM-202417,Waste,Standard,Classified as Waste because the description mentions 'waste'.,
AM-202421,Noise,Standard,Classified as Noise because the description mentions 'music'.,
AM-202424,Road Damage,Standard,Classified as Road Damage because the description mentions 'road'.,
AM-202429,Other,Standard,Could not determine a specific category from the description.,NEEDS_REVIEW
AM-202431,Heritage Damage,Standard,Classified as Heritage Damage because the description mentions 'heritage'.,
AM-202435,Heat Hazard,Standard,Classified as Heat Hazard because the description mentions 'heat'.,
AM-202444,Waste,Standard,Classified as Waste because the description mentions 'waste'.,
AM-202445,Other,Standard,Could not determine a specific category 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,Classified as Flooding because the description mentions 'flood'.,
GH-202402,Flooding,Standard,Classified as Flooding because the description mentions 'flood'.,
GH-202406,Flooding,Standard,Classified as Flooding because the description mentions 'rain'.,
GH-202407,Flooding,Standard,Classified as Flooding because the description mentions 'rain'.,
GH-202410,Pothole,Standard,Classified as Pothole because the description mentions 'pothole'.,
GH-202411,Pothole,Urgent,Classified as Pothole because the description mentions 'pothole'.,
GH-202412,Pothole,Urgent,Classified as Pothole because the description mentions 'pothole'.,
GH-202417,Waste,Standard,"Classified as Waste because the description mentions 'garbage, waste'.",
GH-202420,Other,Standard,Could not determine a specific category from the description.,NEEDS_REVIEW
GH-202422,Road Damage,Urgent,Classified as Road Damage because the description mentions 'road'.,
GH-202424,Flooding,Standard,Classified as Flooding because the description mentions 'flood'.,
GH-202428,Waste,Standard,Classified as Waste because the description mentions 'waste'.,
GH-202432,Other,Standard,Could not determine a specific category from the description.,NEEDS_REVIEW
GH-202448,Flooding,Standard,Classified as Flooding because the description mentions 'flood'.,
GH-202438,Flooding,Standard,Classified as Flooding because the description mentions 'rain'.,
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,Heritage Damage,Standard,Classified as Heritage Damage because the description mentions 'heritage'.,
KM-202402,Road Damage,Standard,Classified as Road Damage because the description mentions 'road'.,
KM-202405,Other,Standard,Could not determine a specific category from the description.,NEEDS_REVIEW
KM-202409,Pothole,Standard,Classified as Pothole because the description mentions 'pothole'.,
KM-202410,Pothole,Standard,Classified as Pothole because the description mentions 'pothole'.,
KM-202411,Pothole,Standard,Classified as Pothole because the description mentions 'pothole'.,
KM-202415,Flooding,Standard,Classified as Flooding because the description mentions 'rain'.,
KM-202418,Waste,Standard,Classified as Waste because the description mentions 'waste'.,
KM-202421,Road Damage,Urgent,"Classified as Road Damage because the description mentions 'footpath, sinking'.",
KM-202422,Road Damage,Standard,Classified as Road Damage because the description mentions 'road'.,
KM-202426,Heritage Damage,Standard,Classified as Heritage Damage because the description mentions 'heritage'.,
KM-202430,Road Damage,Standard,Classified as Road Damage because the description mentions 'road'.,
KM-202434,Heritage Damage,Standard,Classified as Heritage Damage because the description mentions 'heritage'.,
KM-202436,Other,Standard,Could not determine a specific category from the description.,NEEDS_REVIEW
KM-202438,Heritage Damage,Standard,Classified as Heritage Damage because the description mentions 'heritage'.,
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,Classified as Pothole because the description mentions 'pothole'.,
PM-202402,Pothole,Urgent,Classified as Pothole because the description mentions 'pothole'.,
PM-202406,Flooding,Standard,Classified as Flooding because the description mentions 'flood'.,
PM-202408,Flooding,Standard,Classified as Flooding because the description mentions 'flood'.,
PM-202410,Streetlight,Standard,Classified as Streetlight because the description mentions 'streetlight'.,
PM-202411,Streetlight,Urgent,Classified as Streetlight because the description mentions 'streetlight'.,
PM-202413,Waste,Standard,Classified as Waste because the description mentions 'garbage'.,
PM-202418,Noise,Standard,Classified as Noise because the description mentions 'music'.,
PM-202419,Road Damage,Standard,"Classified as Road Damage because the description mentions 'road, cracked, sinking'.",
PM-202420,Drain Blockage,Urgent,Classified as Drain Blockage because the description mentions 'manhole'.,
PM-202427,Flooding,Standard,Classified as Flooding because the description mentions 'flood'.,
PM-202428,Waste,Standard,Classified as Waste because the description mentions 'dead animal'.,
PM-202430,Streetlight,Standard,Classified as Streetlight because the description mentions 'lights out'.,
PM-202433,Waste,Standard,"Classified as Waste because the description mentions 'waste, dumped'.",
PM-202446,Road Damage,Urgent,"Classified as Road Damage because the description mentions 'footpath, tiles'.",
24 changes: 11 additions & 13 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.md — UC-0A Complaint Classifier

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 into a predefined taxonomy and priority level with a cited reason.
input: A complaint description string.
output: A JSON object or structured data containing category, priority, reason, and flag.
error_handling: If the text is too short or ambiguous, defaults to category 'Other' and sets flag to '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: Orchestrates the classification of multiple complaints from an input CSV and writes results to an output CSV.
input: Input CSV file path containing complaint descriptions.
output: Output CSV file path containing categorized and prioritized complaints.
error_handling: Validates CSV structure; if a row fails classification, it is flagged for review rather than stopping the batch process.
22 changes: 12 additions & 10 deletions uc-0b/agents.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
# agents.md
# INSTRUCTIONS: Generate a draft using your RICE prompt, then manually refine this file.
# Delete these comments before committing.
# agents.md — UC-0B Policy Summarizer

role: >
[FILL IN: Who is this agent? What is its operational boundary?]
A meticulous policy and legal summarizer. Its operational boundary is to condense policy documents while ensuring zero loss of obligations, specific conditions, or binding constraints. It must act as a fidelity-first filter that prevents clause omission or softening of requirements.

intent: >
[FILL IN: What does a correct output look like — make it verifiable]
A structured, verifiable summary where:
1. Every numbered clause from the source is explicitly addressed.
2. All multi-part conditions (e.g., dual approvals) are preserved in their entirety.
3. No external "industry standard" or "common sense" additions are made.
4. Any ambiguity results in verbatim quoting rather than interpretation.

context: >
[FILL IN: What information is the agent allowed to use? State exclusions explicitly.]
The agent operates exclusively on the provided text in `policy_hr_leave.txt`. It must ignore any prior training data regarding "typical" HR practices or standard government procedures. If it's not in the document, it does not exist for this agent.

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 must be present in the summary with its original reference number."
- "Multi-condition obligations must preserve ALL conditions — never drop an approver or a required step (e.g., Clause 5.2 requires BOTH Department Head and HR Director)."
- "Strict exclusion of scope bleed: Do not use phrases like 'as is standard practice' or 'typically' unless they appear in the source text."
- "Meaning loss refusal: If a clause's obligation cannot be summarized without softening a 'must' to a 'should' or losing a condition, quote the clause verbatim and flag it."
Loading