NimrodDev commited on
Commit
b3fba9f
·
1 Parent(s): cf4aad5
Files changed (1) hide show
  1. app.py +43 -26
app.py CHANGED
@@ -233,6 +233,9 @@ def finalize_booking(user: str) -> str:
233
  return f"All set — your booking is confirmed with code {code}. We’ll call you shortly to confirm details."
234
 
235
  # ---------- Core reply engine ----------
 
 
 
236
  def secretary_reply(text: str, user: str = "unknown") -> str:
237
  raw = text or ""
238
  t = normalize(raw)
@@ -260,16 +263,7 @@ def secretary_reply(text: str, user: str = "unknown") -> str:
260
  return friendly(LAMAKI_SERVICES)
261
  return friendly(LD_EVENTS_SERVICES)
262
 
263
- # --- Event-type suggestions ---
264
- for event, packages in EVENT_TYPES.items():
265
- if event in t:
266
- suggestions = []
267
- for p in packages:
268
- p_norm = normalize(p)
269
- suggestions.append(f"- {p}: {REPLY.get(p_norm, '')}")
270
- return friendly(f"For a {event} we recommend:\n" + "\n".join(suggestions) + "\nWhich one would you like?")
271
-
272
- # --- Tent guest detection (e.g., "tent for 250 people") ---
273
  m = re.search(r"(tent|tents?).{0,20}?(\d{1,4})", raw, flags=re.I)
274
  if m:
275
  guests = int(m.group(2))
@@ -294,7 +288,6 @@ def secretary_reply(text: str, user: str = "unknown") -> str:
294
 
295
  # --- Price / Cost enquiries ---
296
  if any(w in t for w in ("price", "cost", "how much", "rates", "fee", "charge")):
297
- # if user previously selected an item
298
  last = LAST_ITEM.get(user)
299
  if last and normalize(last) in REPLY:
300
  return friendly(REPLY[normalize(last)])
@@ -305,31 +298,60 @@ def secretary_reply(text: str, user: str = "unknown") -> str:
305
  return friendly(REPLY[key])
306
  return friendly("Please tell me which item or package you'd like the price for (e.g., 'gold package' or 'double 18').")
307
 
308
- # --- Alias matching ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  for alias, key in ITEM_ALIASES.items():
310
  if alias in t:
311
  LAST_ITEM[user] = key
312
- return friendly(REPLY.get(normalize(key), f"I found {key}. {REPLY.get(normalize(key),'Price not in catalog.')}"))
 
 
 
313
 
314
- # --- Exact REPLY keys match (packages/items) ---
315
  for k in list(REPLY.keys()):
316
  if k in t:
317
  LAST_ITEM[user] = k
 
318
  if "package" in k or "combo" in k:
319
- add_booking_text = " If you'd like to book this, tell me the date, approximate guest count, and the venue."
320
- return friendly(REPLY[k] + add_booking_text)
321
- return friendly(REPLY[k])
 
 
 
 
 
 
 
322
 
323
- # --- Booking: start booking when user asks to book / schedule / reserve ---
 
 
 
 
 
 
324
  if re.search(r"\b(book|reserve|schedule|site visit|site-visit|sitevisit)\b", t):
325
- # detect site visit vs event booking
326
  if "site" in t:
327
  return friendly(start_booking(user, "site_visit"))
328
  if "consult" in t:
329
  return friendly(start_booking(user, "consultation"))
330
  return friendly(start_booking(user, "event_booking"))
331
 
332
- # --- Adding booking details: date / guests / location ---
333
  dt = find_date_in_text(raw)
334
  if dt:
335
  add_booking_detail(user, "date", dt)
@@ -347,12 +369,10 @@ def secretary_reply(text: str, user: str = "unknown") -> str:
347
  add_booking_detail(user, "location", loc)
348
  return friendly(f"Noted venue: {loc}. Any special requests or additional gear?")
349
 
350
- # --- finalize booking request ---
351
  if any(pat in t for pat in ("confirm booking", "finalize booking", "complete booking", "confirm reservation", "confirm my booking")):
352
  res = finalize_booking(user)
353
  return friendly(res)
354
 
355
- # --- Check booking by code (8 hex chars) ---
356
  mcode = re.search(r"\b([A-F0-9]{8})\b", raw, flags=re.I)
357
  if mcode:
358
  code = mcode.group(1).upper()
@@ -361,17 +381,14 @@ def secretary_reply(text: str, user: str = "unknown") -> str:
361
  return friendly(f"Booking {code} was created on {info.get('confirmed_at')}. Details: {info}")
362
  return friendly("Sorry, I can't find that booking code. Please check and send it again.")
363
 
364
- # --- Lamaki construction queries fallback ---
365
  if any(w in t for w in LAMAKI_WORDS):
366
  return friendly(LAMAKI_SERVICES)
367
 
368
- # --- Short ambiguous inputs prompt ---
369
  if len(t.split()) <= 2:
370
  return friendly("Could you provide a few more details? For example: 'price for silver package' or 'book site visit 2025-12-05 200 guests at ABC Hall'.")
371
 
372
- # --- Default fallback helpful prompt ---
373
  return friendly("I’m here to help — tell me the item, package, or service you want and I’ll assist from there.")
374
- # PART 4/4
375
  """
376
  Flask endpoints, health check, and run instructions.
377
  """
 
233
  return f"All set — your booking is confirmed with code {code}. We’ll call you shortly to confirm details."
234
 
235
  # ---------- Core reply engine ----------
236
+ # ---------- Core reply engine (improved) ----------
237
+ from difflib import get_close_matches
238
+
239
  def secretary_reply(text: str, user: str = "unknown") -> str:
240
  raw = text or ""
241
  t = normalize(raw)
 
263
  return friendly(LAMAKI_SERVICES)
264
  return friendly(LD_EVENTS_SERVICES)
265
 
266
+ # --- Tent guest detection ---
 
 
 
 
 
 
 
 
 
267
  m = re.search(r"(tent|tents?).{0,20}?(\d{1,4})", raw, flags=re.I)
268
  if m:
269
  guests = int(m.group(2))
 
288
 
289
  # --- Price / Cost enquiries ---
290
  if any(w in t for w in ("price", "cost", "how much", "rates", "fee", "charge")):
 
291
  last = LAST_ITEM.get(user)
292
  if last and normalize(last) in REPLY:
293
  return friendly(REPLY[normalize(last)])
 
298
  return friendly(REPLY[key])
299
  return friendly("Please tell me which item or package you'd like the price for (e.g., 'gold package' or 'double 18').")
300
 
301
+ # --- Generic gear suggestions ---
302
+ if "mixer" in t:
303
+ options = ["mixer wing", "mixer skytone"]
304
+ suggestions = "\n".join(f"- {opt}: {REPLY[normalize(opt)]}" for opt in options)
305
+ return friendly(f"We have the following mixers:\n{suggestions}")
306
+
307
+ if "line array" in t or "line arrays" in t:
308
+ return friendly(REPLY.get("line array", "Line arrays are available — please specify how many or which combo you want."))
309
+
310
+ if "sub" in t or "18" in t:
311
+ subs = ["single 18", "double 18"]
312
+ suggestions = "\n".join(f"- {opt}: {REPLY[normalize(opt)]}" for opt in subs)
313
+ return friendly(f"We have the following subwoofers:\n{suggestions}")
314
+
315
+ # --- Alias matching (safe) ---
316
  for alias, key in ITEM_ALIASES.items():
317
  if alias in t:
318
  LAST_ITEM[user] = key
319
+ reply_text = REPLY.get(normalize(key))
320
+ if not reply_text:
321
+ reply_text = f"I found {key}, but price/description not available."
322
+ return friendly(reply_text)
323
 
324
+ # --- Exact REPLY keys match ---
325
  for k in list(REPLY.keys()):
326
  if k in t:
327
  LAST_ITEM[user] = k
328
+ base = REPLY[k]
329
  if "package" in k or "combo" in k:
330
+ base += " If you'd like to book this, tell me the date, approximate guest count, and venue."
331
+ return friendly(base)
332
+
333
+ # --- Fuzzy matching ---
334
+ def fuzzy_lookup(text):
335
+ keys = list(REPLY.keys()) + list(ITEM_ALIASES.keys())
336
+ matches = get_close_matches(text, keys, n=1, cutoff=0.5)
337
+ if matches:
338
+ return ITEM_ALIASES.get(matches[0], matches[0])
339
+ return None
340
 
341
+ fuzzy_key = fuzzy_lookup(t)
342
+ if fuzzy_key:
343
+ LAST_ITEM[user] = fuzzy_key
344
+ reply_text = REPLY.get(normalize(fuzzy_key), f"I found {fuzzy_key}, but price/description not available.")
345
+ return friendly(reply_text)
346
+
347
+ # --- Booking flow ---
348
  if re.search(r"\b(book|reserve|schedule|site visit|site-visit|sitevisit)\b", t):
 
349
  if "site" in t:
350
  return friendly(start_booking(user, "site_visit"))
351
  if "consult" in t:
352
  return friendly(start_booking(user, "consultation"))
353
  return friendly(start_booking(user, "event_booking"))
354
 
 
355
  dt = find_date_in_text(raw)
356
  if dt:
357
  add_booking_detail(user, "date", dt)
 
369
  add_booking_detail(user, "location", loc)
370
  return friendly(f"Noted venue: {loc}. Any special requests or additional gear?")
371
 
 
372
  if any(pat in t for pat in ("confirm booking", "finalize booking", "complete booking", "confirm reservation", "confirm my booking")):
373
  res = finalize_booking(user)
374
  return friendly(res)
375
 
 
376
  mcode = re.search(r"\b([A-F0-9]{8})\b", raw, flags=re.I)
377
  if mcode:
378
  code = mcode.group(1).upper()
 
381
  return friendly(f"Booking {code} was created on {info.get('confirmed_at')}. Details: {info}")
382
  return friendly("Sorry, I can't find that booking code. Please check and send it again.")
383
 
 
384
  if any(w in t for w in LAMAKI_WORDS):
385
  return friendly(LAMAKI_SERVICES)
386
 
 
387
  if len(t.split()) <= 2:
388
  return friendly("Could you provide a few more details? For example: 'price for silver package' or 'book site visit 2025-12-05 200 guests at ABC Hall'.")
389
 
 
390
  return friendly("I’m here to help — tell me the item, package, or service you want and I’ll assist from there.")
391
+
392
  """
393
  Flask endpoints, health check, and run instructions.
394
  """