WaysAhead Global commited on
Commit
74b3e4a
ยท
verified ยท
1 Parent(s): 5da7db6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +129 -134
app.py CHANGED
@@ -3,161 +3,156 @@ import pandas as pd
3
  import os
4
  import matplotlib.pyplot as plt
5
  import seaborn as sns
6
- from sklearn.cluster import KMeans
7
- from langchain_openai import ChatOpenAI, OpenAIEmbeddings
8
- from langchain.chains import LLMChain
9
- from langchain.prompts import PromptTemplate
10
  from dotenv import load_dotenv
11
- from pycaret.regression import setup as setup_reg, compare_models as compare_reg, predict_model
12
- from pandasai import SmartDataframe
13
- from pandasai.llm.openai import OpenAI
14
- from langchain_community.document_loaders import UnstructuredExcelLoader, CSVLoader
 
 
 
15
  from langchain_community.vectorstores import Chroma
16
  from langchain.text_splitter import RecursiveCharacterTextSplitter
17
 
18
- # โœ… Fix: Set Streamlit Page Config at the Beginning (Before Any Other Streamlit Command)
19
- st.set_page_config(page_title="AI Store Replacement & Demand Prediction", layout="wide")
20
-
21
  # โœ… Load Environment Variables
22
  load_dotenv()
23
  openai_api_key = os.getenv("OPENAI_API_KEY")
24
 
25
  if not openai_api_key:
26
- st.error("โŒ OpenAI API Key is missing! Set it in your environment variables.")
27
-
28
- # โœ… Set chart save path
29
- chart_path = "/home/user/app/exports/charts/temp_chart.png"
30
-
31
- # โœ… Load KPI Excel File
32
- folder_path = os.getcwd()
33
- kpi_file = os.path.join(folder_path, "kpi.xlsx")
34
- st.info("๐Ÿ“‚ Loading KPI data...")
35
- try:
36
- df_kpi = pd.read_excel(kpi_file, engine="openpyxl")
37
- st.success(f"โœ… KPI Data Loaded: {df_kpi.shape[0]} rows, {df_kpi.shape[1]} columns")
38
- except Exception as e:
39
- st.error(f"โŒ Error loading KPI data: {e}")
40
-
41
- # โœ… Show a preview of 5 unique rows instead of full dataset
42
- st.subheader("๐Ÿ“Š Sample Data Preview (5 Unique Rows)")
43
- st.dataframe(df_kpi.drop_duplicates().sample(n=5, random_state=42) if len(df_kpi) > 5 else df_kpi)
44
-
45
- # โœ… Load Competitor Data with Error Handling
46
- competitor_files = {
47
- "DEIRA CITY CENTRE": "Competitor Mapping Doc Final1(DEIRA CITY CENTRE).csv",
48
- "ARABIAN CENTRE": "Competitor Mapping Doc Final1(ARABIAN CENTRE).csv",
49
- "AL GHURAIR CENTRE": "Competitor Mapping Doc Final1(AL GHURAIR CENTRE).csv",
50
- "IBN BATTUTA MALL": "Competitor Mapping Doc Final1(IBN BATTUTA MALL).csv",
51
- "DUBAI HILLS": "Competitor Mapping Doc Final1(DUBAI HILLS).csv"
52
- }
53
-
54
- df_competitors = {}
55
- st.info("๐Ÿ“‚ Loading Competitor Data...")
56
- for mall, file_name in competitor_files.items():
57
- file_path = os.path.join(folder_path, file_name)
58
- if os.path.exists(file_path):
59
- try:
60
- df_competitors[mall] = pd.read_csv(file_path, encoding="ISO-8859-1")
61
- st.success(f"โœ… Competitor Data Loaded for {mall}: {df_competitors[mall].shape[0]} rows")
62
- except Exception as e:
63
- st.error(f"โŒ Error loading {file_name}: {e}")
64
-
65
- # โœ… Load Data into ChromaDB Vector Store with File Error Handling
66
- st.info("๐Ÿ”„ Training AI embeddings on KPI and Competitor data...")
67
- vectorstore = None # Initialize vectorstore to prevent NameError
68
-
69
- try:
70
- loader_kpi = UnstructuredExcelLoader(kpi_file, mode="elements")
71
- kpi_docs = loader_kpi.load()
72
-
73
- competitor_docs = []
74
- for mall, file_path in competitor_files.items():
75
- if os.path.exists(file_path):
76
- try:
77
- loader = CSVLoader(file_path=file_path)
78
- competitor_docs.extend(loader.load())
79
- except Exception as e:
80
- st.error(f"โŒ Error processing {file_path} for embeddings: {e}")
81
-
82
- all_docs = kpi_docs + competitor_docs
83
-
84
- if len(all_docs) > 0:
85
- # โœ… Use RecursiveCharacterTextSplitter for better chunking
86
- text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
87
- split_docs = text_splitter.split_documents(all_docs)
88
-
89
- # โœ… Store in ChromaDB
90
- embeddings = OpenAIEmbeddings(api_key=openai_api_key)
91
- vectorstore = Chroma.from_documents(split_docs, embeddings)
92
- st.success("โœ… AI embeddings trained and stored in ChromaDB successfully!")
93
- else:
94
- st.warning("โš ๏ธ No valid documents were found to train embeddings.")
95
- except Exception as e:
96
- st.error(f"โŒ Error training AI embeddings with ChromaDB: {e}")
97
-
98
- # โœ… Initialize Pandas AI Agent (SmartDataframe)
99
- st.info("๐Ÿ”ง Initializing Pandas AI Agent...")
100
- try:
101
- llm = OpenAI(api_token=openai_api_key)
102
- df_smart = SmartDataframe(df_kpi, config={"llm": llm})
103
- st.success("โœ… Pandas AI Agent Initialized!")
104
- except Exception as e:
105
- st.error(f"โŒ Error initializing Pandas AI Agent: {e}")
106
 
107
  # โœ… Title
108
- st.title("๐Ÿ”„ AI-Powered Store Replacement & Forecasting")
109
 
110
- # โœ… Store Replacement System
111
- st.subheader("๐Ÿฌ AI-Based Store Replacement")
 
112
 
113
- selected_mall = st.selectbox("๐Ÿฌ Select a Mall:", df_kpi["Mall"].unique())
 
 
 
114
 
115
- if selected_mall:
116
- st.info(f"๐Ÿ“Œ Selected Mall: {selected_mall}")
117
- mall_data = df_kpi[df_kpi["Mall"] == selected_mall]
118
 
119
- store_to_replace = st.selectbox("๐Ÿšช Select the store that is closing:", mall_data["Store_Brand"].unique())
 
120
 
121
- if store_to_replace:
122
- st.info(f"๐Ÿ“Œ Store to Replace: {store_to_replace}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
- llm = ChatOpenAI(model="gpt-4", api_key=openai_api_key)
 
125
 
 
 
 
 
 
 
126
  # โœ… Identify Store Category
127
- category_prompt = PromptTemplate.from_template(
128
- "What category does {store_name} belong to? Choose from: Fashion, Electronics, Footwear, Food, Home Decor, etc."
129
- )
130
- category_chain = LLMChain(llm=llm, prompt=category_prompt)
131
- store_category = category_chain.run(store_name=store_to_replace)
132
  st.write(f"๐Ÿ” **Identified Category:** {store_category}")
133
 
134
- # โœ… Find Competitor Stores
135
- if selected_mall in df_competitors:
136
- competitor_list = df_competitors[selected_mall]["Competitor_Stores"].dropna().tolist()
137
- st.success(f"โœ… Retrieved {len(competitor_list)} competitors from dataset.")
 
 
 
 
 
 
 
 
138
  else:
139
- st.warning("โš ๏ธ No competitor data found. Using AI embeddings to predict competitors.")
140
- if vectorstore:
141
- search_results = vectorstore.similarity_search(f"Find competitors for {store_category} in {selected_mall}")
142
- competitor_list = [doc.page_content for doc in search_results]
143
- else:
144
- competitor_list = ["No AI embeddings available."]
145
-
146
- st.subheader("๐Ÿ”Ž Competitors in This Mall")
147
- for competitor in competitor_list:
148
- st.write(f"- {competitor}")
149
-
150
- # โœ… AI Chatbot (Using PandasAI + ChromaDB)
151
- st.subheader("๐Ÿ’ฌ AI-Powered Business Chatbot")
152
- user_query = st.text_input("๐Ÿ” Ask AI About Your Data:")
153
-
154
- if user_query:
155
- st.info(f"๐Ÿง  Processing AI Query: {user_query}")
156
- if "chart" in user_query.lower():
157
- st.image(chart_path, caption="Generated Chart", use_column_width=True)
158
- else:
159
- ai_response = df_smart.chat(user_query)
160
- st.markdown(f"๐Ÿค– **AI Response:** {ai_response}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
 
 
162
  st.markdown("---")
163
- st.markdown("๐Ÿ’ก Built with โค๏ธ using **ChromaDB, AI Store Replacement & Business Analytics**")
 
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
  from langchain_community.vectorstores import Chroma
15
  from langchain.text_splitter import RecursiveCharacterTextSplitter
16
 
 
 
 
17
  # โœ… Load Environment Variables
18
  load_dotenv()
19
  openai_api_key = os.getenv("OPENAI_API_KEY")
20
 
21
  if not openai_api_key:
22
+ st.error("โŒ OpenAI API Key is missing! Set it in your .env file.")
23
+
24
+ # โœ… Streamlit Page Configuration
25
+ st.set_page_config(page_title="AI-Powered Store Recommender & Chatbot", layout="wide")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
  # โœ… Title
28
+ st.title("๐Ÿ›๏ธ AI-Powered Apparel Group Store Recommender & Chatbot")
29
 
30
+ # ๐Ÿ“‚ **File Upload Section**
31
+ uploaded_kpi = st.file_uploader("๐Ÿ“‚ Upload KPI Excel file (.xlsx)", type=["xlsx"], key="file_uploader_kpi")
32
+ uploaded_competitor = st.file_uploader("๐Ÿ“‚ Upload Competitor CSV file (.csv)", type=["csv"], key="file_uploader_competitor")
33
 
34
+ if uploaded_kpi and uploaded_competitor:
35
+ # โœ… Load KPI Data
36
+ df_kpi = pd.read_excel(uploaded_kpi, engine="openpyxl")
37
+ df_competitor = pd.read_csv(uploaded_competitor, encoding="utf-8", on_bad_lines="skip")
38
 
39
+ # โœ… Display Previews
40
+ st.subheader("๐Ÿ“Š KPI Data Preview (5 Unique Rows)")
41
+ st.dataframe(df_kpi.drop_duplicates().sample(n=5, random_state=42) if len(df_kpi) > 5 else df_kpi)
42
 
43
+ st.subheader("๐Ÿ† Competitor Data Preview (5 Unique Rows)")
44
+ st.dataframe(df_competitor.drop_duplicates().sample(n=5, random_state=42) if len(df_competitor) > 5 else df_competitor)
45
 
46
+ # โœ… Select Mall for Competitor Insights
47
+ st.subheader("๐Ÿ”Ž Competitor Analysis")
48
+
49
+ selected_mall = st.selectbox("๐Ÿฌ Select a Mall for Competitor Insights:", df_kpi["Mall"].unique())
50
+
51
+ if selected_mall:
52
+ competitors = df_competitor[df_competitor["Mall"] == selected_mall]["Store_Brand"].unique()
53
+
54
+ if len(competitors) > 0:
55
+ st.write(f"๐Ÿ’ก **Competitors in {selected_mall}:**")
56
+ st.write(competitors)
57
+ else:
58
+ # โœ… Use AI to Predict Competitors for Malls Not in Dataset
59
+ llm = ChatOpenAI(model="gpt-4", api_key=openai_api_key)
60
+ prompt = f"Based on the given KPI and competitor data, suggest competitors for stores in {selected_mall}."
61
+ ai_competitors = llm.invoke(prompt)
62
 
63
+ st.warning(f"โš ๏ธ No direct competitor data found. AI has predicted competitors:")
64
+ st.write(ai_competitors)
65
 
66
+ # โœ… AI-Generated Store Recommendations
67
+ st.subheader("๐Ÿ”ฎ AI-Based Store Recommendations")
68
+
69
+ store_to_replace = st.selectbox("๐Ÿšช Select a Store to Replace:", df_kpi["Store_Brand"].unique())
70
+
71
+ if store_to_replace:
72
  # โœ… Identify Store Category
73
+ prompt = f"Identify the category of {store_to_replace} (e.g., Fashion, Electronics, Footwear, etc.)."
74
+ store_category = llm.invoke(prompt)
75
+
 
 
76
  st.write(f"๐Ÿ” **Identified Category:** {store_category}")
77
 
78
+ # โœ… Find 3 AI-Recommended Replacement Brands NOT Present in This Mall
79
+ all_brands = set(df_kpi["Store_Brand"].unique())
80
+ existing_brands = set(df_kpi[df_kpi["Mall"] == selected_mall]["Store_Brand"].unique())
81
+
82
+ available_replacements = list(all_brands - existing_brands)
83
+
84
+ if available_replacements:
85
+ prompt = f"Suggest 3 alternative brands in {store_category} category that are not present in {selected_mall}. Possible replacements: {available_replacements}"
86
+ ai_recommendations = llm.invoke(prompt)
87
+
88
+ st.success(f"๐Ÿ”„ **AI Recommended Replacements for {store_to_replace}:**")
89
+ st.write(ai_recommendations)
90
  else:
91
+ st.warning("โš ๏ธ No new brands found for replacement.")
92
+
93
+ # โœ… Machine Learning-Based Sales Prediction
94
+ st.subheader("๐Ÿ“ˆ Predict Annual Sales for a New Store")
95
+
96
+ selected_brand = st.selectbox("๐Ÿ›๏ธ Select a Brand:", df_kpi["Store_Brand"].unique())
97
+
98
+ if selected_brand:
99
+ # **Step 1: Select Features**
100
+ if "Annual_Sales" in df_kpi.columns:
101
+ numeric_cols = df_kpi.select_dtypes(include=["number"]).columns.tolist()
102
+ feature_cols = st.multiselect("๐Ÿ“Š Select Features for Prediction:", numeric_cols, default=numeric_cols)
103
+
104
+ if feature_cols:
105
+ # **Step 2: Train Model (Only Once Per File)**
106
+ model_save_path = "best_sales_model"
107
+ if not os.path.exists(model_save_path):
108
+ st.info("๐Ÿ”„ Training the ML Model... (This may take a few seconds)")
109
+ setup_reg(df_kpi[feature_cols + ["Annual_Sales"]], target="Annual_Sales", silent=True, session_id=123)
110
+ best_model = compare_models()
111
+ save_model(best_model, model_save_path)
112
+ st.success("โœ… Model Training Complete! Best model saved.")
113
+
114
+ # **Step 3: Load Trained Model**
115
+ best_model = load_model(model_save_path)
116
+
117
+ # **Step 4: Predict Sales for a New Store**
118
+ ref_store = df_kpi[df_kpi["Store_Brand"] == selected_brand]
119
+
120
+ if not ref_store.empty:
121
+ new_store_data = ref_store[feature_cols].mean().to_frame().T # Use mean as input
122
+ predicted_sales = predict_model(best_model, data=new_store_data)["Label"].iloc[0]
123
+
124
+ st.write(f"๐Ÿ“Š **Predicted Annual Sales for {selected_brand}:** **${predicted_sales:,.2f}**")
125
+
126
+ # **Feature Importance Chart**
127
+ st.subheader("๐Ÿ” Key Factors Affecting Sales")
128
+ feature_importance = pull()
129
+ st.bar_chart(feature_importance)
130
+
131
+ else:
132
+ st.warning(f"โš ๏ธ No reference data available to predict sales for {selected_brand}.")
133
+
134
+ # โœ… AI Chatbot for Business Insights
135
+ st.subheader("๐Ÿ’ฌ AI Chatbot for Business Insights")
136
+
137
+ # โœ… Configure AI for PandasAI Queries
138
+ sdl = SmartDatalake([df_kpi, df_competitor], config={
139
+ "llm": OpenAI(api_token=openai_api_key),
140
+ "use_error_correction_framework": True,
141
+ "enable_cache": False,
142
+ "enable_restricted_mode": False,
143
+ "save_charts": True,
144
+ "save_charts_path": "/home/user/app/exports/charts/temp_chart.png"
145
+ })
146
+
147
+ user_query = st.text_input("๐Ÿ” Ask AI About the Dataset:")
148
+ if user_query:
149
+ with st.spinner("๐Ÿค– AI is analyzing..."):
150
+ try:
151
+ ai_response = sdl.chat(user_query)
152
+ st.markdown(f"๐Ÿค– **AI Response:** {ai_response}")
153
+ except Exception as e:
154
+ st.error(f"โŒ AI Error: {str(e)}")
155
 
156
+ # โœ… Footer
157
  st.markdown("---")
158
+ st.markdown("๐Ÿ’ก Built with โค๏ธ using **Streamlit, PandasAI, PyCaret & GPT-4**")