walaa2022 commited on
Commit
288a22c
·
verified ·
1 Parent(s): 31589de

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -1676
app.py DELETED
@@ -1,1676 +0,0 @@
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"