File size: 6,167 Bytes
a1626c0 74136c1 a1626c0 1e74a1e 389dccc a1626c0 389dccc a1626c0 5277275 a1626c0 389dccc 1e74a1e 389dccc 9798986 a1626c0 389dccc a1626c0 389dccc 25c77af 389dccc 5277275 389dccc 5277275 389dccc 5277275 389dccc 5277275 389dccc a1626c0 389dccc a1626c0 389dccc 5277275 a1626c0 389dccc a1626c0 389dccc a1626c0 389dccc a1626c0 389dccc a1626c0 389dccc a1626c0 389dccc a1626c0 389dccc a1626c0 389dccc a1626c0 389dccc a1626c0 389dccc a1626c0 389dccc a1626c0 389dccc a1626c0 389dccc 5277275 a1626c0 389dccc 9798986 389dccc a1626c0 389dccc 9798986 74136c1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
import gradio as gr
import joblib
import json
import math
import re
from deep_translator import GoogleTranslator
import warnings
warnings.filterwarnings("ignore")
# Load models
from xgboost import Booster
xgb = Booster()
xgb.load_model("xgb_model.json")
rf = joblib.load("rf_model.pkl") # Needs scikit-learn
# Load tile catalog and sizes
with open("tile_catalog.json", "r", encoding="utf-8") as f:
tile_catalog = json.load(f)
with open("tile_sizes.json", "r", encoding="utf-8") as f:
tile_sizes = json.load(f)
tile_size_map = {s["label"].lower().replace(" ", ""): s["area_sqft"] for s in tile_sizes}
def translate(text, lang="en"):
try:
return GoogleTranslator(source="auto", target=lang).translate(text)
except:
return text
def extract_tile_area(msg, unit):
msg = msg.lower().replace("ร", "x").replace("into", "x").replace("*", "x")
msg = msg.replace("mm", "").replace("ft", "").replace("feet", "").strip()
if "x" in msg:
parts = re.split(r"x", msg)
if len(parts) == 2:
try:
val1 = float(re.sub(r"[^\d.]", "", parts[0]))
val2 = float(re.sub(r"[^\d.]", "", parts[1]))
if unit == "mm":
sqft = (val1 * val2) / 92903.04
else:
sqft = val1 * val2
return round(sqft, 2)
except:
return None
else:
# Single value fallback for ft
try:
val = float(re.sub(r"[^\d.]", "", msg))
return val if unit == "ft" else None
except:
return None
def chat_fn(message, history, user_state={}):
message = message.strip().lower()
if "lang" not in user_state:
try:
user_state["lang"] = GoogleTranslator(source="auto", target="en").detect(message)
except:
user_state["lang"] = "en"
lang = user_state["lang"]
def reply(text): return translate(text, lang)
# Greeting handler
if message in ["hi", "hello", "hey", "start", "help"]:
user_state.clear()
return reply("๐ Hello! Are you planning for Floor or Wall tiles?"), None, user_state
if message in ["floor", "wall"]:
user_state.clear()
user_state["tile_type"] = message.capitalize()
user_state["step"] = "get_length"
return reply(f"Great! You chose {user_state['tile_type']} tiles.\nPlease enter the **length** of the space in feet:"), None, user_state
# Stepwise logic
if user_state.get("step") == "get_length":
try:
user_state["length"] = float(re.sub(r"[^\d.]", "", message))
user_state["step"] = "get_width"
return reply("Now enter the **width** of the space in feet:"), None, user_state
except:
return reply("Please enter a valid number for length (e.g. 12.5):"), None, user_state
if user_state.get("step") == "get_width":
try:
user_state["width"] = float(re.sub(r"[^\d.]", "", message))
user_state["area"] = round(user_state["length"] * user_state["width"], 2)
user_state["step"] = "get_unit"
return reply(f"Your total area is {user_state['area']} sq.ft.\nWould you like to enter tile size in **mm** or **ft**?"), None, user_state
except:
return reply("Please enter a valid number for width (e.g. 10):"), None, user_state
if user_state.get("step") == "get_unit":
if message not in ["mm", "ft"]:
return reply("Please type either **mm** or **ft** to choose your preferred unit."), None, user_state
user_state["unit"] = message
user_state["step"] = "get_tile_size"
return reply(f"Enter the tile size in {message.upper()} (e.g. 600x600 or 2x2):"), None, user_state
if user_state.get("step") == "get_tile_size":
area_per_tile = extract_tile_area(message, user_state["unit"])
if not area_per_tile:
return reply("I couldn't understand that size. Try something like `600x600`, `2x2`, or just `4` if square in ft."), None, user_state
user_state["tile_area"] = area_per_tile
user_state["step"] = "done"
area_needed = user_state["area"]
tile_type = user_state["tile_type"]
tile_needed = math.ceil((area_needed / area_per_tile) * 1.1)
# Suggest tiles
best = []
for tile in tile_catalog:
if tile["type"].lower() == tile_type.lower():
per_box = tile["coverage"] / area_per_tile
if per_box > 0:
boxes = math.ceil(tile_needed / per_box)
total = boxes * tile["price"]
best.append({
"name": tile["name"],
"size": tile["size"],
"price": tile["price"],
"boxes": boxes,
"total": total,
"url": tile["url"]
})
best.sort(key=lambda x: x["total"])
top3 = best[:3]
summary = f"""๐งฑ Tile Type: {tile_type}
๐ Area: {area_needed} sq.ft
๐งฎ Tile Size Area: {round(area_per_tile, 2)} sq.ft
๐ข Tiles Needed: {tile_needed} (10% extra included)
๐ฏ Top Recommendations:
"""
for i, t in enumerate(top3, 1):
summary += f"{i}. {t['name']} ({t['size']}) โ โน{t['price']} per box, ~{t['boxes']} boxes\n ๐ {t['url']}\n"
summary += "\nType 'Floor' or 'Wall' to start over."
user_state["summary"] = summary
return reply(summary), None, user_state
return reply("๐ Please type 'Floor' or 'Wall' to begin tile estimation."), None, user_state
# UI setup
with gr.Blocks() as demo:
gr.ChatInterface(
fn=chat_fn,
title="๐งฑ TileBot โ Smart Tile Estimator",
description=(
"Plan your tile needs easily. Just type `hi` to begin or start with `Floor` or `Wall`.\n"
"Iโll ask for room size, tile size, and recommend the best fit tiles."
),
theme=gr.themes.Soft(),
retry_btn=None,
undo_btn=None
)
demo.launch()
|