Spaces:
Running
Running
File size: 5,120 Bytes
25c8c70 dffe895 25c8c70 428dafd 25c8c70 d29a4b6 25c8c70 dffe895 25c8c70 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | """Agent 1 — Intent Agent
Uses Gemini 2.5 Flash Lite if GEMINI_API_KEY is valid.
Falls back to rule-based parser if key is missing/invalid (demo mode).
"""
import os, json, re
import google.generativeai as genai
# ── Rule-based fallback (no API key needed) ──────────────────────
SERVICE_KEYWORDS = {
"AC Technician": ["ac", "air condition", "cooling", "hvac", "thanda"],
"Plumber": ["plumber", "plumbing", "pipe", "leakage", "tap", "nal"],
"Electrician": ["electric", "bijli", "wiring", "light", "switch", "fuse"],
"Tutor": ["tutor", "teacher", "teacher", "teacher", "padhai", "math", "science", "english"],
"Beautician": ["beauty", "parlour", "makeup", "salon", "facial", "wax"],
"Carpenter": ["carpenter", "wood", "furniture", "darwaza", "door", "shelf"],
"Painter": ["paint", "rang", "wall", "colour", "color"],
"Driver": ["driver", "car", "ride", "airport", "drop", "pick"],
"Maid": ["maid", "cleaning", "sweep", "jharo", "safai", "cook"],
"Delivery Worker": ["delivery", "parcel", "courier", "deliver", "send"],
}
AREA_KEYWORDS = [
"G-13","G-11","G-10","G-9","G-6","G-7","G-8",
"F-10","F-7","F-6","F-8","F-11",
"E-11","E-7","I-8","I-10","I-9",
]
TIME_KEYWORDS = {
"morning": ["subah", "morning", "صبح", "savere"],
"afternoon": ["dopahar", "afternoon", "دوپہر"],
"evening": ["sham", "evening", "شام", "shaam"],
"asap": ["aaj", "today", "abhi", "now", "jaldi", "asap", "فوری"],
"tomorrow": ["kal", "tomorrow", "کل"],
}
def rule_based_parse(message: str) -> dict:
msg = message.lower()
service = None
for svc, keywords in SERVICE_KEYWORDS.items():
if any(k in msg for k in keywords):
service = svc
break
location = None
for area in AREA_KEYWORDS:
if area.lower() in msg:
location = area
break
time_str = "tomorrow morning"
for label, keywords in TIME_KEYWORDS.items():
if any(k in msg for k in keywords):
time_str = label
break
lang = "roman_urdu"
urdu_chars = set("ابتثجحخدذرزسشصضطظعغفقکگلمنوہیآ")
if any(c in urdu_chars for c in message):
lang = "urdu"
elif all(ord(c) < 128 for c in message):
lang = "english" if re.search(r'\b(i|need|want|please|the|a|an)\b', msg) else "roman_urdu"
return {
"service_type": service,
"location": location or "G-13",
"time": time_str,
"language": lang,
"confidence": 0.75,
"mode": "rule_based_fallback",
}
def run(message: str) -> dict:
api_key = os.environ.get("GEMINI_API_KEY", "GEMINI_API_KEY").strip()
# ── Try Gemini first ─────────────────────────────────────────
if api_key and api_key != "YOUR_GEMINI_API_KEY_HERE":
try:
genai.configure(api_key=api_key)
model = genai.GenerativeModel("gemini-2.5-flash-lite")
prompt = f"""You are a service request parser for Pakistan's informal economy.
Extract structured info from the user message. Respond ONLY with valid JSON, no markdown, no explanation.
User message: "{message}"
Return exactly this JSON:
{{
"service_type": "<one of: AC Technician, Plumber, Electrician, Tutor, Beautician, Carpenter, Painter, Driver, Maid, Delivery Worker>",
"location": "<area name like G-13, F-10, etc. Extract from message>",
"time": "<e.g. tomorrow morning, today evening, asap>",
"language": "<urdu | roman_urdu | english | mixed>",
"confidence": <0.0 to 1.0>,
"mode": "gemini"
}}
If a field cannot be determined use null."""
response = model.generate_content(prompt)
raw = response.text.strip()
raw = re.sub(r"```json|```", "", raw).strip()
result = json.loads(raw)
result["mode"] = "gemini"
return result
except Exception as e:
err = str(e)
# Key invalid → fall through to rule-based, don't crash
if "API_KEY_INVALID" in err or "API key not valid" in err:
result = rule_based_parse(message)
result["_warning"] = "Gemini API key invalid — using rule-based parser. Check HF Secrets."
return result
# Quota exceeded → same fallback
if "quota" in err.lower() or "429" in err:
result = rule_based_parse(message)
result["_warning"] = "Gemini quota exceeded — using rule-based parser."
return result
raise # re-raise unexpected errors
# ── No key set → rule-based ───────────────────────────────────
result = rule_based_parse(message)
result["_warning"] = "GEMINI_API_KEY not set — using rule-based parser (demo mode)."
return result
|