walaa2022 commited on
Commit
4e8c262
·
verified ·
1 Parent(s): bf6a30d

Upload complete-app.py

Browse files
Files changed (1) hide show
  1. complete-app.py +1676 -0
complete-app.py ADDED
@@ -0,0 +1,1676 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # Initialize form values based on selected template
3
+ if selected_template and selected_template != "Custom Scenario":
4
+ new_hires = decision_templates[selected_template]["new_hires"]
5
+ new_marketing = decision_templates[selected_template]["new_marketing"]
6
+ other_expenses = decision_templates[selected_template]["other_expenses"]
7
+ growth_impact = decision_templates[selected_template]["growth_impact"]
8
+ question = decision_templates[selected_template]["question"]
9
+ else:
10
+ new_hires = 0
11
+ new_marketing = 0
12
+ other_expenses = 0
13
+ growth_impact = 0.0
14
+ question = ""
15
+
16
+ # Decision input form
17
+ with st.form("decision_form"):
18
+ st.subheader("Scenario Parameters")
19
+
20
+ col1, col2 = st.columns(2)
21
+
22
+ with col1:
23
+ new_hires = st.number_input("New Engineering Hires", min_value=0, max_value=10, value=new_hires,
24
+ help=f"Each engineer costs ${ENGINEER_SALARY:,} per month")
25
+ st.caption(f"Monthly Cost: ${new_hires * ENGINEER_SALARY:,}")
26
+
27
+ new_marketing = st.number_input("Additional Monthly Marketing Budget",
28
+ min_value=0, max_value=50000, value=new_marketing, step=1000,
29
+ help="Additional marketing spend per month")
30
+
31
+ with col2:
32
+ other_expenses = st.number_input("Other Additional Monthly Expenses",
33
+ min_value=0, max_value=50000, value=other_expenses, step=1000,
34
+ help="Any other additional monthly expenses")
35
+
36
+ growth_impact = st.slider("Estimated Impact on Monthly Growth Rate",
37
+ min_value=0.0, max_value=0.10, value=growth_impact, step=0.01,
38
+ format="%.2f",
39
+ help="Estimated increase in monthly growth rate due to these investments")
40
+ st.caption(f"New Growth Rate: {(startup_data['growth_rate'] + growth_impact) * 100:.1f}% (current: {startup_data['growth_rate'] * 100:.1f}%)")
41
+
42
+ question = st.text_area("Describe your decision scenario",
43
+ value=question,
44
+ height=100,
45
+ placeholder="E.g., We're considering hiring two more engineers and increasing our marketing budget...")
46
+
47
+ decision_summary = f"""
48
+ - {new_hires} new engineers: ${new_hires * ENGINEER_SALARY:,}/month
49
+ - Marketing increase: ${new_marketing:,}/month
50
+ - Other expenses: ${other_expenses:,}/month
51
+ - Total additional burn: ${new_hires * ENGINEER_SALARY + new_marketing + other_expenses:,}/month
52
+ - Growth impact: +{growth_impact * 100:.1f}% monthly growth
53
+ """
54
+
55
+ st.markdown(f"**Decision Summary:**\n{decision_summary}")
56
+
57
+ submitted = st.form_submit_button("Simulate Decision")
58
+
59
+ if submitted:
60
+ # Calculate current and new runway
61
+ current_runway, new_runway, current_df, new_df = simulate_decision(
62
+ startup_data['cash'],
63
+ startup_data['burn_rate'],
64
+ startup_data['revenue'],
65
+ startup_data['growth_rate'],
66
+ other_expenses,
67
+ new_hires,
68
+ new_marketing,
69
+ growth_impact
70
+ )
71
+
72
+ # Display results
73
+ st.markdown("<h3>Decision Impact Analysis</h3>", unsafe_allow_html=True)
74
+
75
+ # Summary metrics
76
+ col1, col2, col3 = st.columns(3)
77
+
78
+ with col1:
79
+ st.metric("Current Runway", f"{current_runway} months")
80
+ with col2:
81
+ runway_change = new_runway - current_runway
82
+ st.metric("New Runway", f"{new_runway} months",
83
+ delta=f"{runway_change} months",
84
+ delta_color="off" if runway_change == 0 else ("normal" if runway_change > 0 else "inverse"))
85
+ with col3:
86
+ new_burn = startup_data['burn_rate'] + other_expenses + (new_hires * ENGINEER_SALARY) + new_marketing
87
+ burn_change = new_burn - startup_data['burn_rate']
88
+ burn_percentage = burn_change / startup_data['burn_rate'] * 100
89
+ st.metric("New Monthly Burn", f"${new_burn:,}",
90
+ delta=f"${burn_change:,} ({burn_percentage:.1f}%)",
91
+ delta_color="inverse")
92
+
93
+ # Cash projection comparison
94
+ st.subheader("Cash Projection Comparison")
95
+
96
+ # Combine dataframes for comparison
97
+ current_df['Scenario'] = 'Current'
98
+ new_df['Scenario'] = 'After Decision'
99
+
100
+ combined_df = pd.concat([current_df, new_df])
101
+ combined_df = combined_df.reset_index()
102
+ combined_df = combined_df.rename(columns={'index': 'Date'})
103
+
104
+ # Plot comparison
105
+ fig = px.line(combined_df, x='Date', y='Cumulative_Cash', color='Scenario',
106
+ title="Cash Runway Comparison",
107
+ labels={'Cumulative_Cash': 'Remaining Cash'},
108
+ color_discrete_sequence=['#4c78a8', '#f58518'])
109
+
110
+ fig.add_hline(y=0, line_dash="dash", line_color="red", annotation_text="Out of Cash")
111
+
112
+ fig.update_layout(
113
+ height=400,
114
+ plot_bgcolor='rgba(240,247,255,0.8)',
115
+ xaxis_title="Date",
116
+ yaxis_title="Cash Balance ($)",
117
+ font=dict(family="Arial, sans-serif", size=12),
118
+ margin=dict(l=20, r=20, t=40, b=20),
119
+ )
120
+
121
+ st.plotly_chart(fig, use_container_width=True)
122
+
123
+ # Get AI analysis
124
+ if question:
125
+ decision_params = {
126
+ "new_hires": new_hires,
127
+ "new_marketing": new_marketing,
128
+ "other_expenses": other_expenses,
129
+ "growth_impact": growth_impact
130
+ }
131
+
132
+ analysis_key = f"decision_analysis_{new_hires}_{new_marketing}_{other_expenses}_{growth_impact}"
133
+ if analysis_key not in st.session_state.insights_cache:
134
+ analysis = generate_ai_response(f"""
135
+ You are a financial advisor for startups. A founder asks:
136
+ "{question}"
137
+
138
+ Here's their current financial situation:
139
+ - Current cash: ${startup_data['cash']}
140
+ - Monthly burn rate: ${startup_data['burn_rate']}
141
+ - Monthly revenue: ${startup_data['revenue']}
142
+ - Monthly growth rate: {startup_data['growth_rate'] * 100}%
143
+
144
+ They're considering these changes:
145
+ - Adding {decision_params['new_hires']} new engineers (${ENGINEER_SALARY}/month each)
146
+ - Increasing marketing budget by ${decision_params['new_marketing']}/month
147
+ - Adding ${decision_params['other_expenses']}/month in other expenses
148
+ - Expecting {decision_params['growth_impact'] * 100}% additional monthly growth
149
+
150
+ Analyze this decision thoroughly:
151
+ 1. Quantify the impact on runway (exact calculation)
152
+ 2. Assess the risk level (low, medium, high)
153
+ 3. Compare the ROI potential
154
+ 4. Provide 3 specific recommendations or alternatives
155
+ 5. Suggest timeline and milestones for implementation if approved
156
+
157
+ Be direct and specific with numbers and timeframes.
158
+ """)
159
+ st.session_state.insights_cache[analysis_key] = analysis
160
+
161
+ st.markdown("<div class='advisor-card'>", unsafe_allow_html=True)
162
+ st.markdown("<span class='ai-badge'>AI Decision Analysis</span>", unsafe_allow_html=True)
163
+ st.markdown(f"<p class='advice-text'>{st.session_state.insights_cache[analysis_key]}</p>", unsafe_allow_html=True)
164
+ st.markdown("</div>", unsafe_allow_html=True)
165
+
166
+ # Risk assessment
167
+ risk_level = "High" if new_runway < 3 else ("Medium" if new_runway < 6 else "Low")
168
+ risk_color = "danger-metric" if risk_level == "High" else ("warning-metric" if risk_level == "Medium" else "good-metric")
169
+
170
+ st.markdown(f"""
171
+ <div class='metric-card'>
172
+ <p class='metric-label'>Risk Assessment</p>
173
+ <p class='metric-value {risk_color}'>{risk_level} Risk Decision</p>
174
+ <p>This decision would give you {new_runway} months of runway.</p>
175
+ </div>
176
+ """, unsafe_allow_html=True)
177
+
178
+ # Render Fund Monitoring page
179
+ def render_fund_monitoring():
180
+ """Render the AI-powered fund monitoring page"""
181
+ if not st.session_state.current_startup or st.session_state.current_startup not in st.session_state.startups:
182
+ st.warning("No startup selected. Please upload data or select a sample startup.")
183
+ render_upload_page()
184
+ return
185
+
186
+ # Get the selected startup data
187
+ transactions_df = st.session_state.startups[st.session_state.current_startup]['transactions']
188
+
189
+ st.markdown("<h1 class='main-header'>Investor Fund Monitoring</h1>", unsafe_allow_html=True)
190
+ st.markdown("<p class='sub-header'>AI-powered fraud detection and spending analysis</p>", unsafe_allow_html=True)
191
+
192
+ # How AI helps with fund monitoring
193
+ with st.expander("ℹ️ How AI enhances fund monitoring"):
194
+ st.markdown("""
195
+ ### How AI Powers Your Fund Monitoring
196
+
197
+ The fund monitoring system uses AI to help maintain investor trust and optimize spending:
198
+
199
+ - **Anomaly Detection**: Our AI models identify unusual transactions that don't match typical startup spending patterns
200
+ - **Risk Scoring**: Each transaction is assigned a risk score based on multiple factors like amount, category, vendor, and description
201
+ - **Pattern Recognition**: The system identifies potentially concerning spending trends across categories over time
202
+ - **Fraud Prevention**: AI algorithms flag transactions that match known patterns of misuse before they become issues
203
+ - **Investor-Ready Reporting**: Generate reports that demonstrate responsible financial stewardship to investors
204
+
205
+ This helps founders maintain investor trust, prevent misuse of funds, and create transparency in financial operations.
206
+ """)
207
+
208
+ st.write("Monitor your startup's spending to maintain investor trust and ensure proper fund usage. Our AI algorithms automatically flag suspicious transactions and identify spending patterns.")
209
+
210
+ # AI insights for fund monitoring
211
+ insights_key = f"fund_monitoring_{date.today().isoformat()}"
212
+ if insights_key not in st.session_state.insights_cache:
213
+ insights = generate_ai_response("""
214
+ You are a financial fraud detection expert. Provide 2-3 critical spending patterns that investors typically look for when monitoring startup fund usage.
215
+ Format as brief bullet points focused on maintaining investor trust.
216
+ """)
217
+ st.session_state.insights_cache[insights_key] = insights
218
+
219
+ with st.expander("🔍 AI Monitoring Insights", expanded=True):
220
+ st.markdown("<span class='ai-badge'>AI-Generated Insights</span>", unsafe_allow_html=True)
221
+ st.markdown(st.session_state.insights_cache[insights_key])
222
+
223
+ # Process transactions to detect suspicious ones with AI enhancement
224
+ processed_df = detect_suspicious_transactions(transactions_df)
225
+
226
+ # Summary metrics
227
+ total_transactions = len(processed_df)
228
+ suspicious_transactions = processed_df[processed_df['Suspicious']].copy()
229
+ suspicious_count = len(suspicious_transactions)
230
+ suspicious_amount = suspicious_transactions['Amount'].sum()
231
+ total_amount = processed_df['Amount'].sum()
232
+
233
+ col1, col2, col3, col4 = st.columns(4)
234
+
235
+ with col1:
236
+ st.markdown(f"""
237
+ <div class='metric-card'>
238
+ <p class='metric-label'>Total Transactions</p>
239
+ <p class='metric-value'>{total_transactions}</p>
240
+ </div>
241
+ """, unsafe_allow_html=True)
242
+
243
+ with col2:
244
+ flagged_percent = suspicious_count/total_transactions*100 if total_transactions > 0 else 0
245
+ status = "danger-metric" if flagged_percent > 10 else ("warning-metric" if flagged_percent > 5 else "good-metric")
246
+ st.markdown(f"""
247
+ <div class='metric-card'>
248
+ <p class='metric-label'>Flagged Transactions</p>
249
+ <p class='metric-value {status}'>{suspicious_count} ({flagged_percent:.1f}%)</p>
250
+ </div>
251
+ """, unsafe_allow_html=True)
252
+
253
+ with col3:
254
+ amount_percent = suspicious_amount/total_amount*100 if total_amount > 0 else 0
255
+ status = "danger-metric" if amount_percent > 15 else ("warning-metric" if amount_percent > 7 else "good-metric")
256
+ st.markdown(f"""
257
+ <div class='metric-card'>
258
+ <p class='metric-label'>Flagged Amount</p>
259
+ <p class='metric-value {status}'>${suspicious_amount:,.0f} ({amount_percent:.1f}%)</p>
260
+ </div>
261
+ """, unsafe_allow_html=True)
262
+
263
+ with col4:
264
+ avg_risk = suspicious_transactions['Risk_Score'].mean() if not suspicious_transactions.empty else 0
265
+ status = "danger-metric" if avg_risk > 50 else ("warning-metric" if avg_risk > 30 else "good-metric")
266
+ st.markdown(f"""
267
+ <div class='metric-card'>
268
+ <p class='metric-label'>Average Risk Score</p>
269
+ <p class='metric-value {status}'>{avg_risk:.1f}/100</p>
270
+ </div>
271
+ """, unsafe_allow_html=True)
272
+
273
+ # Tabs for different views
274
+ tab1, tab2 = st.tabs(["Flagged Transactions", "All Transactions"])
275
+
276
+ with tab1:
277
+ if suspicious_count > 0:
278
+ # Add risk score visualization (color coded)
279
+ suspicious_view = suspicious_transactions.copy()
280
+
281
+ # Display dataframe
282
+ st.dataframe(
283
+ suspicious_view[['Date', 'Category', 'Vendor', 'Amount', 'Description', 'Risk_Score', 'Reason']],
284
+ use_container_width=True
285
+ )
286
+
287
+ # Get AI analysis of suspicious transactions
288
+ fraud_key = f"fraud_{date.today().isoformat()}"
289
+ if fraud_key not in st.session_state.insights_cache:
290
+ suspicious_text = "\n".join([
291
+ f"- {row['Date']}: {row['Vendor']} (${row['Amount']:.2f}) - {row['Description']}"
292
+ for _, row in suspicious_transactions.head(5).iterrows()
293
+ ])
294
+
295
+ fraud_analysis = generate_ai_response(f"""
296
+ You are a financial fraud detection expert. Review these flagged suspicious transactions:
297
+
298
+ {suspicious_text}
299
+
300
+ Provide a detailed analysis:
301
+ 1. Identify concerning patterns in these transactions
302
+ 2. Recommend specific actions to address these issues
303
+ 3. Suggest preventive measures to avoid similar issues in the future
304
+
305
+ Format your response with clear sections and actionable recommendations.
306
+ """)
307
+ st.session_state.insights_cache[fraud_key] = fraud_analysis
308
+
309
+ st.markdown("<div class='advisor-card'>", unsafe_allow_html=True)
310
+ st.markdown("<span class='ai-badge'>AI Fraud Analysis</span>", unsafe_allow_html=True)
311
+ st.markdown(f"<p class='advice-text'>{st.session_state.insights_cache[fraud_key]}</p>", unsafe_allow_html=True)
312
+ st.markdown("</div>", unsafe_allow_html=True)
313
+
314
+ # Action buttons
315
+ st.subheader("Recommended Actions")
316
+
317
+ col1, col2, col3 = st.columns(3)
318
+ with col1:
319
+ if st.button("🔍 Investigate All Flagged"):
320
+ st.session_state.investigation_started = True
321
+ with col2:
322
+ if st.button("📝 Generate Investor Report"):
323
+ st.session_state.report_generated = True
324
+ with col3:
325
+ if st.button("✅ Mark Reviewed"):
326
+ st.session_state.marked_reviewed = True
327
+
328
+ # Simulate action responses
329
+ if 'investigation_started' in st.session_state and st.session_state.investigation_started:
330
+ st.success("Investigation initiated for all flagged transactions. Your financial team will be notified.")
331
+
332
+ if 'report_generated' in st.session_state and st.session_state.report_generated:
333
+ st.success("Investor report generated and ready for review before sending.")
334
+
335
+ if 'marked_reviewed' in st.session_state and st.session_state.marked_reviewed:
336
+ st.success("All transactions marked as reviewed. Status will be updated in the system.")
337
+ else:
338
+ st.success("No suspicious transactions detected by our AI system. Your spending appears to be normal for a startup at your stage.")
339
+
340
+ with tab2:
341
+ st.dataframe(processed_df[['Date', 'Category', 'Vendor', 'Amount', 'Description', 'Suspicious', 'Risk_Score']],
342
+ use_container_width=True)
343
+
344
+ # Spending patterns
345
+ st.subheader("Spending Pattern Analysis")
346
+
347
+ # Category breakdown
348
+ category_spending = processed_df.groupby('Category')['Amount'].sum().reset_index()
349
+
350
+ col1, col2 = st.columns(2)
351
+
352
+ with col1:
353
+ fig = px.bar(category_spending, x='Category', y='Amount',
354
+ title="Spending by Category",
355
+ labels={'Amount': 'Total Spent ($)'},
356
+ color='Amount',
357
+ color_continuous_scale='Blues')
358
+ fig.update_layout(
359
+ height=400,
360
+ plot_bgcolor='rgba(240,247,255,0.8)',
361
+ xaxis_title="Category",
362
+ yaxis_title="Amount Spent ($)",
363
+ font=dict(family="Arial, sans-serif", size=12),
364
+ margin=dict(l=20, r=20, t=40, b=20),
365
+ )
366
+ st.plotly_chart(fig, use_container_width=True)
367
+
368
+ with col2:
369
+ # AI spending pattern analysis
370
+ spending_key = f"spending_pattern_{date.today().isoformat()}"
371
+ if spending_key not in st.session_state.insights_cache:
372
+ spending_pattern_analysis = generate_ai_response("""
373
+ You are a startup spending analyst. Review the spending patterns and provide 3 key insights about:
374
+ 1. Categories that appear to have unusually high spending
375
+ 2. Potential areas where spending could be optimized
376
+ 3. Changes in spending patterns that investors might find concerning
377
+
378
+ Format as concise, actionable bullet points.
379
+ """)
380
+ st.session_state.insights_cache[spending_key] = spending_pattern_analysis
381
+
382
+ st.markdown("<div class='insight-card'>", unsafe_allow_html=True)
383
+ st.markdown("<span class='ai-badge'>AI Spending Analysis</span>", unsafe_allow_html=True)
384
+ st.markdown(st.session_state.insights_cache[spending_key])
385
+ st.markdown("</div>", unsafe_allow_html=True)
386
+
387
+ # AI-powered spending controls recommendation
388
+ st.subheader("AI-Recommended Spending Controls")
389
+
390
+ # Get AI recommendations for spending controls
391
+ controls_key = f"spending_controls_{date.today().isoformat()}"
392
+ if controls_key not in st.session_state.insights_cache:
393
+ controls_recommendations = generate_ai_response("""
394
+ You are a financial controls expert for startups. Based on the spending patterns and suspicious transactions,
395
+ recommend 3-4 specific spending controls that the startup should implement to prevent misuse of funds.
396
+
397
+ For each control, provide:
398
+ 1. A clear policy statement
399
+ 2. Implementation steps
400
+ 3. Expected impact
401
+
402
+ Format as concise, actionable recommendations.
403
+ """)
404
+ st.session_state.insights_cache[controls_key] = controls_recommendations
405
+
406
+ st.markdown("<div class='advisor-card'>", unsafe_allow_html=True)
407
+ st.markdown("<span class='ai-badge'>AI Control Recommendations</span>", unsafe_allow_html=True)
408
+ st.markdown(f"<p class='advice-text'>{st.session_state.insights_cache[controls_key]}</p>", unsafe_allow_html=True)
409
+ st.markdown("</div>", unsafe_allow_html=True)
410
+
411
+ # Call-to-action
412
+ st.info("📅 Need help implementing financial controls? Schedule a session with our AI financial advisor.")
413
+
414
+ # Render AI Financial Advisor page
415
+ def render_ai_financial_advisor():
416
+ """Render the AI financial advisor page with voice chat capabilities"""
417
+ if not st.session_state.current_startup or st.session_state.current_startup not in st.session_state.startups:
418
+ st.warning("No startup selected. Please upload data or select a sample startup.")
419
+ render_upload_page()
420
+ return
421
+
422
+ # Get the selected startup data
423
+ startup_data = st.session_state.startups[st.session_state.current_startup]['profile']
424
+
425
+ st.markdown("<h1 class='main-header'>AI Financial Advisor</h1>", unsafe_allow_html=True)
426
+ st.markdown("<p class='sub-header'>Get expert financial guidance through our AI-powered advisor</p>", unsafe_allow_html=True)
427
+
428
+ # How AI helps with financial advisory
429
+ with st.expander("ℹ️ How AI powers your financial advisor"):
430
+ st.markdown("""
431
+ ### How AI Powers Your Financial Advisor
432
+
433
+ Our AI financial advisor combines advanced language models with financial expertise:
434
+
435
+ - **Natural Language Understanding**: The system interprets complex financial questions in plain English
436
+ - **Domain-Specific Knowledge**: Our AI is trained on startup finance, venture capital, and financial modeling
437
+ - **Context-Aware Responses**: The advisor takes into account your specific financial situation and history
438
+ - **Voice Synthesis**: ElevenLabs voice technology creates natural, high-quality voice responses
439
+ - **Customized Guidance**: AI tailors advice specifically to your stage, industry, and financial position
440
+
441
+ This gives founders 24/7 access to high-quality financial guidance without the high cost of consultants.
442
+ """)
443
+
444
+ # Chat container
445
+ st.markdown("<div style='background-color: #f8f9fa; padding: 20px; border-radius: 10px; margin-bottom: 20px;'>", unsafe_allow_html=True)
446
+
447
+ # Display chat history
448
+ st.subheader("Chat with your Financial Advisor")
449
+
450
+ # Display chat messages
451
+ for message in st.session_state.chat_history:
452
+ if message["role"] == "user":
453
+ st.markdown(f"<div style='background-color: #e6f7ff; padding: 10px; border-radius: 10px; margin-bottom: 10px;'><strong>You:</strong> {message['content']}</div>", unsafe_allow_html=True)
454
+ else:
455
+ st.markdown(f"<div style='background-color: #f0f7ff; padding: 10px; border-radius: 10px; margin-bottom: 10px;'><strong>Financial Advisor:</strong> {message['content']}</div>", unsafe_allow_html=True)
456
+
457
+ # Show play button for voice if it exists
458
+ if 'audio' in message and message['audio']:
459
+ st.audio(message['audio'], format='audio/mp3')
460
+
461
+ # Input for new message
462
+ col1, col2 = st.columns([5, 1])
463
+
464
+ with col1:
465
+ user_input = st.text_input("Ask a financial question", key="user_question")
466
+
467
+ with col2:
468
+ use_voice = st.checkbox("Enable voice", value=True)
469
+
470
+ # Common financial questions
471
+ st.markdown("### Common Questions")
472
+ question_cols = st.columns(3)
473
+
474
+ common_questions = [
475
+ "How much runway do we have at our current burn rate?",
476
+ "Should we increase our marketing spend given our growth rate?",
477
+ "When should we start preparing for our next fundraising round?",
478
+ "How can we optimize our burn rate without impacting growth?",
479
+ "What metrics should we focus on improving right now?",
480
+ "How do our unit economics compare to similar startups?"
481
+ ]
482
+
483
+ selected_question = None
484
+
485
+ for i, question in enumerate(common_questions):
486
+ with question_cols[i % 3]:
487
+ if st.button(question, key=f"q_{i}"):
488
+ selected_question = question
489
+
490
+ # Process user input (either from text input or selected question)
491
+ if user_input or selected_question:
492
+ question = user_input or selected_question
493
+
494
+ # Add user message to chat history
495
+ st.session_state.chat_history.append({"role": "user", "content": question})
496
+
497
+ # Get AI response
498
+ response = generate_ai_response(f"""
499
+ You are a strategic financial advisor for startups. A founder asks:
500
+ "{question}"
501
+
502
+ Here's their current financial situation:
503
+ - Stage: {startup_data['stage']}
504
+ - Current cash: ${startup_data['cash']}
505
+ - Monthly burn rate: ${startup_data['burn_rate']}
506
+ - Monthly revenue: ${startup_data['revenue']}
507
+ - Monthly growth rate: {startup_data['growth_rate'] * 100}%
508
+ - Last funding: {startup_data['last_funding']}
509
+ - Team size: {startup_data['employees']}
510
+
511
+ Provide detailed, actionable advice addressing their question. Include:
512
+ 1. Clear assessment of their current situation
513
+ 2. 3-5 specific, actionable recommendations with expected outcomes
514
+ 3. Relevant metrics they should track
515
+ 4. Industry benchmarks for comparison
516
+ 5. Timeline for implementation and results
517
+
518
+ Be specific with numbers, timeframes, and expected outcomes.
519
+ """)
520
+
521
+ # Generate voice response if enabled
522
+ audio_data = None
523
+ if use_voice:
524
+ audio_data = generate_voice_response(response)
525
+
526
+ # Add AI response to chat history
527
+ st.session_state.chat_history.append({
528
+ "role": "assistant",
529
+ "content": response,
530
+ "audio": audio_data
531
+ })
532
+
533
+ # Rerun to display updated chat
534
+ st.rerun()
535
+
536
+ st.markdown("</div>", unsafe_allow_html=True)
537
+
538
+ # Advanced tools
539
+ st.subheader("Advanced Financial Tools")
540
+
541
+ tool_cols = st.columns(3)
542
+
543
+ with tool_cols[0]:
544
+ st.markdown("""
545
+ <div style='background-color: white; padding: 15px; border-radius: 10px; height: 200px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);'>
546
+ <h4>Financial Model Review</h4>
547
+ <p>Upload your financial model for AI analysis and recommendations.</p>
548
+ <div style='position: absolute; bottom: 15px;'>
549
+ <button disabled style="background-color: #E6F3FF; color: #0066cc; border-radius: 5px; padding: 5px 10px; border: none;">Coming Soon</button>
550
+ </div>
551
+ </div>
552
+ """, unsafe_allow_html=True)
553
+
554
+ with tool_cols[1]:
555
+ st.markdown("""
556
+ <div style='background-color: white; padding: 15px; border-radius: 10px; height: 200px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);'>
557
+ <h4>Investor Pitch Review</h4>
558
+ <p>Get AI feedback on your investor pitch deck and financial projections.</p>
559
+ <div style='position: absolute; bottom: 15px;'>
560
+ <button disabled style="background-color: #E6F3FF; color: #0066cc; border-radius: 5px; padding: 5px 10px; border: none;">Coming Soon</button>
561
+ </div>
562
+ </div>
563
+ """, unsafe_allow_html=True)
564
+
565
+ with tool_cols[2]:
566
+ st.markdown("""
567
+ <div style='background-color: white; padding: 15px; border-radius: 10px; height: 200px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);'>
568
+ <h4>Fundraising Strategy</h4>
569
+ <p>Generate a customized fundraising strategy based on your metrics.</p>
570
+ <div style='position: absolute; bottom: 15px;'>
571
+ <button disabled style="background-color: #E6F3FF; color: #0066cc; border-radius: 5px; padding: 5px 10px; border: none;">Coming Soon</button>
572
+ </div>
573
+ </div>
574
+ """, unsafe_allow_html=True)
575
+
576
+ # Main function
577
+ def main():
578
+ # Initialize Gemini API
579
+ initialize_gemini()
580
+
581
+ # Create sidebar navigation
582
+ create_sidebar()
583
+
584
+ # Render the correct page based on session state
585
+ if st.session_state.current_page == 'upload':
586
+ render_upload_page()
587
+ elif st.session_state.current_page == 'dashboard':
588
+ render_financial_dashboard()
589
+ elif st.session_state.current_page == 'simulator':
590
+ render_decision_simulator()
591
+ elif st.session_state.current_page == 'monitoring':
592
+ render_fund_monitoring()
593
+ elif st.session_state.current_page == 'advisor':
594
+ render_ai_financial_advisor()
595
+
596
+ if __name__ == "__main__":
597
+ main()
598
+ import streamlit as st
599
+ import pandas as pd
600
+ import numpy as np
601
+ import plotly.express as px
602
+ import plotly.graph_objects as go
603
+ from datetime import datetime, timedelta, date
604
+ import time
605
+ import io
606
+ import base64
607
+ import requests
608
+ import google.generativeai as genai
609
+
610
+ # Constants
611
+ DEFAULT_GROWTH_RATE = 0.08 # 8% monthly growth
612
+ DEFAULT_BURN_RATE = 85000 # $85,000 monthly burn
613
+ ENGINEER_SALARY = 10000 # $10,000 monthly cost per engineer ($120K/year)
614
+
615
+ # Initialize session state variables
616
+ if 'startups' not in st.session_state:
617
+ st.session_state.startups = {} # Dictionary to store multiple startup data
618
+ if 'current_startup' not in st.session_state:
619
+ st.session_state.current_startup = None # Currently selected startup
620
+ if 'current_page' not in st.session_state:
621
+ st.session_state.current_page = 'upload' # Default page
622
+ if 'insights_cache' not in st.session_state:
623
+ st.session_state.insights_cache = {}
624
+ if 'chat_history' not in st.session_state:
625
+ st.session_state.chat_history = [
626
+ {"role": "assistant", "content": "Hi there! I'm your AI financial advisor. How can I help with your startup's finances today?"}
627
+ ]
628
+
629
+ # Configure Google GenerativeAI (Gemini)
630
+ def initialize_gemini():
631
+ """Initialize Google's GenerativeAI (Gemini) with API key"""
632
+ try:
633
+ # In production, get this from st.secrets or environment variables
634
+ api_key = st.secrets.get("GEMINI_API_KEY", None)
635
+ if api_key:
636
+ genai.configure(api_key=api_key)
637
+ return True
638
+ else:
639
+ st.warning("Gemini API key not found. Using simulated AI responses.")
640
+ return False
641
+ except Exception as e:
642
+ st.error(f"Failed to initialize Gemini AI: {e}")
643
+ return False
644
+
645
+ def generate_ai_response(prompt, simulate=True):
646
+ """Generate text using Google's GenerativeAI (Gemini)"""
647
+ if simulate:
648
+ # Return a generic response for simulation
649
+ return """
650
+ Based on your financial situation, I recommend focusing on these key areas:
651
+
652
+ 1. **Extend Your Runway**: With your current burn rate, consider reducing non-essential expenses by 15-20%. Focus particularly on optimizing marketing efficiency while maintaining growth activities.
653
+
654
+ 2. **Accelerate Revenue Growth**: Your current monthly growth is good, but increasing it would significantly improve your cash position. Consider focusing sales efforts on higher-value customers with shorter sales cycles.
655
+
656
+ 3. **Prepare for Fundraising**: Begin conversations with existing investors about potential bridge funding. Prepare updated metrics showing clear progress on unit economics and customer acquisition.
657
+
658
+ I recommend reviewing your expense categories weekly and tracking your burn rate closely.
659
+ """
660
+ else:
661
+ try:
662
+ # Initialize Gemini model
663
+ model = genai.GenerativeModel('gemini-pro')
664
+ response = model.generate_content(prompt)
665
+ return response.text
666
+ except Exception as e:
667
+ st.error(f"Error generating AI response: {e}")
668
+ return "Sorry, I couldn't generate a response at this time."
669
+
670
+ def generate_voice_response(text, simulate=True):
671
+ """Generate voice response using ElevenLabs API"""
672
+ if simulate:
673
+ # Return empty audio data for simulation
674
+ return None
675
+ else:
676
+ try:
677
+ # Get API key from secrets
678
+ api_key = st.secrets.get("ELEVENLABS_API_KEY", None)
679
+ if not api_key:
680
+ st.warning("ElevenLabs API key not found. Voice response not available.")
681
+ return None
682
+
683
+ # ElevenLabs API endpoint
684
+ url = "https://api.elevenlabs.io/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM" # Rachel voice ID
685
+
686
+ # Headers and payload
687
+ headers = {
688
+ "Accept": "audio/mpeg",
689
+ "Content-Type": "application/json",
690
+ "xi-api-key": api_key
691
+ }
692
+
693
+ data = {
694
+ "text": text,
695
+ "model_id": "eleven_monolingual_v1",
696
+ "voice_settings": {
697
+ "stability": 0.5,
698
+ "similarity_boost": 0.5
699
+ }
700
+ }
701
+
702
+ # Make the API call
703
+ response = requests.post(url, json=data, headers=headers)
704
+
705
+ if response.status_code == 200:
706
+ return response.content
707
+ else:
708
+ st.error(f"Error with ElevenLabs API: {response.status_code}")
709
+ return None
710
+
711
+ except Exception as e:
712
+ st.error(f"Error generating voice response: {e}")
713
+ return None
714
+
715
+ def switch_page(page_name):
716
+ """Function to switch between pages"""
717
+ st.session_state.current_page = page_name
718
+ st.rerun()
719
+
720
+ # Calculate runway for business decisions
721
+ def calculate_runway(cash, burn_rate, revenue, growth_rate, months=24):
722
+ """
723
+ Calculate runway based on cash, burn, revenue and growth
724
+ Returns runway in months and dataframe with projections
725
+ """
726
+ # Create date range
727
+ current_date = datetime.now()
728
+ date_range = [current_date + timedelta(days=30*i) for i in range(months)]
729
+
730
+ # Initialize data structures
731
+ cash_flow = []
732
+ remaining_cash = cash
733
+ monthly_revenue = revenue
734
+
735
+ # Calculate cash flow for each month
736
+ for i in range(months):
737
+ # Calculate cash flow for this month
738
+ net_burn = burn_rate - monthly_revenue
739
+ cash_flow.append(net_burn)
740
+
741
+ # Update remaining cash
742
+ remaining_cash -= net_burn
743
+
744
+ # Update revenue with growth
745
+ monthly_revenue *= (1 + growth_rate)
746
+
747
+ # Create dataframe
748
+ df = pd.DataFrame({
749
+ 'Net_Burn': cash_flow,
750
+ 'Cumulative_Cash': [cash - sum(cash_flow[:i+1]) for i in range(len(cash_flow))]
751
+ }, index=date_range)
752
+
753
+ # Calculate runway (when cumulative cash goes negative)
754
+ negative_cash = df[df['Cumulative_Cash'] < 0]
755
+ if len(negative_cash) > 0:
756
+ runway_months = (negative_cash.index[0] - current_date).days // 30
757
+ else:
758
+ runway_months = months
759
+
760
+ return runway_months, df
761
+
762
+ # Simulate decisions
763
+ def simulate_decision(cash, burn_rate, revenue, growth_rate,
764
+ additional_expenses, new_hires, marketing_increase, growth_impact):
765
+ """
766
+ Simulate the financial impact of a business decision
767
+ """
768
+ # Current projection
769
+ current_runway, current_df = calculate_runway(
770
+ cash, burn_rate, revenue, growth_rate
771
+ )
772
+
773
+ # New projection with decision impact
774
+ new_burn_rate = burn_rate + additional_expenses + (new_hires * ENGINEER_SALARY) + marketing_increase
775
+ new_growth_rate = growth_rate + growth_impact
776
+
777
+ new_runway, new_df = calculate_runway(
778
+ cash, new_burn_rate, revenue, new_growth_rate
779
+ )
780
+
781
+ return current_runway, new_runway, current_df, new_df
782
+
783
+ # Detect suspicious transactions
784
+ def detect_suspicious_transactions(transactions_df):
785
+ """AI-enhanced suspicious transaction detection."""
786
+ df = transactions_df.copy()
787
+
788
+ # Define thresholds for each category
789
+ category_thresholds = {
790
+ "Travel": 3000,
791
+ "Marketing": 10000,
792
+ "Office": 7000,
793
+ "Software": 6000,
794
+ "Consulting": 5000,
795
+ "Legal": 6000
796
+ }
797
+
798
+ # Define suspicious terms
799
+ suspicious_terms = ['luxury', 'cruise', 'premium', 'personal', 'gift']
800
+
801
+ # Add suspicious column
802
+ df['Suspicious'] = False
803
+ df['Reason'] = ""
804
+ df['Risk_Score'] = 0
805
+
806
+ # Check for suspicious patterns
807
+ for idx, row in df.iterrows():
808
+ reasons = []
809
+ risk_score = 0
810
+
811
+ # Check if amount exceeds category threshold
812
+ if row['Category'] in category_thresholds:
813
+ if row['Amount'] > category_thresholds[row['Category']]:
814
+ reasons.append(f"Amount exceeds typical spending for {row['Category']}")
815
+ risk_score += 30
816
+
817
+ # Higher risk for significantly exceeding threshold
818
+ excess_percentage = (row['Amount'] - category_thresholds[row['Category']]) / category_thresholds[row['Category']] * 100
819
+ if excess_percentage > 100: # More than double the threshold
820
+ risk_score += 20
821
+
822
+ # Check for suspicious vendors or descriptions
823
+ if any(term in str(row['Vendor']).lower() for term in suspicious_terms):
824
+ reasons.append(f"Vendor name contains suspicious term")
825
+ risk_score += 25
826
+
827
+ if any(term in str(row['Description']).lower() for term in suspicious_terms):
828
+ reasons.append(f"Description contains suspicious term")
829
+ risk_score += 20
830
+
831
+ # Check for rounded amounts (potential indicator of estimation/fabrication)
832
+ if row['Amount'] % 1000 == 0 and row['Amount'] > 3000:
833
+ reasons.append(f"Suspiciously round amount")
834
+ risk_score += 15
835
+
836
+ # Mark as suspicious if risk score is high enough
837
+ if risk_score >= 30:
838
+ df.at[idx, 'Suspicious'] = True
839
+ df.at[idx, 'Reason'] = "; ".join(reasons)
840
+ df.at[idx, 'Risk_Score'] = risk_score
841
+
842
+ # Sort by risk score
843
+ df = df.sort_values(by='Risk_Score', ascending=False)
844
+
845
+ return df
846
+
847
+ # Parse CSV file to dataframe
848
+ def parse_csv_to_df(file):
849
+ """Parse uploaded CSV file to Pandas DataFrame"""
850
+ try:
851
+ df = pd.read_csv(file)
852
+ return df, None
853
+ except Exception as e:
854
+ return None, f"Error parsing CSV: {e}"
855
+
856
+ # Page config
857
+ st.set_page_config(
858
+ page_title="StartupFinancePilot",
859
+ page_icon="💰",
860
+ layout="wide",
861
+ initial_sidebar_state="expanded"
862
+ )
863
+
864
+ # Custom CSS
865
+ st.markdown("""
866
+ <style>
867
+ #MainMenu {visibility: hidden;}
868
+ footer {visibility: hidden;}
869
+ .stDeployButton {display:none;}
870
+
871
+ .main-header {
872
+ font-size: 2.5rem;
873
+ color: #0066cc;
874
+ margin-bottom: 0.5rem;
875
+ }
876
+ .sub-header {
877
+ font-size: 1.5rem;
878
+ color: #5c5c5c;
879
+ margin-bottom: 1.5rem;
880
+ }
881
+ .metric-card {
882
+ background-color: #f8f9fa;
883
+ border-radius: 10px;
884
+ padding: 20px;
885
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
886
+ }
887
+ .metric-label {
888
+ font-size: 1rem;
889
+ color: #5c5c5c;
890
+ }
891
+ .metric-value {
892
+ font-size: 1.8rem;
893
+ color: #0066cc;
894
+ font-weight: bold;
895
+ }
896
+ .good-metric {
897
+ color: #28a745;
898
+ }
899
+ .warning-metric {
900
+ color: #ffc107;
901
+ }
902
+ .danger-metric {
903
+ color: #dc3545;
904
+ }
905
+
906
+ /* Style for sidebar buttons */
907
+ div.stButton > button {
908
+ width: 100%;
909
+ padding: 10px 10px;
910
+ border: none;
911
+ background-color: #E6F3FF;
912
+ color: #0066cc;
913
+ border-radius: 10px;
914
+ text-align: left;
915
+ margin: 5px 0;
916
+ font-weight: bold;
917
+ }
918
+
919
+ div.stButton > button:hover {
920
+ background-color: #CCE5FF;
921
+ color: #004080;
922
+ }
923
+
924
+ /* Style for title box */
925
+ .title-box {
926
+ background: linear-gradient(45deg, #0066cc, #66b3ff);
927
+ padding: 20px;
928
+ border-radius: 10px;
929
+ margin-bottom: 20px;
930
+ text-align: center;
931
+ color: white;
932
+ cursor: pointer;
933
+ }
934
+
935
+ .ai-badge {
936
+ display: inline-block;
937
+ background-color: #0066cc;
938
+ color: white;
939
+ border-radius: 4px;
940
+ padding: 2px 6px;
941
+ font-size: 0.7rem;
942
+ font-weight: bold;
943
+ margin-bottom: 8px;
944
+ }
945
+
946
+ .insight-card, .advisor-card {
947
+ background-color: #f8f9fa;
948
+ border-radius: 10px;
949
+ padding: 15px;
950
+ margin-bottom: 20px;
951
+ box-shadow: 0 2px 4px rgba(0,0,0,0.05);
952
+ }
953
+
954
+ .advice-text {
955
+ margin-top: 10px;
956
+ line-height: 1.6;
957
+ }
958
+ </style>
959
+ """, unsafe_allow_html=True)
960
+
961
+ # Create sidebar navigation
962
+ def create_sidebar():
963
+ with st.sidebar:
964
+ # Title box that works as home button
965
+ st.markdown("""
966
+ <div class="title-box">
967
+ <h1>💰 StartupFinancePilot</h1>
968
+ <p>AI-powered financial assistant for startups</p>
969
+ </div>
970
+ """, unsafe_allow_html=True)
971
+
972
+ # Startup selector (if there are startups in the session state)
973
+ if st.session_state.startups:
974
+ st.subheader("Selected Startup")
975
+ startup_names = list(st.session_state.startups.keys())
976
+ selected_startup = st.selectbox(
977
+ "Choose Startup",
978
+ startup_names,
979
+ index=startup_names.index(st.session_state.current_startup) if st.session_state.current_startup in startup_names else 0
980
+ )
981
+ st.session_state.current_startup = selected_startup
982
+
983
+ # Show basic startup info
984
+ if selected_startup in st.session_state.startups:
985
+ startup_data = st.session_state.startups[selected_startup]['profile']
986
+ st.markdown(f"""
987
+ **Stage:** {startup_data['stage']}
988
+ **Cash:** ${startup_data['cash']:,}
989
+ **Monthly Burn:** ${startup_data['burn_rate']:,}
990
+ **Monthly Revenue:** ${startup_data['revenue']:,}
991
+ """)
992
+
993
+ st.markdown("<hr>", unsafe_allow_html=True) # Divider
994
+
995
+ # Upload data button at the top
996
+ if st.button("📤 Upload Startup Data", use_container_width=True):
997
+ switch_page('upload')
998
+
999
+ # Navigation buttons
1000
+ if st.button("📊 Financial Dashboard", use_container_width=True):
1001
+ switch_page('dashboard')
1002
+
1003
+ if st.button("🔮 Decision Simulator", use_container_width=True):
1004
+ switch_page('simulator')
1005
+
1006
+ if st.button("🕵️ Fund Monitoring", use_container_width=True):
1007
+ switch_page('monitoring')
1008
+
1009
+ if st.button("🤖 AI Financial Advisor", use_container_width=True):
1010
+ switch_page('advisor')
1011
+
1012
+ # Upload and process financial data files
1013
+ def render_upload_page():
1014
+ """Render the upload page for startup data"""
1015
+ st.markdown("<h1 class='main-header'>Upload Your Startup Data</h1>", unsafe_allow_html=True)
1016
+ st.markdown("<p class='sub-header'>Upload CSV files or use sample data to get started</p>", unsafe_allow_html=True)
1017
+
1018
+ with st.expander("Upload Instructions", expanded=False):
1019
+ st.markdown("""
1020
+ ### How to Upload Your Startup Data
1021
+
1022
+ You can upload three types of files:
1023
+
1024
+ 1. **Company Profile** - A CSV with basic information about your startup including:
1025
+ - name, stage, founded, employees, last_funding, cash, burn_rate, revenue, growth_rate
1026
+
1027
+ 2. **Cash Flow Data** - A CSV with monthly cash flow data with columns:
1028
+ - Month, Revenue, Payroll, Marketing, Office, Software, Travel, Legal, Misc
1029
+
1030
+ 3. **Transaction Data** - A CSV with transaction details:
1031
+ - Date, Category, Vendor, Amount, Description, Flag
1032
+
1033
+ If you don't have these files ready, you can use our sample data.
1034
+ """)
1035
+
1036
+ col1, col2 = st.columns(2)
1037
+
1038
+ with col1:
1039
+ startup_name = st.text_input("Startup Name", value="My Startup")
1040
+
1041
+ profile_file = st.file_uploader("Upload Company Profile (CSV)", type=['csv'])
1042
+ cash_flow_file = st.file_uploader("Upload Cash Flow Data (CSV)", type=['csv'])
1043
+ transactions_file = st.file_uploader("Upload Transactions Data (CSV)", type=['csv'])
1044
+
1045
+ with col2:
1046
+ st.markdown("""
1047
+ <div style="background-color: #f0f7ff; padding: 15px; border-radius: 10px; height: 90%;">
1048
+ <h4>Why Upload Your Data?</h4>
1049
+ <p>By uploading your actual financial data, you'll get:</p>
1050
+ <ul>
1051
+ <li>Personalized AI insights tailored to your startup</li>
1052
+ <li>Accurate runway projections based on your real spending patterns</li>
1053
+ <li>Custom recommendations to optimize your burn rate</li>
1054
+ <li>More realistic decision simulations</li>
1055
+ </ul>
1056
+ <p>All data is processed securely and never stored permanently.</p>
1057
+ </div>
1058
+ """, unsafe_allow_html=True)
1059
+
1060
+ # Process the files if uploaded
1061
+ if st.button("Process Data"):
1062
+ # Initialize with default values
1063
+ startup_data = {
1064
+ "name": startup_name,
1065
+ "stage": "Seed",
1066
+ "founded": "12 months ago",
1067
+ "employees": 5,
1068
+ "last_funding": "Not specified",
1069
+ "cash": 100000,
1070
+ "burn_rate": 20000,
1071
+ "revenue": 5000,
1072
+ "growth_rate": 0.05
1073
+ }
1074
+
1075
+ cash_flow_df = None
1076
+ transactions_df = None
1077
+
1078
+ # Parse company profile
1079
+ if profile_file:
1080
+ try:
1081
+ profile_df, error = parse_csv_to_df(profile_file)
1082
+ if error:
1083
+ st.error(error)
1084
+ else:
1085
+ # Get the first row as a dictionary
1086
+ if len(profile_df) > 0:
1087
+ startup_data.update(profile_df.iloc[0].to_dict())
1088
+ st.success(f"Successfully loaded company profile for {startup_data['name']}")
1089
+ except Exception as e:
1090
+ st.error(f"Error processing company profile: {e}")
1091
+
1092
+ # Parse cash flow data
1093
+ if cash_flow_file:
1094
+ cash_flow_df, error = parse_csv_to_df(cash_flow_file)
1095
+ if error:
1096
+ st.error(error)
1097
+ else:
1098
+ # Add calculated fields if not present
1099
+ if "Total_Expenses" not in cash_flow_df.columns:
1100
+ expense_columns = [col for col in cash_flow_df.columns if col not in ["Month", "Revenue", "Total_Expenses", "Net_Burn"]]
1101
+ cash_flow_df["Total_Expenses"] = cash_flow_df[expense_columns].sum(axis=1)
1102
+
1103
+ if "Net_Burn" not in cash_flow_df.columns:
1104
+ cash_flow_df["Net_Burn"] = cash_flow_df["Total_Expenses"] - cash_flow_df["Revenue"]
1105
+
1106
+ st.success("Successfully loaded cash flow data")
1107
+
1108
+ # Parse transactions data
1109
+ if transactions_file:
1110
+ transactions_df, error = parse_csv_to_df(transactions_file)
1111
+ if error:
1112
+ st.error(error)
1113
+ else:
1114
+ # Ensure transactions data has required columns
1115
+ required_columns = ["Date", "Category", "Vendor", "Amount", "Description"]
1116
+ if all(col in transactions_df.columns for col in required_columns):
1117
+ if "Flag" not in transactions_df.columns:
1118
+ transactions_df["Flag"] = "Normal" # Default flag
1119
+
1120
+ st.success("Successfully loaded transactions data")
1121
+ else:
1122
+ st.error("Transactions file is missing required columns")
1123
+
1124
+ # If any files were processed, save the data to session state
1125
+ if profile_file or cash_flow_file or transactions_file:
1126
+ # Create a sample cash flow dataframe if none was uploaded
1127
+ if cash_flow_df is None:
1128
+ cash_flow_df = create_sample_cash_flow(startup_data)
1129
+
1130
+ # Create a sample transactions dataframe if none was uploaded
1131
+ if transactions_df is None:
1132
+ transactions_df = create_sample_transactions(startup_data)
1133
+
1134
+ # Store in session state
1135
+ st.session_state.startups[startup_data['name']] = {
1136
+ 'profile': startup_data,
1137
+ 'cash_flow': cash_flow_df,
1138
+ 'transactions': transactions_df
1139
+ }
1140
+
1141
+ # Set as current startup
1142
+ st.session_state.current_startup = startup_data['name']
1143
+
1144
+ st.success(f"Successfully added {startup_data['name']} to your startups")
1145
+ st.info("You can now analyze this startup's data in the dashboard")
1146
+
1147
+ # Redirect to dashboard
1148
+ switch_page('dashboard')
1149
+
1150
+ # Sample data options
1151
+ st.subheader("Or Use Sample Data")
1152
+
1153
+ sample_col1, sample_col2 = st.columns(2)
1154
+
1155
+ with sample_col1:
1156
+ if st.button("Use TechHealth AI Sample"):
1157
+ # Load sample data (function would generate or load from file)
1158
+ load_sample_data("TechHealth AI")
1159
+ st.success("Successfully loaded TechHealth AI sample data")
1160
+ # Redirect to dashboard
1161
+ switch_page('dashboard')
1162
+
1163
+ with sample_col2:
1164
+ if st.button("Use GreenTech Innovations Sample"):
1165
+ # Load another sample (function would generate or load from file)
1166
+ load_sample_data("GreenTech Innovations")
1167
+ st.success("Successfully loaded GreenTech Innovations sample data")
1168
+ # Redirect to dashboard
1169
+ switch_page('dashboard')
1170
+
1171
+ def create_sample_cash_flow(startup_data):
1172
+ """Create a sample cash flow dataframe for a startup"""
1173
+ cash_flow_data = {
1174
+ "Month": [f"Month {i}" for i in range(1, 7)],
1175
+ "Revenue": [startup_data['revenue'] * (1 + startup_data['growth_rate'])**i for i in range(6)],
1176
+ "Payroll": [startup_data['burn_rate'] * 0.7] * 6,
1177
+ "Marketing": [startup_data['burn_rate'] * 0.15] * 6,
1178
+ "Office": [startup_data['burn_rate'] * 0.05] * 6,
1179
+ "Software": [startup_data['burn_rate'] * 0.03] * 6,
1180
+ "Travel": [startup_data['burn_rate'] * 0.02] * 6,
1181
+ "Legal": [startup_data['burn_rate'] * 0.01] * 6,
1182
+ "Misc": [startup_data['burn_rate'] * 0.04] * 6
1183
+ }
1184
+ cash_flow_df = pd.DataFrame(cash_flow_data)
1185
+ cash_flow_df["Total_Expenses"] = cash_flow_df[["Payroll", "Marketing", "Office", "Software", "Travel", "Legal", "Misc"]].sum(axis=1)
1186
+ cash_flow_df["Net_Burn"] = cash_flow_df["Total_Expenses"] - cash_flow_df["Revenue"]
1187
+ return cash_flow_df
1188
+
1189
+ def create_sample_transactions(startup_data):
1190
+ """Create sample transaction data for a startup"""
1191
+ transactions_data = {
1192
+ "Date": [(datetime.now() - timedelta(days=i*5)).strftime("%Y-%m-%d") for i in range(10)],
1193
+ "Category": ["Payroll", "Marketing", "Office", "Software", "Travel", "Legal", "Misc", "Payroll", "Marketing", "Office"],
1194
+ "Vendor": ["Payroll Provider", "Facebook Ads", "Office Rent", "AWS", "Travel Agency", "Legal Firm", "Miscellaneous", "Payroll Provider", "Google Ads", "Office Supplies"],
1195
+ "Amount": [startup_data['burn_rate'] * 0.7, startup_data['burn_rate'] * 0.15, startup_data['burn_rate'] * 0.05, startup_data['burn_rate'] * 0.03, startup_data['burn_rate'] * 0.02, startup_data['burn_rate'] * 0.01, startup_data['burn_rate'] * 0.04, startup_data['burn_rate'] * 0.7, startup_data['burn_rate'] * 0.15, startup_data['burn_rate'] * 0.05],
1196
+ "Description": ["Monthly Payroll", "Ad Campaign", "Monthly Rent", "Cloud Services", "Business Travel", "Legal Services", "Miscellaneous Expenses", "Monthly Payroll", "Ad Campaign", "Office Supplies"],
1197
+ "Flag": ["Normal", "Normal", "Normal", "Normal", "Normal", "Normal", "Normal", "Normal", "Normal", "Normal"]
1198
+ }
1199
+ return pd.DataFrame(transactions_data)
1200
+
1201
+ def load_sample_data(sample_name):
1202
+ """Load sample data for demonstration"""
1203
+ if sample_name == "TechHealth AI":
1204
+ # Create TechHealth AI sample
1205
+ startup_data = {
1206
+ "name": "TechHealth AI",
1207
+ "stage": "Seed",
1208
+ "founded": "18 months ago",
1209
+ "employees": 12,
1210
+ "last_funding": "$1.2M seed round 10 months ago",
1211
+ "cash": 320000,
1212
+ "burn_rate": 85000,
1213
+ "revenue": 15000,
1214
+ "growth_rate": 0.08
1215
+ }
1216
+ else:
1217
+ # Create GreenTech Innovations sample
1218
+ startup_data = {
1219
+ "name": "GreenTech Innovations",
1220
+ "stage": "Series A",
1221
+ "founded": "3 years ago",
1222
+ "employees": 25,
1223
+ "last_funding": "$4.5M Series A 8 months ago",
1224
+ "cash": 2800000,
1225
+ "burn_rate": 220000,
1226
+ "revenue": 75000,
1227
+ "growth_rate": 0.12
1228
+ }
1229
+
1230
+ # Generate cash flow and transaction data
1231
+ cash_flow_df = create_sample_cash_flow(startup_data)
1232
+ transactions_df = create_sample_transactions(startup_data)
1233
+
1234
+ # Add some suspicious transactions for the sample
1235
+ if sample_name == "TechHealth AI":
1236
+ suspicious_transactions = pd.DataFrame([
1237
+ {"Date": "2023-11-05", "Category": "Travel", "Vendor": "Caribbean Cruises", "Amount": 8500, "Description": "Team Retreat Planning", "Flag": "Suspicious"},
1238
+ {"Date": "2023-11-12", "Category": "Marketing", "Vendor": "LuxuryGifts Inc", "Amount": 4200, "Description": "Client Appreciation", "Flag": "Suspicious"},
1239
+ {"Date": "2023-11-22", "Category": "Office", "Vendor": "Premium Furniture", "Amount": 12000, "Description": "Office Upgrades", "Flag": "Suspicious"}
1240
+ ])
1241
+ transactions_df = pd.concat([suspicious_transactions, transactions_df], ignore_index=True)
1242
+
1243
+ # Store in session state
1244
+ st.session_state.startups[startup_data['name']] = {
1245
+ 'profile': startup_data,
1246
+ 'cash_flow': cash_flow_df,
1247
+ 'transactions': transactions_df
1248
+ }
1249
+
1250
+ # Set as current startup
1251
+ st.session_state.current_startup = startup_data['name']
1252
+
1253
+ # Render Financial Dashboard
1254
+ def render_financial_dashboard():
1255
+ """Render the AI-powered financial dashboard page"""
1256
+ if not st.session_state.current_startup or st.session_state.current_startup not in st.session_state.startups:
1257
+ st.warning("No startup selected. Please upload data or select a sample startup.")
1258
+ render_upload_page()
1259
+ return
1260
+
1261
+ # Get the selected startup data
1262
+ startup_data = st.session_state.startups[st.session_state.current_startup]['profile']
1263
+ cash_flow_df = st.session_state.startups[st.session_state.current_startup]['cash_flow']
1264
+
1265
+ st.markdown("<h1 class='main-header'>Financial Dashboard</h1>", unsafe_allow_html=True)
1266
+ st.markdown("<p class='sub-header'>AI-powered financial insights at a glance</p>", unsafe_allow_html=True)
1267
+
1268
+ # How AI helps with financial dashboards
1269
+ with st.expander("ℹ️ How AI enhances your financial dashboard"):
1270
+ st.markdown("""
1271
+ ### How AI Powers Your Financial Dashboard
1272
+
1273
+ The financial dashboard uses AI to transform raw financial data into actionable intelligence:
1274
+
1275
+ - **Automated Analysis**: Instead of manually calculating runway and burn rates, our AI model analyzes your data and highlights critical trends
1276
+ - **Predictive Forecasting**: AI forecasts your runway using pattern recognition and predictive analytics to account for varying growth rates
1277
+ - **Anomaly Detection**: The system identifies unusual spending patterns or concerning financial trends that human analysis might miss
1278
+ - **Strategic Recommendations**: Based on your specific financial situation, the AI provides tailored recommendations to optimize your runway
1279
+ - **Benchmark Comparison**: Your metrics are automatically compared against industry standards for startups at your funding stage
1280
+
1281
+ This helps founders save time, catch financial issues early, and make data-driven decisions without needing financial expertise.
1282
+ """)
1283
+
1284
+ # AI Insights Summary
1285
+ insights_key = f"dashboard_{date.today().isoformat()}"
1286
+ if insights_key not in st.session_state.insights_cache:
1287
+ insights = generate_ai_response(f"""
1288
+ You are a financial advisor for startups. Based on this startup's data:
1289
+ - Current cash: ${startup_data['cash']}
1290
+ - Monthly burn rate: ${startup_data['burn_rate']}
1291
+ - Monthly revenue: ${startup_data['revenue']}
1292
+ - Monthly growth rate: {startup_data['growth_rate'] * 100}%
1293
+
1294
+ Provide the top 3 most important financial insights that the founder should know today.
1295
+ Format each insight as a brief, action-oriented bullet point.
1296
+ """)
1297
+ st.session_state.insights_cache[insights_key] = insights
1298
+
1299
+ with st.expander("📊 AI Financial Insights", expanded=True):
1300
+ st.markdown("<span class='ai-badge'>AI-Generated Insights</span>", unsafe_allow_html=True)
1301
+ st.markdown(st.session_state.insights_cache[insights_key])
1302
+
1303
+ # Key metrics
1304
+ col1, col2, col3, col4 = st.columns(4)
1305
+
1306
+ # Calculate runway
1307
+ runway_months, runway_df = calculate_runway(
1308
+ startup_data['cash'],
1309
+ startup_data['burn_rate'],
1310
+ startup_data['revenue'],
1311
+ startup_data['growth_rate']
1312
+ )
1313
+
1314
+ # Determine status colors based on financial health indicators
1315
+ runway_status = "danger-metric" if runway_months < 6 else ("warning-metric" if runway_months < 9 else "good-metric")
1316
+ burn_status = "danger-metric" if startup_data['burn_rate'] > 100000 else ("warning-metric" if startup_data['burn_rate'] > 80000 else "good-metric")
1317
+ revenue_status = "good-metric" if startup_data['revenue'] > 20000 else ("warning-metric" if startup_data['revenue'] > 10000 else "danger-metric")
1318
+
1319
+ with col1:
1320
+ st.markdown(f"""
1321
+ <div class='metric-card'>
1322
+ <p class='metric-label'>Current Cash</p>
1323
+ <p class='metric-value'>${startup_data['cash']:,}</p>
1324
+ </div>
1325
+ """, unsafe_allow_html=True)
1326
+
1327
+ with col2:
1328
+ st.markdown(f"""
1329
+ <div class='metric-card'>
1330
+ <p class='metric-label'>Monthly Burn</p>
1331
+ <p class='metric-value {burn_status}'>${startup_data['burn_rate']:,}</p>
1332
+ </div>
1333
+ """, unsafe_allow_html=True)
1334
+
1335
+ with col3:
1336
+ st.markdown(f"""
1337
+ <div class='metric-card'>
1338
+ <p class='metric-label'>Monthly Revenue</p>
1339
+ <p class='metric-value {revenue_status}'>${startup_data['revenue']:,}</p>
1340
+ </div>
1341
+ """, unsafe_allow_html=True)
1342
+
1343
+ with col4:
1344
+ st.markdown(f"""
1345
+ <div class='metric-card'>
1346
+ <p class='metric-label'>Runway</p>
1347
+ <p class='metric-value {runway_status}'>{runway_months} months</p>
1348
+ </div>
1349
+ """, unsafe_allow_html=True)
1350
+
1351
+ # Financial charts
1352
+ st.subheader("Financial Overview")
1353
+
1354
+ tab1, tab2, tab3 = st.tabs(["Runway Projection", "Revenue vs. Expenses", "Burn Rate Trend"])
1355
+
1356
+ with tab1:
1357
+ # Runway projection chart
1358
+ fig = px.line(runway_df.reset_index(), x='index', y='Cumulative_Cash',
1359
+ title="Cash Runway Projection",
1360
+ labels={'index': 'Date', 'Cumulative_Cash': 'Remaining Cash ($)'},
1361
+ color_discrete_sequence=['#0066cc'])
1362
+ fig.add_hline(y=0, line_dash="dash", line_color="red", annotation_text="Out of Cash")
1363
+ fig.update_layout(
1364
+ height=400,
1365
+ plot_bgcolor='rgba(240,247,255,0.8)',
1366
+ xaxis_title="Date",
1367
+ yaxis_title="Cash Balance ($)",
1368
+ font=dict(family="Arial, sans-serif", size=12),
1369
+ margin=dict(l=20, r=20, t=40, b=20),
1370
+ )
1371
+ st.plotly_chart(fig, use_container_width=True)
1372
+
1373
+ # Get analysis from AI
1374
+ with st.expander("🔍 AI Financial Analysis", expanded=True):
1375
+ # Use cache to avoid repeated API calls
1376
+ analysis_key = f"runway_{date.today().isoformat()}"
1377
+ if analysis_key not in st.session_state.insights_cache:
1378
+ analysis = generate_ai_response(f"""
1379
+ You are a financial advisor for startups. Analyze this startup's financial data:
1380
+ - Current cash: ${startup_data['cash']}
1381
+ - Monthly burn rate: ${startup_data['burn_rate']}
1382
+ - Monthly revenue: ${startup_data['revenue']}
1383
+ - Monthly growth rate: {startup_data['growth_rate'] * 100}%
1384
+
1385
+ Provide a detailed analysis of their runway and financial health. Include:
1386
+ 1. Exact runway calculation in months
1387
+ 2. Assessment of financial health (critical, concerning, stable, or healthy)
1388
+ 3. Benchmarks compared to similar seed-stage startups
1389
+ 4. Three specific, actionable recommendations to improve runway
1390
+ 5. Key metrics they should focus on
1391
+
1392
+ Format your response in a structured, easy-to-read format with clear sections and bullet points.
1393
+ """)
1394
+ st.session_state.insights_cache[analysis_key] = analysis
1395
+
1396
+ st.markdown("<span class='ai-badge'>AI Financial Analysis</span>", unsafe_allow_html=True)
1397
+ st.markdown(st.session_state.insights_cache[analysis_key])
1398
+
1399
+ with tab2:
1400
+ # Revenue vs Expenses chart
1401
+ rev_exp_df = cash_flow_df.copy()
1402
+ fig = px.bar(rev_exp_df, x='Month', y=['Revenue', 'Total_Expenses'],
1403
+ title="Revenue vs. Expenses",
1404
+ barmode='group',
1405
+ labels={'value': 'Amount ($)', 'variable': 'Category'},
1406
+ color_discrete_sequence=['#28a745', '#dc3545'])
1407
+ fig.update_layout(
1408
+ height=400,
1409
+ plot_bgcolor='rgba(240,247,255,0.8)',
1410
+ xaxis_title="Month",
1411
+ yaxis_title="Amount ($)",
1412
+ font=dict(family="Arial, sans-serif", size=12),
1413
+ legend_title="",
1414
+ margin=dict(l=20, r=20, t=40, b=20),
1415
+ )
1416
+ st.plotly_chart(fig, use_container_width=True)
1417
+
1418
+ # Calculate revenue growth
1419
+ revenue_growth = [(cash_flow_df['Revenue'].iloc[i] / cash_flow_df['Revenue'].iloc[i-1] - 1) * 100 if i > 0 else 0
1420
+ for i in range(len(cash_flow_df))]
1421
+ avg_growth = sum(revenue_growth[1:]) / len(revenue_growth[1:])
1422
+
1423
+ col1, col2 = st.columns(2)
1424
+ with col1:
1425
+ st.metric("Average Monthly Revenue Growth", f"{avg_growth:.1f}%")
1426
+ with col2:
1427
+ expense_growth = (cash_flow_df['Total_Expenses'].iloc[-1] / cash_flow_df['Total_Expenses'].iloc[0] - 1) * 100
1428
+ st.metric("Total Expense Growth", f"{expense_growth:.1f}%", delta=f"{expense_growth - avg_growth:.1f}%", delta_color="inverse")
1429
+
1430
+ with tab3:
1431
+ # Burn rate trend
1432
+ fig = px.line(cash_flow_df, x='Month', y='Net_Burn',
1433
+ title="Monthly Net Burn Trend",
1434
+ labels={'Net_Burn': 'Net Burn ($)'},
1435
+ color_discrete_sequence=['#dc3545'])
1436
+ fig.update_layout(
1437
+ height=400,
1438
+ plot_bgcolor='rgba(240,247,255,0.8)',
1439
+ xaxis_title="Month",
1440
+ yaxis_title="Net Burn ($)",
1441
+ font=dict(family="Arial, sans-serif", size=12),
1442
+ margin=dict(l=20, r=20, t=40, b=20),
1443
+ )
1444
+
1445
+ # Add efficiency ratio as a second y-axis
1446
+ efficiency_ratio = [cash_flow_df['Revenue'].iloc[i] / cash_flow_df['Total_Expenses'].iloc[i] * 100
1447
+ for i in range(len(cash_flow_df))]
1448
+
1449
+ fig.add_trace(go.Scatter(
1450
+ x=cash_flow_df['Month'],
1451
+ y=efficiency_ratio,
1452
+ name='Efficiency Ratio (%)',
1453
+ yaxis='y2',
1454
+ line=dict(color='#0066cc', width=2, dash='dot')
1455
+ ))
1456
+
1457
+ fig.update_layout(
1458
+ yaxis2=dict(
1459
+ title='Efficiency Ratio (%)',
1460
+ overlaying='y',
1461
+ side='right',
1462
+ range=[0, max(efficiency_ratio) * 1.2]
1463
+ )
1464
+ )
1465
+
1466
+ st.plotly_chart(fig, use_container_width=True)
1467
+
1468
+ with st.expander("🔎 Understanding Efficiency Ratio"):
1469
+ st.info("The efficiency ratio measures how efficiently your startup is generating revenue relative to expenses. A higher percentage means you're getting more revenue per dollar spent. Venture-backed startups typically aim for at least 40% before Series B funding.")
1470
+
1471
+ # Expense breakdown
1472
+ st.subheader("Expense Breakdown")
1473
+
1474
+ # Last month expenses
1475
+ last_month = cash_flow_df.iloc[-1]
1476
+ expense_categories = ['Payroll', 'Marketing', 'Office', 'Software', 'Travel', 'Legal', 'Misc']
1477
+ expense_values = [last_month[cat] for cat in expense_categories]
1478
+
1479
+ col1, col2 = st.columns([2, 1])
1480
+
1481
+ with col1:
1482
+ fig = px.pie(values=expense_values, names=expense_categories,
1483
+ title="Current Month Expense Breakdown",
1484
+ color_discrete_sequence=px.colors.sequential.Blues_r)
1485
+ fig.update_layout(
1486
+ height=400,
1487
+ font=dict(family="Arial, sans-serif", size=12),
1488
+ margin=dict(l=20, r=20, t=40, b=20),
1489
+ )
1490
+ fig.update_traces(textposition='inside', textinfo='percent+label')
1491
+ st.plotly_chart(fig, use_container_width=True)
1492
+
1493
+ with col2:
1494
+ # Expense analysis
1495
+ st.markdown("<h4>Expense Analysis</h4>", unsafe_allow_html=True)
1496
+
1497
+ # Calculate industry benchmarks (simulated)
1498
+ benchmarks = {
1499
+ "Payroll": "70-80%",
1500
+ "Marketing": "10-15%",
1501
+ "Office": "5-8%",
1502
+ "Software": "3-5%"
1503
+ }
1504
+
1505
+ # Create a table with expense categories, amounts, and % of total
1506
+ expense_df = pd.DataFrame({
1507
+ "Category": expense_categories,
1508
+ "Amount": expense_values,
1509
+ "% of Total": [v / sum(expense_values) * 100 for v in expense_values]
1510
+ })
1511
+
1512
+ # Add benchmark column
1513
+ expense_df["Industry Benchmark"] = expense_df["Category"].map(
1514
+ lambda x: benchmarks.get(x, "N/A")
1515
+ )
1516
+
1517
+ # Format the dataframe for display
1518
+ formatted_df = expense_df.copy()
1519
+ formatted_df["Amount"] = formatted_df["Amount"].apply(lambda x: f"${x:,.0f}")
1520
+ formatted_df["% of Total"] = formatted_df["% of Total"].apply(lambda x: f"{x:.1f}%")
1521
+
1522
+ st.table(formatted_df)
1523
+
1524
+ # AI-powered spending optimization
1525
+ with st.expander("💡 AI Spending Optimization"):
1526
+ st.markdown("<span class='ai-badge'>AI Recommendation</span>", unsafe_allow_html=True)
1527
+
1528
+ # Use cache to avoid repeated API calls
1529
+ spending_key = f"spending_{date.today().isoformat()}"
1530
+ if spending_key not in st.session_state.insights_cache:
1531
+ spending_recommendation = generate_ai_response("""
1532
+ Based on your expense breakdown, recommend 2-3 specific ways to optimize spending to extend runway.
1533
+ Focus on industry best practices for seed-stage startups.
1534
+ """)
1535
+ st.session_state.insights_cache[spending_key] = spending_recommendation
1536
+
1537
+ st.markdown(st.session_state.insights_cache[spending_key])
1538
+
1539
+ # Fundraising Readiness Assessment
1540
+ st.subheader("Fundraising Readiness")
1541
+
1542
+ # Get AI analysis of fundraising readiness
1543
+ fundraising_key = f"fundraising_{date.today().isoformat()}"
1544
+ if fundraising_key not in st.session_state.insights_cache:
1545
+ # Calculate metrics for assessment
1546
+ runway_calc = startup_data['cash'] / (startup_data['burn_rate'] - startup_data['revenue'])
1547
+
1548
+ # Calculate some example metrics
1549
+ try:
1550
+ mrr_growth = (cash_flow_df['Revenue'].iloc[-1] / cash_flow_df['Revenue'].iloc[-2] - 1) * 100
1551
+ gross_margin = (cash_flow_df['Revenue'].iloc[-1] - cash_flow_df['Total_Expenses'].iloc[-1] / 2) / cash_flow_df['Revenue'].iloc[-1] * 100
1552
+ except:
1553
+ mrr_growth = 5.0
1554
+ gross_margin = 60.0
1555
+
1556
+ metrics = {
1557
+ "MRR Growth": f"{mrr_growth:.1f}%",
1558
+ "Gross Margin": f"{gross_margin:.1f}%",
1559
+ "CAC": "$950", # Example value
1560
+ "LTV": "$4,500", # Example value
1561
+ "Churn": "3.2%", # Example value
1562
+ }
1563
+
1564
+ metrics_text = "\n".join([f"- {k}: {v}" for k, v in metrics.items()])
1565
+
1566
+ fundraising_analysis = generate_ai_response(f"""
1567
+ You are a startup fundraising advisor. Analyze this startup's readiness for their next funding round:
1568
+
1569
+ Company Profile:
1570
+ - Stage: {startup_data['stage']}
1571
+ - Last Funding: {startup_data['last_funding']}
1572
+ - Current Cash: ${startup_data['cash']}
1573
+ - Monthly Burn: ${startup_data['burn_rate']}
1574
+ - Runway: {runway_calc:.1f} months
1575
+
1576
+ Key Metrics:
1577
+ {metrics_text}
1578
+
1579
+ Provide a comprehensive fundraising readiness assessment:
1580
+ 1. Overall fundraising readiness score (0-10)
1581
+ 2. Assessment of current metrics compared to investor expectations for next round
1582
+ 3. Identify the 3 most critical metrics to improve before fundraising
1583
+ 4. Recommend specific targets for each key metric
1584
+ 5. Suggest timeline and specific milestones for fundraising preparation
1585
+ 6. Estimate reasonable valuation range based on metrics and market conditions
1586
+
1587
+ Be specific with numbers, timelines, and actionable targets.
1588
+ """)
1589
+ st.session_state.insights_cache[fundraising_key] = fundraising_analysis
1590
+
1591
+ st.markdown("<div class='advisor-card'>", unsafe_allow_html=True)
1592
+ st.markdown("<span class='ai-badge'>AI Fundraising Assessment</span>", unsafe_allow_html=True)
1593
+ st.markdown(f"<p class='advice-text'>{st.session_state.insights_cache[fundraising_key]}</p>", unsafe_allow_html=True)
1594
+ st.markdown("</div>", unsafe_allow_html=True)
1595
+
1596
+ # Call-to-action for advisor
1597
+ st.info("📅 Need personalized guidance on fundraising? Schedule a session with our AI financial advisor to get detailed recommendations.")
1598
+
1599
+ # Render Decision Simulator page
1600
+ def render_decision_simulator():
1601
+ """Render the AI-powered decision simulator page"""
1602
+ if not st.session_state.current_startup or st.session_state.current_startup not in st.session_state.startups:
1603
+ st.warning("No startup selected. Please upload data or select a sample startup.")
1604
+ render_upload_page()
1605
+ return
1606
+
1607
+ # Get the selected startup data
1608
+ startup_data = st.session_state.startups[st.session_state.current_startup]['profile']
1609
+
1610
+ st.markdown("<h1 class='main-header'>Decision Simulator</h1>", unsafe_allow_html=True)
1611
+ st.markdown("<p class='sub-header'>AI-powered analysis of business decisions</p>", unsafe_allow_html=True)
1612
+
1613
+ # How AI helps with decision-making
1614
+ with st.expander("ℹ️ How AI enhances your decision-making"):
1615
+ st.markdown("""
1616
+ ### How AI Powers Your Decision Simulator
1617
+
1618
+ The decision simulator uses AI to help you make better strategic decisions:
1619
+
1620
+ - **Scenario Analysis**: Our AI model simulates multiple financial scenarios based on your input variables
1621
+ - **Risk Assessment**: The system automatically evaluates risk levels based on your cash runway and growth metrics
1622
+ - **Return Prediction**: AI algorithms predict potential returns on investments like hiring or marketing
1623
+ - **Opportunity Cost Analysis**: The model compares different allocations of capital to maximize growth
1624
+ - **Personalized Recommendations**: Based on your specific situation, the AI provides tailored alternatives
1625
+
1626
+ This helps founders make data-driven decisions with less guesswork, avoid costly mistakes, and optimize resource allocation.
1627
+ """)
1628
+
1629
+ st.write("Test the financial impact of key business decisions before implementing them. Our AI advisor will analyze the risks and benefits.")
1630
+
1631
+ # Quick decision templates
1632
+ st.subheader("Common Scenarios")
1633
+
1634
+ decision_templates = {
1635
+ "Hiring Engineering Team": {
1636
+ "description": "Evaluate the impact of growing your engineering team",
1637
+ "new_hires": 3,
1638
+ "new_marketing": 0,
1639
+ "other_expenses": 2000,
1640
+ "growth_impact": 0.02,
1641
+ "question": "We're considering hiring 3 more engineers to accelerate product development. How will this affect our runway and what growth impact should we expect to justify this investment?"
1642
+ },
1643
+ "Marketing Expansion": {
1644
+ "description": "Test increasing your marketing budget",
1645
+ "new_hires": 0,
1646
+ "new_marketing": 15000,
1647
+ "other_expenses": 0,
1648
+ "growth_impact": 0.04,
1649
+ "question": "We want to increase our marketing spend by $15K/month to drive growth. What growth rate would we need to achieve to make this financially viable?"
1650
+ },
1651
+ "Office Expansion": {
1652
+ "description": "Analyze the cost of moving to a larger office",
1653
+ "new_hires": 0,
1654
+ "new_marketing": 0,
1655
+ "other_expenses": 8000,
1656
+ "growth_impact": 0.01,
1657
+ "question": "We're considering moving to a larger office space that would add $8K/month to our expenses. Is this justified at our current stage?"
1658
+ },
1659
+ "Custom Scenario": {
1660
+ "description": "Create your own custom scenario",
1661
+ "new_hires": 0,
1662
+ "new_marketing": 0,
1663
+ "other_expenses": 0,
1664
+ "growth_impact": 0.0,
1665
+ "question": ""
1666
+ }
1667
+ }
1668
+
1669
+ # Template selection
1670
+ template_cols = st.columns(4)
1671
+ selected_template = None
1672
+
1673
+ for i, (template_name, template) in enumerate(decision_templates.items()):
1674
+ with template_cols[i]:
1675
+ if st.button(f"{template_name}\n{template['description']}", key=f"template_{i}"):
1676
+ selected_template = template_name"