Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,6 +1,11 @@
|
|
| 1 |
import json, re
|
| 2 |
import gradio as gr
|
| 3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
# Load knowledge
|
| 5 |
with open("kb.json", "r", encoding="utf-8") as f:
|
| 6 |
KB = json.load(f)
|
|
@@ -28,6 +33,59 @@ GUIDE_QS = [
|
|
| 28 |
("extras", "Extras available? (pick any, or 'None')", ["Fan","Washing machine","Garden","Rooftop","None"])
|
| 29 |
]
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
def map_habit_to_cards(focus, habit):
|
| 32 |
focus = focus.lower()
|
| 33 |
if focus=="water":
|
|
@@ -116,6 +174,7 @@ def bot_reply(user, state):
|
|
| 116 |
# TUTOR mode quick topic guess
|
| 117 |
t = (user or "").lower()
|
| 118 |
normalized = re.sub(r"[^\w\s]", "", t).strip()
|
|
|
|
| 119 |
if any(w in t for w in ["water","shower","tap","leak","plant","tree","bottle"]):
|
| 120 |
topic="water"
|
| 121 |
elif any(w in t for w in ["ac","power","electric","fan","bulb","led"]):
|
|
@@ -125,6 +184,9 @@ def bot_reply(user, state):
|
|
| 125 |
else:
|
| 126 |
topic=None
|
| 127 |
|
|
|
|
|
|
|
|
|
|
| 128 |
if topic:
|
| 129 |
home_hint = "apartment" if "apartment" in t else ("house" if "house" in t else None)
|
| 130 |
cards = find_cards(topic, home_hint) or find_cards(topic)
|
|
@@ -132,19 +194,29 @@ def bot_reply(user, state):
|
|
| 132 |
return short_answer(card), state
|
| 133 |
|
| 134 |
# small talk and acknowledgements
|
|
|
|
|
|
|
| 135 |
if re.search(r"\b(hi|hello|hey|salaam|assalam|assalamu alaikum|assalamualaikum)\b", t):
|
| 136 |
return "Salaam! I'm your Green Guide bot - ask me about water, electricity, or waste habits anytime.", state
|
|
|
|
|
|
|
| 137 |
if "how are you" in t:
|
| 138 |
return "I'm running on code and clean energy facts! How can I help with your sustainability goal?", state
|
|
|
|
|
|
|
| 139 |
if normalized in {"ok","okay","yes","yup","sure","cool","great","thanks","thank you","thankyou","nice"}:
|
| 140 |
return "Noted! Tell me what you want to improve: water, electricity, or waste, and I'll share tips.", state
|
|
|
|
|
|
|
| 141 |
|
| 142 |
# checklists
|
|
|
|
|
|
|
| 143 |
if re.search(r"\b(checklist|pledge)\b", t):
|
| 144 |
-
if "power" in t:
|
| 145 |
-
return "Power Ninja 7-day: LED swap
|
| 146 |
-
if "waste" in t:
|
| 147 |
-
return "Waste Warrior 7-day: 2-bin
|
| 148 |
return "Water Saver 7-day: fix drip 路 5-min showers 路 reuse rinse for plants 路 full loads 路 cold bottle in fridge 路 log habits 路 share one tip", state
|
| 149 |
|
| 150 |
return "Try **Tutor**: ask me anything about water/electricity/waste. Or type **Guide** for a mini plan.", state
|
|
|
|
| 1 |
import json, re
|
| 2 |
import gradio as gr
|
| 3 |
|
| 4 |
+
try:
|
| 5 |
+
from transformers import pipeline
|
| 6 |
+
except ImportError: # pragma: no cover - handled gracefully if transformers missing
|
| 7 |
+
pipeline = None
|
| 8 |
+
|
| 9 |
# Load knowledge
|
| 10 |
with open("kb.json", "r", encoding="utf-8") as f:
|
| 11 |
KB = json.load(f)
|
|
|
|
| 33 |
("extras", "Extras available? (pick any, or 'None')", ["Fan","Washing machine","Garden","Rooftop","None"])
|
| 34 |
]
|
| 35 |
|
| 36 |
+
INTENT_LABELS = [
|
| 37 |
+
"water",
|
| 38 |
+
"electricity",
|
| 39 |
+
"waste",
|
| 40 |
+
"greeting",
|
| 41 |
+
"smalltalk",
|
| 42 |
+
"affirmation",
|
| 43 |
+
"gratitude",
|
| 44 |
+
"checklist",
|
| 45 |
+
"goodbye"
|
| 46 |
+
]
|
| 47 |
+
INTENT_THRESHOLD = 0.45
|
| 48 |
+
_INTENT_PIPELINE = None
|
| 49 |
+
_INTENT_PIPELINE_ERR = None
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def load_intent_classifier():
|
| 53 |
+
"""Lazily load the zero-shot intent classifier pipeline."""
|
| 54 |
+
global _INTENT_PIPELINE, _INTENT_PIPELINE_ERR
|
| 55 |
+
if pipeline is None:
|
| 56 |
+
_INTENT_PIPELINE_ERR = "transformers not installed"
|
| 57 |
+
return None
|
| 58 |
+
if _INTENT_PIPELINE is not None or _INTENT_PIPELINE_ERR:
|
| 59 |
+
return _INTENT_PIPELINE
|
| 60 |
+
try:
|
| 61 |
+
_INTENT_PIPELINE = pipeline(
|
| 62 |
+
"zero-shot-classification",
|
| 63 |
+
model="typeform/distilbert-base-uncased-mnli"
|
| 64 |
+
)
|
| 65 |
+
except Exception as err: # pragma: no cover - model download/setup issues
|
| 66 |
+
_INTENT_PIPELINE_ERR = err
|
| 67 |
+
return None
|
| 68 |
+
return _INTENT_PIPELINE
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
def classify_intent(text):
|
| 72 |
+
"""Return (label, score) for the strongest intent, or (None, 0.0)."""
|
| 73 |
+
if not text:
|
| 74 |
+
return None, 0.0
|
| 75 |
+
clf = load_intent_classifier()
|
| 76 |
+
if clf is None:
|
| 77 |
+
return None, 0.0
|
| 78 |
+
result = clf(text, candidate_labels=INTENT_LABELS, multi_label=True)
|
| 79 |
+
labels = result.get("labels") or []
|
| 80 |
+
scores = result.get("scores") or []
|
| 81 |
+
if not labels or not scores:
|
| 82 |
+
return None, 0.0
|
| 83 |
+
best_label, best_score = max(zip(labels, scores), key=lambda pair: pair[1])
|
| 84 |
+
if best_score < INTENT_THRESHOLD:
|
| 85 |
+
return None, best_score
|
| 86 |
+
return best_label, best_score
|
| 87 |
+
|
| 88 |
+
|
| 89 |
def map_habit_to_cards(focus, habit):
|
| 90 |
focus = focus.lower()
|
| 91 |
if focus=="water":
|
|
|
|
| 174 |
# TUTOR mode quick topic guess
|
| 175 |
t = (user or "").lower()
|
| 176 |
normalized = re.sub(r"[^\w\s]", "", t).strip()
|
| 177 |
+
intent_label, intent_score = classify_intent(user or "")
|
| 178 |
if any(w in t for w in ["water","shower","tap","leak","plant","tree","bottle"]):
|
| 179 |
topic="water"
|
| 180 |
elif any(w in t for w in ["ac","power","electric","fan","bulb","led"]):
|
|
|
|
| 184 |
else:
|
| 185 |
topic=None
|
| 186 |
|
| 187 |
+
if topic is None and intent_label in {"water","electricity","waste"}:
|
| 188 |
+
topic = intent_label
|
| 189 |
+
|
| 190 |
if topic:
|
| 191 |
home_hint = "apartment" if "apartment" in t else ("house" if "house" in t else None)
|
| 192 |
cards = find_cards(topic, home_hint) or find_cards(topic)
|
|
|
|
| 194 |
return short_answer(card), state
|
| 195 |
|
| 196 |
# small talk and acknowledgements
|
| 197 |
+
if intent_label == "greeting" and intent_score >= INTENT_THRESHOLD:
|
| 198 |
+
return "Salaam! I'm your Green Guide bot - ask me about water, electricity, or waste habits anytime.", state
|
| 199 |
if re.search(r"\b(hi|hello|hey|salaam|assalam|assalamu alaikum|assalamualaikum)\b", t):
|
| 200 |
return "Salaam! I'm your Green Guide bot - ask me about water, electricity, or waste habits anytime.", state
|
| 201 |
+
if intent_label == "smalltalk" and intent_score >= INTENT_THRESHOLD:
|
| 202 |
+
return "Happy to chat! Got any water, electricity, or waste question for me?", state
|
| 203 |
if "how are you" in t:
|
| 204 |
return "I'm running on code and clean energy facts! How can I help with your sustainability goal?", state
|
| 205 |
+
if intent_label in {"affirmation","gratitude"} and intent_score >= INTENT_THRESHOLD:
|
| 206 |
+
return "Noted! Tell me what you want to improve: water, electricity, or waste, and I'll share tips.", state
|
| 207 |
if normalized in {"ok","okay","yes","yup","sure","cool","great","thanks","thank you","thankyou","nice"}:
|
| 208 |
return "Noted! Tell me what you want to improve: water, electricity, or waste, and I'll share tips.", state
|
| 209 |
+
if intent_label == "goodbye" and intent_score >= INTENT_THRESHOLD:
|
| 210 |
+
return "Khuda hafiz! Come back anytime you need another green tip.", state
|
| 211 |
|
| 212 |
# checklists
|
| 213 |
+
if intent_label == "checklist" and intent_score >= INTENT_THRESHOLD:
|
| 214 |
+
return "Need a checklist? Type **water**, **power**, or **waste** and I'll drop a 7-day plan.", state
|
| 215 |
if re.search(r"\b(checklist|pledge)\b", t):
|
| 216 |
+
if "power" in t:
|
| 217 |
+
return "Power Ninja 7-day: LED swap ? 26?C nights ? fan-first ? unplug at 10pm ? kill standby ? use daylight ? share result", state
|
| 218 |
+
if "waste" in t:
|
| 219 |
+
return "Waste Warrior 7-day: 2-bin ? rinse items ? paper stack ? e-waste box ? no plastic bag ? find drop-off ? share photo", state
|
| 220 |
return "Water Saver 7-day: fix drip 路 5-min showers 路 reuse rinse for plants 路 full loads 路 cold bottle in fridge 路 log habits 路 share one tip", state
|
| 221 |
|
| 222 |
return "Try **Tutor**: ask me anything about water/electricity/waste. Or type **Guide** for a mini plan.", state
|