Rahul2298 commited on
Commit
5762392
·
verified ·
1 Parent(s): 118beac

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +65 -110
src/streamlit_app.py CHANGED
@@ -1,26 +1,22 @@
1
  # personal_finance_chatbot.py
2
  import streamlit as st
3
- from transformers import AutoModelForSeq2SeqLM, AutoTokenizer, pipeline
4
  import json
5
  from datetime import datetime
6
- import random
7
- import pandas as pd
8
- import numpy as np
9
 
10
  # Configuration
11
- MODEL_NAME = "ibm/granite-7b-base" # Using IBM Granite model via HuggingFace
12
  USER_TYPES = ["student", "professional"]
13
- FINANCE_CATEGORIES = ["savings", "taxes", "investments", "budget", "spending"]
14
 
15
  # Initialize NLP pipeline
16
  @st.cache_resource
17
  def load_model():
18
- """Load and cache the language model"""
19
  tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
20
- model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_NAME)
21
- return pipeline("text2text-generation", model=model, tokenizer=tokenizer)
22
 
23
- # User profile management
24
  class UserProfile:
25
  def __init__(self, user_type, financial_goals=None, income=0, expenses=None):
26
  self.user_type = user_type
@@ -40,20 +36,17 @@ class UserProfile:
40
 
41
  def get_budget_summary(self):
42
  """Generate a budget summary"""
43
- total_expenses = sum(t["amount"] for t in self.transaction_history
44
- if t["amount"] < 0)
45
- total_income = sum(t["amount"] for t in self.transaction_history
46
- if t["amount"] > 0)
47
 
48
  return {
49
  "total_income": total_income,
50
  "total_expenses": abs(total_expenses),
51
- "net_savings": total_income + total_expenses,
52
  "category_breakdown": self._get_category_breakdown()
53
  }
54
 
55
  def _get_category_breakdown(self):
56
- """Get expense breakdown by category"""
57
  breakdown = {}
58
  for t in self.transaction_history:
59
  if t["amount"] < 0:
@@ -61,7 +54,7 @@ class UserProfile:
61
  breakdown[cat] = breakdown.get(cat, 0) + abs(t["amount"])
62
  return breakdown
63
 
64
- # Chatbot core functionality
65
  class FinanceChatbot:
66
  def __init__(self):
67
  self.nlp = load_model()
@@ -69,96 +62,83 @@ class FinanceChatbot:
69
  self.current_user = None
70
 
71
  def set_user(self, user_id, user_type):
72
- """Initialize or switch user profile"""
73
  if user_id not in self.user_profiles:
74
  self.user_profiles[user_id] = UserProfile(user_type=user_type)
75
  self.current_user = user_id
76
 
77
  def generate_response(self, query):
78
- """Generate context-aware response to user query"""
79
  if not self.current_user:
80
- return "Please identify yourself first. Are you a student or professional?"
81
 
82
  profile = self.user_profiles[self.current_user]
83
  context = self._build_context(profile)
84
 
85
- # Adjust tone based on user type
86
  tone_instruction = (
87
- "Use simple, encouraging language suitable for a student."
88
  if profile.user_type == "student" else
89
- "Use professional, concise language suitable for a financial professional."
90
  )
91
 
92
  prompt = f"""
93
- You are a helpful financial assistant. {tone_instruction}
94
- User profile context: {context}
95
- Current query: {query}
96
-
97
- Provide a helpful response that:
98
- 1. Directly answers the financial question
99
- 2. Offers 1-2 specific actionable suggestions when appropriate
100
- 3. Maintains a {profile.user_type}-appropriate tone
101
- 4. Is concise (3 sentences or less unless more detail is requested)
 
102
  """
103
 
104
  try:
105
- result = self.nlp(prompt, max_length=200, num_return_sequences=1)
106
- response = result[0]['generated_text'].strip()
107
-
108
- # Post-process to extract clean response
109
- if "Response:" in response:
110
- response = response.split("Response:")[-1].strip()
111
  return response
112
  except Exception as e:
113
- return f"Sorry, I encountered an error processing your request. {str(e)}"
114
 
115
  def _build_context(self, profile):
116
- """Build context string from user profile"""
117
  budget = profile.get_budget_summary()
118
  return json.dumps({
119
  "user_type": profile.user_type,
120
  "income": profile.income,
121
  "net_savings": budget["net_savings"],
122
  "top_expenses": sorted(budget["category_breakdown"].items(),
123
- key=lambda x: x[1], reverse=True)[:3],
124
- "recent_transactions": profile.transaction_history[-3:] if profile.transaction_history else []
125
  })
126
 
127
  def analyze_spending(self):
128
- """Generate spending insights"""
129
  if not self.current_user:
130
- return "No user profile selected"
131
 
132
  profile = self.user_profiles[self.current_user]
133
  budget = profile.get_budget_summary()
134
-
135
  if not budget["category_breakdown"]:
136
- return "No spending data available for analysis"
137
 
138
  prompt = f"""
139
- Analyze this spending data and provide insights:
140
- {json.dumps(budget['category_breakdown'])}
141
-
142
- User type: {profile.user_type}
143
- Income: {profile.income}
144
 
145
  Provide:
146
- 1. 1 key insight about spending patterns
147
- 2. 1 specific suggestion for optimization
148
- 3. Formatted for {profile.user_type} audience
149
  """
150
 
151
  try:
152
- result = self.nlp(prompt, max_length=150)
153
- return result[0]['generated_text'].strip()
154
  except Exception as e:
155
- return f"Error generating insights: {str(e)}"
156
 
157
- # Streamlit UI
158
  def main():
159
  st.set_page_config(page_title="Personal Finance Chatbot", layout="wide")
160
 
161
- # Initialize chatbot
162
  if 'chatbot' not in st.session_state:
163
  st.session_state.chatbot = FinanceChatbot()
164
  if 'user_id' not in st.session_state:
@@ -166,10 +146,10 @@ def main():
166
  if 'messages' not in st.session_state:
167
  st.session_state.messages = []
168
 
169
- # Sidebar for user setup
170
  with st.sidebar:
171
- st.title("User Profile")
172
- user_id = st.text_input("Your ID (any name)", value=st.session_state.get('user_id', ''))
173
  user_type = st.selectbox("I am a:", USER_TYPES)
174
 
175
  if st.button("Save Profile"):
@@ -178,72 +158,47 @@ def main():
178
  st.success(f"Profile saved as {user_type}")
179
 
180
  st.divider()
181
- st.subheader("Quick Actions")
182
 
183
  if st.session_state.user_id:
184
- col1, col2 = st.columns(2)
185
- with col1:
186
- if st.button("Budget Summary"):
187
- profile = st.session_state.chatbot.user_profiles[st.session_state.user_id]
188
- summary = profile.get_budget_summary()
189
- st.session_state.messages.append(
190
- {"role": "assistant", "content": f"### Your Budget Summary\n\n"
191
- f"- **Income**: ${summary['total_income']:.2f}\n"
192
- f"- **Expenses**: ${summary['total_expenses']:.2f}\n"
193
- f"- **Net Savings**: ${summary['net_savings']:.2f}\n\n"
194
- f"Top Expenses: {', '.join([f'{k}(${v:.2f})' for k,v in summary['category_breakdown'].items()])}"
195
- }
196
- )
197
- with col2:
198
- if st.button("Spending Insights"):
199
- insights = st.session_state.chatbot.analyze_spending()
200
- st.session_state.messages.append(
201
- {"role": "assistant", "content": f"### Spending Insights\n\n{insights}"}
202
- )
203
-
204
- # Main chat interface
205
  st.title("💰 Personal Finance Chatbot")
206
- st.write("Ask me about savings, taxes, investments, or budgeting!")
207
 
208
- # Display chat messages
209
  for message in st.session_state.messages:
210
  with st.chat_message(message["role"]):
211
  st.markdown(message["content"])
212
 
213
- # Chat input
214
- if prompt := st.chat_input("What would you like to know about your finances?"):
215
  if not st.session_state.user_id:
216
- st.error("Please set up your profile first!")
217
  else:
218
- # Add user message to chat history
219
  st.session_state.messages.append({"role": "user", "content": prompt})
220
  with st.chat_message("user"):
221
  st.markdown(prompt)
222
 
223
- # Generate and display assistant response
224
- with st.spinner("Thinking..."):
225
  response = st.session_state.chatbot.generate_response(prompt)
226
  with st.chat_message("assistant"):
227
  st.markdown(response)
228
  st.session_state.messages.append({"role": "assistant", "content": response})
229
 
230
- # Sample transactions for demo
231
- if st.session_state.user_id and st.checkbox("Load sample data (demo only)"):
232
- profile = st.session_state.chatbot.user_profiles[st.session_state.user_id]
233
- sample_data = [
234
- (1200, "income", "Monthly salary"),
235
- (-400, "housing", "Rent payment"),
236
- (-200, "food", "Groceries"),
237
- (-150, "transportation", "Public transport"),
238
- (-100, "entertainment", "Movies"),
239
- (50, "investments", "Stock purchase"),
240
- (-80, "utilities", "Electricity bill")
241
- ]
242
-
243
- for amount, category, desc in sample_data:
244
- profile.add_transaction(amount, category, desc)
245
-
246
- st.success("Loaded sample transactions! Try asking about your budget or spending.")
247
-
248
  if __name__ == "__main__":
249
  main()
 
1
  # personal_finance_chatbot.py
2
  import streamlit as st
3
+ from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
4
  import json
5
  from datetime import datetime
 
 
 
6
 
7
  # Configuration
8
+ MODEL_NAME = "ibm-granite/granite-7b-base" # Correct Granite HF name
9
  USER_TYPES = ["student", "professional"]
 
10
 
11
  # Initialize NLP pipeline
12
  @st.cache_resource
13
  def load_model():
14
+ """Load and cache Granite model for text generation"""
15
  tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
16
+ model = AutoModelForCausalLM.from_pretrained(MODEL_NAME)
17
+ return pipeline("text-generation", model=model, tokenizer=tokenizer)
18
 
19
+ # ------------------ USER PROFILE ------------------
20
  class UserProfile:
21
  def __init__(self, user_type, financial_goals=None, income=0, expenses=None):
22
  self.user_type = user_type
 
36
 
37
  def get_budget_summary(self):
38
  """Generate a budget summary"""
39
+ total_expenses = sum(t["amount"] for t in self.transaction_history if t["amount"] < 0)
40
+ total_income = sum(t["amount"] for t in self.transaction_history if t["amount"] > 0)
 
 
41
 
42
  return {
43
  "total_income": total_income,
44
  "total_expenses": abs(total_expenses),
45
+ "net_savings": total_income + total_expenses, # total_expenses is negative already
46
  "category_breakdown": self._get_category_breakdown()
47
  }
48
 
49
  def _get_category_breakdown(self):
 
50
  breakdown = {}
51
  for t in self.transaction_history:
52
  if t["amount"] < 0:
 
54
  breakdown[cat] = breakdown.get(cat, 0) + abs(t["amount"])
55
  return breakdown
56
 
57
+ # ------------------ CHATBOT CORE ------------------
58
  class FinanceChatbot:
59
  def __init__(self):
60
  self.nlp = load_model()
 
62
  self.current_user = None
63
 
64
  def set_user(self, user_id, user_type):
 
65
  if user_id not in self.user_profiles:
66
  self.user_profiles[user_id] = UserProfile(user_type=user_type)
67
  self.current_user = user_id
68
 
69
  def generate_response(self, query):
 
70
  if not self.current_user:
71
+ return "⚠️ Please set up your profile first (student or professional)."
72
 
73
  profile = self.user_profiles[self.current_user]
74
  context = self._build_context(profile)
75
 
 
76
  tone_instruction = (
77
+ "Use simple, encouraging language for a student."
78
  if profile.user_type == "student" else
79
+ "Use concise, professional language for a working professional."
80
  )
81
 
82
  prompt = f"""
83
+ You are an AI-powered financial assistant.
84
+ User profile: {context}
85
+ Instruction: {tone_instruction}
86
+
87
+ User asked: "{query}"
88
+
89
+ Respond with:
90
+ 1. Direct and clear answer
91
+ 2. 1-2 actionable suggestions
92
+ 3. Keep it under 3 sentences unless more detail is needed.
93
  """
94
 
95
  try:
96
+ result = self.nlp(prompt, max_new_tokens=200, do_sample=True, temperature=0.7)
97
+ response = result[0]['generated_text'].replace(prompt, "").strip()
 
 
 
 
98
  return response
99
  except Exception as e:
100
+ return f" Error: {str(e)}"
101
 
102
  def _build_context(self, profile):
 
103
  budget = profile.get_budget_summary()
104
  return json.dumps({
105
  "user_type": profile.user_type,
106
  "income": profile.income,
107
  "net_savings": budget["net_savings"],
108
  "top_expenses": sorted(budget["category_breakdown"].items(),
109
+ key=lambda x: x[1], reverse=True)[:3],
110
+ "recent_transactions": profile.transaction_history[-3:]
111
  })
112
 
113
  def analyze_spending(self):
 
114
  if not self.current_user:
115
+ return "⚠️ No user profile selected."
116
 
117
  profile = self.user_profiles[self.current_user]
118
  budget = profile.get_budget_summary()
 
119
  if not budget["category_breakdown"]:
120
+ return "ℹ️ No spending data yet."
121
 
122
  prompt = f"""
123
+ Analyze the spending breakdown: {json.dumps(budget['category_breakdown'])}.
124
+ User type: {profile.user_type}, Income: {profile.income}.
 
 
 
125
 
126
  Provide:
127
+ 1. One key spending insight
128
+ 2. One actionable saving tip
129
+ 3. Tone adapted for {profile.user_type}
130
  """
131
 
132
  try:
133
+ result = self.nlp(prompt, max_new_tokens=150, do_sample=True, temperature=0.7)
134
+ return result[0]['generated_text'].replace(prompt, "").strip()
135
  except Exception as e:
136
+ return f"Error: {str(e)}"
137
 
138
+ # ------------------ STREAMLIT UI ------------------
139
  def main():
140
  st.set_page_config(page_title="Personal Finance Chatbot", layout="wide")
141
 
 
142
  if 'chatbot' not in st.session_state:
143
  st.session_state.chatbot = FinanceChatbot()
144
  if 'user_id' not in st.session_state:
 
146
  if 'messages' not in st.session_state:
147
  st.session_state.messages = []
148
 
149
+ # Sidebar
150
  with st.sidebar:
151
+ st.title("👤 User Profile")
152
+ user_id = st.text_input("Your ID", value=st.session_state.get('user_id', ''))
153
  user_type = st.selectbox("I am a:", USER_TYPES)
154
 
155
  if st.button("Save Profile"):
 
158
  st.success(f"Profile saved as {user_type}")
159
 
160
  st.divider()
161
+ st.subheader("📊 Quick Actions")
162
 
163
  if st.session_state.user_id:
164
+ if st.button("View Budget Summary"):
165
+ profile = st.session_state.chatbot.user_profiles[st.session_state.user_id]
166
+ summary = profile.get_budget_summary()
167
+ st.session_state.messages.append(
168
+ {"role": "assistant", "content":
169
+ f"### Budget Summary\n- Income: ${summary['total_income']:.2f}\n"
170
+ f"- Expenses: ${summary['total_expenses']:.2f}\n"
171
+ f"- Net Savings: ${summary['net_savings']:.2f}\n"
172
+ f"- Top Expenses: {summary['category_breakdown']}"}
173
+ )
174
+
175
+ if st.button("Get Spending Insights"):
176
+ insights = st.session_state.chatbot.analyze_spending()
177
+ st.session_state.messages.append(
178
+ {"role": "assistant", "content": f"### Spending Insights\n{insights}"}
179
+ )
180
+
181
+ # Main chat
 
 
 
182
  st.title("💰 Personal Finance Chatbot")
183
+ st.write("Ask me about **savings, taxes, investments, or budgeting!**")
184
 
 
185
  for message in st.session_state.messages:
186
  with st.chat_message(message["role"]):
187
  st.markdown(message["content"])
188
 
189
+ if prompt := st.chat_input("Type your financial question here..."):
 
190
  if not st.session_state.user_id:
191
+ st.error("⚠️ Please set up your profile first!")
192
  else:
 
193
  st.session_state.messages.append({"role": "user", "content": prompt})
194
  with st.chat_message("user"):
195
  st.markdown(prompt)
196
 
197
+ with st.spinner("💡 Thinking..."):
 
198
  response = st.session_state.chatbot.generate_response(prompt)
199
  with st.chat_message("assistant"):
200
  st.markdown(response)
201
  st.session_state.messages.append({"role": "assistant", "content": response})
202
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  if __name__ == "__main__":
204
  main()