Coots commited on
Commit
b627340
ยท
verified ยท
1 Parent(s): 762a646

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -33
app.py CHANGED
@@ -4,15 +4,15 @@ import json
4
  import math
5
  import re
6
  from deep_translator import GoogleTranslator
7
- import warnings
8
  from xgboost import Booster
 
9
 
10
  warnings.filterwarnings("ignore")
11
 
12
  # Load models
13
  xgb = Booster()
14
  xgb.load_model("xgb_model.json")
15
- rf = joblib.load("rf_model.pkl") # Requires scikit-learn
16
 
17
  # Load tile catalog and sizes
18
  with open("tile_catalog.json", "r", encoding="utf-8") as f:
@@ -30,9 +30,15 @@ def translate(text, lang="en"):
30
  return text
31
 
32
  def extract_tile_area(msg, unit):
33
- msg = msg.lower().replace("ร—", "x").replace("into", "x").replace("*", "x")
34
  msg = msg.replace("mm", "").replace("ft", "").replace("feet", "").strip()
35
-
 
 
 
 
 
 
36
  if "x" in msg:
37
  parts = re.split(r"x", msg)
38
  if len(parts) == 2:
@@ -46,12 +52,7 @@ def extract_tile_area(msg, unit):
46
  return round(sqft, 2)
47
  except:
48
  return None
49
- else:
50
- try:
51
- val = float(re.sub(r"[^\d.]", "", msg))
52
- return val if unit == "ft" else None
53
- except:
54
- return None
55
 
56
  def chat_fn(message, history, user_state={}):
57
  message = message.strip().lower()
@@ -64,23 +65,23 @@ def chat_fn(message, history, user_state={}):
64
  lang = user_state["lang"]
65
  def reply(text): return translate(text, lang)
66
 
67
- # Greeting handler
68
  if message in ["hi", "hello", "hey", "start", "help"]:
69
  user_state.clear()
70
  return reply("๐Ÿ‘‹ Hello! Are you planning for Floor or Wall tiles?"), None, user_state
71
 
 
72
  if message in ["floor", "wall"]:
73
  user_state.clear()
74
  user_state["tile_type"] = message.capitalize()
75
  user_state["step"] = "get_length"
76
- return reply(f"Great! You chose {user_state['tile_type']} tiles.\nPlease enter the **length** of the space in feet:"), None, user_state
77
 
78
- # Stepwise input
79
  if user_state.get("step") == "get_length":
80
  try:
81
  user_state["length"] = float(re.sub(r"[^\d.]", "", message))
82
  user_state["step"] = "get_width"
83
- return reply("Now enter the **width** of the space in feet:"), None, user_state
84
  except:
85
  return reply("Please enter a valid number for length (e.g. 12.5):"), None, user_state
86
 
@@ -98,25 +99,24 @@ def chat_fn(message, history, user_state={}):
98
  return reply("Please type either **mm** or **ft** to choose your preferred unit."), None, user_state
99
  user_state["unit"] = message
100
  user_state["step"] = "get_tile_size"
101
- return reply(f"Enter the tile size in {message.upper()} (e.g. 600x600 or 2x2 or 4):"), None, user_state
102
 
103
  if user_state.get("step") == "get_tile_size":
104
- area_per_tile = extract_tile_area(message, user_state["unit"])
105
- if not area_per_tile:
106
- return reply("I couldn't understand that size. Try something like `600x600`, `2x2`, or just `4` (for square tile in ft)."), None, user_state
107
 
108
- user_state["tile_area"] = area_per_tile
109
  user_state["step"] = "done"
110
 
111
  area_needed = user_state["area"]
112
  tile_type = user_state["tile_type"]
113
- tile_needed = math.ceil((area_needed / area_per_tile) * 1.1)
114
 
115
- # Suggest tiles
116
  best = []
117
  for tile in tile_catalog:
118
  if tile["type"].lower() == tile_type.lower():
119
- per_box = tile["coverage"] / area_per_tile
120
  if per_box > 0:
121
  boxes = math.ceil(tile_needed / per_box)
122
  total = boxes * tile["price"]
@@ -134,30 +134,26 @@ def chat_fn(message, history, user_state={}):
134
 
135
  summary = f"""๐Ÿงฑ Tile Type: {tile_type}
136
  ๐Ÿ“ Area: {area_needed} sq.ft
137
- ๐Ÿงฎ Tile Size Area: {round(area_per_tile, 2)} sq.ft
138
  ๐Ÿ”ข Tiles Needed: {tile_needed} (10% extra included)
139
 
140
- ๐ŸŽฏ Top Recommendations:
141
  """
142
  for i, t in enumerate(top3, 1):
143
- summary += f"{i}. {t['name']} ({t['size']}) โ€“ โ‚น{t['price']} per box, ~{t['boxes']} boxes\n ๐Ÿ”— {t['url']}\n"
144
 
145
- summary += "\nType 'Floor' or 'Wall' to start over."
146
 
147
- user_state["summary"] = summary
148
  return reply(summary), None, user_state
149
 
150
- return reply("๐Ÿ‘‹ Please type 'Floor' or 'Wall' to begin tile estimation."), None, user_state
151
 
152
- # Gradio UI
153
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
154
  gr.ChatInterface(
155
  fn=chat_fn,
156
  title="๐Ÿงฑ TileBot โ€“ Smart Tile Estimator",
157
- description=(
158
- "Plan your tile needs easily. Just type `hi` to begin or start with `Floor` or `Wall`.\n"
159
- "I'll ask for room size, tile size, and recommend the best-fit tiles for your space."
160
- )
161
  )
162
 
163
  demo.launch()
 
4
  import math
5
  import re
6
  from deep_translator import GoogleTranslator
 
7
  from xgboost import Booster
8
+ import warnings
9
 
10
  warnings.filterwarnings("ignore")
11
 
12
  # Load models
13
  xgb = Booster()
14
  xgb.load_model("xgb_model.json")
15
+ rf = joblib.load("rf_model.pkl")
16
 
17
  # Load tile catalog and sizes
18
  with open("tile_catalog.json", "r", encoding="utf-8") as f:
 
30
  return text
31
 
32
  def extract_tile_area(msg, unit):
33
+ msg = msg.lower().replace("ร—", "x").replace("into", "x").replace("*", "x").replace("x", "x")
34
  msg = msg.replace("mm", "").replace("ft", "").replace("feet", "").strip()
35
+
36
+ # match single value (like 2 or 4)
37
+ if re.fullmatch(r"\d+(\.\d+)?", msg):
38
+ val = float(msg)
39
+ return round(val * val, 2) if unit == "ft" else None
40
+
41
+ # match pattern like 2x2 or 600x600
42
  if "x" in msg:
43
  parts = re.split(r"x", msg)
44
  if len(parts) == 2:
 
52
  return round(sqft, 2)
53
  except:
54
  return None
55
+ return None
 
 
 
 
 
56
 
57
  def chat_fn(message, history, user_state={}):
58
  message = message.strip().lower()
 
65
  lang = user_state["lang"]
66
  def reply(text): return translate(text, lang)
67
 
68
+ # Reset / greet
69
  if message in ["hi", "hello", "hey", "start", "help"]:
70
  user_state.clear()
71
  return reply("๐Ÿ‘‹ Hello! Are you planning for Floor or Wall tiles?"), None, user_state
72
 
73
+ # Start
74
  if message in ["floor", "wall"]:
75
  user_state.clear()
76
  user_state["tile_type"] = message.capitalize()
77
  user_state["step"] = "get_length"
78
+ return reply(f"Great! You chose {user_state['tile_type']} tiles.\nPlease enter the **length** of your space in feet:"), None, user_state
79
 
 
80
  if user_state.get("step") == "get_length":
81
  try:
82
  user_state["length"] = float(re.sub(r"[^\d.]", "", message))
83
  user_state["step"] = "get_width"
84
+ return reply("Now enter the **width** of your space in feet:"), None, user_state
85
  except:
86
  return reply("Please enter a valid number for length (e.g. 12.5):"), None, user_state
87
 
 
99
  return reply("Please type either **mm** or **ft** to choose your preferred unit."), None, user_state
100
  user_state["unit"] = message
101
  user_state["step"] = "get_tile_size"
102
+ return reply(f"Enter the tile size in {message.upper()} (e.g. 600x600, 2x2, or 4):"), None, user_state
103
 
104
  if user_state.get("step") == "get_tile_size":
105
+ tile_area = extract_tile_area(message, user_state["unit"])
106
+ if not tile_area:
107
+ return reply("โŒ I couldn't understand the tile size. Try `600x600`, `2x2`, or just `4`."), None, user_state
108
 
109
+ user_state["tile_area"] = tile_area
110
  user_state["step"] = "done"
111
 
112
  area_needed = user_state["area"]
113
  tile_type = user_state["tile_type"]
114
+ tile_needed = math.ceil((area_needed / tile_area) * 1.1)
115
 
 
116
  best = []
117
  for tile in tile_catalog:
118
  if tile["type"].lower() == tile_type.lower():
119
+ per_box = tile["coverage"] / tile_area
120
  if per_box > 0:
121
  boxes = math.ceil(tile_needed / per_box)
122
  total = boxes * tile["price"]
 
134
 
135
  summary = f"""๐Ÿงฑ Tile Type: {tile_type}
136
  ๐Ÿ“ Area: {area_needed} sq.ft
137
+ ๐Ÿงฎ Tile Size Area: {tile_area} sq.ft
138
  ๐Ÿ”ข Tiles Needed: {tile_needed} (10% extra included)
139
 
140
+ ๐ŸŽฏ Top Suggestions:
141
  """
142
  for i, t in enumerate(top3, 1):
143
+ summary += f"{i}. {t['name']} ({t['size']}) โ€“ โ‚น{t['price']}/box (~{t['boxes']} boxes)\n๐Ÿ”— {t['url']}\n"
144
 
145
+ summary += "\nType 'Floor' or 'Wall' to start again."
146
 
 
147
  return reply(summary), None, user_state
148
 
149
+ return reply("Type 'hi' or 'floor' or 'wall' to begin!"), None, user_state
150
 
151
+ # UI
152
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
153
  gr.ChatInterface(
154
  fn=chat_fn,
155
  title="๐Ÿงฑ TileBot โ€“ Smart Tile Estimator",
156
+ description="Type `hi`, `floor`, or `wall` to begin. I'll guide you step-by-step to estimate tile needs."
 
 
 
157
  )
158
 
159
  demo.launch()