WaysAheadGlobal commited on
Commit
13d6511
Β·
verified Β·
1 Parent(s): 5806a5d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +147 -46
app.py CHANGED
@@ -13,31 +13,74 @@ import base64
13
  from io import BytesIO
14
  import re
15
  import seaborn as sns
16
-
17
  # βœ… Load Environment Variables
18
  load_dotenv()
19
- openrouter_api_key = os.getenv("OPENROUTER_API_KEY")
20
-
21
- # βœ… Streamlit UI Configuration
22
  st.set_page_config(page_title="AI Store Replacement & KPI Projection", layout="wide")
23
- st.title("πŸ”„ AI-Powered Store Replacement & KPI Projection")
24
 
25
- if not openrouter_api_key:
26
- st.error("❌ OpenRouter API Key is missing! Set it in your environment variables.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
- # βœ… OpenRouter API Configuration with Base URL
29
- llm = ChatOpenAI(
30
- base_url="https://openrouter.ai/api/v1",
31
- openai_api_key=openrouter_api_key,
32
- model_name="deepseek/deepseek-chat"
 
 
33
  )
34
 
35
- # βœ… Load KPI Data
 
 
 
 
36
  folder_path = os.getcwd()
37
  kpi_file = os.path.join(folder_path, "kpi.xlsx")
38
  df_kpi = pd.read_excel(kpi_file, engine="openpyxl")
39
-
40
- # βœ… List of 5 Malls
41
  supported_malls = [
42
  "IBN BATTUTA MALL",
43
  "DUBAI HILLS MALL",
@@ -45,8 +88,7 @@ supported_malls = [
45
  "DEIRA CITY CENTRE DUBAI",
46
  "ARABIAN CENTRE DUBAI"
47
  ]
48
-
49
- # βœ… Load Competitor Mapping Files
50
  mall_files = {
51
  "Deira City Centre": "Competitor Mapping Doc Final1(DEIRA CITY CENTRE).csv",
52
  "Arabian Centre": "Competitor Mapping Doc Final1(ARABIAN CENTRE).csv",
@@ -63,18 +105,25 @@ for mall, file_name in mall_files.items():
63
  except Exception as e:
64
  st.error(f"⚠️ Error loading {file_name}: {e}")
65
 
66
- # βœ… Sample KPI Data Preview
 
 
 
 
 
67
  st.subheader("πŸ“Š Sample Data from KPI Sheet")
68
  st.dataframe(df_kpi.sample(5))
69
 
70
- # βœ… Select Mall & Store for Replacement
71
  selected_mall = st.selectbox("🏬 Select a Mall:", supported_malls)
72
 
73
  if selected_mall:
74
  store_to_replace = st.selectbox("πŸšͺ Select the store to replace:", df_kpi[df_kpi["Mall"] == selected_mall]["Store_Brand"].unique())
75
 
76
  if store_to_replace:
77
- # βœ… AI-Based Category Identification
 
 
78
  category_prompt = PromptTemplate.from_template(
79
  "Given that {store_name} is a retail brand, categorize it broadly (e.g., Fashion, Electronics, Footwear, Food, Home Decor)."
80
  )
@@ -82,12 +131,13 @@ if selected_mall:
82
  store_category = category_chain.run(store_name=store_to_replace)
83
  st.write(f"πŸ” **Identified Category:** {store_category}")
84
 
85
- # βœ… Find Best Replacement Stores (Cosine Similarity)
86
  df_kpi_filtered = df_kpi.drop(columns=["Store_Brand", "Mall", "Location", "City", "Country"]).dropna()
87
  similarity_matrix = cosine_similarity(df_kpi_filtered)
88
  store_index = df_kpi[df_kpi["Store_Brand"] == store_to_replace].index[0]
89
  similarity_scores = list(enumerate(similarity_matrix[store_index]))
90
 
 
91
  recommended_stores = []
92
  used_stores = set(df_kpi[df_kpi["Mall"] == selected_mall]["Store_Brand"].unique())
93
 
@@ -100,51 +150,88 @@ if selected_mall:
100
 
101
  if recommended_stores:
102
  st.success("πŸ”„ **Recommended Replacement Stores:**")
 
103
  for replacement_store in recommended_stores:
104
  store_data = df_kpi[df_kpi["Store_Brand"] == replacement_store]
 
105
  if not store_data.empty:
106
- # βœ… Extract KPI Data
107
  sales = store_data["Annual_Sales"].values[0]
108
  footfall = store_data["Footfall"].values[0]
109
  margin = store_data["Gross_Margin"].values[0]
110
- conversion_rate = store_data["Footfall_Conversion_Percent"].values[0] * 100
111
 
112
  # βœ… AI-Based Justification
113
  justification_prompt = PromptTemplate.from_template(
114
- "Explain why {replacement_store} is the best replacement for {store_to_replace} in {mall_name}, "
115
- "considering these KPIs: Sales: {sales}, Footfall: {footfall}, Margin: {margin}, Conversion Rate: {conversion_rate}%."
 
 
 
 
 
116
  )
117
  justification_chain = LLMChain(llm=llm, prompt=justification_prompt)
118
  justification = justification_chain.run(
119
  replacement_store=replacement_store,
120
  store_to_replace=store_to_replace,
121
  mall_name=selected_mall,
122
- sales=sales,
123
- footfall=footfall,
124
- margin=margin,
125
- conversion_rate=conversion_rate
126
  )
127
 
128
  st.write(f"πŸ“Œ **{replacement_store}**")
129
  st.write(f"πŸ€– **AI Justification:** {justification}")
130
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  # βœ… AI Chatbot with System Prompt
 
 
132
  st.subheader("πŸ’¬ Chat with WaysAhead AI Engine")
133
 
134
  system_prompt = """
135
- You are an AI specializing in retail analytics. You:
136
- - Recommend store replacements based on category and KPIs.
137
- - Generate insights from sales data.
138
- - Create visualizations (bar charts, heatmaps).
139
- - If a visualization request is made, generate clean Python code.
140
  """
141
 
142
  agent = create_pandas_dataframe_agent(
143
- ChatOpenAI(
144
- base_url="https://openrouter.ai/api/v1",
145
- openai_api_key=openrouter_api_key,
146
- model_name="deepseek/deepseek-chat"
147
- ),
148
  df_kpi,
149
  verbose=True,
150
  agent_type="openai-tools",
@@ -153,31 +240,45 @@ agent = create_pandas_dataframe_agent(
153
  system_prompt=system_prompt
154
  )
155
 
156
- # βœ… User Query Input
157
- user_query = st.text_input("πŸ” Ask AI about store replacements or analytics:")
158
-
159
  if user_query:
160
  try:
161
  response = agent.run(user_query)
162
 
163
- # βœ… Detect and Execute Visualization Code
164
  if "import matplotlib.pyplot" in response or "sns.heatmap" in response:
165
- st.write("πŸ–ΌοΈ **Rendering Visualization...**")
166
 
 
167
  code_match = re.search(r"```python\n(.*?)```", response, re.DOTALL)
168
- ai_generated_code = code_match.group(1) if code_match else response
 
 
 
 
 
169
  ai_generated_code = ai_generated_code.replace("```", "").strip()
170
 
 
171
  exec_globals = {"df": df_kpi, "plt": plt, "sns": sns}
 
 
172
  try:
173
  exec(ai_generated_code, exec_globals)
 
 
174
  fig = plt.gcf()
175
  buf = BytesIO()
176
  fig.savefig(buf, format="png")
177
  buf.seek(0)
 
 
178
  st.image(buf, caption="πŸ“Š AI-Generated Chart", use_column_width=True)
 
179
  except Exception as e:
180
  st.error(f"⚠️ Error generating chart: {e}")
 
181
  else:
182
  st.markdown(f"πŸ€– **AI Response:** {response}")
183
 
@@ -185,4 +286,4 @@ if user_query:
185
  st.error(f"⚠️ Error: {e}")
186
 
187
  st.markdown("---")
188
- st.markdown("πŸš€ **Powered by WaysAhead Global AI Engine**")
 
13
  from io import BytesIO
14
  import re
15
  import seaborn as sns
 
16
  # βœ… Load Environment Variables
17
  load_dotenv()
18
+ openai_api_key = os.getenv("OPENAI_API_KEY")
19
+ # βœ… First command MUST be st.set_page_config()
 
20
  st.set_page_config(page_title="AI Store Replacement & KPI Projection", layout="wide")
 
21
 
22
+ # βœ… Disable Right-Click
23
+ # βœ… Hide iframe using CSS
24
+ st.markdown(
25
+ """
26
+ <style>
27
+ iframe {
28
+ display: none !important; /* Hides the iframe */
29
+ visibility: hidden !important; /* Makes it invisible */
30
+ pointer-events: none !important; /* Disables interaction */
31
+ user-select: none !important; /* Prevents text selection */
32
+ }
33
+ </style>
34
+ """,
35
+ unsafe_allow_html=True
36
+ )
37
+
38
+ # βœ… Disable Right-Click & Prevent Inspect Element
39
+ st.markdown(
40
+ """
41
+ <script>
42
+ document.addEventListener("contextmenu", function(event) {
43
+ event.preventDefault();
44
+ });
45
+ document.addEventListener("keydown", function(event) {
46
+ if (event.ctrlKey && (event.key === "u" || event.key === "U" || event.key === "i" || event.key === "I" ||
47
+ event.key === "j" || event.key === "J" || event.key === "c" || event.key === "C")) {
48
+ event.preventDefault();
49
+ }
50
+ });
51
+ setInterval(function() {
52
+ let devtools = /./;
53
+ devtools.toString = function() {
54
+ this.opened = true;
55
+ };
56
+ console.log("%c", devtools);
57
+ if (devtools.opened) {
58
+ alert("🚫 DevTools detected! Please close it.");
59
+ window.location.reload();
60
+ }
61
+ }, 1000);
62
+ </script>
63
+ """,
64
+ unsafe_allow_html=True
65
+ )
66
 
67
+ st.markdown(
68
+ """
69
+ <iframe id="hiddenIframe" src="https://waysaheadglobal-data-analyzer.hf.space"
70
+ style="display: none !important; visibility: hidden !important;">
71
+ </iframe>
72
+ """,
73
+ unsafe_allow_html=True
74
  )
75
 
76
+
77
+ if not openai_api_key:
78
+ st.error("❌ OpenAI API Key is missing! Set it in your environment variables.")
79
+
80
+ # βœ… Load KPI Excel File
81
  folder_path = os.getcwd()
82
  kpi_file = os.path.join(folder_path, "kpi.xlsx")
83
  df_kpi = pd.read_excel(kpi_file, engine="openpyxl")
 
 
84
  supported_malls = [
85
  "IBN BATTUTA MALL",
86
  "DUBAI HILLS MALL",
 
88
  "DEIRA CITY CENTRE DUBAI",
89
  "ARABIAN CENTRE DUBAI"
90
  ]
91
+ # βœ… Load Competitor Mapping Files (ISO-8859-1 Encoding)
 
92
  mall_files = {
93
  "Deira City Centre": "Competitor Mapping Doc Final1(DEIRA CITY CENTRE).csv",
94
  "Arabian Centre": "Competitor Mapping Doc Final1(ARABIAN CENTRE).csv",
 
105
  except Exception as e:
106
  st.error(f"⚠️ Error loading {file_name}: {e}")
107
 
108
+
109
+
110
+ # βœ… Title
111
+ st.title("πŸ”„ AI-Powered Store Replacement & KPI Projection")
112
+
113
+ # βœ… 1️⃣ Sample Data Preview
114
  st.subheader("πŸ“Š Sample Data from KPI Sheet")
115
  st.dataframe(df_kpi.sample(5))
116
 
117
+ # βœ… 2️⃣ Select Mall & Closing Store
118
  selected_mall = st.selectbox("🏬 Select a Mall:", supported_malls)
119
 
120
  if selected_mall:
121
  store_to_replace = st.selectbox("πŸšͺ Select the store to replace:", df_kpi[df_kpi["Mall"] == selected_mall]["Store_Brand"].unique())
122
 
123
  if store_to_replace:
124
+ # βœ… 3️⃣ AI-Based Category Identification
125
+ llm = ChatOpenAI(model="gpt-3.5-turbo", api_key=openai_api_key)
126
+
127
  category_prompt = PromptTemplate.from_template(
128
  "Given that {store_name} is a retail brand, categorize it broadly (e.g., Fashion, Electronics, Footwear, Food, Home Decor)."
129
  )
 
131
  store_category = category_chain.run(store_name=store_to_replace)
132
  st.write(f"πŸ” **Identified Category:** {store_category}")
133
 
134
+ # βœ… 4️⃣ Find Best Replacement Stores (Cosine Similarity)
135
  df_kpi_filtered = df_kpi.drop(columns=["Store_Brand", "Mall", "Location", "City", "Country"]).dropna()
136
  similarity_matrix = cosine_similarity(df_kpi_filtered)
137
  store_index = df_kpi[df_kpi["Store_Brand"] == store_to_replace].index[0]
138
  similarity_scores = list(enumerate(similarity_matrix[store_index]))
139
 
140
+ # βœ… Select top 3 unique stores
141
  recommended_stores = []
142
  used_stores = set(df_kpi[df_kpi["Mall"] == selected_mall]["Store_Brand"].unique())
143
 
 
150
 
151
  if recommended_stores:
152
  st.success("πŸ”„ **Recommended Replacement Stores:**")
153
+
154
  for replacement_store in recommended_stores:
155
  store_data = df_kpi[df_kpi["Store_Brand"] == replacement_store]
156
+
157
  if not store_data.empty:
158
+ # βœ… Extract Numeric Justification from KPI Data
159
  sales = store_data["Annual_Sales"].values[0]
160
  footfall = store_data["Footfall"].values[0]
161
  margin = store_data["Gross_Margin"].values[0]
162
+ conversion_rate = store_data["Footfall_Conversion_Percent"].values[0] * 100 # βœ… Multiply by 100
163
 
164
  # βœ… AI-Based Justification
165
  justification_prompt = PromptTemplate.from_template(
166
+ "Analyze the historical data trends and customer demographics of {mall_name} from your knowledge"
167
+ "Explain why {replacement_store} is the best replacement for {store_to_replace}, considering these factors: "
168
+ "- Customer spending habits at {mall_name}. "
169
+ "- Historical footfall patterns. "
170
+ "- Expected revenue growth for {replacement_store}. "
171
+ "- How it aligns with customer demographics and preferences. "
172
+ "Use these KPIs for prediction: Sales: {sales}, Footfall: {footfall}, Margin: {margin}, Conversion Rate: {conversion_rate}%."
173
  )
174
  justification_chain = LLMChain(llm=llm, prompt=justification_prompt)
175
  justification = justification_chain.run(
176
  replacement_store=replacement_store,
177
  store_to_replace=store_to_replace,
178
  mall_name=selected_mall,
179
+ sales=f"{sales:,.2f} AED",
180
+ footfall=f"{footfall:,.0f} visitors",
181
+ margin=f"{margin:,.2f} AED",
182
+ conversion_rate=f"{conversion_rate:.2f}%"
183
  )
184
 
185
  st.write(f"πŸ“Œ **{replacement_store}**")
186
  st.write(f"πŸ€– **AI Justification:** {justification}")
187
 
188
+ # βœ… Display Projected KPIs
189
+ st.write(f"πŸ“Š **Projected KPIs for {replacement_store}:**")
190
+ st.write(f"πŸ’° **Projected Sales:** AED {sales:,.2f}")
191
+ st.write(f"πŸ‘£ **Projected Footfall:** {footfall:,.0f} visitors")
192
+ st.write(f"πŸ“ˆ **Projected Margin:** AED {margin:,.2f}")
193
+ st.write(f"πŸ”„ **Projected Conversion Rate:** {conversion_rate:.2f}%")
194
+
195
+ # βœ… Fetch Competitors (Prefer Sheet Over AI)
196
+ competitor_list = []
197
+ if selected_mall in mall_data:
198
+ mall_df = mall_data[selected_mall]
199
+ if "Brand Name" in mall_df.columns:
200
+ competitors = mall_df[mall_df["Brand Name"].str.strip().str.lower() == replacement_store.lower()]
201
+ competitor_list = competitors.iloc[:, 2:].dropna(axis=1).values.flatten().tolist()
202
+ competitor_list = [c.strip() for c in competitor_list if isinstance(c, str)]
203
+
204
+ if competitor_list:
205
+ st.subheader(f"πŸ”Ž Competitors of {replacement_store} (from Sheet)")
206
+ for competitor in competitor_list:
207
+ st.write(f"- {competitor}")
208
+ else:
209
+ competitor_ai_prompt = PromptTemplate.from_template(
210
+ "Generate a list of 5 competing brands for {store_name} in the retail industry."
211
+ )
212
+ competitor_ai_chain = LLMChain(llm=llm, prompt=competitor_ai_prompt)
213
+ competitor_list = competitor_ai_chain.run(store_name=replacement_store).split("\n")
214
+
215
+ st.subheader(f"πŸ€– AI-Suggested Competitors for {replacement_store}")
216
+ for competitor in competitor_list:
217
+ st.write(f"- {competitor}")
218
+
219
+
220
  # βœ… AI Chatbot with System Prompt
221
+
222
+
223
  st.subheader("πŸ’¬ Chat with WaysAhead AI Engine")
224
 
225
  system_prompt = """
226
+ You are an advanced AI specializing in retail analytics. You help users:
227
+ 1. Find similar stores based on category and sales performance.
228
+ 2. Generate insights from sales data.
229
+ 3. Create visualizations like bar charts, line charts, and heatmaps.
230
+ 4. If a visualization request is made, generate clean Python code without markdown formatting or any text just give code.
231
  """
232
 
233
  agent = create_pandas_dataframe_agent(
234
+ ChatOpenAI(model="gpt-3.5-turbo", api_key=openai_api_key),
 
 
 
 
235
  df_kpi,
236
  verbose=True,
237
  agent_type="openai-tools",
 
240
  system_prompt=system_prompt
241
  )
242
 
243
+ # βœ… User Input
244
+ user_query = st.text_input("πŸ” Ask AI for similar stores or analytics:")
 
245
  if user_query:
246
  try:
247
  response = agent.run(user_query)
248
 
249
+ # βœ… Detect if AI Generated Python Code for a Chart
250
  if "import matplotlib.pyplot" in response or "sns.heatmap" in response:
251
+ st.write("πŸ›  AI is generating a chart based on your request...")
252
 
253
+ # βœ… Extract Python Code Using Regex
254
  code_match = re.search(r"```python\n(.*?)```", response, re.DOTALL)
255
+ if code_match:
256
+ ai_generated_code = code_match.group(1) # Extracted Python code
257
+ else:
258
+ ai_generated_code = response # Use full response if no markdown formatting
259
+
260
+ # βœ… Remove Any Remaining Triple Quotes or Formatting Issues
261
  ai_generated_code = ai_generated_code.replace("```", "").strip()
262
 
263
+ # βœ… Create a dictionary for exec() and ensure df_kpi is accessible
264
  exec_globals = {"df": df_kpi, "plt": plt, "sns": sns}
265
+
266
+ # βœ… Execute the AI-generated Python Code
267
  try:
268
  exec(ai_generated_code, exec_globals)
269
+
270
+ # βœ… Capture Matplotlib Figure
271
  fig = plt.gcf()
272
  buf = BytesIO()
273
  fig.savefig(buf, format="png")
274
  buf.seek(0)
275
+
276
+ # βœ… Display Image in Streamlit
277
  st.image(buf, caption="πŸ“Š AI-Generated Chart", use_column_width=True)
278
+
279
  except Exception as e:
280
  st.error(f"⚠️ Error generating chart: {e}")
281
+
282
  else:
283
  st.markdown(f"πŸ€– **AI Response:** {response}")
284
 
 
286
  st.error(f"⚠️ Error: {e}")
287
 
288
  st.markdown("---")
289
+ st.markdown("πŸš€ **Powered by WaysAhead Global AI Engine**")