Rahul2298 commited on
Commit
48df105
·
verified ·
1 Parent(s): dd92cd2

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +100 -547
src/streamlit_app.py CHANGED
@@ -1,556 +1,109 @@
1
- # Personal Finance Chatbot: AI-Powered Financial Advisor
2
- # Enhanced with OpenAI GPT for superior accuracy and intelligence
3
-
4
- import os
5
- import io
6
- import re
7
- import json
8
- from dataclasses import dataclass
9
- from typing import List, Dict, Optional, Any, Union
10
-
11
- import pandas as pd
12
  import streamlit as st
 
13
 
14
- # OpenAI Integration
15
- try:
16
- from openai import OpenAI
17
- OPENAI_AVAILABLE = True
18
- except ImportError:
19
- OPENAI_AVAILABLE = False
20
-
21
- # HuggingFace Fallback
22
- try:
23
- from transformers import pipeline
24
- HF_AVAILABLE = True
25
- HF_PIPELINE = pipeline
26
- except ImportError:
27
- HF_AVAILABLE = False
28
- HF_PIPELINE = None
29
-
30
- st.set_page_config(
31
- page_title="FinanceAI - Smart Financial Advisor",
32
- page_icon="🤖",
33
- layout="wide",
34
- initial_sidebar_state="collapsed"
35
- )
36
-
37
- if "chat_history" not in st.session_state:
38
- st.session_state.chat_history = []
39
- if "provider_inited" not in st.session_state:
40
- st.session_state.provider_inited = False
41
- if "provider_name" not in st.session_state:
42
- st.session_state.provider_name = "openai"
43
-
44
- class AIProvider:
45
- def __init__(self):
46
- self.name = "base"
47
- def generate(self, prompt: str, max_tokens: int = 512) -> str:
48
- raise NotImplementedError
49
-
50
- class OpenAIProvider(AIProvider):
51
- def __init__(self):
52
- super().__init__()
53
- self.name = "OpenAI GPT-4"
54
- self.client = None
55
- api_key = os.environ.get("OPENAI_API_KEY")
56
- if OPENAI_AVAILABLE and api_key:
57
- try:
58
- self.client = OpenAI(api_key=api_key)
59
- # Test the connection
60
- self.client.models.list()
61
- self.available = True
62
- except Exception as e:
63
- st.warning(f"OpenAI connection failed: {e}")
64
- self.available = False
65
- self.client = None
66
- else:
67
- self.available = False
68
-
69
- def generate(self, prompt: str, max_tokens: int = 768) -> str:
70
- if not self.available or not self.client:
71
- return "OpenAI service unavailable. Please check your API key."
72
-
73
- try:
74
- # Use GPT-4 for superior financial advice
75
- response = self.client.chat.completions.create(
76
- model="gpt-4o-mini", # Using the latest efficient model
77
- messages=[
78
- {"role": "system", "content": "You are FinanceAI, a highly knowledgeable financial advisor specializing in Indian markets, tax laws, and investment strategies. Provide accurate, actionable advice with specific amounts and calculations."},
79
- {"role": "user", "content": prompt}
80
- ],
81
- max_tokens=max_tokens,
82
- temperature=0.7,
83
- top_p=0.9
84
- )
85
- return response.choices[0].message.content.strip()
86
- except Exception as e:
87
- return f"Error generating response: {str(e)}"
88
-
89
- class HuggingFaceProvider(AIProvider):
90
- def __init__(self):
91
- super().__init__()
92
- self.name = "HuggingFace Fallback"
93
- self.gen = None
94
- if HF_AVAILABLE and HF_PIPELINE:
95
- try:
96
- self.gen = HF_PIPELINE("text2text-generation", model="google/flan-t5-base")
97
- self.available = True
98
- except Exception as e:
99
- st.warning(f"HuggingFace pipeline failed to load: {e}")
100
- self.available = False
101
- else:
102
- self.available = False
103
-
104
- def generate(self, prompt: str, max_tokens: int = 512) -> str:
105
- if not self.available or self.gen is None:
106
- return self._fallback_response(prompt)
107
-
108
- try:
109
- out = self.gen(prompt, max_length=min(1024, max_tokens), do_sample=False)
110
- return out[0]["generated_text"].strip()
111
- except Exception:
112
- return self._fallback_response(prompt)
113
-
114
- def _fallback_response(self, prompt: str) -> str:
115
- return (
116
- "🤖 **AI-Enhanced Financial Guidance**\n\n"
117
- "Based on your query, here are key recommendations:\n"
118
- "• **Emergency Fund**: Build 6 months of expenses in liquid funds\n"
119
- "• **Tax Saving**: Utilize Section 80C (₹1.5L limit) through ELSS/PPF\n"
120
- "• **Investment**: Balance equity (60%) and debt (40%) based on risk profile\n"
121
- "• **Insurance**: Term life insurance of 10x annual income\n\n"
122
- "For personalized calculations, please provide your monthly income and goals."
123
  )
124
-
125
- CATEGORIES = {
126
- "groceries": ["grocery", "supermarket", "food", "mart", "vegetables", "fruits"],
127
- "rent": ["rent", "landlord", "housing"],
128
- "utilities": ["electric", "water", "gas", "utility", "internet", "mobile", "phone"],
129
- "transport": ["uber", "ola", "fuel", "bus", "metro", "train", "cab", "petrol", "diesel"],
130
- "entertainment": ["netflix", "spotify", "movie", "cinema", "concert", "game", "youtube"],
131
- "health": ["pharmacy", "doctor", "hospital", "clinic", "medicine", "health"],
132
- "eating_out": ["restaurant", "cafe", "bar", "eatery", "diner", "zomato", "swiggy"],
133
- "shopping": ["amazon", "flipkart", "myntra", "shop", "store", "clothing"],
134
- "income": ["salary", "stipend", "bonus", "interest", "dividend", "freelance"],
135
- "investment": ["sip", "mutual fund", "stock", "gold", "ppf", "fd"],
136
- "insurance": ["insurance", "premium", "policy"],
137
- "education": ["fees", "books", "course", "training"],
138
- "travel": ["flight", "hotel", "vacation", "trip"]
139
- }
140
-
141
- def categorize(desc: str) -> str:
142
- desc_l = (desc or "").lower()
143
- for cat, keys in CATEGORIES.items():
144
- if any(k in desc_l for k in keys):
145
- return cat
146
- return "other"
147
-
148
- @dataclass
149
- class UserProfile:
150
- name: str
151
- user_type: str
152
- age: int
153
- country: str
154
- monthly_income: float
155
- risk_tolerance: str
156
- goals: str
157
-
158
- def get_risk_level(self) -> str:
159
- risk_map = {
160
- "conservative": "low",
161
- "moderate": "medium",
162
- "aggressive": "high"
163
- }
164
- return risk_map.get(self.risk_tolerance.lower(), "medium")
165
-
166
- def load_transactions(uploaded_file: Optional[io.BytesIO]) -> pd.DataFrame:
167
- if uploaded_file is None:
168
- # Enhanced sample data with more realistic transactions
169
- data = {
170
- "date": pd.date_range("2025-01-01", periods=30, freq="D"),
171
- "description": [
172
- "Salary Credit", "Rent Payment", "Grocery Store", "Restaurant Bill", "Metro Card",
173
- "Internet Bill", "Pharmacy", "Movie Ticket", "Amazon Purchase", "Fuel Station",
174
- "Bonus Credit", "Electricity Bill", "Coffee Shop", "Supermarket", "Hospital",
175
- "Netflix Subscription", "Uber Ride", "Water Bill", "Gym Membership", "Flipkart",
176
- "Bus Pass", "Medicine", "Dividend Credit", "Train Ticket", "SIP Investment",
177
- "Insurance Premium", "Mobile Recharge", "Zomato Order", "Book Purchase", "ATM Withdrawal"
178
- ],
179
- "amount": [
180
- 75000, -18000, -3200, -1200, -500, -1500, -800, -400, -2800, -2000,
181
- 15000, -2200, -300, -2800, -3500, -800, -250, -600, -2000, -1500,
182
- -400, -450, 2500, -180, -5000, -3000, -399, -850, -550, -2000
183
- ],
184
- }
185
- df = pd.DataFrame(data)
186
  else:
187
- df = pd.read_csv(uploaded_file)
188
-
189
- df["category"] = df["description"].apply(categorize)
190
- return df
191
-
192
- def budget_summary(df: pd.DataFrame, monthly_income_hint: Optional[float] = None) -> Dict[str, Union[float, str]]:
193
- try:
194
- df["month"] = pd.to_datetime(df["date"]).dt.to_period("M").astype(str)
195
- income = df.loc[df["amount"] > 0, "amount"].sum()
196
- expenses = -df.loc[df["amount"] < 0, "amount"].sum()
197
- net = income - expenses
198
-
199
- if monthly_income_hint and monthly_income_hint > 0:
200
- income = max(income, monthly_income_hint)
201
- net = income - expenses
202
-
203
- savings_rate = (net / income) * 100 if income > 0 else 0.0
204
-
205
- # Category breakdown
206
- expense_by_category = df[df["amount"] < 0].groupby("category")["amount"].sum().abs()
207
- top_expenses = expense_by_category.nlargest(5)
208
-
209
- return {
210
- "income_total": float(round(income, 2)),
211
- "expense_total": float(round(expenses, 2)),
212
- "net_savings": float(round(net, 2)),
213
- "savings_rate_pct": float(round(savings_rate, 2)),
214
- "top_expenses": top_expenses.to_dict(),
215
- "expense_breakdown": expense_by_category.to_dict()
216
  }
217
- except Exception as e:
218
- return {
219
- "income_total": monthly_income_hint or 50000,
220
- "expense_total": 35000,
221
- "net_savings": 15000,
222
- "savings_rate_pct": 30.0,
223
- "top_expenses": {},
224
- "expense_breakdown": {}
225
- }
226
-
227
- def generate_ai_financial_plan(profile: UserProfile, summary: Dict[str, Union[float, str]]) -> str:
228
- """Generate comprehensive AI-powered financial plan"""
229
-
230
- income = summary["income_total"]
231
- savings = summary["net_savings"]
232
- savings_rate = summary["savings_rate_pct"]
233
-
234
- plan = []
235
-
236
- # Emergency Fund Strategy
237
- emergency_fund_target = profile.monthly_income * 6
238
- monthly_emergency_save = min(profile.monthly_income * 0.15, 10000)
239
- plan.append(f"🚨 **Emergency Fund Strategy**")
240
- plan.append(f"Target: ₹{emergency_fund_target:,.0f} (6 months expenses)")
241
- plan.append(f"Monthly allocation: ₹{monthly_emergency_save:,.0f}")
242
- plan.append(f"Investment: Liquid funds or high-yield savings (6-8% returns)")
243
-
244
- # Tax Optimization
245
- plan.append(f"\n📊 **Tax Optimization Plan**")
246
- max_80c = 150000
247
- recommended_80c = min(profile.monthly_income * 12 * 0.125, max_80c)
248
- monthly_80c = recommended_80c / 12
249
- plan.append(f"Section 80C: ₹{monthly_80c:,.0f}/month (₹{recommended_80c:,.0f}/year)")
250
- plan.append(f"Options: ELSS (12-15% returns), PPF (7.1% tax-free), NSC")
251
-
252
- # Investment Strategy
253
- plan.append(f"\n🚀 **Investment Allocation Strategy**")
254
- investable_amount = max(0, savings - monthly_emergency_save)
255
-
256
- if investable_amount > 1000:
257
- risk_level = profile.get_risk_level()
258
- if risk_level == "low":
259
- equity_pct, debt_pct = 40, 60
260
- expected_return = "8-10%"
261
- elif risk_level == "high":
262
- equity_pct, debt_pct = 80, 20
263
- expected_return = "12-15%"
264
  else:
265
- equity_pct, debt_pct = 60, 40
266
- expected_return = "10-12%"
267
-
268
- equity_amount = investable_amount * (equity_pct / 100)
269
- debt_amount = investable_amount * (debt_pct / 100)
270
-
271
- plan.append(f"Monthly Investment: ₹{investable_amount:,.0f}")
272
- plan.append(f"Equity allocation: ₹{equity_amount:,.0f} ({equity_pct}%) - Nifty 50, Large Cap funds")
273
- plan.append(f"Debt allocation: ₹{debt_amount:,.0f} ({debt_pct}%) - Debt funds, Bonds")
274
- plan.append(f"Expected annual returns: {expected_return}")
275
-
276
- # Goal-based Planning
277
- if "retirement" in profile.goals.lower():
278
- plan.append(f"\n🏖️ **Retirement Planning**")
279
- retirement_corpus = profile.monthly_income * 12 * 25
280
- years_to_retire = 65 - profile.age
281
- monthly_retirement_sip = retirement_corpus / (years_to_retire * 12) if years_to_retire > 0 else 0
282
- plan.append(f"Target corpus: ₹{retirement_corpus:,.0f}")
283
- plan.append(f"Monthly SIP needed: ₹{monthly_retirement_sip:,.0f}")
284
- plan.append(f"Time horizon: {years_to_retire} years")
285
-
286
- if any(word in profile.goals.lower() for word in ["house", "home", "property"]):
287
- plan.append(f"\n🏠 **Home Purchase Plan**")
288
- home_value = profile.monthly_income * 12 * 5
289
- down_payment = home_value * 0.2
290
- years_to_buy = 7
291
- monthly_home_save = down_payment / (years_to_buy * 12)
292
- plan.append(f"Target home value: ₹{home_value:,.0f}")
293
- plan.append(f"Down payment needed: ₹{down_payment:,.0f}")
294
- plan.append(f"Monthly savings: ₹{monthly_home_save:,.0f} for {years_to_buy} years")
295
-
296
- # Insurance Strategy
297
- if profile.user_type.lower() == "professional":
298
- plan.append(f"\n🛡️ **Insurance Protection**")
299
- term_coverage = profile.monthly_income * 12 * 10
300
- term_premium_estimate = term_coverage / 1000 # Rough estimate
301
- plan.append(f"Term life insurance: ₹{term_coverage:,.0f}")
302
- plan.append(f"Estimated premium: ₹{term_premium_estimate:,.0f}/month")
303
- plan.append(f"Health insurance: ₹10L family floater recommended")
304
-
305
- # Performance Analysis
306
- plan.append(f"\n📈 **Current Performance Analysis**")
307
- plan.append(f"Savings rate: {savings_rate:.1f}% {'✅ Excellent' if savings_rate > 30 else '⚠️ Needs improvement' if savings_rate > 20 else '🚨 Critical'}")
308
- plan.append(f"Monthly surplus: ₹{savings:,.0f}")
309
-
310
- if savings_rate < 20:
311
- plan.append(f"💡 **Immediate Action**: Increase savings rate to 25% minimum")
312
- plan.append(f"Target monthly savings: ₹{profile.monthly_income * 0.25:,.0f}")
313
-
314
- return "\n".join(plan)
315
-
316
- def build_enhanced_prompt(profile: UserProfile, summary: Dict, user_query: str) -> str:
317
- """Build enhanced prompt for AI with comprehensive context"""
318
-
319
- context = f"""
320
- FINANCIAL PROFILE:
321
- - User Type: {profile.user_type}
322
- - Monthly Income: ₹{profile.monthly_income:,.0f}
323
- - Risk Tolerance: {profile.risk_tolerance}
324
- - Financial Goals: {profile.goals}
325
- - Current Savings Rate: {summary['savings_rate_pct']:.1f}%
326
- - Monthly Surplus: ₹{summary['net_savings']:,.0f}
327
 
328
- EXPENSE ANALYSIS:
329
- - Total Monthly Expenses: ₹{summary['expense_total']:,.0f}
330
- - Top Spending Categories: {', '.join([f"{k}: ₹{v:,.0f}" for k, v in list(summary.get('top_expenses', {}).items())[:3]])}
331
 
332
- USER QUERY: {user_query}
333
-
334
- INSTRUCTIONS:
335
- As FinanceAI, provide specific, actionable financial advice for Indian markets. Include:
336
- 1. Exact amounts and calculations
337
- 2. Specific investment products (fund names, tax sections)
338
- 3. Expected returns and time horizons
339
- 4. Implementation steps
340
- 5. Risk considerations
341
-
342
- Use current Indian financial regulations, tax laws (FY 2024-25), and market conditions.
343
- Be conversational but professional. Include emojis for better readability.
344
- """
345
-
346
- return context
347
-
348
- INTENT_PATTERNS = {
349
- "savings": r"save|savings|emergency|fd|rd|goal|corpus",
350
- "tax": r"tax|80c|deduction|income tax|regime|tds|refund|section",
351
- "invest": r"invest|sip|mutual fund|stock|index|portfolio|asset|equity|debt",
352
- "budget": r"budget|spend|expense|track|summary|report|category",
353
- "insurance": r"insurance|term|health|life|cover|premium|policy",
354
- "retirement": r"retirement|pension|retire|old age|corpus",
355
- "loan": r"loan|emi|mortgage|credit|debt|interest rate"
356
- }
357
-
358
- def detect_intent(text: str) -> str:
359
- t = text.lower()
360
- for intent, pattern in INTENT_PATTERNS.items():
361
- if re.search(pattern, t):
362
- return intent
363
- return "general"
364
-
365
- # Modern Styling
366
- st.markdown("""
367
- <style>
368
- .main-header {
369
- text-align: center;
370
- padding: 2rem 0;
371
- background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
372
- -webkit-background-clip: text;
373
- -webkit-text-fill-color: transparent;
374
- font-size: 3.5rem;
375
- font-weight: 800;
376
- margin-bottom: 1rem;
377
- text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
378
- }
379
- .subtitle {
380
- text-align: center;
381
- color: #6b7280;
382
- font-size: 1.3rem;
383
- margin-bottom: 2rem;
384
- font-weight: 500;
385
- }
386
- .ai-badge {
387
- background: linear-gradient(45deg, #10b981, #3b82f6);
388
- color: white;
389
- padding: 0.5rem 1rem;
390
- border-radius: 20px;
391
- font-size: 0.9rem;
392
- font-weight: 600;
393
- display: inline-block;
394
- margin: 0.5rem 0;
395
- }
396
- .financial-plan {
397
- background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
398
- border-left: 5px solid #0ea5e9;
399
- padding: 1.5rem;
400
- margin: 1rem 0;
401
- border-radius: 10px;
402
- box-shadow: 0 4px 6px rgba(0,0,0,0.1);
403
- }
404
- .metric-card {
405
- background: white;
406
- border-radius: 12px;
407
- padding: 1.5rem;
408
- box-shadow: 0 2px 8px rgba(0,0,0,0.1);
409
- border: 1px solid #e2e8f0;
410
- text-align: center;
411
- }
412
- .chat-container {
413
- max-width: 900px;
414
- margin: 0 auto;
415
- padding: 0 1rem;
416
- }
417
- </style>
418
- """, unsafe_allow_html=True)
419
-
420
- # Header
421
- st.markdown('<h1 class="main-header">🤖 FinanceAI</h1>', unsafe_allow_html=True)
422
- st.markdown('<p class="subtitle">AI-Powered Financial Advisor with GPT Intelligence</p>', unsafe_allow_html=True)
423
-
424
- # AI Status Badge
425
- if OPENAI_AVAILABLE and os.environ.get("OPENAI_API_KEY"):
426
- st.markdown('<div class="ai-badge">🚀 Powered by OpenAI GPT-4 • Maximum Accuracy</div>', unsafe_allow_html=True)
427
- else:
428
- st.markdown('<div class="ai-badge">⚡ Enhanced AI Fallback • Smart Responses</div>', unsafe_allow_html=True)
429
-
430
- # Quick Setup
431
- with st.expander("⚙️ Financial Profile Setup", expanded=True):
432
- col1, col2, col3 = st.columns(3)
433
- with col1:
434
- monthly_income = st.number_input("💰 Monthly Income (₹)", min_value=0, value=50000, step=5000, help="Your total monthly earnings")
435
- user_type = st.selectbox("👤 Profile Type", ["Professional", "Student"], index=0)
436
- with col2:
437
- risk = st.selectbox("📊 Risk Tolerance", ["Conservative", "Moderate", "Aggressive"], index=1, help="Your comfort level with investment risk")
438
- uploaded = st.file_uploader("📄 Upload Transactions (CSV)", type=["csv"], help="Optional: Upload your expense data")
439
- with col3:
440
- provider_choice = st.selectbox("🤖 AI Engine", ["OpenAI GPT-4 (Recommended)", "Smart Fallback"], index=0)
441
- goals = st.text_input("🎯 Financial Goals", value="Tax saving, wealth building, retirement planning", help="Your financial objectives")
442
-
443
- # Create profile
444
- profile = UserProfile(
445
- name="User", user_type=user_type, age=28, country="India",
446
- monthly_income=float(monthly_income), risk_tolerance=risk.lower(), goals=goals
447
- )
448
-
449
- # Initialize AI Providers
450
- if not st.session_state.provider_inited:
451
- openai_provider = OpenAIProvider()
452
- hf_provider = HuggingFaceProvider()
453
-
454
- if provider_choice.startswith("OpenAI") and openai_provider.available:
455
- chosen_provider = openai_provider
456
- else:
457
- chosen_provider = hf_provider
458
-
459
- st.session_state.provider = chosen_provider
460
- st.session_state.provider_inited = True
461
-
462
- provider = st.session_state.provider
463
-
464
- # Load and analyze financial data
465
- df = load_transactions(uploaded)
466
- summary = budget_summary(df, monthly_income_hint=profile.monthly_income)
467
-
468
- # Financial Overview
469
- st.markdown("### 📊 Financial Dashboard")
470
- col1, col2, col3, col4 = st.columns(4)
471
-
472
- with col1:
473
- st.metric("💰 Monthly Income", f"₹{summary['income_total']:,.0f}", help="Total monthly earnings")
474
- with col2:
475
- st.metric("💸 Expenses", f"₹{summary['expense_total']:,.0f}", help="Total monthly spending")
476
- with col3:
477
- st.metric("🎯 Net Savings", f"₹{summary['net_savings']:,.0f}", help="Monthly surplus amount")
478
- with col4:
479
- savings_color = "normal" if summary['savings_rate_pct'] > 20 else "inverse"
480
- st.metric("📈 Savings Rate", f"{summary['savings_rate_pct']:.1f}%", help="Percentage of income saved")
481
-
482
- st.divider()
483
-
484
- # AI-Generated Financial Plan
485
- ai_plan = generate_ai_financial_plan(profile, summary)
486
- st.markdown("### 🎯 AI-Generated Financial Plan")
487
- st.markdown(f'<div class="financial-plan">{ai_plan}</div>', unsafe_allow_html=True)
488
-
489
- st.divider()
490
-
491
- # Enhanced Chat Interface
492
- st.markdown('<div class="chat-container">', unsafe_allow_html=True)
493
- st.markdown("### 💬 Ask Your Financial Questions")
494
-
495
- # Display chat history
496
- for turn in st.session_state.chat_history:
497
- avatar = "🤖" if turn["role"] == "assistant" else "👤"
498
- with st.chat_message(turn["role"], avatar=avatar):
499
- st.markdown(turn["content"])
500
-
501
- # Chat input
502
- user_msg = st.chat_input("💬 Ask anything about investments, taxes, savings, or financial planning...")
503
-
504
- if user_msg:
505
- # Add user message
506
- st.session_state.chat_history.append({"role": "user", "content": user_msg})
507
-
508
- # Detect intent and build enhanced prompt
509
- intent = detect_intent(user_msg)
510
- enhanced_prompt = build_enhanced_prompt(profile, summary, user_msg)
511
-
512
- # Generate AI response
513
- with st.chat_message("assistant", avatar="🤖"):
514
- with st.spinner(f"🧠 {provider.name} is analyzing your query..."):
515
- try:
516
- ai_response = provider.generate(enhanced_prompt, max_tokens=1000)
517
-
518
- # Enhance response with intent-specific formatting
519
- if intent == "tax":
520
- ai_response = f"📊 **Tax Optimization Advice**\n\n{ai_response}"
521
- elif intent == "invest":
522
- ai_response = f"🚀 **Investment Strategy**\n\n{ai_response}"
523
- elif intent == "savings":
524
- ai_response = f"💰 **Savings Plan**\n\n{ai_response}"
525
- elif intent == "insurance":
526
- ai_response = f"🛡️ **Insurance Strategy**\n\n{ai_response}"
527
-
528
- except Exception as e:
529
- ai_response = f"⚠️ **AI Service Temporarily Unavailable**\n\nI apologize for the inconvenience. Here's a quick response based on your query:\n\n"
530
-
531
- # Fallback responses based on intent
532
- if intent == "tax":
533
- ai_response += "For tax optimization:\n• Invest ₹12,500/month in ELSS for Section 80C\n• Consider NPS for additional ₹50,000 deduction\n• Use tax-saving FDs for conservative investors"
534
- elif intent == "invest":
535
- ai_response += f"For investment strategy:\n• Monthly SIP: ₹{summary['net_savings']*.6:.0f} in equity funds\n• Emergency fund: ₹{summary['net_savings']*.3:.0f} in liquid funds\n• Debt allocation: ₹{summary['net_savings']*.1:.0f} in debt funds"
536
- else:
537
- ai_response += "Please check your internet connection and try again. For immediate help, consider:\n• Building 6-month emergency fund\n• Starting systematic investment plans\n• Optimizing tax-saving investments"
538
-
539
- st.markdown(ai_response)
540
-
541
- # Add AI response to history
542
- st.session_state.chat_history.append({"role": "assistant", "content": ai_response})
543
-
544
- st.markdown('</div>', unsafe_allow_html=True)
545
 
546
- # Enhanced Footer
547
- st.markdown("""
548
- <div style="text-align: center; padding: 3rem 2rem; background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%); border-radius: 15px; margin-top: 3rem; border: 1px solid #cbd5e1;">
549
- <h3 style="color: #1e293b; margin-bottom: 1rem;">🤖 FinanceAI</h3>
550
- <p style="color: #475569; font-size: 1.1rem; margin-bottom: 0.5rem;"><strong>AI-Powered Financial Intelligence</strong></p>
551
- <p style="color: #64748b; font-size: 0.95rem;">Powered by advanced AI models • Personalized recommendations • Always verify with current regulations</p>
552
- <div style="margin-top: 1rem; font-size: 0.85rem; color: #94a3b8;">
553
- 🔒 Secure • 🎯 Accurate • 📊 Data-Driven • 🇮🇳 India-Focused
554
- </div>
555
- </div>
556
- """, unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
+ from transformers import pipeline
3
 
4
+ # ---- Load HuggingFace Model ----
5
+ @st.cache_resource
6
+ def load_model():
7
+ try:
8
+ # Try Falcon-7B first (best results, requires GPU)
9
+ return pipeline(
10
+ "text-generation",
11
+ model="tiiuae/falcon-7b-instruct",
12
+ device_map="auto",
13
+ trust_remote_code=True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  )
15
+ except Exception as e1:
16
+ st.warning("⚠️ Falcon-7B could not load. Falling back to FLAN-T5-Base (lighter).")
17
+ try:
18
+ return pipeline("text2text-generation", model="google/flan-t5-base")
19
+ except Exception as e2:
20
+ st.error(f" Failed to load any model.\nFalcon error: {e1}\nFLAN error: {e2}")
21
+ return None
22
+
23
+ generator = load_model()
24
+
25
+ # ---- Build prompt ----
26
+ def build_prompt(user_input, profile, summary, is_t5=False):
27
+ profile_text = (
28
+ f"You are FinanceAI, an expert Indian financial advisor.\n\n"
29
+ f"Profile:\n"
30
+ f"Age: {profile['age']}, "
31
+ f"Occupation: {profile['occupation']}, "
32
+ f"Income: ₹{profile['income']}/month, "
33
+ f"Risk Appetite: {profile['risk_appetite']}, "
34
+ f"Goals: {', '.join(profile['goals'])}\n\n"
35
+ )
36
+ summary_text = f"Financial Summary:\n{summary}\n\n" if summary else ""
37
+ if is_t5:
38
+ return f"{profile_text}{summary_text}Question: {user_input}\nAnswer with step-by-step financial advice."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  else:
40
+ return f"{profile_text}{summary_text}User question: {user_input}\n\nGive clear, step-by-step financial advice with examples."
41
+
42
+ # ---- Streamlit UI ----
43
+ def main():
44
+ st.set_page_config(page_title="FinanceAI Chatbot", layout="wide")
45
+ st.title("💰 Personal Finance Chatbot")
46
+ st.write("This chatbot runs on **Hugging Face Spaces**.\n\n"
47
+ "It tries **Falcon-7B-Instruct** (GPU) first, then falls back to **FLAN-T5-Base** (CPU-friendly).")
48
+
49
+ # --- Initialize session state ---
50
+ if "profile" not in st.session_state:
51
+ st.session_state.profile = {
52
+ "age": 25,
53
+ "occupation": "Student",
54
+ "income": 50000,
55
+ "risk_appetite": "Moderate",
56
+ "goals": [],
 
 
 
 
 
 
 
 
 
 
 
 
57
  }
58
+ if "summary" not in st.session_state:
59
+ st.session_state.summary = "Income ₹50,000; Expenses ₹30,000; Savings ₹20,000"
60
+ if "chat_history" not in st.session_state:
61
+ st.session_state.chat_history = []
62
+
63
+ # Sidebar profile setup
64
+ st.sidebar.header("👤 User Profile")
65
+ st.session_state.profile["age"] = st.sidebar.number_input("Age", min_value=18, max_value=100, value=st.session_state.profile["age"])
66
+ st.session_state.profile["occupation"] = st.sidebar.selectbox("Occupation", ["Student", "Salaried", "Freelancer", "Business Owner"], index=["Student", "Salaried", "Freelancer", "Business Owner"].index(st.session_state.profile["occupation"]))
67
+ st.session_state.profile["income"] = st.sidebar.number_input("Monthly Income (₹)", min_value=0, value=st.session_state.profile["income"])
68
+ st.session_state.profile["risk_appetite"] = st.sidebar.selectbox("Risk Appetite", ["Low", "Moderate", "High"], index=["Low", "Moderate", "High"].index(st.session_state.profile["risk_appetite"]))
69
+ st.session_state.profile["goals"] = st.sidebar.multiselect("Financial Goals", ["Emergency Fund", "Retirement", "Travel", "Home", "Education", "Wealth Growth"], default=st.session_state.profile["goals"])
70
+
71
+ st.session_state.summary = st.sidebar.text_area("📊 Financial Summary", st.session_state.summary)
72
+
73
+ # Chat section
74
+ st.header("💬 Chat with FinanceAI")
75
+
76
+ user_input = st.text_input("Ask your financial question:")
77
+
78
+ if st.button("Send") and user_input:
79
+ if generator:
80
+ is_t5 = "text2text" in str(type(generator))
81
+ prompt = build_prompt(user_input, st.session_state.profile, st.session_state.summary, is_t5=is_t5)
82
+
83
+ if is_t5:
84
+ response = generator(prompt, max_length=256)
85
+ ai_response = response[0]['generated_text']
86
+ else:
87
+ response = generator(
88
+ prompt,
89
+ max_length=512,
90
+ do_sample=True,
91
+ top_p=0.9,
92
+ temperature=0.6
93
+ )
94
+ ai_response = response[0]['generated_text'].replace(prompt, "").strip()
 
 
 
 
 
 
 
 
 
 
95
  else:
96
+ ai_response = "⚠️ No model available. Please check setup."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
 
98
+ st.session_state.chat_history.append({"role": "user", "content": user_input})
99
+ st.session_state.chat_history.append({"role": "ai", "content": ai_response})
 
100
 
101
+ # Display chat history
102
+ for msg in st.session_state.chat_history:
103
+ if msg["role"] == "user":
104
+ st.markdown(f"**👤 You:** {msg['content']}")
105
+ else:
106
+ st.markdown(f"**🤖 FinanceAI:** {msg['content']}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
+ if __name__ == "__main__":
109
+ main()