AnilNiraula commited on
Commit
5066868
·
verified ·
1 Parent(s): 71dc240

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +15 -275
app.py CHANGED
@@ -38,7 +38,7 @@ response_cache = {
38
  "what is better individual stocks or etfs?": (
39
  "Here’s a comparison of individual stocks vs. ETFs:\n"
40
  "1. **Individual Stocks**: High returns possible (e.g., Apple up 80% in 2020) but riskier due to lack of diversification. Require active research.\n"
41
- "2. **ETFs**: Diversify risk by tracking indices (e.g., SPY, S&P 500, ~12% avg. return 2015–2025). Lower fees and less research needed.\n"
42
  "3. **Recommendation**: Beginners should start with ETFs; experienced investors may add stocks.\n"
43
  "Consult a financial planner."
44
  ),
@@ -81,21 +81,21 @@ response_cache = {
81
  "Consult a financial planner."
82
  ),
83
  "do you have a list of companies you recommend?": (
84
- "I can’t recommend specific companies without data. Try ETFs like SPY (S&P 500, ~12% avg. return 2015–2025) or QQQ (tech). "
85
  "Research stocks like Apple (AAPL, ~80% return in 2020) or Johnson & Johnson on Yahoo Finance.\n"
86
  "Consult a financial planner."
87
  ),
88
  "how do i start investing in stocks?": (
89
  "Learn from Investopedia. Set goals and assess risk. Open a brokerage account (Fidelity, Vanguard) "
90
- "and start with ETFs (e.g., SPY, ~10% avg. return). Consult a financial planner."
91
  ),
92
  "what's the difference between stocks and bonds?": (
93
- "Stocks are company ownership with high risk and growth potential (e.g., S&P 500 ~10% avg. return). Bonds are loans to companies/governments "
94
  "with lower risk and steady interest. Diversify for balance."
95
  ),
96
  "how much should i invest?": (
97
  "Invest what you can afford after expenses and an emergency fund. Start with $100-$500 monthly "
98
- "in ETFs like SPY (~10% avg. return). Consult a financial planner."
99
  ),
100
  "what is dollar-cost averaging?": (
101
  "Dollar-cost averaging is investing a fixed amount regularly (e.g., $100 monthly) in ETFs, "
@@ -105,7 +105,7 @@ response_cache = {
105
  "Here are investing ideas:\n"
106
  "1. Open a brokerage account (e.g., Fidelity) if 18 or older.\n"
107
  "2. Deposit $100 or what you can afford.\n"
108
- "3. Buy a researched ETF (e.g., SPY, ~10% avg. return) or index fund.\n"
109
  "4. Check regularly and enable dividend reinvesting.\n"
110
  "5. Use dollar-cost averaging (e.g., monthly buys).\n"
111
  "Consult a financial planner."
@@ -114,7 +114,7 @@ response_cache = {
114
  "Here are investing tips:\n"
115
  "1. Educate yourself with Investopedia or books.\n"
116
  "2. Open a brokerage account (e.g., Vanguard).\n"
117
- "3. Start small with ETFs like SPY (~10% avg. return).\n"
118
  "4. Invest regularly using dollar-cost averaging.\n"
119
  "5. Diversify to manage risk.\n"
120
  "Consult a financial planner."
@@ -124,7 +124,7 @@ response_cache = {
124
  "1. Study basics on Investopedia.\n"
125
  "2. Open a brokerage account (e.g., Fidelity).\n"
126
  "3. Deposit $100 or more after securing savings.\n"
127
- "4. Buy an ETF like SPY (~10% avg. return) after research.\n"
128
  "5. Invest monthly with dollar-cost averaging.\n"
129
  "Consult a financial planner."
130
  ),
@@ -132,7 +132,7 @@ response_cache = {
132
  "Here’s investing advice:\n"
133
  "1. Learn basics from Investopedia.\n"
134
  "2. Open a brokerage account (e.g., Vanguard).\n"
135
- "3. Start with $100 in an ETF like SPY (~10% avg. return).\n"
136
  "4. Use dollar-cost averaging for regular investments.\n"
137
  "5. Monitor and diversify your portfolio.\n"
138
  "Consult a financial planner."
@@ -142,13 +142,13 @@ response_cache = {
142
  "1. Educate yourself using Investopedia.\n"
143
  "2. Open a brokerage account (e.g., Fidelity).\n"
144
  "3. Deposit an initial $100 after savings.\n"
145
- "4. Buy an ETF like SPY (~10% avg. return) after research.\n"
146
  "5. Use dollar-cost averaging monthly.\n"
147
  "Consult a financial planner."
148
  ),
149
  "what is the s&p 500 index fund average growth rate?": (
150
  "The S&P 500 index fund’s average annual return is approximately 10–12% over the long term (1927–2025), including dividends, based on historical data. "
151
- "For example, from 2015 to 2025, it averaged ~12% annually. Returns vary yearly due to market conditions. Consult a financial planner."
152
  ),
153
  "what was the s&p 500 return in 2020?": (
154
  "The S&P 500 returned approximately 16.3% in 2020, including dividends, driven by recovery from the COVID-19 market crash."
@@ -174,6 +174,9 @@ response_cache = {
174
  ),
175
  "what was the 5-year average annual growth rate of the s&p 500 from 2016?": (
176
  "The S&P 500’s average annual growth rate from 2016 to 2020 was approximately 13.6%, including dividends, driven by strong market recovery."
 
 
 
177
  )
178
  }
179
 
@@ -200,267 +203,4 @@ try:
200
  torch_dtype=torch.float16,
201
  low_cpu_mem_usage=True
202
  ).to(device)
203
- logger.info(f"Successfully loaded model: {model_name}")
204
- except Exception as e:
205
- logger.error(f"Error loading model/tokenizer: {e}")
206
- raise RuntimeError(f"Failed to load model: {str(e)}")
207
-
208
- # Parse period from user input
209
- def parse_period(query):
210
- # Match specific year ranges (e.g., "2000 to 2008", "2011–2016")
211
- match = re.search(r'(\d{4})\s*(?:to|-|–)\s*(\d{4})', query, re.IGNORECASE)
212
- if match:
213
- start_year, end_year = map(int, match.groups())
214
- return start_year, end_year, None
215
- # Match duration-based queries (e.g., "1-year from 2020", "3-year growth rate")
216
- match = re.search(r'(\d+)-year.*from\s*(\d{4})', query, re.IGNORECASE)
217
- if match:
218
- duration, start_year = map(int, match.groups())
219
- end_year = start_year + duration - 1
220
- return start_year, end_year, duration
221
- # Match general duration queries (e.g., "1-year growth rate")
222
- match = re.search(r'(\d+)-year.*growth\s*rate', query, re.IGNORECASE)
223
- if match:
224
- duration = int(match.group(1))
225
- max_year = df['Date'].dt.year.max() if df is not None else 2025
226
- start_year = max_year - duration + 1
227
- end_year = max_year
228
- return start_year, end_year, duration
229
- return None, None, None
230
-
231
- # Calculate average growth rate
232
- def calculate_growth_rate(start_year, end_year, duration=None):
233
- if df is None or start_year is None or end_year is None:
234
- return None, "Data not available or invalid period."
235
- df_period = df[(df['Date'].dt.year >= start_year) & (df['Date'].dt.year <= end_year)]
236
- if df_period.empty:
237
- return None, f"No data available for {start_year} to {end_year}."
238
- avg_return = df_period['Return'].mean()
239
- if duration:
240
- response = f"The S&P 500’s {duration}-year average annual growth rate from {start_year} to {end_year} was approximately {avg_return:.1f}%, including dividends."
241
- else:
242
- response = f"The S&P 500’s average annual growth rate from {start_year} to {end_year} was approximately {avg_return:.1f}%, including dividends."
243
- return avg_return, response
244
-
245
- # Parse investment return query
246
- def parse_investment_query(query):
247
- match = re.search(r'\$(\d+).*\s(\d+)\s*years?.*\bs&p\s*500', query, re.IGNORECASE)
248
- if match:
249
- amount = float(match.group(1))
250
- years = int(match.group(2))
251
- return amount, years
252
- return None, None
253
-
254
- # Calculate future value
255
- def calculate_future_value(amount, years):
256
- if df is None or amount is None or years is None:
257
- return None, "Data not available or invalid input."
258
- avg_annual_return = 10.0 # Historical S&P 500 average (1927–2025)
259
- future_value = amount * (1 + avg_annual_return / 100) ** years
260
- return future_value, (
261
- f"Assuming a 10% average annual return, a ${amount:,.0f} investment in the S&P 500 would grow to approximately ${future_value:,.0f} "
262
- f"in {years} years with annual compounding. This is based on the historical average return of 10–12% (1927–2025). "
263
- "Future returns vary and are not guaranteed. Consult a financial planner."
264
- )
265
-
266
- # Define chat function
267
- def chat_with_model(user_input, history=None, is_processing=False):
268
- try:
269
- start_time = time.time()
270
- logger.info(f"Processing user input: {user_input}")
271
- is_processing = True
272
- logger.info("Showing loading animation")
273
-
274
- # Normalize and check cache
275
- cache_key = user_input.lower().strip()
276
- cache_keys = list(response_cache.keys())
277
- closest_key = cache_key if cache_key in response_cache else get_closest_cache_key(cache_key, cache_keys)
278
- if closest_key:
279
- logger.info(f"Cache hit for: {closest_key}")
280
- response = response_cache[closest_key]
281
- logger.info(f"Chatbot response: {response}")
282
- history = history or []
283
- history.append({"role": "user", "content": user_input})
284
- history.append({"role": "assistant", "content": response})
285
- end_time = time.time()
286
- logger.info(f"Response time: {end_time - start_time:.2f} seconds")
287
- return response, history, False, ""
288
-
289
- # Check for investment return query
290
- amount, years = parse_investment_query(user_input)
291
- if amount and years:
292
- future_value, response = calculate_future_value(amount, years)
293
- if future_value is not None:
294
- response_cache[cache_key] = response
295
- logger.info(f"Investment query: ${amount} for {years} years, added to cache")
296
- logger.info(f"Chatbot response: {response}")
297
- history = history or []
298
- history.append({"role": "user", "content": user_input})
299
- history.append({"role": "assistant", "content": response})
300
- end_time = time.time()
301
- logger.info(f"Response time: {end_time - start_time:.2f} seconds")
302
- return response, history, False, ""
303
-
304
- # Check for period-specific query
305
- start_year, end_year, duration = parse_period(user_input)
306
- if start_year and end_year:
307
- avg_return, response = calculate_growth_rate(start_year, end_year, duration)
308
- if avg_return is not None:
309
- response_cache[cache_key] = response
310
- logger.info(f"Dynamic period query: {start_year}–{end_year}, added to cache")
311
- logger.info(f"Chatbot response: {response}")
312
- history = history or []
313
- history.append({"role": "user", "content": user_input})
314
- history.append({"role": "assistant", "content": response})
315
- end_time = time.time()
316
- logger.info(f"Response time: {end_time - start_time:.2f} seconds")
317
- return response, history, False, ""
318
-
319
- # Skip model for short prompts
320
- if len(user_input.strip()) <= 5:
321
- logger.info("Short prompt, returning default response")
322
- response = "Hello! I'm FinChat, your financial advisor. Ask about investing!"
323
- logger.info(f"Chatbot response: {response}")
324
- history = history or []
325
- history.append({"role": "user", "content": user_input})
326
- history.append({"role": "assistant", "content": response})
327
- end_time = time.time()
328
- logger.info(f"Response time: {end_time - start_time:.2f} seconds")
329
- return response, history, False, ""
330
-
331
- # Construct prompt
332
- full_prompt = prompt_prefix + user_input + "\nA:"
333
- try:
334
- inputs = tokenizer(full_prompt, return_tensors="pt", truncation=True, max_length=512).to(device)
335
- except Exception as e:
336
- logger.error(f"Error tokenizing input: {e}")
337
- response = f"Error: Failed to process input: {str(e)}"
338
- logger.info(f"Chatbot response: {response}")
339
- history = history or []
340
- history.append({"role": "user", "content": user_input})
341
- history.append({"role": "assistant", "content": response})
342
- end_time = time.time()
343
- logger.info(f"Response time: {end_time - start_time:.2f} seconds")
344
- return response, history, False, ""
345
-
346
- # Generate response
347
- with torch.inference_mode():
348
- logger.info("Generating response with model")
349
- gen_start_time = time.time()
350
- outputs = model.generate(
351
- **inputs,
352
- max_new_tokens=50,
353
- min_length=20,
354
- do_sample=False,
355
- repetition_penalty=2.0,
356
- pad_token_id=tokenizer.eos_token_id
357
- )
358
- gen_end_time = time.time()
359
- logger.info(f"Generation time: {gen_end_time - gen_start_time:.2f} seconds")
360
- response = tokenizer.decode(outputs[0], skip_special_tokens=True)
361
- response = response[len(full_prompt):].strip() if response.startswith(full_prompt) else response
362
- logger.info(f"Chatbot response: {response}")
363
-
364
- # Update cache
365
- response_cache[cache_key] = response
366
- logger.info("Cache miss, added to in-memory cache")
367
-
368
- # Update history
369
- history = history or []
370
- history.append({"role": "user", "content": user_input})
371
- history.append({"role": "assistant", "content": response})
372
- torch.cuda.empty_cache()
373
- end_time = time.time()
374
- logger.info(f"Response time: {end_time - start_time:.2f} seconds")
375
- return response, history, False, ""
376
-
377
- except Exception as e:
378
- logger.error(f"Error generating response: {e}")
379
- response = f"Error: {str(e)}"
380
- logger.info(f"Chatbot response: {response}")
381
- history = history or []
382
- history.append({"role": "user", "content": user_input})
383
- history.append({"role": "assistant", "content": response})
384
- end_time = time.time()
385
- logger.info(f"Response time: {end_time - start_time:.2f} seconds")
386
- return response, history, False, ""
387
-
388
- # Save cache on exit
389
- def save_cache():
390
- try:
391
- with open(cache_file, 'w') as f:
392
- json.dump(response_cache, f, indent=2)
393
- logger.info("Saved cache to cache.json")
394
- except Exception as e:
395
- logger.warning(f"Failed to save cache.json: {e}")
396
-
397
- # Create Gradio interface with loading animation
398
- logger.info("Initializing Gradio interface")
399
- try:
400
- with gr.Blocks(
401
- title="FinChat: An LLM based on distilgpt2 model",
402
- css="""
403
- .loader {
404
- border: 5px solid #f3f3f3;
405
- border-top: 5px solid #3498db;
406
- border-radius: 50%;
407
- width: 30px;
408
- height: 30px;
409
- animation: spin 1s linear infinite;
410
- margin: 10px auto;
411
- display: block;
412
- }
413
- @keyframes spin {
414
- 0% { transform: rotate(0deg); }
415
- 100% { transform: rotate(360deg); }
416
- }
417
- .hidden { display: none; }
418
- """
419
- ) as interface:
420
- gr.Markdown(
421
- """
422
- # FinChat: An LLM based on distilgpt2 model
423
- FinChat provides financial advice using the lightweight distilgpt2 model, optimized for fast, detailed responses.
424
- Ask about investing strategies, ETFs, stocks, or budgeting to get started!
425
- """
426
- )
427
- chatbot = gr.Chatbot(type="messages")
428
- msg = gr.Textbox(label="Your message")
429
- submit = gr.Button("Send")
430
- clear = gr.Button("Clear")
431
- loading = gr.HTML('<div class="loader hidden"></div>', label="Loading")
432
- is_processing = gr.State(value=False)
433
-
434
- def submit_message(user_input, history, is_processing):
435
- response, updated_history, new_processing, clear_input = chat_with_model(user_input, history, is_processing)
436
- loader_html = '<div class="loader"></div>' if new_processing else '<div class="loader hidden"></div>'
437
- return clear_input, updated_history, loader_html, new_processing
438
-
439
- submit.click(
440
- fn=submit_message,
441
- inputs=[msg, chatbot, is_processing],
442
- outputs=[msg, chatbot, loading, is_processing]
443
- )
444
- clear.click(
445
- fn=lambda: ("", [], '<div class="loader hidden"></div>', False),
446
- outputs=[msg, chatbot, loading, is_processing]
447
- )
448
- logger.info("Gradio interface initialized successfully")
449
- except Exception as e:
450
- logger.error(f"Error initializing Gradio interface: {e}")
451
- raise
452
-
453
- # Launch interface (conditional for Spaces)
454
- if __name__ == "__main__" and not os.getenv("HF_SPACE"):
455
- logger.info("Launching Gradio interface locally")
456
- try:
457
- interface.launch(share=False, debug=True)
458
- except Exception as e:
459
- logger.error(f"Error launching interface: {e}")
460
- raise
461
- finally:
462
- save_cache()
463
- else:
464
- logger.info("Running in Hugging Face Spaces, interface defined but not launched")
465
- import atexit
466
- atexit.register(save_cache)
 
38
  "what is better individual stocks or etfs?": (
39
  "Here’s a comparison of individual stocks vs. ETFs:\n"
40
  "1. **Individual Stocks**: High returns possible (e.g., Apple up 80% in 2020) but riskier due to lack of diversification. Require active research.\n"
41
+ "2. **ETFs**: Diversify risk by tracking indices (e.g., SPY, S&P 500, ~12% avg. return 2015–2024). Lower fees and less research needed.\n"
42
  "3. **Recommendation**: Beginners should start with ETFs; experienced investors may add stocks.\n"
43
  "Consult a financial planner."
44
  ),
 
81
  "Consult a financial planner."
82
  ),
83
  "do you have a list of companies you recommend?": (
84
+ "I can’t recommend specific companies without data. Try ETFs like SPY (S&P 500, ~12% avg. return 2015–2024) or QQQ (tech). "
85
  "Research stocks like Apple (AAPL, ~80% return in 2020) or Johnson & Johnson on Yahoo Finance.\n"
86
  "Consult a financial planner."
87
  ),
88
  "how do i start investing in stocks?": (
89
  "Learn from Investopedia. Set goals and assess risk. Open a brokerage account (Fidelity, Vanguard) "
90
+ "and start with ETFs (e.g., SPY, ~12% avg. return 2015–2024). Consult a financial planner."
91
  ),
92
  "what's the difference between stocks and bonds?": (
93
+ "Stocks are company ownership with high risk and growth potential (e.g., S&P 500 ~12% avg. return 2015–2024). Bonds are loans to companies/governments "
94
  "with lower risk and steady interest. Diversify for balance."
95
  ),
96
  "how much should i invest?": (
97
  "Invest what you can afford after expenses and an emergency fund. Start with $100-$500 monthly "
98
+ "in ETFs like SPY (~12% avg. return 2015–2024). Consult a financial planner."
99
  ),
100
  "what is dollar-cost averaging?": (
101
  "Dollar-cost averaging is investing a fixed amount regularly (e.g., $100 monthly) in ETFs, "
 
105
  "Here are investing ideas:\n"
106
  "1. Open a brokerage account (e.g., Fidelity) if 18 or older.\n"
107
  "2. Deposit $100 or what you can afford.\n"
108
+ "3. Buy a researched ETF (e.g., SPY, ~12% avg. return 2015–2024) or index fund.\n"
109
  "4. Check regularly and enable dividend reinvesting.\n"
110
  "5. Use dollar-cost averaging (e.g., monthly buys).\n"
111
  "Consult a financial planner."
 
114
  "Here are investing tips:\n"
115
  "1. Educate yourself with Investopedia or books.\n"
116
  "2. Open a brokerage account (e.g., Vanguard).\n"
117
+ "3. Start small with ETFs like SPY (~12% avg. return 2015–2024).\n"
118
  "4. Invest regularly using dollar-cost averaging.\n"
119
  "5. Diversify to manage risk.\n"
120
  "Consult a financial planner."
 
124
  "1. Study basics on Investopedia.\n"
125
  "2. Open a brokerage account (e.g., Fidelity).\n"
126
  "3. Deposit $100 or more after securing savings.\n"
127
+ "4. Buy an ETF like SPY (~12% avg. return 2015–2024) after research.\n"
128
  "5. Invest monthly with dollar-cost averaging.\n"
129
  "Consult a financial planner."
130
  ),
 
132
  "Here’s investing advice:\n"
133
  "1. Learn basics from Investopedia.\n"
134
  "2. Open a brokerage account (e.g., Vanguard).\n"
135
+ "3. Start with $100 in an ETF like SPY (~12% avg. return 2015–2024).\n"
136
  "4. Use dollar-cost averaging for regular investments.\n"
137
  "5. Monitor and diversify your portfolio.\n"
138
  "Consult a financial planner."
 
142
  "1. Educate yourself using Investopedia.\n"
143
  "2. Open a brokerage account (e.g., Fidelity).\n"
144
  "3. Deposit an initial $100 after savings.\n"
145
+ "4. Buy an ETF like SPY (~12% avg. return 2015–2024) after research.\n"
146
  "5. Use dollar-cost averaging monthly.\n"
147
  "Consult a financial planner."
148
  ),
149
  "what is the s&p 500 index fund average growth rate?": (
150
  "The S&P 500 index fund’s average annual return is approximately 10–12% over the long term (1927–2025), including dividends, based on historical data. "
151
+ "For example, from 2015 to 2024, it averaged ~12.2% annually. Returns vary yearly due to market conditions. Consult a financial planner."
152
  ),
153
  "what was the s&p 500 return in 2020?": (
154
  "The S&P 500 returned approximately 16.3% in 2020, including dividends, driven by recovery from the COVID-19 market crash."
 
174
  ),
175
  "what was the 5-year average annual growth rate of the s&p 500 from 2016?": (
176
  "The S&P 500’s average annual growth rate from 2016 to 2020 was approximately 13.6%, including dividends, driven by strong market recovery."
177
+ ),
178
+ "what is the average return rate of the s&p 500 in the past 10 years?": (
179
+ "The S&P 500’s average annual return rate from 2015 to 2024 was approximately 12.2%, including dividends, based on historical data."
180
  )
181
  }
182
 
 
203
  torch_dtype=torch.float16,
204
  low_cpu_mem_usage=True
205
  ).to(device)
206
+ logger.info(f"Successfully