WaysAhead Global commited on
Commit
e64cd16
·
verified ·
1 Parent(s): bba55c0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +110 -130
app.py CHANGED
@@ -1,162 +1,142 @@
1
  import streamlit as st
2
  import pandas as pd
 
3
  import os
4
  import matplotlib.pyplot as plt
5
  import seaborn as sns
6
- from dotenv import load_dotenv
7
- from io import BytesIO
8
-
9
- # AI & ML Components
10
  from langchain_openai import ChatOpenAI
11
- from pandasai import SmartDatalake
12
- from pandasai.llm import OpenAI
13
- from pycaret.regression import setup as setup_reg, compare_models, predict_model, pull, save_model, load_model
14
 
15
  # ✅ Load Environment Variables
16
  load_dotenv()
17
  openai_api_key = os.getenv("OPENAI_API_KEY")
18
 
19
  if not openai_api_key:
20
- st.error("❌ OpenAI API Key is missing! Set it in your .env file.")
21
 
22
- # ✅ Streamlit Page Configuration
23
- st.set_page_config(page_title="AI-Powered Store Recommender & Chatbot", layout="wide")
24
 
25
- # ✅ Title
26
- st.title("🛍️ AI-Powered Apparel Group Store Recommender & Chatbot")
 
27
 
28
- # ✅ Load KPI & Competitor Data from Repo
29
- repo_path = os.getcwd()
30
- kpi_file = os.path.join(repo_path, "kpi.xlsx")
31
  competitor_files = {
32
- "DEIRA CITY CENTRE": "Competitor Mapping Doc Final1(DEIRA CITY CENTRE).csv",
33
- "ARABIAN CENTRE": "Competitor Mapping Doc Final1(ARABIAN CENTRE).csv",
34
- "AL GHURAIR CENTRE": "Competitor Mapping Doc Final1(AL GHURAIR CENTRE).csv",
35
- "IBN BATTUTA MALL": "Competitor Mapping Doc Final1(IBN BATTUTA MALL).csv",
36
- "DUBAI HILLS": "Competitor Mapping Doc Final1(DUBAI HILLS).csv"
37
  }
38
 
39
- # ✅ Load KPI Data
40
- df_kpi = pd.read_excel(kpi_file, engine="openpyxl")
 
 
41
 
42
- # ✅ Load Competitor Data with ISO Encoding
43
- df_competitors = {}
44
- for mall, file_name in competitor_files.items():
45
- file_path = os.path.join(repo_path, file_name)
46
- if os.path.exists(file_path):
47
- try:
48
- df_competitors[mall] = pd.read_csv(file_path, encoding="ISO-8859-1", on_bad_lines="skip")
49
- except Exception as e:
50
- st.error(f"❌ Error loading {file_name}: {e}")
51
 
52
- # ✅ Display Previews
53
- st.subheader("📊 KPI Data Preview (5 Unique Rows)")
54
- st.dataframe(df_kpi.drop_duplicates().sample(n=5, random_state=42) if len(df_kpi) > 5 else df_kpi)
55
 
56
- st.subheader("🏆 Competitor Data Preview (First 5 Rows of Each Mall)")
57
- for mall, df in df_competitors.items():
58
- st.write(f"### {mall} - Competitors")
59
- st.dataframe(df.head(5))
60
 
61
- # ✅ Competitor Analysis for Selected Mall
62
- st.subheader("🔎 Competitor Analysis")
63
- selected_mall = st.selectbox("🏬 Select a Mall for Competitor Insights:", df_kpi["Mall"].unique())
64
 
65
  if selected_mall:
66
- if selected_mall in df_competitors:
67
- competitors = df_competitors[selected_mall]["Store_Brand"].unique()
68
- st.write(f"💡 **Competitors in {selected_mall}:**")
69
- st.write(competitors)
70
- else:
71
- # ✅ Use AI to Predict Competitors for Malls Not in Dataset
 
72
  llm = ChatOpenAI(model="gpt-4", api_key=openai_api_key)
73
- prompt = f"Based on available data, suggest competitors for {selected_mall}."
74
- ai_competitors = llm.invoke(prompt)
75
- st.warning(f"⚠️ No direct competitor data found. AI has predicted competitors:")
76
- st.write(ai_competitors)
77
-
78
- # ✅ AI-Generated Store Recommendations
79
- st.subheader("🔮 AI-Based Store Recommendations")
80
- store_to_replace = st.selectbox("🚪 Select a Store to Replace:", df_kpi["Store_Brand"].unique())
81
-
82
- if store_to_replace:
83
- # ✅ Identify Store Category
84
- prompt = f"Identify the category of {store_to_replace} (e.g., Fashion, Electronics, Footwear, etc.)."
85
- store_category = llm.invoke(prompt)
86
- st.write(f"🔍 **Identified Category:** {store_category}")
87
-
88
- # ✅ Find 3 AI-Recommended Replacement Brands NOT Present in This Mall
89
- all_brands = set(df_kpi["Store_Brand"].unique())
90
- existing_brands = set(df_kpi[df_kpi["Mall"] == selected_mall]["Store_Brand"].unique())
91
- available_replacements = list(all_brands - existing_brands)
92
-
93
- if available_replacements:
94
- prompt = f"Suggest 3 alternative brands in {store_category} category that are not present in {selected_mall}. Possible replacements: {available_replacements}"
95
- ai_recommendations = llm.invoke(prompt)
96
- st.success(f"🔄 **AI Recommended Replacements for {store_to_replace}:**")
97
- st.write(ai_recommendations)
98
- else:
99
- st.warning("⚠️ No new brands found for replacement.")
100
-
101
- # ✅ Machine Learning-Based Sales Prediction
102
- st.subheader("📈 Predict Annual Sales for a New Store")
103
- selected_brand = st.selectbox("🛍️ Select a Brand:", df_kpi["Store_Brand"].unique())
104
-
105
- if selected_brand:
106
- # **Step 1: Select Features**
107
- if "Annual_Sales" in df_kpi.columns:
108
- numeric_cols = df_kpi.select_dtypes(include=["number"]).columns.tolist()
109
- feature_cols = st.multiselect("📊 Select Features for Prediction:", numeric_cols, default=numeric_cols)
110
-
111
- if feature_cols:
112
- # **Step 2: Train Model (Only Once Per File)**
113
- model_save_path = "best_sales_model"
114
- if not os.path.exists(model_save_path):
115
- st.info("🔄 Training the ML Model... (This may take a few seconds)")
116
- setup_reg(df_kpi[feature_cols + ["Annual_Sales"]], target="Annual_Sales", silent=True, session_id=123)
117
- best_model = compare_models()
118
- save_model(best_model, model_save_path)
119
- st.success("✅ Model Training Complete! Best model saved.")
120
-
121
- # **Step 3: Load Trained Model**
122
- best_model = load_model(model_save_path)
123
-
124
- # **Step 4: Predict Sales for a New Store**
125
- ref_store = df_kpi[df_kpi["Store_Brand"] == selected_brand]
126
- if not ref_store.empty:
127
- new_store_data = ref_store[feature_cols].mean().to_frame().T # Use mean as input
128
- predicted_sales = predict_model(best_model, data=new_store_data)["Label"].iloc[0]
129
-
130
- st.write(f"📊 **Predicted Annual Sales for {selected_brand}:** **${predicted_sales:,.2f}**")
131
-
132
- # **Feature Importance Chart**
133
- st.subheader("🔍 Key Factors Affecting Sales")
134
- feature_importance = pull()
135
- st.bar_chart(feature_importance)
136
-
137
- else:
138
- st.warning(f"⚠️ No reference data available to predict sales for {selected_brand}.")
139
-
140
- # ✅ AI Chatbot for Business Insights
141
- st.subheader("💬 AI Chatbot for Business Insights")
142
- sdl = SmartDatalake([df_kpi, *df_competitors.values()], config={
143
- "llm": OpenAI(api_token=openai_api_key),
144
- "use_error_correction_framework": True,
145
- "enable_cache": False,
146
- "enable_restricted_mode": False,
147
- "save_charts": True,
148
- "save_charts_path": "/home/user/app/exports/charts/temp_chart.png"
149
- })
150
-
151
- user_query = st.text_input("🔍 Ask AI About the Dataset:")
152
  if user_query:
153
- with st.spinner("🤖 AI is analyzing..."):
154
  try:
155
- ai_response = sdl.chat(user_query)
156
- st.markdown(f"🤖 **AI Response:** {ai_response}")
 
 
157
  except Exception as e:
158
  st.error(f"❌ AI Error: {str(e)}")
159
 
160
  # ✅ Footer
161
  st.markdown("---")
162
- st.markdown("💡 Built with ❤️ using **Streamlit, PandasAI, PyCaret & GPT-4**")
 
1
  import streamlit as st
2
  import pandas as pd
3
+ import numpy as np
4
  import os
5
  import matplotlib.pyplot as plt
6
  import seaborn as sns
7
+ from sklearn.cluster import KMeans
8
+ from statsmodels.tsa.holtwinters import ExponentialSmoothing
 
 
9
  from langchain_openai import ChatOpenAI
10
+ from dotenv import load_dotenv
 
 
11
 
12
  # ✅ Load Environment Variables
13
  load_dotenv()
14
  openai_api_key = os.getenv("OPENAI_API_KEY")
15
 
16
  if not openai_api_key:
17
+ st.error("❌ OpenAI API Key is missing! Set it in your environment variables.")
18
 
19
+ # ✅ Auto-Load All Files from the Folder
20
+ folder_path = os.getcwd() # Uses current folder
21
 
22
+ # Load KPI Excel File (Main store dataset)
23
+ data_file = os.path.join(folder_path, "kpi.xlsx")
24
+ df = pd.read_excel(data_file, engine="openpyxl")
25
 
26
+ # Load Competitor Mapping Files
 
 
27
  competitor_files = {
28
+ "Deira City Centre": os.path.join(folder_path, "Competitor Mapping Doc Final1(DEIRA CITY CENTRE).csv"),
29
+ "Arabian Centre": os.path.join(folder_path, "Competitor Mapping Doc Final1(ARABIAN CENTRE).csv"),
30
+ "Al Ghurair Centre": os.path.join(folder_path, "Competitor Mapping Doc Final1(AL GHURAIR CENTRE).csv"),
31
+ "Ibn Battuta Mall": os.path.join(folder_path, "Competitor Mapping Doc Final1(IBN BATTUTA MALL).csv"),
32
+ "Dubai Hills": os.path.join(folder_path, "Competitor Mapping Doc Final1(DUBAI HILLS).csv"),
33
  }
34
 
35
+ # Store all competitor data in a dictionary
36
+ competitor_data = {}
37
+ 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, Demand Prediction & Chatbot", layout="wide")
42
+
43
+ # ✅ Title
44
+ st.title("🔄 AI-Powered Store Replacement, Demand Prediction & Chatbot")
 
 
 
 
45
 
46
+ # ✅ Display Data Preview (5 Random Samples)
47
+ st.subheader("📊 Sample Data Preview from KPI Sheet")
48
+ st.dataframe(df.sample(5)) # Show 5 random unique rows
49
 
50
+ # ✅ Store Replacement System
51
+ st.subheader("🏬 AI-Based Store Replacement")
 
 
52
 
53
+ # Select Mall
54
+ selected_mall = st.selectbox("🏬 Select a Mall:", df["Mall"].unique())
 
55
 
56
  if selected_mall:
57
+ # Get all stores in the selected mall
58
+ mall_data = df[df["Mall"] == selected_mall]
59
+
60
+ # Select the store that will be replaced
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-4", api_key=openai_api_key)
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.)."
68
+ store_category = llm.invoke(category_prompt).content
69
+ st.write(f"🔍 **Identified Category:** {store_category}")
70
+
71
+ # ✅ Find 5 Competitors in the Same Mall
72
+ if selected_mall in competitor_data:
73
+ mall_competitor_data = competitor_data[selected_mall]
74
+ competitor_list = mall_competitor_data["Competitors in mall"].dropna().unique()
75
+
76
+ if len(competitor_list) > 5:
77
+ competitor_list = np.random.choice(competitor_list, 5, replace=False)
78
+
79
+ st.subheader("🔎 Competitors in This Mall")
80
+ for competitor in competitor_list:
81
+ st.write(f"- {competitor}")
82
+
83
+ # ✅ AI-Based Store Clustering (Finding Best Replacements)
84
+ store_features = df[["Annual_Sales", "Footfall", "Gross_Margin"]].dropna()
85
+ kmeans = KMeans(n_clusters=5, random_state=42) # 5 Clusters
86
+ df["Cluster"] = kmeans.fit_predict(store_features)
87
+
88
+ # ✅ Find a replacement store in the same category (From kpi.xlsx, Not in this mall)
89
+ all_stores = set(df["Store_Brand"].unique())
90
+ existing_stores = set(mall_data["Store_Brand"].unique())
91
+ potential_replacements = list(all_stores - existing_stores)
92
+
93
+ if potential_replacements:
94
+ replacement_prompt = f"Based on the category {store_category}, suggest 3 stores from the list below that are not already in {selected_mall}. The stores should match the mall’s customer base. Store List: {potential_replacements}"
95
+ replacement_response = llm.invoke(replacement_prompt).content
96
+ replacement_stores = replacement_response.split(", ")
97
+
98
+ st.success(f"🔄 **Recommended Replacement Stores:**")
99
+ for replacement_store in replacement_stores:
100
+ store_data = df[df["Store_Brand"] == replacement_store]
101
+
102
+ if not store_data.empty:
103
+ sales_history = store_data["Annual_Sales"]
104
+ if len(sales_history) > 3:
105
+ # ✅ Time-Series Forecasting for Demand Prediction
106
+ model = ExponentialSmoothing(sales_history, trend="add", seasonal="add", seasonal_periods=3)
107
+ fit = model.fit()
108
+ forecast_sales = fit.forecast(1).values[0] # Predict next year's sales
109
+
110
+ expected_footfall = store_data["Footfall"].mean()
111
+ expected_conversion = store_data["Conversion_Rate"].mean()
112
+ expected_margin = store_data["Gross_Margin"].mean()
113
+
114
+ st.write(f"**{replacement_store}**")
115
+ st.write(f"📊 **Projected Sales:** AED {forecast_sales:,.2f}")
116
+ st.write(f"👣 **Projected Footfall:** {expected_footfall:,.0f} visitors")
117
+ st.write(f"💰 **Projected Margin:** AED {expected_margin:,.2f}")
118
+ st.write(f"🔄 **Projected Conversion Rate:** {expected_conversion:.2f}%")
119
+
120
+ # ✅ Justification
121
+ 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."
122
+ justification = llm.invoke(justification_prompt).content
123
+ st.write(f"🤖 **AI Justification:** {justification}")
124
+
125
+ # ✅ AI Chatbot for Dynamic Insights
126
+ st.subheader("💬 AI-Powered Chatbot")
127
+
128
+ # AI Chatbot using LangChain
129
+ user_query = st.text_input("🔍 Ask anything about store performance, competitors, or pricing:")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  if user_query:
131
+ with st.spinner("🤖 AI is thinking..."):
132
  try:
133
+ chat_prompt = f"Answer the following retail business question based on your market knowledge: {user_query}"
134
+ chat_response = llm.invoke(chat_prompt).content
135
+ st.markdown(f"🤖 **AI Response:** {chat_response}")
136
+
137
  except Exception as e:
138
  st.error(f"❌ AI Error: {str(e)}")
139
 
140
  # ✅ Footer
141
  st.markdown("---")
142
+ st.markdown("💡 Built with ❤️ using **LangChain AI for Store Replacement & Demand Prediction**")