|
|
|
|
|
if selected_template and selected_template != "Custom Scenario": |
|
new_hires = decision_templates[selected_template]["new_hires"] |
|
new_marketing = decision_templates[selected_template]["new_marketing"] |
|
other_expenses = decision_templates[selected_template]["other_expenses"] |
|
growth_impact = decision_templates[selected_template]["growth_impact"] |
|
question = decision_templates[selected_template]["question"] |
|
else: |
|
new_hires = 0 |
|
new_marketing = 0 |
|
other_expenses = 0 |
|
growth_impact = 0.0 |
|
question = "" |
|
|
|
|
|
with st.form("decision_form"): |
|
st.subheader("Scenario Parameters") |
|
|
|
col1, col2 = st.columns(2) |
|
|
|
with col1: |
|
new_hires = st.number_input("New Engineering Hires", min_value=0, max_value=10, value=new_hires, |
|
help=f"Each engineer costs ${ENGINEER_SALARY:,} per month") |
|
st.caption(f"Monthly Cost: ${new_hires * ENGINEER_SALARY:,}") |
|
|
|
new_marketing = st.number_input("Additional Monthly Marketing Budget", |
|
min_value=0, max_value=50000, value=new_marketing, step=1000, |
|
help="Additional marketing spend per month") |
|
|
|
with col2: |
|
other_expenses = st.number_input("Other Additional Monthly Expenses", |
|
min_value=0, max_value=50000, value=other_expenses, step=1000, |
|
help="Any other additional monthly expenses") |
|
|
|
growth_impact = st.slider("Estimated Impact on Monthly Growth Rate", |
|
min_value=0.0, max_value=0.10, value=growth_impact, step=0.01, |
|
format="%.2f", |
|
help="Estimated increase in monthly growth rate due to these investments") |
|
st.caption(f"New Growth Rate: {(startup_data['growth_rate'] + growth_impact) * 100:.1f}% (current: {startup_data['growth_rate'] * 100:.1f}%)") |
|
|
|
question = st.text_area("Describe your decision scenario", |
|
value=question, |
|
height=100, |
|
placeholder="E.g., We're considering hiring two more engineers and increasing our marketing budget...") |
|
|
|
decision_summary = f""" |
|
- {new_hires} new engineers: ${new_hires * ENGINEER_SALARY:,}/month |
|
- Marketing increase: ${new_marketing:,}/month |
|
- Other expenses: ${other_expenses:,}/month |
|
- Total additional burn: ${new_hires * ENGINEER_SALARY + new_marketing + other_expenses:,}/month |
|
- Growth impact: +{growth_impact * 100:.1f}% monthly growth |
|
""" |
|
|
|
st.markdown(f"**Decision Summary:**\n{decision_summary}") |
|
|
|
submitted = st.form_submit_button("Simulate Decision") |
|
|
|
if submitted: |
|
|
|
current_runway, new_runway, current_df, new_df = simulate_decision( |
|
startup_data['cash'], |
|
startup_data['burn_rate'], |
|
startup_data['revenue'], |
|
startup_data['growth_rate'], |
|
other_expenses, |
|
new_hires, |
|
new_marketing, |
|
growth_impact |
|
) |
|
|
|
|
|
st.markdown("<h3>Decision Impact Analysis</h3>", unsafe_allow_html=True) |
|
|
|
|
|
col1, col2, col3 = st.columns(3) |
|
|
|
with col1: |
|
st.metric("Current Runway", f"{current_runway} months") |
|
with col2: |
|
runway_change = new_runway - current_runway |
|
st.metric("New Runway", f"{new_runway} months", |
|
delta=f"{runway_change} months", |
|
delta_color="off" if runway_change == 0 else ("normal" if runway_change > 0 else "inverse")) |
|
with col3: |
|
new_burn = startup_data['burn_rate'] + other_expenses + (new_hires * ENGINEER_SALARY) + new_marketing |
|
burn_change = new_burn - startup_data['burn_rate'] |
|
burn_percentage = burn_change / startup_data['burn_rate'] * 100 |
|
st.metric("New Monthly Burn", f"${new_burn:,}", |
|
delta=f"${burn_change:,} ({burn_percentage:.1f}%)", |
|
delta_color="inverse") |
|
|
|
|
|
st.subheader("Cash Projection Comparison") |
|
|
|
|
|
current_df['Scenario'] = 'Current' |
|
new_df['Scenario'] = 'After Decision' |
|
|
|
combined_df = pd.concat([current_df, new_df]) |
|
combined_df = combined_df.reset_index() |
|
combined_df = combined_df.rename(columns={'index': 'Date'}) |
|
|
|
|
|
fig = px.line(combined_df, x='Date', y='Cumulative_Cash', color='Scenario', |
|
title="Cash Runway Comparison", |
|
labels={'Cumulative_Cash': 'Remaining Cash'}, |
|
color_discrete_sequence=['#4c78a8', '#f58518']) |
|
|
|
fig.add_hline(y=0, line_dash="dash", line_color="red", annotation_text="Out of Cash") |
|
|
|
fig.update_layout( |
|
height=400, |
|
plot_bgcolor='rgba(240,247,255,0.8)', |
|
xaxis_title="Date", |
|
yaxis_title="Cash Balance ($)", |
|
font=dict(family="Arial, sans-serif", size=12), |
|
margin=dict(l=20, r=20, t=40, b=20), |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
if question: |
|
decision_params = { |
|
"new_hires": new_hires, |
|
"new_marketing": new_marketing, |
|
"other_expenses": other_expenses, |
|
"growth_impact": growth_impact |
|
} |
|
|
|
analysis_key = f"decision_analysis_{new_hires}_{new_marketing}_{other_expenses}_{growth_impact}" |
|
if analysis_key not in st.session_state.insights_cache: |
|
analysis = generate_ai_response(f""" |
|
You are a financial advisor for startups. A founder asks: |
|
"{question}" |
|
|
|
Here's their current financial situation: |
|
- Current cash: ${startup_data['cash']} |
|
- Monthly burn rate: ${startup_data['burn_rate']} |
|
- Monthly revenue: ${startup_data['revenue']} |
|
- Monthly growth rate: {startup_data['growth_rate'] * 100}% |
|
|
|
They're considering these changes: |
|
- Adding {decision_params['new_hires']} new engineers (${ENGINEER_SALARY}/month each) |
|
- Increasing marketing budget by ${decision_params['new_marketing']}/month |
|
- Adding ${decision_params['other_expenses']}/month in other expenses |
|
- Expecting {decision_params['growth_impact'] * 100}% additional monthly growth |
|
|
|
Analyze this decision thoroughly: |
|
1. Quantify the impact on runway (exact calculation) |
|
2. Assess the risk level (low, medium, high) |
|
3. Compare the ROI potential |
|
4. Provide 3 specific recommendations or alternatives |
|
5. Suggest timeline and milestones for implementation if approved |
|
|
|
Be direct and specific with numbers and timeframes. |
|
""") |
|
st.session_state.insights_cache[analysis_key] = analysis |
|
|
|
st.markdown("<div class='advisor-card'>", unsafe_allow_html=True) |
|
st.markdown("<span class='ai-badge'>AI Decision Analysis</span>", unsafe_allow_html=True) |
|
st.markdown(f"<p class='advice-text'>{st.session_state.insights_cache[analysis_key]}</p>", unsafe_allow_html=True) |
|
st.markdown("</div>", unsafe_allow_html=True) |
|
|
|
|
|
risk_level = "High" if new_runway < 3 else ("Medium" if new_runway < 6 else "Low") |
|
risk_color = "danger-metric" if risk_level == "High" else ("warning-metric" if risk_level == "Medium" else "good-metric") |
|
|
|
st.markdown(f""" |
|
<div class='metric-card'> |
|
<p class='metric-label'>Risk Assessment</p> |
|
<p class='metric-value {risk_color}'>{risk_level} Risk Decision</p> |
|
<p>This decision would give you {new_runway} months of runway.</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
def render_fund_monitoring(): |
|
"""Render the AI-powered fund monitoring page""" |
|
if not st.session_state.current_startup or st.session_state.current_startup not in st.session_state.startups: |
|
st.warning("No startup selected. Please upload data or select a sample startup.") |
|
render_upload_page() |
|
return |
|
|
|
|
|
transactions_df = st.session_state.startups[st.session_state.current_startup]['transactions'] |
|
|
|
st.markdown("<h1 class='main-header'>Investor Fund Monitoring</h1>", unsafe_allow_html=True) |
|
st.markdown("<p class='sub-header'>AI-powered fraud detection and spending analysis</p>", unsafe_allow_html=True) |
|
|
|
|
|
with st.expander("ℹ️ How AI enhances fund monitoring"): |
|
st.markdown(""" |
|
### How AI Powers Your Fund Monitoring |
|
|
|
The fund monitoring system uses AI to help maintain investor trust and optimize spending: |
|
|
|
- **Anomaly Detection**: Our AI models identify unusual transactions that don't match typical startup spending patterns |
|
- **Risk Scoring**: Each transaction is assigned a risk score based on multiple factors like amount, category, vendor, and description |
|
- **Pattern Recognition**: The system identifies potentially concerning spending trends across categories over time |
|
- **Fraud Prevention**: AI algorithms flag transactions that match known patterns of misuse before they become issues |
|
- **Investor-Ready Reporting**: Generate reports that demonstrate responsible financial stewardship to investors |
|
|
|
This helps founders maintain investor trust, prevent misuse of funds, and create transparency in financial operations. |
|
""") |
|
|
|
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.") |
|
|
|
|
|
insights_key = f"fund_monitoring_{date.today().isoformat()}" |
|
if insights_key not in st.session_state.insights_cache: |
|
insights = generate_ai_response(""" |
|
You are a financial fraud detection expert. Provide 2-3 critical spending patterns that investors typically look for when monitoring startup fund usage. |
|
Format as brief bullet points focused on maintaining investor trust. |
|
""") |
|
st.session_state.insights_cache[insights_key] = insights |
|
|
|
with st.expander("🔍 AI Monitoring Insights", expanded=True): |
|
st.markdown("<span class='ai-badge'>AI-Generated Insights</span>", unsafe_allow_html=True) |
|
st.markdown(st.session_state.insights_cache[insights_key]) |
|
|
|
|
|
processed_df = detect_suspicious_transactions(transactions_df) |
|
|
|
|
|
total_transactions = len(processed_df) |
|
suspicious_transactions = processed_df[processed_df['Suspicious']].copy() |
|
suspicious_count = len(suspicious_transactions) |
|
suspicious_amount = suspicious_transactions['Amount'].sum() |
|
total_amount = processed_df['Amount'].sum() |
|
|
|
col1, col2, col3, col4 = st.columns(4) |
|
|
|
with col1: |
|
st.markdown(f""" |
|
<div class='metric-card'> |
|
<p class='metric-label'>Total Transactions</p> |
|
<p class='metric-value'>{total_transactions}</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
with col2: |
|
flagged_percent = suspicious_count/total_transactions*100 if total_transactions > 0 else 0 |
|
status = "danger-metric" if flagged_percent > 10 else ("warning-metric" if flagged_percent > 5 else "good-metric") |
|
st.markdown(f""" |
|
<div class='metric-card'> |
|
<p class='metric-label'>Flagged Transactions</p> |
|
<p class='metric-value {status}'>{suspicious_count} ({flagged_percent:.1f}%)</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
with col3: |
|
amount_percent = suspicious_amount/total_amount*100 if total_amount > 0 else 0 |
|
status = "danger-metric" if amount_percent > 15 else ("warning-metric" if amount_percent > 7 else "good-metric") |
|
st.markdown(f""" |
|
<div class='metric-card'> |
|
<p class='metric-label'>Flagged Amount</p> |
|
<p class='metric-value {status}'>${suspicious_amount:,.0f} ({amount_percent:.1f}%)</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
with col4: |
|
avg_risk = suspicious_transactions['Risk_Score'].mean() if not suspicious_transactions.empty else 0 |
|
status = "danger-metric" if avg_risk > 50 else ("warning-metric" if avg_risk > 30 else "good-metric") |
|
st.markdown(f""" |
|
<div class='metric-card'> |
|
<p class='metric-label'>Average Risk Score</p> |
|
<p class='metric-value {status}'>{avg_risk:.1f}/100</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
tab1, tab2 = st.tabs(["Flagged Transactions", "All Transactions"]) |
|
|
|
with tab1: |
|
if suspicious_count > 0: |
|
|
|
suspicious_view = suspicious_transactions.copy() |
|
|
|
|
|
st.dataframe( |
|
suspicious_view[['Date', 'Category', 'Vendor', 'Amount', 'Description', 'Risk_Score', 'Reason']], |
|
use_container_width=True |
|
) |
|
|
|
|
|
fraud_key = f"fraud_{date.today().isoformat()}" |
|
if fraud_key not in st.session_state.insights_cache: |
|
suspicious_text = "\n".join([ |
|
f"- {row['Date']}: {row['Vendor']} (${row['Amount']:.2f}) - {row['Description']}" |
|
for _, row in suspicious_transactions.head(5).iterrows() |
|
]) |
|
|
|
fraud_analysis = generate_ai_response(f""" |
|
You are a financial fraud detection expert. Review these flagged suspicious transactions: |
|
|
|
{suspicious_text} |
|
|
|
Provide a detailed analysis: |
|
1. Identify concerning patterns in these transactions |
|
2. Recommend specific actions to address these issues |
|
3. Suggest preventive measures to avoid similar issues in the future |
|
|
|
Format your response with clear sections and actionable recommendations. |
|
""") |
|
st.session_state.insights_cache[fraud_key] = fraud_analysis |
|
|
|
st.markdown("<div class='advisor-card'>", unsafe_allow_html=True) |
|
st.markdown("<span class='ai-badge'>AI Fraud Analysis</span>", unsafe_allow_html=True) |
|
st.markdown(f"<p class='advice-text'>{st.session_state.insights_cache[fraud_key]}</p>", unsafe_allow_html=True) |
|
st.markdown("</div>", unsafe_allow_html=True) |
|
|
|
|
|
st.subheader("Recommended Actions") |
|
|
|
col1, col2, col3 = st.columns(3) |
|
with col1: |
|
if st.button("🔍 Investigate All Flagged"): |
|
st.session_state.investigation_started = True |
|
with col2: |
|
if st.button("📝 Generate Investor Report"): |
|
st.session_state.report_generated = True |
|
with col3: |
|
if st.button("✅ Mark Reviewed"): |
|
st.session_state.marked_reviewed = True |
|
|
|
|
|
if 'investigation_started' in st.session_state and st.session_state.investigation_started: |
|
st.success("Investigation initiated for all flagged transactions. Your financial team will be notified.") |
|
|
|
if 'report_generated' in st.session_state and st.session_state.report_generated: |
|
st.success("Investor report generated and ready for review before sending.") |
|
|
|
if 'marked_reviewed' in st.session_state and st.session_state.marked_reviewed: |
|
st.success("All transactions marked as reviewed. Status will be updated in the system.") |
|
else: |
|
st.success("No suspicious transactions detected by our AI system. Your spending appears to be normal for a startup at your stage.") |
|
|
|
with tab2: |
|
st.dataframe(processed_df[['Date', 'Category', 'Vendor', 'Amount', 'Description', 'Suspicious', 'Risk_Score']], |
|
use_container_width=True) |
|
|
|
|
|
st.subheader("Spending Pattern Analysis") |
|
|
|
|
|
category_spending = processed_df.groupby('Category')['Amount'].sum().reset_index() |
|
|
|
col1, col2 = st.columns(2) |
|
|
|
with col1: |
|
fig = px.bar(category_spending, x='Category', y='Amount', |
|
title="Spending by Category", |
|
labels={'Amount': 'Total Spent ($)'}, |
|
color='Amount', |
|
color_continuous_scale='Blues') |
|
fig.update_layout( |
|
height=400, |
|
plot_bgcolor='rgba(240,247,255,0.8)', |
|
xaxis_title="Category", |
|
yaxis_title="Amount Spent ($)", |
|
font=dict(family="Arial, sans-serif", size=12), |
|
margin=dict(l=20, r=20, t=40, b=20), |
|
) |
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
with col2: |
|
|
|
spending_key = f"spending_pattern_{date.today().isoformat()}" |
|
if spending_key not in st.session_state.insights_cache: |
|
spending_pattern_analysis = generate_ai_response(""" |
|
You are a startup spending analyst. Review the spending patterns and provide 3 key insights about: |
|
1. Categories that appear to have unusually high spending |
|
2. Potential areas where spending could be optimized |
|
3. Changes in spending patterns that investors might find concerning |
|
|
|
Format as concise, actionable bullet points. |
|
""") |
|
st.session_state.insights_cache[spending_key] = spending_pattern_analysis |
|
|
|
st.markdown("<div class='insight-card'>", unsafe_allow_html=True) |
|
st.markdown("<span class='ai-badge'>AI Spending Analysis</span>", unsafe_allow_html=True) |
|
st.markdown(st.session_state.insights_cache[spending_key]) |
|
st.markdown("</div>", unsafe_allow_html=True) |
|
|
|
|
|
st.subheader("AI-Recommended Spending Controls") |
|
|
|
|
|
controls_key = f"spending_controls_{date.today().isoformat()}" |
|
if controls_key not in st.session_state.insights_cache: |
|
controls_recommendations = generate_ai_response(""" |
|
You are a financial controls expert for startups. Based on the spending patterns and suspicious transactions, |
|
recommend 3-4 specific spending controls that the startup should implement to prevent misuse of funds. |
|
|
|
For each control, provide: |
|
1. A clear policy statement |
|
2. Implementation steps |
|
3. Expected impact |
|
|
|
Format as concise, actionable recommendations. |
|
""") |
|
st.session_state.insights_cache[controls_key] = controls_recommendations |
|
|
|
st.markdown("<div class='advisor-card'>", unsafe_allow_html=True) |
|
st.markdown("<span class='ai-badge'>AI Control Recommendations</span>", unsafe_allow_html=True) |
|
st.markdown(f"<p class='advice-text'>{st.session_state.insights_cache[controls_key]}</p>", unsafe_allow_html=True) |
|
st.markdown("</div>", unsafe_allow_html=True) |
|
|
|
|
|
st.info("📅 Need help implementing financial controls? Schedule a session with our AI financial advisor.") |
|
|
|
|
|
def render_ai_financial_advisor(): |
|
"""Render the AI financial advisor page with voice chat capabilities""" |
|
if not st.session_state.current_startup or st.session_state.current_startup not in st.session_state.startups: |
|
st.warning("No startup selected. Please upload data or select a sample startup.") |
|
render_upload_page() |
|
return |
|
|
|
|
|
startup_data = st.session_state.startups[st.session_state.current_startup]['profile'] |
|
|
|
st.markdown("<h1 class='main-header'>AI Financial Advisor</h1>", unsafe_allow_html=True) |
|
st.markdown("<p class='sub-header'>Get expert financial guidance through our AI-powered advisor</p>", unsafe_allow_html=True) |
|
|
|
|
|
with st.expander("ℹ️ How AI powers your financial advisor"): |
|
st.markdown(""" |
|
### How AI Powers Your Financial Advisor |
|
|
|
Our AI financial advisor combines advanced language models with financial expertise: |
|
|
|
- **Natural Language Understanding**: The system interprets complex financial questions in plain English |
|
- **Domain-Specific Knowledge**: Our AI is trained on startup finance, venture capital, and financial modeling |
|
- **Context-Aware Responses**: The advisor takes into account your specific financial situation and history |
|
- **Voice Synthesis**: ElevenLabs voice technology creates natural, high-quality voice responses |
|
- **Customized Guidance**: AI tailors advice specifically to your stage, industry, and financial position |
|
|
|
This gives founders 24/7 access to high-quality financial guidance without the high cost of consultants. |
|
""") |
|
|
|
|
|
st.markdown("<div style='background-color: #f8f9fa; padding: 20px; border-radius: 10px; margin-bottom: 20px;'>", unsafe_allow_html=True) |
|
|
|
|
|
st.subheader("Chat with your Financial Advisor") |
|
|
|
|
|
for message in st.session_state.chat_history: |
|
if message["role"] == "user": |
|
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) |
|
else: |
|
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) |
|
|
|
|
|
if 'audio' in message and message['audio']: |
|
st.audio(message['audio'], format='audio/mp3') |
|
|
|
|
|
col1, col2 = st.columns([5, 1]) |
|
|
|
with col1: |
|
user_input = st.text_input("Ask a financial question", key="user_question") |
|
|
|
with col2: |
|
use_voice = st.checkbox("Enable voice", value=True) |
|
|
|
|
|
st.markdown("### Common Questions") |
|
question_cols = st.columns(3) |
|
|
|
common_questions = [ |
|
"How much runway do we have at our current burn rate?", |
|
"Should we increase our marketing spend given our growth rate?", |
|
"When should we start preparing for our next fundraising round?", |
|
"How can we optimize our burn rate without impacting growth?", |
|
"What metrics should we focus on improving right now?", |
|
"How do our unit economics compare to similar startups?" |
|
] |
|
|
|
selected_question = None |
|
|
|
for i, question in enumerate(common_questions): |
|
with question_cols[i % 3]: |
|
if st.button(question, key=f"q_{i}"): |
|
selected_question = question |
|
|
|
|
|
if user_input or selected_question: |
|
question = user_input or selected_question |
|
|
|
|
|
st.session_state.chat_history.append({"role": "user", "content": question}) |
|
|
|
|
|
response = generate_ai_response(f""" |
|
You are a strategic financial advisor for startups. A founder asks: |
|
"{question}" |
|
|
|
Here's their current financial situation: |
|
- Stage: {startup_data['stage']} |
|
- Current cash: ${startup_data['cash']} |
|
- Monthly burn rate: ${startup_data['burn_rate']} |
|
- Monthly revenue: ${startup_data['revenue']} |
|
- Monthly growth rate: {startup_data['growth_rate'] * 100}% |
|
- Last funding: {startup_data['last_funding']} |
|
- Team size: {startup_data['employees']} |
|
|
|
Provide detailed, actionable advice addressing their question. Include: |
|
1. Clear assessment of their current situation |
|
2. 3-5 specific, actionable recommendations with expected outcomes |
|
3. Relevant metrics they should track |
|
4. Industry benchmarks for comparison |
|
5. Timeline for implementation and results |
|
|
|
Be specific with numbers, timeframes, and expected outcomes. |
|
""") |
|
|
|
|
|
audio_data = None |
|
if use_voice: |
|
audio_data = generate_voice_response(response) |
|
|
|
|
|
st.session_state.chat_history.append({ |
|
"role": "assistant", |
|
"content": response, |
|
"audio": audio_data |
|
}) |
|
|
|
|
|
st.rerun() |
|
|
|
st.markdown("</div>", unsafe_allow_html=True) |
|
|
|
|
|
st.subheader("Advanced Financial Tools") |
|
|
|
tool_cols = st.columns(3) |
|
|
|
with tool_cols[0]: |
|
st.markdown(""" |
|
<div style='background-color: white; padding: 15px; border-radius: 10px; height: 200px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);'> |
|
<h4>Financial Model Review</h4> |
|
<p>Upload your financial model for AI analysis and recommendations.</p> |
|
<div style='position: absolute; bottom: 15px;'> |
|
<button disabled style="background-color: #E6F3FF; color: #0066cc; border-radius: 5px; padding: 5px 10px; border: none;">Coming Soon</button> |
|
</div> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
with tool_cols[1]: |
|
st.markdown(""" |
|
<div style='background-color: white; padding: 15px; border-radius: 10px; height: 200px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);'> |
|
<h4>Investor Pitch Review</h4> |
|
<p>Get AI feedback on your investor pitch deck and financial projections.</p> |
|
<div style='position: absolute; bottom: 15px;'> |
|
<button disabled style="background-color: #E6F3FF; color: #0066cc; border-radius: 5px; padding: 5px 10px; border: none;">Coming Soon</button> |
|
</div> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
with tool_cols[2]: |
|
st.markdown(""" |
|
<div style='background-color: white; padding: 15px; border-radius: 10px; height: 200px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);'> |
|
<h4>Fundraising Strategy</h4> |
|
<p>Generate a customized fundraising strategy based on your metrics.</p> |
|
<div style='position: absolute; bottom: 15px;'> |
|
<button disabled style="background-color: #E6F3FF; color: #0066cc; border-radius: 5px; padding: 5px 10px; border: none;">Coming Soon</button> |
|
</div> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
def main(): |
|
|
|
initialize_gemini() |
|
|
|
|
|
create_sidebar() |
|
|
|
|
|
if st.session_state.current_page == 'upload': |
|
render_upload_page() |
|
elif st.session_state.current_page == 'dashboard': |
|
render_financial_dashboard() |
|
elif st.session_state.current_page == 'simulator': |
|
render_decision_simulator() |
|
elif st.session_state.current_page == 'monitoring': |
|
render_fund_monitoring() |
|
elif st.session_state.current_page == 'advisor': |
|
render_ai_financial_advisor() |
|
|
|
if __name__ == "__main__": |
|
main() |
|
import streamlit as st |
|
import pandas as pd |
|
import numpy as np |
|
import plotly.express as px |
|
import plotly.graph_objects as go |
|
from datetime import datetime, timedelta, date |
|
import time |
|
import io |
|
import base64 |
|
import requests |
|
import google.generativeai as genai |
|
|
|
|
|
DEFAULT_GROWTH_RATE = 0.08 |
|
DEFAULT_BURN_RATE = 85000 |
|
ENGINEER_SALARY = 10000 |
|
|
|
|
|
if 'startups' not in st.session_state: |
|
st.session_state.startups = {} |
|
if 'current_startup' not in st.session_state: |
|
st.session_state.current_startup = None |
|
if 'current_page' not in st.session_state: |
|
st.session_state.current_page = 'upload' |
|
if 'insights_cache' not in st.session_state: |
|
st.session_state.insights_cache = {} |
|
if 'chat_history' not in st.session_state: |
|
st.session_state.chat_history = [ |
|
{"role": "assistant", "content": "Hi there! I'm your AI financial advisor. How can I help with your startup's finances today?"} |
|
] |
|
|
|
|
|
def initialize_gemini(): |
|
"""Initialize Google's GenerativeAI (Gemini) with API key""" |
|
try: |
|
|
|
api_key = st.secrets.get("GEMINI_API_KEY", None) |
|
if api_key: |
|
genai.configure(api_key=api_key) |
|
return True |
|
else: |
|
st.warning("Gemini API key not found. Using simulated AI responses.") |
|
return False |
|
except Exception as e: |
|
st.error(f"Failed to initialize Gemini AI: {e}") |
|
return False |
|
|
|
def generate_ai_response(prompt, simulate=True): |
|
"""Generate text using Google's GenerativeAI (Gemini)""" |
|
if simulate: |
|
|
|
return """ |
|
Based on your financial situation, I recommend focusing on these key areas: |
|
|
|
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. |
|
|
|
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. |
|
|
|
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. |
|
|
|
I recommend reviewing your expense categories weekly and tracking your burn rate closely. |
|
""" |
|
else: |
|
try: |
|
|
|
model = genai.GenerativeModel('gemini-pro') |
|
response = model.generate_content(prompt) |
|
return response.text |
|
except Exception as e: |
|
st.error(f"Error generating AI response: {e}") |
|
return "Sorry, I couldn't generate a response at this time." |
|
|
|
def generate_voice_response(text, simulate=True): |
|
"""Generate voice response using ElevenLabs API""" |
|
if simulate: |
|
|
|
return None |
|
else: |
|
try: |
|
|
|
api_key = st.secrets.get("ELEVENLABS_API_KEY", None) |
|
if not api_key: |
|
st.warning("ElevenLabs API key not found. Voice response not available.") |
|
return None |
|
|
|
|
|
url = "https://api.elevenlabs.io/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM" |
|
|
|
|
|
headers = { |
|
"Accept": "audio/mpeg", |
|
"Content-Type": "application/json", |
|
"xi-api-key": api_key |
|
} |
|
|
|
data = { |
|
"text": text, |
|
"model_id": "eleven_monolingual_v1", |
|
"voice_settings": { |
|
"stability": 0.5, |
|
"similarity_boost": 0.5 |
|
} |
|
} |
|
|
|
|
|
response = requests.post(url, json=data, headers=headers) |
|
|
|
if response.status_code == 200: |
|
return response.content |
|
else: |
|
st.error(f"Error with ElevenLabs API: {response.status_code}") |
|
return None |
|
|
|
except Exception as e: |
|
st.error(f"Error generating voice response: {e}") |
|
return None |
|
|
|
def switch_page(page_name): |
|
"""Function to switch between pages""" |
|
st.session_state.current_page = page_name |
|
st.rerun() |
|
|
|
|
|
def calculate_runway(cash, burn_rate, revenue, growth_rate, months=24): |
|
""" |
|
Calculate runway based on cash, burn, revenue and growth |
|
Returns runway in months and dataframe with projections |
|
""" |
|
|
|
current_date = datetime.now() |
|
date_range = [current_date + timedelta(days=30*i) for i in range(months)] |
|
|
|
|
|
cash_flow = [] |
|
remaining_cash = cash |
|
monthly_revenue = revenue |
|
|
|
|
|
for i in range(months): |
|
|
|
net_burn = burn_rate - monthly_revenue |
|
cash_flow.append(net_burn) |
|
|
|
|
|
remaining_cash -= net_burn |
|
|
|
|
|
monthly_revenue *= (1 + growth_rate) |
|
|
|
|
|
df = pd.DataFrame({ |
|
'Net_Burn': cash_flow, |
|
'Cumulative_Cash': [cash - sum(cash_flow[:i+1]) for i in range(len(cash_flow))] |
|
}, index=date_range) |
|
|
|
|
|
negative_cash = df[df['Cumulative_Cash'] < 0] |
|
if len(negative_cash) > 0: |
|
runway_months = (negative_cash.index[0] - current_date).days // 30 |
|
else: |
|
runway_months = months |
|
|
|
return runway_months, df |
|
|
|
|
|
def simulate_decision(cash, burn_rate, revenue, growth_rate, |
|
additional_expenses, new_hires, marketing_increase, growth_impact): |
|
""" |
|
Simulate the financial impact of a business decision |
|
""" |
|
|
|
current_runway, current_df = calculate_runway( |
|
cash, burn_rate, revenue, growth_rate |
|
) |
|
|
|
|
|
new_burn_rate = burn_rate + additional_expenses + (new_hires * ENGINEER_SALARY) + marketing_increase |
|
new_growth_rate = growth_rate + growth_impact |
|
|
|
new_runway, new_df = calculate_runway( |
|
cash, new_burn_rate, revenue, new_growth_rate |
|
) |
|
|
|
return current_runway, new_runway, current_df, new_df |
|
|
|
|
|
def detect_suspicious_transactions(transactions_df): |
|
"""AI-enhanced suspicious transaction detection.""" |
|
df = transactions_df.copy() |
|
|
|
|
|
category_thresholds = { |
|
"Travel": 3000, |
|
"Marketing": 10000, |
|
"Office": 7000, |
|
"Software": 6000, |
|
"Consulting": 5000, |
|
"Legal": 6000 |
|
} |
|
|
|
|
|
suspicious_terms = ['luxury', 'cruise', 'premium', 'personal', 'gift'] |
|
|
|
|
|
df['Suspicious'] = False |
|
df['Reason'] = "" |
|
df['Risk_Score'] = 0 |
|
|
|
|
|
for idx, row in df.iterrows(): |
|
reasons = [] |
|
risk_score = 0 |
|
|
|
|
|
if row['Category'] in category_thresholds: |
|
if row['Amount'] > category_thresholds[row['Category']]: |
|
reasons.append(f"Amount exceeds typical spending for {row['Category']}") |
|
risk_score += 30 |
|
|
|
|
|
excess_percentage = (row['Amount'] - category_thresholds[row['Category']]) / category_thresholds[row['Category']] * 100 |
|
if excess_percentage > 100: |
|
risk_score += 20 |
|
|
|
|
|
if any(term in str(row['Vendor']).lower() for term in suspicious_terms): |
|
reasons.append(f"Vendor name contains suspicious term") |
|
risk_score += 25 |
|
|
|
if any(term in str(row['Description']).lower() for term in suspicious_terms): |
|
reasons.append(f"Description contains suspicious term") |
|
risk_score += 20 |
|
|
|
|
|
if row['Amount'] % 1000 == 0 and row['Amount'] > 3000: |
|
reasons.append(f"Suspiciously round amount") |
|
risk_score += 15 |
|
|
|
|
|
if risk_score >= 30: |
|
df.at[idx, 'Suspicious'] = True |
|
df.at[idx, 'Reason'] = "; ".join(reasons) |
|
df.at[idx, 'Risk_Score'] = risk_score |
|
|
|
|
|
df = df.sort_values(by='Risk_Score', ascending=False) |
|
|
|
return df |
|
|
|
|
|
def parse_csv_to_df(file): |
|
"""Parse uploaded CSV file to Pandas DataFrame""" |
|
try: |
|
df = pd.read_csv(file) |
|
return df, None |
|
except Exception as e: |
|
return None, f"Error parsing CSV: {e}" |
|
|
|
|
|
st.set_page_config( |
|
page_title="StartupFinancePilot", |
|
page_icon="💰", |
|
layout="wide", |
|
initial_sidebar_state="expanded" |
|
) |
|
|
|
|
|
st.markdown(""" |
|
<style> |
|
#MainMenu {visibility: hidden;} |
|
footer {visibility: hidden;} |
|
.stDeployButton {display:none;} |
|
|
|
.main-header { |
|
font-size: 2.5rem; |
|
color: #0066cc; |
|
margin-bottom: 0.5rem; |
|
} |
|
.sub-header { |
|
font-size: 1.5rem; |
|
color: #5c5c5c; |
|
margin-bottom: 1.5rem; |
|
} |
|
.metric-card { |
|
background-color: #f8f9fa; |
|
border-radius: 10px; |
|
padding: 20px; |
|
box-shadow: 0 4px 6px rgba(0,0,0,0.1); |
|
} |
|
.metric-label { |
|
font-size: 1rem; |
|
color: #5c5c5c; |
|
} |
|
.metric-value { |
|
font-size: 1.8rem; |
|
color: #0066cc; |
|
font-weight: bold; |
|
} |
|
.good-metric { |
|
color: #28a745; |
|
} |
|
.warning-metric { |
|
color: #ffc107; |
|
} |
|
.danger-metric { |
|
color: #dc3545; |
|
} |
|
|
|
/* Style for sidebar buttons */ |
|
div.stButton > button { |
|
width: 100%; |
|
padding: 10px 10px; |
|
border: none; |
|
background-color: #E6F3FF; |
|
color: #0066cc; |
|
border-radius: 10px; |
|
text-align: left; |
|
margin: 5px 0; |
|
font-weight: bold; |
|
} |
|
|
|
div.stButton > button:hover { |
|
background-color: #CCE5FF; |
|
color: #004080; |
|
} |
|
|
|
/* Style for title box */ |
|
.title-box { |
|
background: linear-gradient(45deg, #0066cc, #66b3ff); |
|
padding: 20px; |
|
border-radius: 10px; |
|
margin-bottom: 20px; |
|
text-align: center; |
|
color: white; |
|
cursor: pointer; |
|
} |
|
|
|
.ai-badge { |
|
display: inline-block; |
|
background-color: #0066cc; |
|
color: white; |
|
border-radius: 4px; |
|
padding: 2px 6px; |
|
font-size: 0.7rem; |
|
font-weight: bold; |
|
margin-bottom: 8px; |
|
} |
|
|
|
.insight-card, .advisor-card { |
|
background-color: #f8f9fa; |
|
border-radius: 10px; |
|
padding: 15px; |
|
margin-bottom: 20px; |
|
box-shadow: 0 2px 4px rgba(0,0,0,0.05); |
|
} |
|
|
|
.advice-text { |
|
margin-top: 10px; |
|
line-height: 1.6; |
|
} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
def create_sidebar(): |
|
with st.sidebar: |
|
|
|
st.markdown(""" |
|
<div class="title-box"> |
|
<h1>💰 StartupFinancePilot</h1> |
|
<p>AI-powered financial assistant for startups</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
if st.session_state.startups: |
|
st.subheader("Selected Startup") |
|
startup_names = list(st.session_state.startups.keys()) |
|
selected_startup = st.selectbox( |
|
"Choose Startup", |
|
startup_names, |
|
index=startup_names.index(st.session_state.current_startup) if st.session_state.current_startup in startup_names else 0 |
|
) |
|
st.session_state.current_startup = selected_startup |
|
|
|
|
|
if selected_startup in st.session_state.startups: |
|
startup_data = st.session_state.startups[selected_startup]['profile'] |
|
st.markdown(f""" |
|
**Stage:** {startup_data['stage']} |
|
**Cash:** ${startup_data['cash']:,} |
|
**Monthly Burn:** ${startup_data['burn_rate']:,} |
|
**Monthly Revenue:** ${startup_data['revenue']:,} |
|
""") |
|
|
|
st.markdown("<hr>", unsafe_allow_html=True) |
|
|
|
|
|
if st.button("📤 Upload Startup Data", use_container_width=True): |
|
switch_page('upload') |
|
|
|
|
|
if st.button("📊 Financial Dashboard", use_container_width=True): |
|
switch_page('dashboard') |
|
|
|
if st.button("🔮 Decision Simulator", use_container_width=True): |
|
switch_page('simulator') |
|
|
|
if st.button("🕵️ Fund Monitoring", use_container_width=True): |
|
switch_page('monitoring') |
|
|
|
if st.button("🤖 AI Financial Advisor", use_container_width=True): |
|
switch_page('advisor') |
|
|
|
|
|
def render_upload_page(): |
|
"""Render the upload page for startup data""" |
|
st.markdown("<h1 class='main-header'>Upload Your Startup Data</h1>", unsafe_allow_html=True) |
|
st.markdown("<p class='sub-header'>Upload CSV files or use sample data to get started</p>", unsafe_allow_html=True) |
|
|
|
with st.expander("Upload Instructions", expanded=False): |
|
st.markdown(""" |
|
### How to Upload Your Startup Data |
|
|
|
You can upload three types of files: |
|
|
|
1. **Company Profile** - A CSV with basic information about your startup including: |
|
- name, stage, founded, employees, last_funding, cash, burn_rate, revenue, growth_rate |
|
|
|
2. **Cash Flow Data** - A CSV with monthly cash flow data with columns: |
|
- Month, Revenue, Payroll, Marketing, Office, Software, Travel, Legal, Misc |
|
|
|
3. **Transaction Data** - A CSV with transaction details: |
|
- Date, Category, Vendor, Amount, Description, Flag |
|
|
|
If you don't have these files ready, you can use our sample data. |
|
""") |
|
|
|
col1, col2 = st.columns(2) |
|
|
|
with col1: |
|
startup_name = st.text_input("Startup Name", value="My Startup") |
|
|
|
profile_file = st.file_uploader("Upload Company Profile (CSV)", type=['csv']) |
|
cash_flow_file = st.file_uploader("Upload Cash Flow Data (CSV)", type=['csv']) |
|
transactions_file = st.file_uploader("Upload Transactions Data (CSV)", type=['csv']) |
|
|
|
with col2: |
|
st.markdown(""" |
|
<div style="background-color: #f0f7ff; padding: 15px; border-radius: 10px; height: 90%;"> |
|
<h4>Why Upload Your Data?</h4> |
|
<p>By uploading your actual financial data, you'll get:</p> |
|
<ul> |
|
<li>Personalized AI insights tailored to your startup</li> |
|
<li>Accurate runway projections based on your real spending patterns</li> |
|
<li>Custom recommendations to optimize your burn rate</li> |
|
<li>More realistic decision simulations</li> |
|
</ul> |
|
<p>All data is processed securely and never stored permanently.</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
if st.button("Process Data"): |
|
|
|
startup_data = { |
|
"name": startup_name, |
|
"stage": "Seed", |
|
"founded": "12 months ago", |
|
"employees": 5, |
|
"last_funding": "Not specified", |
|
"cash": 100000, |
|
"burn_rate": 20000, |
|
"revenue": 5000, |
|
"growth_rate": 0.05 |
|
} |
|
|
|
cash_flow_df = None |
|
transactions_df = None |
|
|
|
|
|
if profile_file: |
|
try: |
|
profile_df, error = parse_csv_to_df(profile_file) |
|
if error: |
|
st.error(error) |
|
else: |
|
|
|
if len(profile_df) > 0: |
|
startup_data.update(profile_df.iloc[0].to_dict()) |
|
st.success(f"Successfully loaded company profile for {startup_data['name']}") |
|
except Exception as e: |
|
st.error(f"Error processing company profile: {e}") |
|
|
|
|
|
if cash_flow_file: |
|
cash_flow_df, error = parse_csv_to_df(cash_flow_file) |
|
if error: |
|
st.error(error) |
|
else: |
|
|
|
if "Total_Expenses" not in cash_flow_df.columns: |
|
expense_columns = [col for col in cash_flow_df.columns if col not in ["Month", "Revenue", "Total_Expenses", "Net_Burn"]] |
|
cash_flow_df["Total_Expenses"] = cash_flow_df[expense_columns].sum(axis=1) |
|
|
|
if "Net_Burn" not in cash_flow_df.columns: |
|
cash_flow_df["Net_Burn"] = cash_flow_df["Total_Expenses"] - cash_flow_df["Revenue"] |
|
|
|
st.success("Successfully loaded cash flow data") |
|
|
|
|
|
if transactions_file: |
|
transactions_df, error = parse_csv_to_df(transactions_file) |
|
if error: |
|
st.error(error) |
|
else: |
|
|
|
required_columns = ["Date", "Category", "Vendor", "Amount", "Description"] |
|
if all(col in transactions_df.columns for col in required_columns): |
|
if "Flag" not in transactions_df.columns: |
|
transactions_df["Flag"] = "Normal" |
|
|
|
st.success("Successfully loaded transactions data") |
|
else: |
|
st.error("Transactions file is missing required columns") |
|
|
|
|
|
if profile_file or cash_flow_file or transactions_file: |
|
|
|
if cash_flow_df is None: |
|
cash_flow_df = create_sample_cash_flow(startup_data) |
|
|
|
|
|
if transactions_df is None: |
|
transactions_df = create_sample_transactions(startup_data) |
|
|
|
|
|
st.session_state.startups[startup_data['name']] = { |
|
'profile': startup_data, |
|
'cash_flow': cash_flow_df, |
|
'transactions': transactions_df |
|
} |
|
|
|
|
|
st.session_state.current_startup = startup_data['name'] |
|
|
|
st.success(f"Successfully added {startup_data['name']} to your startups") |
|
st.info("You can now analyze this startup's data in the dashboard") |
|
|
|
|
|
switch_page('dashboard') |
|
|
|
|
|
st.subheader("Or Use Sample Data") |
|
|
|
sample_col1, sample_col2 = st.columns(2) |
|
|
|
with sample_col1: |
|
if st.button("Use TechHealth AI Sample"): |
|
|
|
load_sample_data("TechHealth AI") |
|
st.success("Successfully loaded TechHealth AI sample data") |
|
|
|
switch_page('dashboard') |
|
|
|
with sample_col2: |
|
if st.button("Use GreenTech Innovations Sample"): |
|
|
|
load_sample_data("GreenTech Innovations") |
|
st.success("Successfully loaded GreenTech Innovations sample data") |
|
|
|
switch_page('dashboard') |
|
|
|
def create_sample_cash_flow(startup_data): |
|
"""Create a sample cash flow dataframe for a startup""" |
|
cash_flow_data = { |
|
"Month": [f"Month {i}" for i in range(1, 7)], |
|
"Revenue": [startup_data['revenue'] * (1 + startup_data['growth_rate'])**i for i in range(6)], |
|
"Payroll": [startup_data['burn_rate'] * 0.7] * 6, |
|
"Marketing": [startup_data['burn_rate'] * 0.15] * 6, |
|
"Office": [startup_data['burn_rate'] * 0.05] * 6, |
|
"Software": [startup_data['burn_rate'] * 0.03] * 6, |
|
"Travel": [startup_data['burn_rate'] * 0.02] * 6, |
|
"Legal": [startup_data['burn_rate'] * 0.01] * 6, |
|
"Misc": [startup_data['burn_rate'] * 0.04] * 6 |
|
} |
|
cash_flow_df = pd.DataFrame(cash_flow_data) |
|
cash_flow_df["Total_Expenses"] = cash_flow_df[["Payroll", "Marketing", "Office", "Software", "Travel", "Legal", "Misc"]].sum(axis=1) |
|
cash_flow_df["Net_Burn"] = cash_flow_df["Total_Expenses"] - cash_flow_df["Revenue"] |
|
return cash_flow_df |
|
|
|
def create_sample_transactions(startup_data): |
|
"""Create sample transaction data for a startup""" |
|
transactions_data = { |
|
"Date": [(datetime.now() - timedelta(days=i*5)).strftime("%Y-%m-%d") for i in range(10)], |
|
"Category": ["Payroll", "Marketing", "Office", "Software", "Travel", "Legal", "Misc", "Payroll", "Marketing", "Office"], |
|
"Vendor": ["Payroll Provider", "Facebook Ads", "Office Rent", "AWS", "Travel Agency", "Legal Firm", "Miscellaneous", "Payroll Provider", "Google Ads", "Office Supplies"], |
|
"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], |
|
"Description": ["Monthly Payroll", "Ad Campaign", "Monthly Rent", "Cloud Services", "Business Travel", "Legal Services", "Miscellaneous Expenses", "Monthly Payroll", "Ad Campaign", "Office Supplies"], |
|
"Flag": ["Normal", "Normal", "Normal", "Normal", "Normal", "Normal", "Normal", "Normal", "Normal", "Normal"] |
|
} |
|
return pd.DataFrame(transactions_data) |
|
|
|
def load_sample_data(sample_name): |
|
"""Load sample data for demonstration""" |
|
if sample_name == "TechHealth AI": |
|
|
|
startup_data = { |
|
"name": "TechHealth AI", |
|
"stage": "Seed", |
|
"founded": "18 months ago", |
|
"employees": 12, |
|
"last_funding": "$1.2M seed round 10 months ago", |
|
"cash": 320000, |
|
"burn_rate": 85000, |
|
"revenue": 15000, |
|
"growth_rate": 0.08 |
|
} |
|
else: |
|
|
|
startup_data = { |
|
"name": "GreenTech Innovations", |
|
"stage": "Series A", |
|
"founded": "3 years ago", |
|
"employees": 25, |
|
"last_funding": "$4.5M Series A 8 months ago", |
|
"cash": 2800000, |
|
"burn_rate": 220000, |
|
"revenue": 75000, |
|
"growth_rate": 0.12 |
|
} |
|
|
|
|
|
cash_flow_df = create_sample_cash_flow(startup_data) |
|
transactions_df = create_sample_transactions(startup_data) |
|
|
|
|
|
if sample_name == "TechHealth AI": |
|
suspicious_transactions = pd.DataFrame([ |
|
{"Date": "2023-11-05", "Category": "Travel", "Vendor": "Caribbean Cruises", "Amount": 8500, "Description": "Team Retreat Planning", "Flag": "Suspicious"}, |
|
{"Date": "2023-11-12", "Category": "Marketing", "Vendor": "LuxuryGifts Inc", "Amount": 4200, "Description": "Client Appreciation", "Flag": "Suspicious"}, |
|
{"Date": "2023-11-22", "Category": "Office", "Vendor": "Premium Furniture", "Amount": 12000, "Description": "Office Upgrades", "Flag": "Suspicious"} |
|
]) |
|
transactions_df = pd.concat([suspicious_transactions, transactions_df], ignore_index=True) |
|
|
|
|
|
st.session_state.startups[startup_data['name']] = { |
|
'profile': startup_data, |
|
'cash_flow': cash_flow_df, |
|
'transactions': transactions_df |
|
} |
|
|
|
|
|
st.session_state.current_startup = startup_data['name'] |
|
|
|
|
|
def render_financial_dashboard(): |
|
"""Render the AI-powered financial dashboard page""" |
|
if not st.session_state.current_startup or st.session_state.current_startup not in st.session_state.startups: |
|
st.warning("No startup selected. Please upload data or select a sample startup.") |
|
render_upload_page() |
|
return |
|
|
|
|
|
startup_data = st.session_state.startups[st.session_state.current_startup]['profile'] |
|
cash_flow_df = st.session_state.startups[st.session_state.current_startup]['cash_flow'] |
|
|
|
st.markdown("<h1 class='main-header'>Financial Dashboard</h1>", unsafe_allow_html=True) |
|
st.markdown("<p class='sub-header'>AI-powered financial insights at a glance</p>", unsafe_allow_html=True) |
|
|
|
|
|
with st.expander("ℹ️ How AI enhances your financial dashboard"): |
|
st.markdown(""" |
|
### How AI Powers Your Financial Dashboard |
|
|
|
The financial dashboard uses AI to transform raw financial data into actionable intelligence: |
|
|
|
- **Automated Analysis**: Instead of manually calculating runway and burn rates, our AI model analyzes your data and highlights critical trends |
|
- **Predictive Forecasting**: AI forecasts your runway using pattern recognition and predictive analytics to account for varying growth rates |
|
- **Anomaly Detection**: The system identifies unusual spending patterns or concerning financial trends that human analysis might miss |
|
- **Strategic Recommendations**: Based on your specific financial situation, the AI provides tailored recommendations to optimize your runway |
|
- **Benchmark Comparison**: Your metrics are automatically compared against industry standards for startups at your funding stage |
|
|
|
This helps founders save time, catch financial issues early, and make data-driven decisions without needing financial expertise. |
|
""") |
|
|
|
|
|
insights_key = f"dashboard_{date.today().isoformat()}" |
|
if insights_key not in st.session_state.insights_cache: |
|
insights = generate_ai_response(f""" |
|
You are a financial advisor for startups. Based on this startup's data: |
|
- Current cash: ${startup_data['cash']} |
|
- Monthly burn rate: ${startup_data['burn_rate']} |
|
- Monthly revenue: ${startup_data['revenue']} |
|
- Monthly growth rate: {startup_data['growth_rate'] * 100}% |
|
|
|
Provide the top 3 most important financial insights that the founder should know today. |
|
Format each insight as a brief, action-oriented bullet point. |
|
""") |
|
st.session_state.insights_cache[insights_key] = insights |
|
|
|
with st.expander("📊 AI Financial Insights", expanded=True): |
|
st.markdown("<span class='ai-badge'>AI-Generated Insights</span>", unsafe_allow_html=True) |
|
st.markdown(st.session_state.insights_cache[insights_key]) |
|
|
|
|
|
col1, col2, col3, col4 = st.columns(4) |
|
|
|
|
|
runway_months, runway_df = calculate_runway( |
|
startup_data['cash'], |
|
startup_data['burn_rate'], |
|
startup_data['revenue'], |
|
startup_data['growth_rate'] |
|
) |
|
|
|
|
|
runway_status = "danger-metric" if runway_months < 6 else ("warning-metric" if runway_months < 9 else "good-metric") |
|
burn_status = "danger-metric" if startup_data['burn_rate'] > 100000 else ("warning-metric" if startup_data['burn_rate'] > 80000 else "good-metric") |
|
revenue_status = "good-metric" if startup_data['revenue'] > 20000 else ("warning-metric" if startup_data['revenue'] > 10000 else "danger-metric") |
|
|
|
with col1: |
|
st.markdown(f""" |
|
<div class='metric-card'> |
|
<p class='metric-label'>Current Cash</p> |
|
<p class='metric-value'>${startup_data['cash']:,}</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
with col2: |
|
st.markdown(f""" |
|
<div class='metric-card'> |
|
<p class='metric-label'>Monthly Burn</p> |
|
<p class='metric-value {burn_status}'>${startup_data['burn_rate']:,}</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
with col3: |
|
st.markdown(f""" |
|
<div class='metric-card'> |
|
<p class='metric-label'>Monthly Revenue</p> |
|
<p class='metric-value {revenue_status}'>${startup_data['revenue']:,}</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
with col4: |
|
st.markdown(f""" |
|
<div class='metric-card'> |
|
<p class='metric-label'>Runway</p> |
|
<p class='metric-value {runway_status}'>{runway_months} months</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
st.subheader("Financial Overview") |
|
|
|
tab1, tab2, tab3 = st.tabs(["Runway Projection", "Revenue vs. Expenses", "Burn Rate Trend"]) |
|
|
|
with tab1: |
|
|
|
fig = px.line(runway_df.reset_index(), x='index', y='Cumulative_Cash', |
|
title="Cash Runway Projection", |
|
labels={'index': 'Date', 'Cumulative_Cash': 'Remaining Cash ($)'}, |
|
color_discrete_sequence=['#0066cc']) |
|
fig.add_hline(y=0, line_dash="dash", line_color="red", annotation_text="Out of Cash") |
|
fig.update_layout( |
|
height=400, |
|
plot_bgcolor='rgba(240,247,255,0.8)', |
|
xaxis_title="Date", |
|
yaxis_title="Cash Balance ($)", |
|
font=dict(family="Arial, sans-serif", size=12), |
|
margin=dict(l=20, r=20, t=40, b=20), |
|
) |
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
with st.expander("🔍 AI Financial Analysis", expanded=True): |
|
|
|
analysis_key = f"runway_{date.today().isoformat()}" |
|
if analysis_key not in st.session_state.insights_cache: |
|
analysis = generate_ai_response(f""" |
|
You are a financial advisor for startups. Analyze this startup's financial data: |
|
- Current cash: ${startup_data['cash']} |
|
- Monthly burn rate: ${startup_data['burn_rate']} |
|
- Monthly revenue: ${startup_data['revenue']} |
|
- Monthly growth rate: {startup_data['growth_rate'] * 100}% |
|
|
|
Provide a detailed analysis of their runway and financial health. Include: |
|
1. Exact runway calculation in months |
|
2. Assessment of financial health (critical, concerning, stable, or healthy) |
|
3. Benchmarks compared to similar seed-stage startups |
|
4. Three specific, actionable recommendations to improve runway |
|
5. Key metrics they should focus on |
|
|
|
Format your response in a structured, easy-to-read format with clear sections and bullet points. |
|
""") |
|
st.session_state.insights_cache[analysis_key] = analysis |
|
|
|
st.markdown("<span class='ai-badge'>AI Financial Analysis</span>", unsafe_allow_html=True) |
|
st.markdown(st.session_state.insights_cache[analysis_key]) |
|
|
|
with tab2: |
|
|
|
rev_exp_df = cash_flow_df.copy() |
|
fig = px.bar(rev_exp_df, x='Month', y=['Revenue', 'Total_Expenses'], |
|
title="Revenue vs. Expenses", |
|
barmode='group', |
|
labels={'value': 'Amount ($)', 'variable': 'Category'}, |
|
color_discrete_sequence=['#28a745', '#dc3545']) |
|
fig.update_layout( |
|
height=400, |
|
plot_bgcolor='rgba(240,247,255,0.8)', |
|
xaxis_title="Month", |
|
yaxis_title="Amount ($)", |
|
font=dict(family="Arial, sans-serif", size=12), |
|
legend_title="", |
|
margin=dict(l=20, r=20, t=40, b=20), |
|
) |
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
revenue_growth = [(cash_flow_df['Revenue'].iloc[i] / cash_flow_df['Revenue'].iloc[i-1] - 1) * 100 if i > 0 else 0 |
|
for i in range(len(cash_flow_df))] |
|
avg_growth = sum(revenue_growth[1:]) / len(revenue_growth[1:]) |
|
|
|
col1, col2 = st.columns(2) |
|
with col1: |
|
st.metric("Average Monthly Revenue Growth", f"{avg_growth:.1f}%") |
|
with col2: |
|
expense_growth = (cash_flow_df['Total_Expenses'].iloc[-1] / cash_flow_df['Total_Expenses'].iloc[0] - 1) * 100 |
|
st.metric("Total Expense Growth", f"{expense_growth:.1f}%", delta=f"{expense_growth - avg_growth:.1f}%", delta_color="inverse") |
|
|
|
with tab3: |
|
|
|
fig = px.line(cash_flow_df, x='Month', y='Net_Burn', |
|
title="Monthly Net Burn Trend", |
|
labels={'Net_Burn': 'Net Burn ($)'}, |
|
color_discrete_sequence=['#dc3545']) |
|
fig.update_layout( |
|
height=400, |
|
plot_bgcolor='rgba(240,247,255,0.8)', |
|
xaxis_title="Month", |
|
yaxis_title="Net Burn ($)", |
|
font=dict(family="Arial, sans-serif", size=12), |
|
margin=dict(l=20, r=20, t=40, b=20), |
|
) |
|
|
|
|
|
efficiency_ratio = [cash_flow_df['Revenue'].iloc[i] / cash_flow_df['Total_Expenses'].iloc[i] * 100 |
|
for i in range(len(cash_flow_df))] |
|
|
|
fig.add_trace(go.Scatter( |
|
x=cash_flow_df['Month'], |
|
y=efficiency_ratio, |
|
name='Efficiency Ratio (%)', |
|
yaxis='y2', |
|
line=dict(color='#0066cc', width=2, dash='dot') |
|
)) |
|
|
|
fig.update_layout( |
|
yaxis2=dict( |
|
title='Efficiency Ratio (%)', |
|
overlaying='y', |
|
side='right', |
|
range=[0, max(efficiency_ratio) * 1.2] |
|
) |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
with st.expander("🔎 Understanding Efficiency Ratio"): |
|
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.") |
|
|
|
|
|
st.subheader("Expense Breakdown") |
|
|
|
|
|
last_month = cash_flow_df.iloc[-1] |
|
expense_categories = ['Payroll', 'Marketing', 'Office', 'Software', 'Travel', 'Legal', 'Misc'] |
|
expense_values = [last_month[cat] for cat in expense_categories] |
|
|
|
col1, col2 = st.columns([2, 1]) |
|
|
|
with col1: |
|
fig = px.pie(values=expense_values, names=expense_categories, |
|
title="Current Month Expense Breakdown", |
|
color_discrete_sequence=px.colors.sequential.Blues_r) |
|
fig.update_layout( |
|
height=400, |
|
font=dict(family="Arial, sans-serif", size=12), |
|
margin=dict(l=20, r=20, t=40, b=20), |
|
) |
|
fig.update_traces(textposition='inside', textinfo='percent+label') |
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
with col2: |
|
|
|
st.markdown("<h4>Expense Analysis</h4>", unsafe_allow_html=True) |
|
|
|
|
|
benchmarks = { |
|
"Payroll": "70-80%", |
|
"Marketing": "10-15%", |
|
"Office": "5-8%", |
|
"Software": "3-5%" |
|
} |
|
|
|
|
|
expense_df = pd.DataFrame({ |
|
"Category": expense_categories, |
|
"Amount": expense_values, |
|
"% of Total": [v / sum(expense_values) * 100 for v in expense_values] |
|
}) |
|
|
|
|
|
expense_df["Industry Benchmark"] = expense_df["Category"].map( |
|
lambda x: benchmarks.get(x, "N/A") |
|
) |
|
|
|
|
|
formatted_df = expense_df.copy() |
|
formatted_df["Amount"] = formatted_df["Amount"].apply(lambda x: f"${x:,.0f}") |
|
formatted_df["% of Total"] = formatted_df["% of Total"].apply(lambda x: f"{x:.1f}%") |
|
|
|
st.table(formatted_df) |
|
|
|
|
|
with st.expander("💡 AI Spending Optimization"): |
|
st.markdown("<span class='ai-badge'>AI Recommendation</span>", unsafe_allow_html=True) |
|
|
|
|
|
spending_key = f"spending_{date.today().isoformat()}" |
|
if spending_key not in st.session_state.insights_cache: |
|
spending_recommendation = generate_ai_response(""" |
|
Based on your expense breakdown, recommend 2-3 specific ways to optimize spending to extend runway. |
|
Focus on industry best practices for seed-stage startups. |
|
""") |
|
st.session_state.insights_cache[spending_key] = spending_recommendation |
|
|
|
st.markdown(st.session_state.insights_cache[spending_key]) |
|
|
|
|
|
st.subheader("Fundraising Readiness") |
|
|
|
|
|
fundraising_key = f"fundraising_{date.today().isoformat()}" |
|
if fundraising_key not in st.session_state.insights_cache: |
|
|
|
runway_calc = startup_data['cash'] / (startup_data['burn_rate'] - startup_data['revenue']) |
|
|
|
|
|
try: |
|
mrr_growth = (cash_flow_df['Revenue'].iloc[-1] / cash_flow_df['Revenue'].iloc[-2] - 1) * 100 |
|
gross_margin = (cash_flow_df['Revenue'].iloc[-1] - cash_flow_df['Total_Expenses'].iloc[-1] / 2) / cash_flow_df['Revenue'].iloc[-1] * 100 |
|
except: |
|
mrr_growth = 5.0 |
|
gross_margin = 60.0 |
|
|
|
metrics = { |
|
"MRR Growth": f"{mrr_growth:.1f}%", |
|
"Gross Margin": f"{gross_margin:.1f}%", |
|
"CAC": "$950", |
|
"LTV": "$4,500", |
|
"Churn": "3.2%", |
|
} |
|
|
|
metrics_text = "\n".join([f"- {k}: {v}" for k, v in metrics.items()]) |
|
|
|
fundraising_analysis = generate_ai_response(f""" |
|
You are a startup fundraising advisor. Analyze this startup's readiness for their next funding round: |
|
|
|
Company Profile: |
|
- Stage: {startup_data['stage']} |
|
- Last Funding: {startup_data['last_funding']} |
|
- Current Cash: ${startup_data['cash']} |
|
- Monthly Burn: ${startup_data['burn_rate']} |
|
- Runway: {runway_calc:.1f} months |
|
|
|
Key Metrics: |
|
{metrics_text} |
|
|
|
Provide a comprehensive fundraising readiness assessment: |
|
1. Overall fundraising readiness score (0-10) |
|
2. Assessment of current metrics compared to investor expectations for next round |
|
3. Identify the 3 most critical metrics to improve before fundraising |
|
4. Recommend specific targets for each key metric |
|
5. Suggest timeline and specific milestones for fundraising preparation |
|
6. Estimate reasonable valuation range based on metrics and market conditions |
|
|
|
Be specific with numbers, timelines, and actionable targets. |
|
""") |
|
st.session_state.insights_cache[fundraising_key] = fundraising_analysis |
|
|
|
st.markdown("<div class='advisor-card'>", unsafe_allow_html=True) |
|
st.markdown("<span class='ai-badge'>AI Fundraising Assessment</span>", unsafe_allow_html=True) |
|
st.markdown(f"<p class='advice-text'>{st.session_state.insights_cache[fundraising_key]}</p>", unsafe_allow_html=True) |
|
st.markdown("</div>", unsafe_allow_html=True) |
|
|
|
|
|
st.info("📅 Need personalized guidance on fundraising? Schedule a session with our AI financial advisor to get detailed recommendations.") |
|
|
|
|
|
def render_decision_simulator(): |
|
"""Render the AI-powered decision simulator page""" |
|
if not st.session_state.current_startup or st.session_state.current_startup not in st.session_state.startups: |
|
st.warning("No startup selected. Please upload data or select a sample startup.") |
|
render_upload_page() |
|
return |
|
|
|
|
|
startup_data = st.session_state.startups[st.session_state.current_startup]['profile'] |
|
|
|
st.markdown("<h1 class='main-header'>Decision Simulator</h1>", unsafe_allow_html=True) |
|
st.markdown("<p class='sub-header'>AI-powered analysis of business decisions</p>", unsafe_allow_html=True) |
|
|
|
|
|
with st.expander("ℹ️ How AI enhances your decision-making"): |
|
st.markdown(""" |
|
### How AI Powers Your Decision Simulator |
|
|
|
The decision simulator uses AI to help you make better strategic decisions: |
|
|
|
- **Scenario Analysis**: Our AI model simulates multiple financial scenarios based on your input variables |
|
- **Risk Assessment**: The system automatically evaluates risk levels based on your cash runway and growth metrics |
|
- **Return Prediction**: AI algorithms predict potential returns on investments like hiring or marketing |
|
- **Opportunity Cost Analysis**: The model compares different allocations of capital to maximize growth |
|
- **Personalized Recommendations**: Based on your specific situation, the AI provides tailored alternatives |
|
|
|
This helps founders make data-driven decisions with less guesswork, avoid costly mistakes, and optimize resource allocation. |
|
""") |
|
|
|
st.write("Test the financial impact of key business decisions before implementing them. Our AI advisor will analyze the risks and benefits.") |
|
|
|
|
|
st.subheader("Common Scenarios") |
|
|
|
decision_templates = { |
|
"Hiring Engineering Team": { |
|
"description": "Evaluate the impact of growing your engineering team", |
|
"new_hires": 3, |
|
"new_marketing": 0, |
|
"other_expenses": 2000, |
|
"growth_impact": 0.02, |
|
"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?" |
|
}, |
|
"Marketing Expansion": { |
|
"description": "Test increasing your marketing budget", |
|
"new_hires": 0, |
|
"new_marketing": 15000, |
|
"other_expenses": 0, |
|
"growth_impact": 0.04, |
|
"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?" |
|
}, |
|
"Office Expansion": { |
|
"description": "Analyze the cost of moving to a larger office", |
|
"new_hires": 0, |
|
"new_marketing": 0, |
|
"other_expenses": 8000, |
|
"growth_impact": 0.01, |
|
"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?" |
|
}, |
|
"Custom Scenario": { |
|
"description": "Create your own custom scenario", |
|
"new_hires": 0, |
|
"new_marketing": 0, |
|
"other_expenses": 0, |
|
"growth_impact": 0.0, |
|
"question": "" |
|
} |
|
} |
|
|
|
|
|
template_cols = st.columns(4) |
|
selected_template = None |
|
|
|
for i, (template_name, template) in enumerate(decision_templates.items()): |
|
with template_cols[i]: |
|
if st.button(f"{template_name}\n{template['description']}", key=f"template_{i}"): |
|
selected_template = template_name" |