Coots commited on
Commit
f5f9a76
ยท
verified ยท
1 Parent(s): c949fbe

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +31 -34
app.py CHANGED
@@ -5,22 +5,19 @@ import math
5
  import re
6
  from deep_translator import GoogleTranslator
7
  import warnings
8
-
9
  warnings.filterwarnings("ignore")
10
 
11
  # Load models
12
  xgb = joblib.load("xgb_model.pkl")
13
  rf = joblib.load("rf_model.pkl")
14
 
15
- # Load tile catalog and size mappings
16
  with open("tile_catalog.json", "r", encoding="utf-8") as f:
17
  tile_catalog = json.load(f)
18
 
19
  with open("tile_sizes.json", "r", encoding="utf-8") as f:
20
  tile_sizes = json.load(f)
21
 
22
- tile_size_map = {s["label"].lower().replace(" ", ""): s["area_sqft"] for s in tile_sizes}
23
-
24
  def translate(text, lang="en"):
25
  try:
26
  return GoogleTranslator(source="auto", target=lang).translate(text)
@@ -37,10 +34,10 @@ def extract_tile_area(msg):
37
  try:
38
  val1 = float(re.sub(r"[^\d.]", "", parts[0]))
39
  val2 = float(re.sub(r"[^\d.]", "", parts[1]))
40
- if val1 > 20: # mm
41
- sqft = (val1 * val2) / 92903.04
42
  else:
43
- sqft = val1 * val2
44
  return round(sqft, 2)
45
  except:
46
  return None
@@ -56,12 +53,11 @@ def extract_tile_area(msg):
56
  return None
57
 
58
  def chat_fn(message, history, user_state={}):
59
- message_clean = message.strip().lower()
60
 
61
- # Reset flow
62
- if message_clean in ["restart", "reset", "start"]:
63
  user_state.clear()
64
- return "๐Ÿ”„ Restarted. Are you looking for Floor or Wall tiles?", None, user_state
65
 
66
  if "lang" not in user_state:
67
  try:
@@ -71,28 +67,29 @@ def chat_fn(message, history, user_state={}):
71
  lang = user_state["lang"]
72
  def reply(text): return translate(text, lang)
73
 
74
- # Step 1: Start
75
  if "step" not in user_state:
76
- if message_clean in ["floor", "wall"]:
77
  user_state["tile_type"] = message.capitalize()
78
  user_state["step"] = "get_area"
79
- return reply(f"โœ… You chose {user_state['tile_type']} tiles. What's the total area in sq.ft?"), None, user_state
80
- return reply("๐Ÿ‘‹ Hi! Are you looking for Floor or Wall tiles?"), None, user_state
 
81
 
82
- # Step 2: Get Area
83
  if user_state["step"] == "get_area":
84
  try:
85
  user_state["area"] = float(message)
86
  user_state["step"] = "get_tile_size"
87
- return reply("๐Ÿ“ Enter the tile size (e.g. 2 x 2 ft, 600x600 mm, or 200 * 200):"), None, user_state
88
  except:
89
- return reply("โ— Please enter a valid number for area in sq.ft (e.g. 120)."), None, user_state
90
 
91
- # Step 3: Get Tile Size
92
  if user_state["step"] == "get_tile_size":
93
  area = extract_tile_area(message)
94
  if area is None:
95
- return reply("โ— Invalid format. Try: 2 x 2, 600x600, or 1.5 * 1.5"), None, user_state
96
 
97
  user_state["tile_area"] = area
98
  user_state["step"] = "done"
@@ -102,32 +99,32 @@ def chat_fn(message, history, user_state={}):
102
  tile_needed = math.ceil((total_area / area) * 1.1)
103
 
104
  # Recommendations
105
- best = []
106
  for tile in tile_catalog:
107
  if tile["type"].lower() == tile_type.lower():
108
  per_box = tile["coverage"] / area
109
  if per_box > 0:
110
  boxes = math.ceil(tile_needed / per_box)
111
- total = boxes * tile["price"]
112
- best.append({
113
  "name": tile["name"],
114
  "size": tile["size"],
115
  "price": tile["price"],
116
  "boxes": boxes,
117
- "total": total,
118
  "url": tile["url"]
119
  })
120
 
121
- best.sort(key=lambda x: x["total"])
122
- top3 = best[:3]
123
 
124
  result = f"""
125
  ๐Ÿงฑ Tile Type: {tile_type}
126
- ๐Ÿ“ Area: {total_area} sq.ft
127
- ๐Ÿ“ฆ Tile Size: {round(area, 2)} sq.ft
128
- ๐Ÿ”ข Tiles Needed (with 10% buffer): {tile_needed}
129
 
130
- ๐ŸŽฏ Recommendations:
131
  """
132
  for i, t in enumerate(top3, 1):
133
  result += f"{i}. {t['name']} ({t['size']}) - โ‚น{t['price']}/box\n ~{t['boxes']} boxes โ†’ โ‚น{int(t['total'])}\n ๐Ÿ”— {t['url']}\n\n"
@@ -135,14 +132,14 @@ def chat_fn(message, history, user_state={}):
135
  result += "You can type 'Floor' or 'Wall' to estimate again."
136
  return reply(result), None, {}
137
 
138
- return reply("Say 'Floor' or 'Wall' to begin a new estimate."), None, {}
139
 
140
- # Gradio UI
141
  with gr.Blocks() as demo:
142
  gr.ChatInterface(
143
  fn=chat_fn,
144
- title="๐Ÿงฑ Tilo - Tile Estimator Bot",
145
- description="Chat naturally to estimate tiles needed. Start by typing 'Floor' or 'Wall'.",
146
  type="messages"
147
  )
148
 
 
5
  import re
6
  from deep_translator import GoogleTranslator
7
  import warnings
 
8
  warnings.filterwarnings("ignore")
9
 
10
  # Load models
11
  xgb = joblib.load("xgb_model.pkl")
12
  rf = joblib.load("rf_model.pkl")
13
 
14
+ # Load tile catalog and sizes
15
  with open("tile_catalog.json", "r", encoding="utf-8") as f:
16
  tile_catalog = json.load(f)
17
 
18
  with open("tile_sizes.json", "r", encoding="utf-8") as f:
19
  tile_sizes = json.load(f)
20
 
 
 
21
  def translate(text, lang="en"):
22
  try:
23
  return GoogleTranslator(source="auto", target=lang).translate(text)
 
34
  try:
35
  val1 = float(re.sub(r"[^\d.]", "", parts[0]))
36
  val2 = float(re.sub(r"[^\d.]", "", parts[1]))
37
+ if val1 > 20:
38
+ sqft = (val1 * val2) / 92903.04 # mm
39
  else:
40
+ sqft = val1 * val2 # ft
41
  return round(sqft, 2)
42
  except:
43
  return None
 
53
  return None
54
 
55
  def chat_fn(message, history, user_state={}):
56
+ msg = message.strip().lower()
57
 
58
+ # Reset flow on keywords
59
+ if msg in ["restart", "reset", "start", "floor", "wall"]:
60
  user_state.clear()
 
61
 
62
  if "lang" not in user_state:
63
  try:
 
67
  lang = user_state["lang"]
68
  def reply(text): return translate(text, lang)
69
 
70
+ # Step 1: Detect tile type
71
  if "step" not in user_state:
72
+ if msg in ["floor", "wall"]:
73
  user_state["tile_type"] = message.capitalize()
74
  user_state["step"] = "get_area"
75
+ return reply(f"โœ… You selected {user_state['tile_type']} tiles. What's the total area in sq.ft?"), None, user_state
76
+ else:
77
+ return reply("๐Ÿ‘‹ Welcome! Are you planning for Floor or Wall tiles? Type 'Floor' or 'Wall' to begin."), None, user_state
78
 
79
+ # Step 2: Get area
80
  if user_state["step"] == "get_area":
81
  try:
82
  user_state["area"] = float(message)
83
  user_state["step"] = "get_tile_size"
84
+ return reply("๐Ÿ“ Now enter the tile size (e.g. 2x2, 600x600 mm, 200 * 200):"), None, user_state
85
  except:
86
+ return reply("โ— Please enter a valid number for the area (e.g. 120)."), None, user_state
87
 
88
+ # Step 3: Get tile size
89
  if user_state["step"] == "get_tile_size":
90
  area = extract_tile_area(message)
91
  if area is None:
92
+ return reply("โ— I couldn't understand that tile size. Try: 2 x 2, 600x600 mm, 200*200."), None, user_state
93
 
94
  user_state["tile_area"] = area
95
  user_state["step"] = "done"
 
99
  tile_needed = math.ceil((total_area / area) * 1.1)
100
 
101
  # Recommendations
102
+ recommendations = []
103
  for tile in tile_catalog:
104
  if tile["type"].lower() == tile_type.lower():
105
  per_box = tile["coverage"] / area
106
  if per_box > 0:
107
  boxes = math.ceil(tile_needed / per_box)
108
+ total_price = boxes * tile["price"]
109
+ recommendations.append({
110
  "name": tile["name"],
111
  "size": tile["size"],
112
  "price": tile["price"],
113
  "boxes": boxes,
114
+ "total": total_price,
115
  "url": tile["url"]
116
  })
117
 
118
+ recommendations.sort(key=lambda x: x["total"])
119
+ top3 = recommendations[:3]
120
 
121
  result = f"""
122
  ๐Ÿงฑ Tile Type: {tile_type}
123
+ ๐Ÿ“ Area to Cover: {total_area} sq.ft
124
+ ๐Ÿงฎ Tile Size Area: {round(area, 2)} sq.ft
125
+ ๐Ÿ”ข Tiles Needed (with buffer): {tile_needed}
126
 
127
+ ๐ŸŽฏ Top Product Suggestions:
128
  """
129
  for i, t in enumerate(top3, 1):
130
  result += f"{i}. {t['name']} ({t['size']}) - โ‚น{t['price']}/box\n ~{t['boxes']} boxes โ†’ โ‚น{int(t['total'])}\n ๐Ÿ”— {t['url']}\n\n"
 
132
  result += "You can type 'Floor' or 'Wall' to estimate again."
133
  return reply(result), None, {}
134
 
135
+ return reply("Say 'Floor' or 'Wall' to begin."), None, {}
136
 
137
+ # Gradio interface
138
  with gr.Blocks() as demo:
139
  gr.ChatInterface(
140
  fn=chat_fn,
141
+ title="๐Ÿงฑ Tilo โ€“ Tile Estimator",
142
+ description="Type 'Floor' or 'Wall' to start. Then give your room size and tile size (e.g. 2x2 ft, 600x600 mm).",
143
  type="messages"
144
  )
145