Update app.py
Browse files
app.py
CHANGED
@@ -8,17 +8,18 @@ from fpdf import FPDF
|
|
8 |
import tempfile
|
9 |
from deep_translator import GoogleTranslator
|
10 |
import warnings
|
11 |
-
import xgboost as xgb
|
12 |
|
13 |
warnings.filterwarnings("ignore")
|
14 |
|
15 |
-
#
|
16 |
xgb_model = xgb.Booster()
|
17 |
-
xgb_model.load_model("xgb_model.json")
|
18 |
|
|
|
19 |
rf = joblib.load("rf_model.pkl")
|
20 |
|
21 |
-
#
|
22 |
with open("tile_catalog.json", "r", encoding="utf-8") as f:
|
23 |
tile_catalog = json.load(f)
|
24 |
|
@@ -50,29 +51,30 @@ def create_pdf(text):
|
|
50 |
return tmp.name
|
51 |
|
52 |
def extract_tile_area(msg, unit):
|
53 |
-
msg = msg.lower().replace("
|
54 |
-
|
55 |
-
if
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
|
|
|
|
|
|
68 |
return None
|
69 |
|
70 |
def chat_fn(message, history, user_state={}):
|
71 |
-
# Reset state if user types Floor or Wall
|
72 |
if message.strip().lower() in ["floor", "wall"]:
|
73 |
user_state.clear()
|
74 |
|
75 |
-
# Language detection
|
76 |
if "lang" not in user_state:
|
77 |
try:
|
78 |
user_state["lang"] = GoogleTranslator(source="auto", target="en").detect(message)
|
@@ -81,7 +83,6 @@ def chat_fn(message, history, user_state={}):
|
|
81 |
lang = user_state["lang"]
|
82 |
def reply(text): return translate(text, lang)
|
83 |
|
84 |
-
# Handle PDF command
|
85 |
if message.strip().lower() in ["pdf", "report", "download"]:
|
86 |
if "summary" in user_state:
|
87 |
pdf_path = create_pdf(user_state["summary"])
|
@@ -89,7 +90,6 @@ def chat_fn(message, history, user_state={}):
|
|
89 |
else:
|
90 |
return reply("No estimate yet. Please start by typing 'Floor' or 'Wall'."), None, user_state
|
91 |
|
92 |
-
# Start flow
|
93 |
if "step" not in user_state:
|
94 |
if message.lower() in ["floor", "wall"]:
|
95 |
user_state["tile_type"] = message.capitalize()
|
@@ -111,12 +111,12 @@ def chat_fn(message, history, user_state={}):
|
|
111 |
user_state["unit"] = message.lower()
|
112 |
user_state["step"] = "get_tile_size"
|
113 |
unit_label = "mm" if user_state["unit"] == "mm" else "feet"
|
114 |
-
return reply(f"Please enter the tile size in {unit_label} (e.g. 600 x 600):"), None, user_state
|
115 |
|
116 |
if user_state["step"] == "get_tile_size":
|
117 |
area = extract_tile_area(message, user_state["unit"])
|
118 |
if area is None:
|
119 |
-
return reply("I couldnβt understand that size. Try something like 600 x 600 or 2 x 2."), None, user_state
|
120 |
|
121 |
user_state["tile_area"] = area
|
122 |
user_state["step"] = "done"
|
@@ -163,20 +163,39 @@ def chat_fn(message, history, user_state={}):
|
|
163 |
|
164 |
return reply("Type 'Floor' or 'Wall' to begin a new estimate."), None, user_state
|
165 |
|
166 |
-
|
167 |
-
with
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
chatbot = gr.ChatInterface(
|
169 |
fn=chat_fn,
|
170 |
-
title=
|
171 |
-
description=
|
172 |
-
"π§± TileBot is here to help you estimate tiles for your space.\n\n"
|
173 |
-
"Start by telling me if you're working on a Floor or Wall. Then share your room size and tile size in mm or feet β "
|
174 |
-
"I'll do the rest.\n\n"
|
175 |
-
"Iβll calculate how many tiles you need, recommend suitable products, and give you a PDF report.\n\n"
|
176 |
-
"Type 'Floor' or 'Wall' to begin!"
|
177 |
-
),
|
178 |
type="messages",
|
179 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
180 |
)
|
181 |
|
182 |
demo.launch()
|
|
|
8 |
import tempfile
|
9 |
from deep_translator import GoogleTranslator
|
10 |
import warnings
|
11 |
+
import xgboost as xgb
|
12 |
|
13 |
warnings.filterwarnings("ignore")
|
14 |
|
15 |
+
# Load XGBoost model (native JSON format)
|
16 |
xgb_model = xgb.Booster()
|
17 |
+
xgb_model.load_model("xgb_model.json")
|
18 |
|
19 |
+
# Load Random Forest model
|
20 |
rf = joblib.load("rf_model.pkl")
|
21 |
|
22 |
+
# Load tile catalog and sizes
|
23 |
with open("tile_catalog.json", "r", encoding="utf-8") as f:
|
24 |
tile_catalog = json.load(f)
|
25 |
|
|
|
51 |
return tmp.name
|
52 |
|
53 |
def extract_tile_area(msg, unit):
|
54 |
+
msg = msg.lower().replace("feet", "").replace("ft", "").replace("mm", "").strip()
|
55 |
+
parts = re.split(r"\s*[xΓ*into]+\s*", msg)
|
56 |
+
if len(parts) == 2:
|
57 |
+
try:
|
58 |
+
val1 = float(re.sub(r"[^\d.]", "", parts[0]))
|
59 |
+
val2 = float(re.sub(r"[^\d.]", "", parts[1]))
|
60 |
+
if unit == "mm":
|
61 |
+
sqft = (val1 * val2) / 92903.04
|
62 |
+
else:
|
63 |
+
sqft = val1 * val2
|
64 |
+
return round(sqft, 2)
|
65 |
+
except:
|
66 |
+
return None
|
67 |
+
elif len(parts) == 1:
|
68 |
+
try:
|
69 |
+
return float(parts[0]) # Direct sqft entry
|
70 |
+
except:
|
71 |
+
return None
|
72 |
return None
|
73 |
|
74 |
def chat_fn(message, history, user_state={}):
|
|
|
75 |
if message.strip().lower() in ["floor", "wall"]:
|
76 |
user_state.clear()
|
77 |
|
|
|
78 |
if "lang" not in user_state:
|
79 |
try:
|
80 |
user_state["lang"] = GoogleTranslator(source="auto", target="en").detect(message)
|
|
|
83 |
lang = user_state["lang"]
|
84 |
def reply(text): return translate(text, lang)
|
85 |
|
|
|
86 |
if message.strip().lower() in ["pdf", "report", "download"]:
|
87 |
if "summary" in user_state:
|
88 |
pdf_path = create_pdf(user_state["summary"])
|
|
|
90 |
else:
|
91 |
return reply("No estimate yet. Please start by typing 'Floor' or 'Wall'."), None, user_state
|
92 |
|
|
|
93 |
if "step" not in user_state:
|
94 |
if message.lower() in ["floor", "wall"]:
|
95 |
user_state["tile_type"] = message.capitalize()
|
|
|
111 |
user_state["unit"] = message.lower()
|
112 |
user_state["step"] = "get_tile_size"
|
113 |
unit_label = "mm" if user_state["unit"] == "mm" else "feet"
|
114 |
+
return reply(f"Please enter the tile size in {unit_label} (e.g. 600 x 600 or 2 x 2 or 4):"), None, user_state
|
115 |
|
116 |
if user_state["step"] == "get_tile_size":
|
117 |
area = extract_tile_area(message, user_state["unit"])
|
118 |
if area is None:
|
119 |
+
return reply("I couldnβt understand that size. Try something like 600 x 600 or 2 x 2 or 4."), None, user_state
|
120 |
|
121 |
user_state["tile_area"] = area
|
122 |
user_state["step"] = "done"
|
|
|
163 |
|
164 |
return reply("Type 'Floor' or 'Wall' to begin a new estimate."), None, user_state
|
165 |
|
166 |
+
|
167 |
+
# --- Modern Gradio UI with Theme ---
|
168 |
+
with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", radius_size="full")) as demo:
|
169 |
+
gr.Markdown(
|
170 |
+
"""
|
171 |
+
# π§± <span style="color:#3B82F6">TileBot</span> β Smart Tile Estimator
|
172 |
+
Welcome! I'm here to help you estimate tile needs for your floor or wall.
|
173 |
+
|
174 |
+
π Start by typing **"Floor"** or **"Wall"**
|
175 |
+
π Then give me the **area** and **tile size** in `mm` or `ft`
|
176 |
+
βοΈ Example: `600 x 600`, `2 x 2`, or just `4` sq.ft
|
177 |
+
π Iβll recommend tiles and generate a **PDF Report**!
|
178 |
+
""",
|
179 |
+
elem_id="header"
|
180 |
+
)
|
181 |
+
|
182 |
chatbot = gr.ChatInterface(
|
183 |
fn=chat_fn,
|
184 |
+
title=None,
|
185 |
+
description=None,
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
type="messages",
|
187 |
+
chatbot=gr.Chatbot(height=500, bubble_full_width=False),
|
188 |
+
additional_outputs=[gr.File(label="π Download Report")],
|
189 |
+
clear_btn="Clear",
|
190 |
+
)
|
191 |
+
|
192 |
+
gr.Markdown(
|
193 |
+
"""
|
194 |
+
---
|
195 |
+
π‘ Tip: Type `"pdf"` anytime to get a downloadable report.
|
196 |
+
π Need a new estimate? Just say `"Floor"` or `"Wall"` to start over.
|
197 |
+
""",
|
198 |
+
elem_id="footer"
|
199 |
)
|
200 |
|
201 |
demo.launch()
|