Spaces:
Paused
Paused
WaysAhead Global commited on
Update app.py
Browse files
app.py
CHANGED
|
@@ -4,8 +4,7 @@ import numpy as np
|
|
| 4 |
import os
|
| 5 |
import matplotlib.pyplot as plt
|
| 6 |
import seaborn as sns
|
| 7 |
-
from
|
| 8 |
-
from statsmodels.tsa.holtwinters import ExponentialSmoothing
|
| 9 |
from langchain_openai import ChatOpenAI
|
| 10 |
from dotenv import load_dotenv
|
| 11 |
|
|
@@ -38,7 +37,7 @@ for mall, file in competitor_files.items():
|
|
| 38 |
competitor_data[mall] = pd.read_csv(file, encoding="ISO-8859-1")
|
| 39 |
|
| 40 |
# β
Streamlit Page Configuration
|
| 41 |
-
st.set_page_config(page_title="AI Store Replacement
|
| 42 |
|
| 43 |
# β
Title
|
| 44 |
st.title("π AI-Powered Store Replacement, Demand Prediction & Chatbot")
|
|
@@ -61,7 +60,7 @@ if selected_mall:
|
|
| 61 |
store_to_replace = st.selectbox("πͺ Select the store that is closing:", mall_data["Store_Brand"].unique())
|
| 62 |
|
| 63 |
if store_to_replace:
|
| 64 |
-
llm = ChatOpenAI(model="gpt-
|
| 65 |
|
| 66 |
# β
Identify Store Category
|
| 67 |
category_prompt = f"Given that {store_to_replace} is a retail brand, what type of store is it? Categorize it broadly (e.g., Fashion, Electronics, Footwear, Food, Home Decor, etc.)."
|
|
@@ -80,55 +79,45 @@ if selected_mall:
|
|
| 80 |
for competitor in competitor_list:
|
| 81 |
st.write(f"- {competitor}")
|
| 82 |
|
| 83 |
-
# β
|
| 84 |
-
|
| 85 |
-
kmeans = KMeans(n_clusters=5, random_state=42) # 5 Clusters
|
| 86 |
-
df["Cluster"] = kmeans.fit_predict(store_features)
|
| 87 |
|
| 88 |
-
|
| 89 |
-
|
|
|
|
|
|
|
| 90 |
|
| 91 |
-
# β
|
| 92 |
-
|
| 93 |
|
| 94 |
if available_stores:
|
| 95 |
replacement_prompt = f"Suggest 3 replacement stores from the list below that are not already in {selected_mall}. The stores should match the mallβs customer base and the category: {store_category}. Store List: {available_stores}"
|
| 96 |
replacement_response = llm.invoke(replacement_prompt).content
|
| 97 |
-
|
| 98 |
-
# β
Debugging: Print AI Response
|
| 99 |
-
st.write(f"π§ **AI Raw Response:** {replacement_response}")
|
| 100 |
-
|
| 101 |
-
# β
Ensure AI Response is Valid
|
| 102 |
replacement_stores = [store.strip() for store in replacement_response.split("\n") if store.strip()]
|
| 103 |
replacement_stores = [store for store in replacement_stores if store in available_stores]
|
| 104 |
|
| 105 |
if replacement_stores:
|
| 106 |
-
st.success(f"π **Recommended Replacement Stores:**")
|
| 107 |
for replacement_store in replacement_stores:
|
| 108 |
store_data = df[df["Store_Brand"] == replacement_store]
|
| 109 |
|
| 110 |
if not store_data.empty:
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
# β
Justification
|
| 129 |
-
justification_prompt = f"Explain why {replacement_store} is a good replacement for {store_to_replace} in {selected_mall}. Include numeric KPIs: expected sales, footfall, conversion rate, and profit margins."
|
| 130 |
-
justification = llm.invoke(justification_prompt).content
|
| 131 |
-
st.write(f"π€ **AI Justification:** {justification}")
|
| 132 |
|
| 133 |
# β
AI Chatbot for Dynamic Insights
|
| 134 |
st.subheader("π¬ AI-Powered Chatbot")
|
|
|
|
| 4 |
import os
|
| 5 |
import matplotlib.pyplot as plt
|
| 6 |
import seaborn as sns
|
| 7 |
+
from pycaret.regression import setup, compare_models, predict_model, pull
|
|
|
|
| 8 |
from langchain_openai import ChatOpenAI
|
| 9 |
from dotenv import load_dotenv
|
| 10 |
|
|
|
|
| 37 |
competitor_data[mall] = pd.read_csv(file, encoding="ISO-8859-1")
|
| 38 |
|
| 39 |
# β
Streamlit Page Configuration
|
| 40 |
+
st.set_page_config(page_title="AI Store Replacement with PyCaret KPI Forecasting", layout="wide")
|
| 41 |
|
| 42 |
# β
Title
|
| 43 |
st.title("π AI-Powered Store Replacement, Demand Prediction & Chatbot")
|
|
|
|
| 60 |
store_to_replace = st.selectbox("πͺ Select the store that is closing:", mall_data["Store_Brand"].unique())
|
| 61 |
|
| 62 |
if store_to_replace:
|
| 63 |
+
llm = ChatOpenAI(model="gpt-4", api_key=openai_api_key)
|
| 64 |
|
| 65 |
# β
Identify Store Category
|
| 66 |
category_prompt = f"Given that {store_to_replace} is a retail brand, what type of store is it? Categorize it broadly (e.g., Fashion, Electronics, Footwear, Food, Home Decor, etc.)."
|
|
|
|
| 79 |
for competitor in competitor_list:
|
| 80 |
st.write(f"- {competitor}")
|
| 81 |
|
| 82 |
+
# β
Train PyCaret Model for KPI Prediction
|
| 83 |
+
st.subheader("π Training PyCaret Model for KPI Forecasting")
|
|
|
|
|
|
|
| 84 |
|
| 85 |
+
kpi_data = df.drop(columns=["Store_Brand", "Mall", "Location", "Country", "City"]) # Exclude categorical features
|
| 86 |
+
reg = setup(kpi_data, target="Annual_Sales", silent=True)
|
| 87 |
+
best_model = compare_models()
|
| 88 |
+
st.write("π Best Model Selected:", best_model)
|
| 89 |
|
| 90 |
+
# β
Find a replacement store in the same category (From kpi.xlsx, Not in this mall)
|
| 91 |
+
available_stores = list(set(df["Store_Brand"].unique()) - set(mall_data["Store_Brand"].unique()))
|
| 92 |
|
| 93 |
if available_stores:
|
| 94 |
replacement_prompt = f"Suggest 3 replacement stores from the list below that are not already in {selected_mall}. The stores should match the mallβs customer base and the category: {store_category}. Store List: {available_stores}"
|
| 95 |
replacement_response = llm.invoke(replacement_prompt).content
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
replacement_stores = [store.strip() for store in replacement_response.split("\n") if store.strip()]
|
| 97 |
replacement_stores = [store for store in replacement_stores if store in available_stores]
|
| 98 |
|
| 99 |
if replacement_stores:
|
| 100 |
+
st.success(f"π **Recommended Replacement Stores with Forecasted KPIs:**")
|
| 101 |
for replacement_store in replacement_stores:
|
| 102 |
store_data = df[df["Store_Brand"] == replacement_store]
|
| 103 |
|
| 104 |
if not store_data.empty:
|
| 105 |
+
forecast_kpis = predict_model(best_model, data=store_data)
|
| 106 |
+
forecasted_sales = forecast_kpis["Label"].values[0]
|
| 107 |
+
expected_footfall = store_data["Footfall"].mean()
|
| 108 |
+
expected_conversion = store_data["Conversion_Rate"].mean()
|
| 109 |
+
expected_margin = store_data["Gross_Margin"].mean()
|
| 110 |
+
|
| 111 |
+
st.write(f"**{replacement_store}**")
|
| 112 |
+
st.write(f"π **Projected Sales:** AED {forecasted_sales:,.2f}")
|
| 113 |
+
st.write(f"π£ **Projected Footfall:** {expected_footfall:,.0f} visitors")
|
| 114 |
+
st.write(f"π° **Projected Margin:** AED {expected_margin:,.2f}")
|
| 115 |
+
st.write(f"π **Projected Conversion Rate:** {expected_conversion:.2f}%")
|
| 116 |
+
|
| 117 |
+
# β
Justification
|
| 118 |
+
justification_prompt = f"Explain why {replacement_store} is a good replacement for {store_to_replace} in {selected_mall}. Include numeric KPIs: expected sales, footfall, conversion rate, and profit margins."
|
| 119 |
+
justification = llm.invoke(justification_prompt).content
|
| 120 |
+
st.write(f"π€ **AI Justification:** {justification}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 121 |
|
| 122 |
# β
AI Chatbot for Dynamic Insights
|
| 123 |
st.subheader("π¬ AI-Powered Chatbot")
|