Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
| 1 |
import os
|
| 2 |
import re
|
| 3 |
-
import
|
| 4 |
-
from typing import List, Tuple
|
| 5 |
from dataclasses import dataclass
|
| 6 |
|
|
|
|
| 7 |
import torch
|
| 8 |
from transformers import AutoTokenizer, AutoModelForCausalLM
|
| 9 |
|
|
@@ -57,8 +57,7 @@ except Exception as e:
|
|
| 57 |
|
| 58 |
def llm_reply(prompt: str, max_new_tokens: int = 100, temperature: float = 0.3) -> str:
|
| 59 |
if not (tok and model):
|
| 60 |
-
|
| 61 |
-
return "safePak: میں آپ کی مدد کے لیے حاضر ہوں۔ براہ کرم مزید وضاحت دیں۔"
|
| 62 |
ids = tok.encode(prompt, return_tensors="pt")
|
| 63 |
out = model.generate(
|
| 64 |
ids,
|
|
@@ -67,7 +66,8 @@ def llm_reply(prompt: str, max_new_tokens: int = 100, temperature: float = 0.3)
|
|
| 67 |
do_sample=True,
|
| 68 |
pad_token_id=tok.eos_token_id,
|
| 69 |
)
|
| 70 |
-
|
|
|
|
| 71 |
|
| 72 |
# ---------------- Helpline rendering ----------------
|
| 73 |
def _clean_phone_for_links(p: str) -> str:
|
|
@@ -109,12 +109,13 @@ def helplines_block(lang: str) -> str:
|
|
| 109 |
lines.append(f"**{nm}**\n{ph}\n[📞 Call]({tel}) | [💬 WhatsApp]({wa})")
|
| 110 |
return "\n\n".join(lines)
|
| 111 |
|
| 112 |
-
# ---------------- Core
|
| 113 |
SAFEPAK_SYSTEM = """
|
| 114 |
You are SafePak – 1122 Guide, a multilingual emergency disaster assistant.
|
| 115 |
-
Always reply in user's language.
|
| 116 |
-
|
| 117 |
-
Never panic. End with
|
|
|
|
| 118 |
"""
|
| 119 |
|
| 120 |
def format_response(base: str, user_msg: str, lang: str) -> str:
|
|
@@ -122,68 +123,192 @@ def format_response(base: str, user_msg: str, lang: str) -> str:
|
|
| 122 |
f"<system>\n{SAFEPAK_SYSTEM}\n</system>\n"
|
| 123 |
f"<user>\n{user_msg}\n\nDraft response:\n{base}\n</user>"
|
| 124 |
)
|
| 125 |
-
|
|
|
|
| 126 |
|
| 127 |
-
# ----------------
|
| 128 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
if not user_msg:
|
| 130 |
-
return
|
|
|
|
| 131 |
lang = detect_lang(user_msg)
|
| 132 |
-
status,
|
| 133 |
|
| 134 |
# BLOCK
|
| 135 |
if status == "BLOCK":
|
| 136 |
msg = GUARD.refusal_msg_ur if lang == "ur" else GUARD.refusal_msg_en
|
| 137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|
| 139 |
-
# base checklist
|
| 140 |
-
|
| 141 |
-
low = user_msg.lower()
|
| 142 |
-
if any(k in low for k in ["fire","آگ","smoke"]):
|
| 143 |
-
checklist = "Fire safety steps"
|
| 144 |
-
elif any(k in low for k in ["زلزلہ","earthquake","tremor"]):
|
| 145 |
-
checklist = "Earthquake safety steps"
|
| 146 |
-
elif any(k in low for k in ["سیلاب","flood","overflow"]):
|
| 147 |
-
checklist = "Flood survival steps"
|
| 148 |
-
elif any(k in low for k in ["gas","گیس","leak"]):
|
| 149 |
-
checklist = "Gas leak safety steps"
|
| 150 |
-
elif any(k in low for k in ["injury","زخمی","bleeding"]):
|
| 151 |
-
checklist = "First aid for injury"
|
| 152 |
-
else:
|
| 153 |
-
checklist = "General emergency guidance"
|
| 154 |
-
|
| 155 |
-
final = format_response(checklist, user_msg, lang)
|
| 156 |
|
| 157 |
-
# SOFT
|
| 158 |
if status == "SOFT":
|
| 159 |
-
if lang
|
| 160 |
-
final = "⚠️ محتاط رہیں: یہ موضوع حساس ہے۔\n\n" + final
|
| 161 |
-
else:
|
| 162 |
-
final = "⚠️ Note: Sensitive topic.\n\n" + final
|
| 163 |
|
|
|
|
|
|
|
| 164 |
final += "\n\n" + helplines_block(lang)
|
| 165 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
# ---------------- UI ----------------
|
| 168 |
with gr.Blocks(title="SafePak – 1122 Guide") as demo:
|
| 169 |
gr.Markdown("## SafePak – 1122 Guide\nMultilingual emergency assistant (CPU-only).")
|
| 170 |
|
| 171 |
-
# ثابت اوپر Helplines panel
|
| 172 |
gr.Markdown(render_quick_helplines_md("ur"))
|
| 173 |
|
| 174 |
state = gr.State({"active": False, "step": 0, "scenario": None})
|
| 175 |
-
|
|
|
|
| 176 |
msg = gr.Textbox(label="پیغام / Message", placeholder="یہاں لکھیں…", lines=2)
|
| 177 |
send = gr.Button("Send / بھیجیں")
|
| 178 |
clear = gr.Button("Clear")
|
| 179 |
|
| 180 |
-
def
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
|
|
|
|
|
|
|
|
|
| 184 |
|
| 185 |
if __name__ == "__main__":
|
| 186 |
-
demo.queue(
|
| 187 |
server_name="0.0.0.0",
|
| 188 |
server_port=7860,
|
| 189 |
share=False
|
|
|
|
| 1 |
import os
|
| 2 |
import re
|
| 3 |
+
from typing import List, Tuple, Dict
|
|
|
|
| 4 |
from dataclasses import dataclass
|
| 5 |
|
| 6 |
+
import gradio as gr
|
| 7 |
import torch
|
| 8 |
from transformers import AutoTokenizer, AutoModelForCausalLM
|
| 9 |
|
|
|
|
| 57 |
|
| 58 |
def llm_reply(prompt: str, max_new_tokens: int = 100, temperature: float = 0.3) -> str:
|
| 59 |
if not (tok and model):
|
| 60 |
+
return ""
|
|
|
|
| 61 |
ids = tok.encode(prompt, return_tensors="pt")
|
| 62 |
out = model.generate(
|
| 63 |
ids,
|
|
|
|
| 66 |
do_sample=True,
|
| 67 |
pad_token_id=tok.eos_token_id,
|
| 68 |
)
|
| 69 |
+
gen_ids = out[0][ids.shape[1]:]
|
| 70 |
+
return tok.decode(gen_ids, skip_special_tokens=True).strip()
|
| 71 |
|
| 72 |
# ---------------- Helpline rendering ----------------
|
| 73 |
def _clean_phone_for_links(p: str) -> str:
|
|
|
|
| 109 |
lines.append(f"**{nm}**\n{ph}\n[📞 Call]({tel}) | [💬 WhatsApp]({wa})")
|
| 110 |
return "\n\n".join(lines)
|
| 111 |
|
| 112 |
+
# ---------------- Core prompt ----------------
|
| 113 |
SAFEPAK_SYSTEM = """
|
| 114 |
You are SafePak – 1122 Guide, a multilingual emergency disaster assistant.
|
| 115 |
+
Always reply in user's language (Urdu/English/regional).
|
| 116 |
+
Return medium-length, action-oriented checklists (5–7 bullets) and, if evacuation is implied or requested, append a Go-Bag sublist (4–8 items).
|
| 117 |
+
Never panic. Provide offline-safe steps. End with a calming line.
|
| 118 |
+
No personal data storage. No medical diagnoses (first aid only).
|
| 119 |
"""
|
| 120 |
|
| 121 |
def format_response(base: str, user_msg: str, lang: str) -> str:
|
|
|
|
| 123 |
f"<system>\n{SAFEPAK_SYSTEM}\n</system>\n"
|
| 124 |
f"<user>\n{user_msg}\n\nDraft response:\n{base}\n</user>"
|
| 125 |
)
|
| 126 |
+
refined = llm_reply(refine_prompt, max_new_tokens=100, temperature=0.3)
|
| 127 |
+
return refined if refined else base
|
| 128 |
|
| 129 |
+
# ---------------- Base checklist + Go-Bag ----------------
|
| 130 |
+
def base_checklist_and_bag(user_msg: str, lang: str) -> Tuple[str, List[str]]:
|
| 131 |
+
low = user_msg.lower()
|
| 132 |
+
evac = False
|
| 133 |
+
if any(k in low for k in ["fire","آگ","smoke"]):
|
| 134 |
+
evac = True
|
| 135 |
+
checklist = ("✅ ابھی یہ کریں:\n"
|
| 136 |
+
"- جھک جائیں/Stay low — دھواں اوپر جاتا ہے\n"
|
| 137 |
+
"- ناک/منہ پر گیلا کپڑا رکھیں\n"
|
| 138 |
+
"- اگر محفوظ ہو تو بجلی/گیس مین بند کریں\n"
|
| 139 |
+
"- گرم دروازہ مت کھولیں؛ دوسرا راستہ لیں\n"
|
| 140 |
+
"- سیڑھیاں استعمال کریں — لفٹ نہیں\n"
|
| 141 |
+
"- بچوں/بزرگوں کو ساتھ رکھیں\n"
|
| 142 |
+
"🕊️ گھبرائیں نہیں — میں آپ کے ساتھ ہوں۔"
|
| 143 |
+
) if lang=="ur" else (
|
| 144 |
+
"✅ Do this now:\n"
|
| 145 |
+
"- Stay low — smoke rises\n"
|
| 146 |
+
"- Wet cloth over nose/mouth\n"
|
| 147 |
+
"- Cut power/gas if safe\n"
|
| 148 |
+
"- Do not open hot doors; use alternate exit\n"
|
| 149 |
+
"- Use stairs, never elevators\n"
|
| 150 |
+
"- Keep kids/elderly close\n"
|
| 151 |
+
"🕊️ Stay calm — I’m with you."
|
| 152 |
+
)
|
| 153 |
+
bag = (["شناختی کارڈ/کاغذات","نقدی","موبائل+پاور بینک","پانی","خشک کھانا","دوائیں","ہلکی چادر","ٹارچ"]
|
| 154 |
+
if lang=="ur" else
|
| 155 |
+
["IDs/documents","Cash","Phone+power bank","Water","Dry food","Medicines","Light blanket","Flashlight"])
|
| 156 |
+
elif any(k in low for k in ["زلزلہ","earthquake","tremor","shaking"]):
|
| 157 |
+
evac = True
|
| 158 |
+
checklist = ("✅ ابھی یہ کریں:\n"
|
| 159 |
+
"- Drop, Cover, Hold — جھکیں، ڈھکیں، پکڑیں\n"
|
| 160 |
+
"- کھڑکیوں/بھاری اشیاء سے دور رہیں\n"
|
| 161 |
+
"- جھٹکے رکنے پر سیڑھیوں سے باہر نکلیں (لفٹ نہیں)\n"
|
| 162 |
+
"- کھلی جگہ میں رکیں\n"
|
| 163 |
+
"🕊️ حوصلہ رکھیں — میں آپ کے ساتھ ہوں۔"
|
| 164 |
+
) if lang=="ur" else (
|
| 165 |
+
"✅ Do this now:\n"
|
| 166 |
+
"- Drop, Cover, Hold On\n"
|
| 167 |
+
"- Stay away from windows/heavy objects\n"
|
| 168 |
+
"- After shaking, exit via stairs (no elevators)\n"
|
| 169 |
+
"- Wait in an open safe area\n"
|
| 170 |
+
"🕊️ Stay calm — I’m with you."
|
| 171 |
+
)
|
| 172 |
+
bag = (["شناختی کارڈ/کاغذات","موبائل+پاور بینک","پانی","خشک کھانا","دوائیں","وسل","چھوٹی فرسٹ ایڈ","ٹارچ"]
|
| 173 |
+
if lang=="ur" else
|
| 174 |
+
["IDs/documents","Phone+power bank","Water","Dry food","Medicines","Whistle","Small first-aid","Flashlight"])
|
| 175 |
+
elif any(k in low for k in ["سیلاب","flood","overflow","water entering","طوفان","storm","آندھی"]):
|
| 176 |
+
evac = True
|
| 177 |
+
checklist = ("✅ ابھی یہ کریں:\n"
|
| 178 |
+
"- اگر محفوظ ہو تو بجلی مین سوئچ بند کریں\n"
|
| 179 |
+
"- اونچی جگہ/چھت پر منتقل ہوں\n"
|
| 180 |
+
"- پانی میں گاڑی نہ چلائیں\n"
|
| 181 |
+
"- بچوں/بزرگوں کو پہلے نکالیں\n"
|
| 182 |
+
"🕊️ گھبرائیں نہیں — آپ محفوظ نکل سکتے ہیں۔"
|
| 183 |
+
) if lang=="ur" else (
|
| 184 |
+
"✅ Do this now:\n"
|
| 185 |
+
"- Turn off main power if safe\n"
|
| 186 |
+
"- Move to higher ground/roof\n"
|
| 187 |
+
"- Do not drive through water\n"
|
| 188 |
+
"- Evacuate kids/elderly first\n"
|
| 189 |
+
"🕊️ Stay calm — you can get to safety."
|
| 190 |
+
)
|
| 191 |
+
bag = (["شناختی کارڈ/کاغذات","نقدی","موبائل+پاور بینک","پانی","خشک کھانا","دوائیں","واٹر پروف بیگ","چپل/بوٹس"]
|
| 192 |
+
if lang=="ur" else
|
| 193 |
+
["IDs/documents","Cash","Phone+power bank","Water","Dry food","Medicines","Waterproof pouches","Boots/Sandals"])
|
| 194 |
+
elif any(k in low for k in ["gas","گیس","leak","smell gas","بو"]):
|
| 195 |
+
checklist = ("✅ ابھی یہ کریں:\n"
|
| 196 |
+
"- کوئی چنگاری/سوئچ/لائٹر استعمال نہ کریں\n"
|
| 197 |
+
"- کھڑکیاں/دروازے کھول کر ہوا دار کریں\n"
|
| 198 |
+
"- گیس مین والو بند کریں\n"
|
| 199 |
+
"- محفوظ فاصلے پر چلے جائیں\n"
|
| 200 |
+
"🕊️ پرسکون رہیں — میں رہنمائی کر رہا/رہی ہوں۔"
|
| 201 |
+
) if lang=="ur" else (
|
| 202 |
+
"✅ Do this now:\n"
|
| 203 |
+
"- No sparks (no switches/lighters/flash)\n"
|
| 204 |
+
"- Ventilate: open windows/doors\n"
|
| 205 |
+
"- Shut the main gas valve\n"
|
| 206 |
+
"- Move to a safe distance\n"
|
| 207 |
+
"🕊️ Stay calm — I’m guiding you."
|
| 208 |
+
)
|
| 209 |
+
bag = (["ماسک/گیلا کپڑا","شناختی کارڈ","موبائل+پاور بینک","پانی","دوائیں"]
|
| 210 |
+
if lang=="ur" else
|
| 211 |
+
["Mask/wet cloth","IDs","Phone+power bank","Water","Medicines"])
|
| 212 |
+
elif any(k in low for k in ["injury","زخمی","bleeding","cut","fracture","burn"]):
|
| 213 |
+
checklist = ("✅ ابھی یہ کریں:\n"
|
| 214 |
+
"- خون ہو تو مضبوط دباؤ دیں (صاف کپڑا)\n"
|
| 215 |
+
"- زخم صاف پانی سے دھوئیں\n"
|
| 216 |
+
"- گہرا زخم/زیادہ خون ہو تو فوری مدد لیں\n"
|
| 217 |
+
"- گردن/کمر چوٹ میں مریض کو نہ ہلائیں\n"
|
| 218 |
+
"🕊️ پرسکون رہیں — آپ سنبھال سکتے ہیں۔"
|
| 219 |
+
) if lang=="ur" else (
|
| 220 |
+
"✅ Do this now:\n"
|
| 221 |
+
"- Apply firm direct pressure (clean cloth)\n"
|
| 222 |
+
"- Rinse with clean water\n"
|
| 223 |
+
"- Deep/heavy bleeding → seek urgent help\n"
|
| 224 |
+
"- Suspected spine injury: do not move\n"
|
| 225 |
+
"🕊️ Stay calm — you’ve got this."
|
| 226 |
+
)
|
| 227 |
+
bag = (["فرسٹ ایڈ کٹ","صاف کپڑا/بینڈیج","پانی","درد کش دوا","شناختی کارڈ"]
|
| 228 |
+
if lang=="ur" else
|
| 229 |
+
["First-aid kit","Clean cloth/bandage","Water","Pain reliever","ID"])
|
| 230 |
+
else:
|
| 231 |
+
checklist = ("✅ فوری رہنمائی:\n"
|
| 232 |
+
"- اردگرد خطرات پہچانیں (بجلی/گیس/دھواں/پانی)\n"
|
| 233 |
+
"- محفوظ کور یا اخراج کا راستہ منتخب کریں\n"
|
| 234 |
+
"- بچوں/بزرگوں کو ساتھ رکھیں\n"
|
| 235 |
+
"- لفٹ سے پرہیز کریں\n"
|
| 236 |
+
"🕊️ گھبرائیں نہیں — میں آپ کے ساتھ ہوں۔"
|
| 237 |
+
) if lang=="ur" else (
|
| 238 |
+
"✅ General guidance:\n"
|
| 239 |
+
"- Identify hazards (electricity/gas/smoke/water)\n"
|
| 240 |
+
"- Choose safe cover or exit route\n"
|
| 241 |
+
"- Keep kids/elderly close\n"
|
| 242 |
+
"- Avoid elevators\n"
|
| 243 |
+
"🕊️ Stay calm — I’m with you."
|
| 244 |
+
)
|
| 245 |
+
evac = True
|
| 246 |
+
bag = (["شناختی کارڈ/کاغذات","نقدی","فون+پاور بینک","پانی","خشک کھانا","دوائیں"]
|
| 247 |
+
if lang=="ur" else
|
| 248 |
+
["IDs/documents","Cash","Phone+power bank","Water","Dry food","Medicines"])
|
| 249 |
+
if evac:
|
| 250 |
+
if lang=="ur":
|
| 251 |
+
checklist += "\n\n🎒 ساتھ کیا لیں (Go-Bag):\n" + "\n".join(f"- {i}" for i in bag)
|
| 252 |
+
else:
|
| 253 |
+
checklist += "\n\n🎒 Take with you (Go-Bag):\n" + "\n".join(f"- {i}" for i in bag)
|
| 254 |
+
return checklist, bag
|
| 255 |
+
|
| 256 |
+
# ---------------- Chat logic (messages format) ----------------
|
| 257 |
+
def chat_fn(user_msg: str, chat_messages: List[Dict[str,str]], sim_state: dict):
|
| 258 |
if not user_msg:
|
| 259 |
+
return chat_messages, sim_state
|
| 260 |
+
|
| 261 |
lang = detect_lang(user_msg)
|
| 262 |
+
status, _ = GUARD.check(user_msg)
|
| 263 |
|
| 264 |
# BLOCK
|
| 265 |
if status == "BLOCK":
|
| 266 |
msg = GUARD.refusal_msg_ur if lang == "ur" else GUARD.refusal_msg_en
|
| 267 |
+
msg += "\n\n" + helplines_block(lang)
|
| 268 |
+
return chat_messages + [
|
| 269 |
+
{"role":"user","content":user_msg},
|
| 270 |
+
{"role":"assistant","content":msg}
|
| 271 |
+
], sim_state
|
| 272 |
|
| 273 |
+
# Build base checklist + go-bag
|
| 274 |
+
base, _ = base_checklist_and_bag(user_msg, lang)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 275 |
|
| 276 |
+
# SOFT prepend note
|
| 277 |
if status == "SOFT":
|
| 278 |
+
base = ("⚠️ محتاط رہیں: یہ موضوع حساس ہے۔\n\n" + base) if lang=="ur" else ("⚠️ Note: sensitive topic.\n\n" + base)
|
|
|
|
|
|
|
|
|
|
| 279 |
|
| 280 |
+
# Refine with LLM (medium length). If model unavailable, keep base.
|
| 281 |
+
final = format_response(base, user_msg, lang)
|
| 282 |
final += "\n\n" + helplines_block(lang)
|
| 283 |
+
|
| 284 |
+
return chat_messages + [
|
| 285 |
+
{"role":"user","content":user_msg},
|
| 286 |
+
{"role":"assistant","content":final}
|
| 287 |
+
], sim_state
|
| 288 |
|
| 289 |
# ---------------- UI ----------------
|
| 290 |
with gr.Blocks(title="SafePak – 1122 Guide") as demo:
|
| 291 |
gr.Markdown("## SafePak – 1122 Guide\nMultilingual emergency assistant (CPU-only).")
|
| 292 |
|
|
|
|
| 293 |
gr.Markdown(render_quick_helplines_md("ur"))
|
| 294 |
|
| 295 |
state = gr.State({"active": False, "step": 0, "scenario": None})
|
| 296 |
+
|
| 297 |
+
chatbot = gr.Chatbot(height=420, type="messages")
|
| 298 |
msg = gr.Textbox(label="پیغام / Message", placeholder="یہاں لکھیں…", lines=2)
|
| 299 |
send = gr.Button("Send / بھیجیں")
|
| 300 |
clear = gr.Button("Clear")
|
| 301 |
|
| 302 |
+
def on_submit(u, h, s):
|
| 303 |
+
new_h, new_s = chat_fn(u, h, s)
|
| 304 |
+
return new_h, "", new_s
|
| 305 |
+
|
| 306 |
+
msg.submit(on_submit, [msg, chatbot, state], [chatbot, msg, state])
|
| 307 |
+
send.click(on_submit, [msg, chatbot, state], [chatbot, msg, state])
|
| 308 |
+
clear.click(lambda: ([], {"active": False, "step": 0, "scenario": None}), [], [chatbot, state])
|
| 309 |
|
| 310 |
if __name__ == "__main__":
|
| 311 |
+
demo.queue().launch(
|
| 312 |
server_name="0.0.0.0",
|
| 313 |
server_port=7860,
|
| 314 |
share=False
|