adham-Ashraf commited on
Commit
75f5f97
Β·
verified Β·
1 Parent(s): 2a19c76

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +82 -27
app.py CHANGED
@@ -38,12 +38,9 @@ MEMORY_FILE = "navigation_memory.json"
38
  GRID_0_FILE = "floor_0_grid.npy"
39
  GRID_1_FILE = "floor_0_grid.npy"
40
 
41
- OPENROUTER_KEY =os.getenv("OPENROUTER_KEY")
42
- OPENROUTER_MODEL = "arcee-ai/trinity-large-preview:free"
43
 
44
- # ============================================================
45
- # DATA LOADING
46
- # ============================================================
47
  def load_json_file(path, default):
48
  try:
49
  with open(path, "r", encoding="utf-8") as f:
@@ -232,7 +229,7 @@ Mall stores:
232
  Rules:
233
  - If the user asks about a store, answer with store information.
234
  - If the user asks for navigation, help them navigate.
235
- - If the user says they are hungry, suggest kitchen / dining / food-related stores.
236
  - Keep answers concise and helpful.
237
  """
238
 
@@ -474,17 +471,25 @@ def save_navigation(username, start_room, dest_room):
474
  # ============================================================
475
  # STORE RECOMMENDATION
476
  # ============================================================
477
- def nearest_store(user_pos):
478
  best_room = None
479
  best_dist = float("inf")
 
480
  for _, room in STORE_CLUSTER_ROOM.items():
 
 
 
 
481
  centroid = get_centroid(room)
482
  if centroid is None:
483
  continue
 
484
  dist = np.sqrt((user_pos[0] - centroid[0]) ** 2 + (user_pos[1] - centroid[1]) ** 2)
 
485
  if dist < best_dist:
486
  best_dist = dist
487
  best_room = room
 
488
  return best_room
489
 
490
 
@@ -1012,8 +1017,7 @@ def chatbot_respond(user_text, history, session):
1012
  bot = f"{info}\n\nWould you like navigation to {ROOM_INFO[info_room]} (Room {info_room})?"
1013
  session["last_referenced_room"] = info_room
1014
  session["last_dest_room"] = info_room
1015
- history.append({"role": "user", "content": user_text})
1016
- history.append({"role": "assistant", "content": bot})
1017
  try:
1018
  gTTS(bot).save("/content/voice.mp3")
1019
  except Exception:
@@ -1168,12 +1172,12 @@ def recommend_store_for_session(session):
1168
  return "<div style='color:#ff6b6b;font-family:monospace'>❌ Please enter your current location first.</div>", session
1169
 
1170
  if session.get("is_new", True):
1171
- room = nearest_store(session["start_xy"])
1172
  msg = "πŸ†• New user β†’ Nearest store recommended"
1173
  else:
1174
  room = most_visited_store(session["username"])
1175
  if room is None:
1176
- room = nearest_store(session["start_xy"])
1177
  msg = "πŸ” Returning user β†’ Most visited store recommended"
1178
 
1179
  store_name = ROOM_INFO.get(room, f"Room {room}")
@@ -1221,13 +1225,18 @@ def handle_agreement(choice, session):
1221
 
1222
  def do_navigate(choice, type_name, cat_name, sub_name, nav_mode_val, danger_room, session):
1223
  session = set_session_defaults(session)
 
1224
  if not session.get("username"):
1225
  return "❌ Please login first.", None
 
1226
  if session.get("start_xy") is None or session.get("start_floor") is None:
1227
  return "❌ Please set your location first.", None
1228
 
1229
  reset_grids()
1230
 
 
 
 
1231
  if "Yes" in (choice or ""):
1232
  dest_room = session.get("recommended_room")
1233
  if dest_room is None:
@@ -1235,15 +1244,29 @@ def do_navigate(choice, type_name, cat_name, sub_name, nav_mode_val, danger_room
1235
  else:
1236
  if not sub_name:
1237
  return "❌ Please select a sub-category.", None
 
1238
  parent = SUB_TO_CATEGORY.get(sub_name, cat_name)
1239
  store = STORE_CLUSTER.get(parent, parent)
1240
  dest_room = STORE_CLUSTER_ROOM.get(store)
 
1241
  if dest_room is None:
1242
  return "❌ Could not map the selected category to a store.", None
1243
 
1244
  session["dest_room"] = dest_room
1245
- session["nav_mode"] = nav_mode_val
1246
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1247
  room_val = None
1248
  try:
1249
  if danger_room is not None and str(danger_room).strip() != "":
@@ -1261,32 +1284,55 @@ def do_navigate(choice, type_name, cat_name, sub_name, nav_mode_val, danger_room
1261
  fire_center = None
1262
  crowded_center = None
1263
 
1264
- if nav_mode_val == "Fire" and room_val is not None and room_val in ROOM_INFO:
1265
  fire_active = True
1266
  fire_room = room_val
1267
  fire_center = get_centroid(room_val)
 
1268
  if fire_center is not None:
1269
  fire_step += 1
1270
  radius = 20 + fire_step * 6
 
1271
  if get_floor(room_val) == 0:
1272
  mark_danger(grid_0, fire_center, radius)
1273
  else:
1274
  mark_danger(grid_1, fire_center, radius)
1275
 
1276
- if nav_mode_val == "Crowded" and room_val is not None and room_val in ROOM_INFO:
1277
  crowded_active = True
1278
  crowded_room = room_val
1279
  crowded_center = get_centroid(room_val)
 
1280
  if crowded_center is not None:
1281
  if get_floor(room_val) == 0:
1282
  mark_crowd(grid_0, crowded_center)
1283
  else:
1284
  mark_crowd(grid_1, crowded_center)
1285
 
1286
- save_navigation(session["username"], (session["start_floor"], session["start_xy"]), dest_room)
1287
- save_navigation_mem((session["start_floor"], session["start_xy"]), dest_room)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1288
 
1289
- img_path, instructions = navigate(session["start_floor"], session["start_xy"], dest_room, nav_mode_val)
1290
  return instructions, img_path
1291
 
1292
 
@@ -1351,6 +1397,11 @@ with gr.Blocks(
1351
  auth_name = gr.Textbox(label="Full Name (signup only)", placeholder="John Doe")
1352
  auth_age = gr.Number(label="Age (signup only)", value=25)
1353
  auth_gender = gr.Dropdown(["male", "female", "other"], label="Gender (signup only)", value="male")
 
 
 
 
 
1354
  auth_budget_l = gr.Number(label="Min Budget EGP (signup only)", value=500)
1355
  auth_budget_h = gr.Number(label="Max Budget EGP (signup only)", value=5000)
1356
 
@@ -1359,7 +1410,7 @@ with gr.Blocks(
1359
  login_btn = gr.Button("LOGIN", variant="secondary")
1360
  auth_status = gr.HTML()
1361
 
1362
- def do_signup(username, password, name, age, gender, low, high, session):
1363
  cursor.execute("SELECT username FROM users WHERE username=?", (username,))
1364
  if cursor.fetchone():
1365
  return "<div style='color:#ff6b6b;font-family:monospace'>❌ Username already exists.</div>", session
@@ -1370,6 +1421,8 @@ with gr.Blocks(
1370
  conn.commit()
1371
  session = set_session_defaults(session)
1372
  session.update({"username": username, "gender": gender, "low": low, "high": high, "is_new": True})
 
 
1373
  return f"<div style='color:#00ff88;font-family:monospace'>βœ… Welcome, {name}! Account created.</div>", session
1374
 
1375
  def do_login(username, password, session):
@@ -1381,7 +1434,11 @@ with gr.Blocks(
1381
  session.update({"username": user[0], "gender": user[4], "low": user[5], "high": user[6], "is_new": False})
1382
  return f"<div style='color:#00ff88;font-family:monospace'>βœ… Welcome back, {user[2]}!</div>", session
1383
 
1384
- signup_btn.click(do_signup, [auth_username, auth_password, auth_name, auth_age, auth_gender, auth_budget_l, auth_budget_h, session_state], [auth_status, session_state])
 
 
 
 
1385
  login_btn.click(do_login, [auth_username, auth_password, session_state], [auth_status, session_state])
1386
 
1387
  # ----------------------------------------------------
@@ -1454,16 +1511,14 @@ with gr.Blocks(
1454
  gr.HTML("<div style='color:#00d4ff;font-family:monospace;font-size:13px;margin-bottom:16px'>Chat with the mall AI assistant</div>")
1455
 
1456
  chatbot_widget = gr.Chatbot(
1457
- label="SmartMall Assistant",
1458
- height=480,
1459
- value=[
1460
- {"role": "assistant", "content": "πŸ‘‹ Welcome to SmartMall! I can help you navigate, find products, or answer any questions. How can I help?"}
1461
- ],
1462
- )
1463
 
1464
  with gr.Row():
1465
  chat_msg = gr.Textbox(placeholder="Ask me anything about the mall...", label="Message", scale=4)
1466
- chat_mic = gr.Audio(sources=["microphone"], type="filepath", label="🎀", scale=1)
1467
 
1468
  chat_audio_out = gr.Audio(label="Voice Response")
1469
  chat_img_out = gr.Image(label="Navigation Map", type="filepath")
@@ -1485,4 +1540,4 @@ with gr.Blocks(
1485
  chat_mic.change(voice_chat, [chat_mic, chatbot_widget, session_state], [chatbot_widget, chat_img_out, chat_audio_out, session_state])
1486
 
1487
  if __name__ == "__main__":
1488
- demo.launch(share=True)
 
38
  GRID_0_FILE = "floor_0_grid.npy"
39
  GRID_1_FILE = "floor_0_grid.npy"
40
 
41
+ OPENROUTER_KEY = "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"
42
+ OPENROUTER_MODEL = "tencent/hy3-preview:free"
43
 
 
 
 
44
  def load_json_file(path, default):
45
  try:
46
  with open(path, "r", encoding="utf-8") as f:
 
229
  Rules:
230
  - If the user asks about a store, answer with store information.
231
  - If the user asks for navigation, help them navigate.
232
+ - If the user says he is hungry, suggest kitchen / dining / food-related stores and when he tells you that he agree os suggestion then help him navigate.
233
  - Keep answers concise and helpful.
234
  """
235
 
 
471
  # ============================================================
472
  # STORE RECOMMENDATION
473
  # ============================================================
474
+ def nearest_store(user_pos, user_floor):
475
  best_room = None
476
  best_dist = float("inf")
477
+
478
  for _, room in STORE_CLUSTER_ROOM.items():
479
+ # βœ… فلΨͺΨ±Ψ© ΨΉΩ„Ω‰ نفس Ψ§Ω„Ψ―ΩˆΨ±
480
+ if get_floor(room) != user_floor:
481
+ continue
482
+
483
  centroid = get_centroid(room)
484
  if centroid is None:
485
  continue
486
+
487
  dist = np.sqrt((user_pos[0] - centroid[0]) ** 2 + (user_pos[1] - centroid[1]) ** 2)
488
+
489
  if dist < best_dist:
490
  best_dist = dist
491
  best_room = room
492
+
493
  return best_room
494
 
495
 
 
1017
  bot = f"{info}\n\nWould you like navigation to {ROOM_INFO[info_room]} (Room {info_room})?"
1018
  session["last_referenced_room"] = info_room
1019
  session["last_dest_room"] = info_room
1020
+ history.append((user_text, bot))
 
1021
  try:
1022
  gTTS(bot).save("/content/voice.mp3")
1023
  except Exception:
 
1172
  return "<div style='color:#ff6b6b;font-family:monospace'>❌ Please enter your current location first.</div>", session
1173
 
1174
  if session.get("is_new", True):
1175
+ room = nearest_store(session["start_xy"], session["start_floor"])
1176
  msg = "πŸ†• New user β†’ Nearest store recommended"
1177
  else:
1178
  room = most_visited_store(session["username"])
1179
  if room is None:
1180
+ room = nearest_store(session["start_xy"], session["start_floor"])
1181
  msg = "πŸ” Returning user β†’ Most visited store recommended"
1182
 
1183
  store_name = ROOM_INFO.get(room, f"Room {room}")
 
1225
 
1226
  def do_navigate(choice, type_name, cat_name, sub_name, nav_mode_val, danger_room, session):
1227
  session = set_session_defaults(session)
1228
+
1229
  if not session.get("username"):
1230
  return "❌ Please login first.", None
1231
+
1232
  if session.get("start_xy") is None or session.get("start_floor") is None:
1233
  return "❌ Please set your location first.", None
1234
 
1235
  reset_grids()
1236
 
1237
+ # =========================================================
1238
+ # DESTINATION SELECTION
1239
+ # =========================================================
1240
  if "Yes" in (choice or ""):
1241
  dest_room = session.get("recommended_room")
1242
  if dest_room is None:
 
1244
  else:
1245
  if not sub_name:
1246
  return "❌ Please select a sub-category.", None
1247
+
1248
  parent = SUB_TO_CATEGORY.get(sub_name, cat_name)
1249
  store = STORE_CLUSTER.get(parent, parent)
1250
  dest_room = STORE_CLUSTER_ROOM.get(store)
1251
+
1252
  if dest_room is None:
1253
  return "❌ Could not map the selected category to a store.", None
1254
 
1255
  session["dest_room"] = dest_room
 
1256
 
1257
+ # =========================================================
1258
+ # NAVIGATION MODE (FIXED LOGIC)
1259
+ # =========================================================
1260
+ if session.get("special_needs"):
1261
+ effective_mode = "Special Needs"
1262
+ else:
1263
+ effective_mode = nav_mode_val
1264
+
1265
+ session["nav_mode"] = effective_mode
1266
+
1267
+ # =========================================================
1268
+ # DANGER / CROWD HANDLING
1269
+ # =========================================================
1270
  room_val = None
1271
  try:
1272
  if danger_room is not None and str(danger_room).strip() != "":
 
1284
  fire_center = None
1285
  crowded_center = None
1286
 
1287
+ if effective_mode == "Fire" and room_val is not None and room_val in ROOM_INFO:
1288
  fire_active = True
1289
  fire_room = room_val
1290
  fire_center = get_centroid(room_val)
1291
+
1292
  if fire_center is not None:
1293
  fire_step += 1
1294
  radius = 20 + fire_step * 6
1295
+
1296
  if get_floor(room_val) == 0:
1297
  mark_danger(grid_0, fire_center, radius)
1298
  else:
1299
  mark_danger(grid_1, fire_center, radius)
1300
 
1301
+ if effective_mode == "Crowded" and room_val is not None and room_val in ROOM_INFO:
1302
  crowded_active = True
1303
  crowded_room = room_val
1304
  crowded_center = get_centroid(room_val)
1305
+
1306
  if crowded_center is not None:
1307
  if get_floor(room_val) == 0:
1308
  mark_crowd(grid_0, crowded_center)
1309
  else:
1310
  mark_crowd(grid_1, crowded_center)
1311
 
1312
+ # =========================================================
1313
+ # SAVE HISTORY
1314
+ # =========================================================
1315
+ save_navigation(
1316
+ session["username"],
1317
+ (session["start_floor"], session["start_xy"]),
1318
+ dest_room
1319
+ )
1320
+
1321
+ save_navigation_mem(
1322
+ f"floor={session['start_floor']},x={session['start_xy'][0]},y={session['start_xy'][1]}",
1323
+ dest_room
1324
+ )
1325
+
1326
+ # =========================================================
1327
+ # NAVIGATION CALL (IMPORTANT FIX)
1328
+ # =========================================================
1329
+ img_path, instructions = navigate(
1330
+ session["start_floor"],
1331
+ session["start_xy"],
1332
+ dest_room,
1333
+ effective_mode
1334
+ )
1335
 
 
1336
  return instructions, img_path
1337
 
1338
 
 
1397
  auth_name = gr.Textbox(label="Full Name (signup only)", placeholder="John Doe")
1398
  auth_age = gr.Number(label="Age (signup only)", value=25)
1399
  auth_gender = gr.Dropdown(["male", "female", "other"], label="Gender (signup only)", value="male")
1400
+ special_needs = gr.Radio(
1401
+ ["No", "Yes"],
1402
+ label="Are you a person with special needs?",
1403
+ value="No"
1404
+ )
1405
  auth_budget_l = gr.Number(label="Min Budget EGP (signup only)", value=500)
1406
  auth_budget_h = gr.Number(label="Max Budget EGP (signup only)", value=5000)
1407
 
 
1410
  login_btn = gr.Button("LOGIN", variant="secondary")
1411
  auth_status = gr.HTML()
1412
 
1413
+ def do_signup(username, password, name, age, gender, low, high,special, session):
1414
  cursor.execute("SELECT username FROM users WHERE username=?", (username,))
1415
  if cursor.fetchone():
1416
  return "<div style='color:#ff6b6b;font-family:monospace'>❌ Username already exists.</div>", session
 
1421
  conn.commit()
1422
  session = set_session_defaults(session)
1423
  session.update({"username": username, "gender": gender, "low": low, "high": high, "is_new": True})
1424
+ session["special_needs"] = (special == "Yes")
1425
+ session["nav_mode"] = "Special Needs" if special == "Yes" else "Normal"
1426
  return f"<div style='color:#00ff88;font-family:monospace'>βœ… Welcome, {name}! Account created.</div>", session
1427
 
1428
  def do_login(username, password, session):
 
1434
  session.update({"username": user[0], "gender": user[4], "low": user[5], "high": user[6], "is_new": False})
1435
  return f"<div style='color:#00ff88;font-family:monospace'>βœ… Welcome back, {user[2]}!</div>", session
1436
 
1437
+ signup_btn.click(
1438
+ do_signup,
1439
+ [auth_username, auth_password, auth_name, auth_age, auth_gender, auth_budget_l, auth_budget_h, special_needs, session_state],
1440
+ [auth_status, session_state]
1441
+ )
1442
  login_btn.click(do_login, [auth_username, auth_password, session_state], [auth_status, session_state])
1443
 
1444
  # ----------------------------------------------------
 
1511
  gr.HTML("<div style='color:#00d4ff;font-family:monospace;font-size:13px;margin-bottom:16px'>Chat with the mall AI assistant</div>")
1512
 
1513
  chatbot_widget = gr.Chatbot(
1514
+ label="SmartMall Assistant",
1515
+ height=480,
1516
+ value=[("", "πŸ‘‹ Welcome to SmartMall! I can help you navigate, find products, or answer any questions. How can I help?")],
1517
+ )
 
 
1518
 
1519
  with gr.Row():
1520
  chat_msg = gr.Textbox(placeholder="Ask me anything about the mall...", label="Message", scale=4)
1521
+ chat_mic = gr.Audio(source="microphone", type="filepath", label="🎀", scale=1)
1522
 
1523
  chat_audio_out = gr.Audio(label="Voice Response")
1524
  chat_img_out = gr.Image(label="Navigation Map", type="filepath")
 
1540
  chat_mic.change(voice_chat, [chat_mic, chatbot_widget, session_state], [chatbot_widget, chat_img_out, chat_audio_out, session_state])
1541
 
1542
  if __name__ == "__main__":
1543
+ demo.launch()