Spaces:
Sleeping
Sleeping
Update app.py
Browse files
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 |
-
|
| 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 |
-
|
| 26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
|
|
|
|
|
|
| 33 |
)
|
| 34 |
|
| 35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
st.subheader("π Sample Data from KPI Sheet")
|
| 68 |
st.dataframe(df_kpi.sample(5))
|
| 69 |
|
| 70 |
-
# β
Select Mall &
|
| 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 |
-
"
|
| 115 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 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
|
| 157 |
-
user_query = st.text_input("π Ask AI
|
| 158 |
-
|
| 159 |
if user_query:
|
| 160 |
try:
|
| 161 |
response = agent.run(user_query)
|
| 162 |
|
| 163 |
-
# β
Detect
|
| 164 |
if "import matplotlib.pyplot" in response or "sns.heatmap" in response:
|
| 165 |
-
st.write("
|
| 166 |
|
|
|
|
| 167 |
code_match = re.search(r"```python\n(.*?)```", response, re.DOTALL)
|
| 168 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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**")
|