AnilNiraula commited on
Commit
df9e7b0
·
verified ·
1 Parent(s): f662e05

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +242 -133
app.py CHANGED
@@ -4,6 +4,7 @@ import time
4
  import torch
5
  import gradio as gr
6
  from transformers import AutoModelForCausalLM, AutoTokenizer
 
7
  import json
8
 
9
  # Set up logging
@@ -14,85 +15,126 @@ logger = logging.getLogger(__name__)
14
  device = torch.device("cpu")
15
  logger.info(f"Using device: {device}")
16
 
17
- # Expanded response cache with new entries
18
  response_cache = {
19
- "hi": "Hello! I'm FinChat, your financial advisor. How can I help with investing today?",
20
- "hello": "Hello! I'm FinChat, your financial advisor. How can I help with investing today?",
21
  "hey": "Hi there! Ready to discuss investment goals with FinChat?",
22
- "how can i start investing with $100 a month?": (
23
- "Here’s a step-by-step guide to start investing with $100 a month:\n"
24
- "1. **Open a brokerage account** with a platform like Fidelity or Robinhood. They offer low fees and no minimums.\n"
25
- "2. **Deposit your $100 monthly**. You can set up automatic transfers from your bank.\n"
26
- "3. **Choose a low-cost ETF** like VOO, which tracks the S&P 500 for broad market exposure.\n"
27
- "4. **Set up automatic investments** to buy shares regularly, reducing the impact of market fluctuations.\n"
28
- "5. **Track your progress** every few months to stay on top of your investments.\n"
29
- "Consult a financial planner for personalized advice."
30
  ),
31
- "where can i open a brokerage account?": (
32
- "You can open a brokerage account with platforms like Vanguard, Fidelity, Charles Schwab, or Robinhood. "
33
- "They are beginner-friendly and offer low fees. Choose one that fits your needs and sign up online."
 
 
 
 
 
34
  ),
35
- "start investing with 100 dollars a month": (
36
- "Here’s how to start investing with $100 a month:\n"
37
- "1. **Open a brokerage account** with a platform like Fidelity or Robinhood.\n"
38
- "2. **Deposit $100 monthly** via automatic transfers.\n"
39
- "3. **Invest in a low-cost ETF** like VOO for diversification.\n"
40
- "4. **Use dollar-cost averaging** to invest regularly.\n"
41
- "5. **Monitor your investments** quarterly.\n"
42
- "Consult a financial planner for tailored advice."
43
  ),
44
- "best places to open a brokerage account": (
45
- "The best places to open a brokerage account include Vanguard, Fidelity, Charles Schwab, and Robinhood. "
46
- "They offer low fees, no minimums, and user-friendly platforms for beginners."
 
 
 
 
 
 
47
  ),
48
- "what is dollar-cost averaging?": (
49
- "Dollar-cost averaging is investing a fixed amount regularly (e.g., $100 monthly) in ETFs, "
50
- "reducing risk by spreading purchases over time."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  ),
52
  "how much should i invest?": (
53
  "Invest what you can afford after expenses and an emergency fund. Start with $100-$500 monthly "
54
- "in ETFs like VOO using dollar-cost averaging. Consult a financial planner."
55
  ),
56
- "how to start investing": (
57
- "Here’s how to start investing:\n"
58
- "1. Educate yourself using resources like Investopedia.\n"
59
- "2. Open a brokerage account with a platform like Fidelity.\n"
60
- "3. Deposit an initial amount, such as $100, after building an emergency fund.\n"
61
- "4. Choose a low-cost ETF like VOO.\n"
62
- "5. Invest regularly using dollar-cost averaging.\n"
63
- "Consult a financial planner for personalized advice."
64
  ),
65
- "best brokerage accounts": (
66
- "The best brokerage accounts for beginners include Fidelity, Vanguard, Charles Schwab, and Robinhood. "
67
- "They offer low fees, no minimums, and user-friendly platforms."
 
 
 
 
 
68
  ),
69
- "investing for beginners": (
70
- "Here’s a beginner’s guide to investing:\n"
71
- "1. Learn the basics from Investopedia or books like 'The Intelligent Investor.'\n"
72
- "2. Set clear investment goals and assess your risk tolerance.\n"
73
- "3. Open a brokerage account with a platform like Fidelity or Robinhood.\n"
74
- "4. Start with low-cost ETFs like VOO or index funds.\n"
75
- "5. Invest regularly using dollar-cost averaging.\n"
76
- "6. Monitor your investments quarterly.\n"
77
- "Consult a financial planner for tailored advice."
78
  ),
79
- "steps to start investing": (
80
- "Here are the steps to start investing:\n"
81
- "1. Educate yourself on investing basics.\n"
82
- "2. Open a brokerage account with a beginner-friendly platform.\n"
83
- "3. Deposit an initial amount you can afford.\n"
84
- "4. Choose a diversified investment like an ETF.\n"
85
- "5. Invest consistently over time.\n"
86
- "Consult a financial planner for more guidance."
87
  ),
88
- "recommended etfs": (
89
- "Recommended ETFs for beginners include VOO (tracks S&P 500), QQQ (tech-focused), and VT (global market exposure). "
90
- "They offer diversification and low fees."
 
 
 
 
 
91
  ),
92
- "how much to invest": (
93
- "The amount to invest depends on your financial situation. Start with what you can afford after covering expenses and an emergency fund. "
94
- "A common starting point is $100-$500 monthly in low-cost ETFs like VOO. Consult a financial planner for personalized advice."
 
 
 
 
 
95
  ),
 
 
 
 
96
  }
97
 
98
  # Load persistent cache
@@ -105,11 +147,12 @@ try:
105
  except Exception as e:
106
  logger.warning(f"Failed to load cache.json: {e}")
107
 
108
- # Load model and tokenizer
109
- model_name = "distilgpt2"
110
  try:
111
  logger.info(f"Loading tokenizer for {model_name}")
112
  tokenizer = AutoTokenizer.from_pretrained(model_name, clean_up_tokenization_spaces=False)
 
113
  logger.info(f"Loading model {model_name}")
114
  with torch.inference_mode():
115
  model = AutoModelForCausalLM.from_pretrained(
@@ -121,47 +164,58 @@ except Exception as e:
121
  logger.error(f"Error loading model/tokenizer: {e}")
122
  raise RuntimeError(f"Failed to load model: {str(e)}")
123
 
124
- # Updated prompt prefix with better instructions and examples
125
  prompt_prefix = (
126
- "You are FinChat, a financial advisor. Always provide clear, step-by-step answers to the user's exact question. "
127
- "Avoid vague or unrelated topics. Use a numbered list format where appropriate and explain each step.\n\n"
128
  "Example 1:\n"
129
- "Q: How can I start investing with $100 a month?\n"
130
- "A: Here’s a step-by-step guide:\n"
131
- "1. Open a brokerage account with a platform like Fidelity or Robinhood. They offer low fees and no minimums.\n"
132
- "2. Deposit your $100 monthly. You can set up automatic transfers.\n"
133
- "3. Choose a low-cost ETF like VOO, which tracks the S&P 500.\n"
134
- "4. Set up automatic investments to buy shares regularly.\n"
135
- "5. Track your progress every few months.\n\n"
136
  "Example 2:\n"
137
- "Q: Where can I open a brokerage account?\n"
138
- "A: You can open an account with platforms like Vanguard, Fidelity, Charles Schwab, or Robinhood. "
139
- "They are beginner-friendly and have low fees.\n\n"
 
 
140
  "Q: "
141
  )
 
 
 
 
 
 
 
 
 
142
 
143
- # Define chat function with substring matching and reduced max_new_tokens
144
- def chat_with_model(user_input, history=None):
145
  try:
146
  start_time = time.time()
147
  logger.info(f"Processing user input: {user_input}")
148
-
149
- user_input_lower = user_input.lower().strip()
150
-
151
- # Substring matching for cache
152
- matching_keys = [key for key in response_cache if key in user_input_lower]
153
- if matching_keys:
154
- longest_key = max(matching_keys, key=len)
155
- logger.info(f"Cache hit for: {longest_key}")
156
- response = response_cache[longest_key]
 
157
  logger.info(f"Chatbot response: {response}")
158
  history = history or []
159
  history.append({"role": "user", "content": user_input})
160
  history.append({"role": "assistant", "content": response})
161
  end_time = time.time()
162
  logger.info(f"Response time: {end_time - start_time:.2f} seconds")
163
- return response, history
164
-
 
165
  if len(user_input.strip()) <= 5:
166
  logger.info("Short prompt, returning default response")
167
  response = "Hello! I'm FinChat, your financial advisor. Ask about investing!"
@@ -171,39 +225,54 @@ def chat_with_model(user_input, history=None):
171
  history.append({"role": "assistant", "content": response})
172
  end_time = time.time()
173
  logger.info(f"Response time: {end_time - start_time:.2f} seconds")
174
- return response, history
175
 
 
176
  full_prompt = prompt_prefix + user_input + "\nA:"
177
- inputs = tokenizer(full_prompt, return_tensors="pt", truncation=True, max_length=512).to(device)
178
-
 
 
 
 
 
 
 
 
 
 
 
 
179
  with torch.inference_mode():
 
180
  gen_start_time = time.time()
181
  outputs = model.generate(
182
  **inputs,
183
- max_new_tokens=50, # Reduced for faster generation
184
  min_length=20,
185
- do_sample=False, # Greedy decoding for speed
186
  repetition_penalty=1.2,
187
  pad_token_id=tokenizer.eos_token_id
188
  )
189
  gen_end_time = time.time()
190
  logger.info(f"Generation time: {gen_end_time - gen_start_time:.2f} seconds")
191
-
192
  response = tokenizer.decode(outputs[0], skip_special_tokens=True)
193
  response = response[len(full_prompt):].strip() if response.startswith(full_prompt) else response
194
  logger.info(f"Chatbot response: {response}")
195
-
196
- # Update cache with exact user input as key
197
- response_cache[user_input_lower] = response
198
  logger.info("Cache miss, added to in-memory cache")
199
-
 
200
  history = history or []
201
  history.append({"role": "user", "content": user_input})
202
  history.append({"role": "assistant", "content": response})
203
  torch.cuda.empty_cache()
204
  end_time = time.time()
205
- logger.info(f"Total response time: {end_time - start_time:.2f} seconds")
206
- return response, history
 
207
  except Exception as e:
208
  logger.error(f"Error generating response: {e}")
209
  response = f"Error: {str(e)}"
@@ -211,38 +280,74 @@ def chat_with_model(user_input, history=None):
211
  history = history or []
212
  history.append({"role": "user", "content": user_input})
213
  history.append({"role": "assistant", "content": response})
214
- return response, history
 
 
215
 
216
- # Create Gradio interface
217
- with gr.Blocks(
218
- title="FinChat: An LLM based on distilgpt2 model",
219
- css=".feedback {display: flex; gap: 10px; justify-content: center; margin-top: 10px;}"
220
- ) as interface:
221
- gr.Markdown(
222
- """
223
- # FinChat: An LLM based on distilgpt2 model
224
- FinChat provides financial advice using the lightweight distilgpt2 model, optimized for fast, detailed responses.
225
- Ask about investing strategies, ETFs, stocks, or budgeting to get started!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
  """
227
- )
228
- chatbot = gr.Chatbot(type="messages")
229
- msg = gr.Textbox(label="Your message")
230
- submit = gr.Button("Send")
231
- clear = gr.Button("Clear")
232
-
233
- def submit_message(user_input, history):
234
- response, updated_history = chat_with_model(user_input, history)
235
- return "", updated_history # Clear input, update chatbot
 
 
 
 
 
236
 
237
- submit.click(
238
- fn=submit_message,
239
- inputs=[msg, chatbot],
240
- outputs=[msg, chatbot]
241
- )
242
- clear.click(
243
- fn=lambda: ("", []), # Clear input and chatbot
244
- outputs=[msg, chatbot]
245
- )
 
 
 
 
 
 
 
 
 
246
 
247
  # Launch interface (conditional for Spaces)
248
  if __name__ == "__main__" and not os.getenv("HF_SPACE"):
@@ -252,5 +357,9 @@ if __name__ == "__main__" and not os.getenv("HF_SPACE"):
252
  except Exception as e:
253
  logger.error(f"Error launching interface: {e}")
254
  raise
 
 
255
  else:
256
- logger.info("Running in Hugging Face Spaces, interface defined but not launched")
 
 
 
4
  import torch
5
  import gradio as gr
6
  from transformers import AutoModelForCausalLM, AutoTokenizer
7
+ import difflib
8
  import json
9
 
10
  # Set up logging
 
15
  device = torch.device("cpu")
16
  logger.info(f"Using device: {device}")
17
 
18
+ # Response cache with financial data entries
19
  response_cache = {
20
+ "hi": "Hello! I'm FinChat, your financial advisor. How can I help with investing?",
21
+ "hello": "Hello! I'm FinChat, your financial advisor. How can I help with investing?",
22
  "hey": "Hi there! Ready to discuss investment goals with FinChat?",
23
+ "what is better individual stocks or etfs?": (
24
+ "Here’s a comparison of individual stocks vs. ETFs:\n"
25
+ "1. **Individual Stocks**: High returns possible (e.g., Apple up 80% in 2020) but riskier due to lack of diversification. Require active research.\n"
26
+ "2. **ETFs**: Diversify risk by tracking indices (e.g., VOO, S&P 500, ~12% avg. return 2015–2025). Lower fees and less research needed.\n"
27
+ "3. **Recommendation**: Beginners should start with ETFs; experienced investors may add stocks.\n"
28
+ "Consult a financial planner."
 
 
29
  ),
30
+ "is $100 per month enough to invest?": (
31
+ "Yes, $100 per month is enough to start investing. Here’s why and how:\n"
32
+ "1. **Feasibility**: Brokerages like Fidelity have no minimums, and commission-free trading eliminates fees.\n"
33
+ "2. **Options**: Buy fractional shares of ETFs (e.g., VOO, ~$500/share) with $100.\n"
34
+ "3. **Strategy**: Use dollar-cost averaging to invest monthly, reducing market timing risks.\n"
35
+ "4. **Growth**: At 10% annual return, $100 monthly could grow to ~$41,000 in 20 years.\n"
36
+ "5. **Tips**: Ensure an emergency fund; diversify.\n"
37
+ "Consult a financial planner."
38
  ),
39
+ "can i invest $100 a month?": (
40
+ "Yes, $100 a month is sufficient. Here’s how:\n"
41
+ "1. **Brokerage**: Open an account with Fidelity or Vanguard (no minimums).\n"
42
+ "2. **Investments**: Buy fractional shares of ETFs like VOO ($100 buys ~0.2 shares).\n"
43
+ "3. **Approach**: Use dollar-cost averaging for steady growth.\n"
44
+ "4. **Long-Term**: At 10% return, $100 monthly could reach ~$41,000 in 20 years.\n"
45
+ "5. **Tips**: Prioritize an emergency fund and diversify.\n"
46
+ "Consult a financial planner."
47
  ),
48
+ "hi, give me step-by-step investing advice": (
49
+ "Here’s a step-by-step guide to start investing:\n"
50
+ "1. Open a brokerage account (e.g., Fidelity, Vanguard) if 18 or older.\n"
51
+ "2. Deposit an affordable amount, like $100, after an emergency fund.\n"
52
+ "3. Research and buy an ETF (e.g., VOO) using Yahoo Finance.\n"
53
+ "4. Monitor monthly and enable dividend reinvesting.\n"
54
+ "5. Use dollar-cost averaging ($100 monthly) to reduce risk.\n"
55
+ "6. Diversify across sectors.\n"
56
+ "Consult a financial planner."
57
  ),
58
+ "hi, pretend you are a financial advisor. now tell me how can i start investing in stock market?": (
59
+ "Here’s a guide to start investing:\n"
60
+ "1. Learn from Investopedia or 'The Intelligent Investor.'\n"
61
+ "2. Set goals (e.g., retirement) and assess risk.\n"
62
+ "3. Choose a brokerage (Fidelity, Vanguard).\n"
63
+ "4. Start with ETFs (e.g., VOO) or mutual funds.\n"
64
+ "5. Use dollar-cost averaging ($100-$500 monthly).\n"
65
+ "6. Diversify and monitor.\n"
66
+ "Consult a financial planner."
67
+ ),
68
+ "do you have a list of companies you recommend?": (
69
+ "I can’t recommend specific companies without data. Try ETFs like VOO (S&P 500, ~12% avg. return 2015–2025) or QQQ (tech). "
70
+ "Research stocks like Apple (AAPL, ~80% return in 2020) or Johnson & Johnson on Yahoo Finance.\n"
71
+ "Consult a financial planner."
72
+ ),
73
+ "how do i start investing in stocks?": (
74
+ "Learn from Investopedia. Set goals and assess risk. Open a brokerage account (Fidelity, Vanguard) "
75
+ "and start with ETFs (e.g., VOO, ~10% avg. return). Consult a financial planner."
76
+ ),
77
+ "what's the difference between stocks and bonds?": (
78
+ "Stocks are company ownership with high risk and growth potential (e.g., S&P 500 ~10% avg. return). Bonds are loans to companies/governments "
79
+ "with lower risk and steady interest. Diversify for balance."
80
  ),
81
  "how much should i invest?": (
82
  "Invest what you can afford after expenses and an emergency fund. Start with $100-$500 monthly "
83
+ "in ETFs like VOO (~10% avg. return). Consult a financial planner."
84
  ),
85
+ "what is dollar-cost averaging?": (
86
+ "Dollar-cost averaging is investing a fixed amount regularly (e.g., $100 monthly) in ETFs, "
87
+ "reducing risk by spreading purchases over time."
 
 
 
 
 
88
  ),
89
+ "give me few investing idea": (
90
+ "Here are investing ideas:\n"
91
+ "1. Open a brokerage account (e.g., Fidelity) if 18 or older.\n"
92
+ "2. Deposit $100 or what you can afford.\n"
93
+ "3. Buy a researched ETF (e.g., VOO, ~10% avg. return) or index fund.\n"
94
+ "4. Check regularly and enable dividend reinvesting.\n"
95
+ "5. Use dollar-cost averaging (e.g., monthly buys).\n"
96
+ "Consult a financial planner."
97
  ),
98
+ "give me investing tips": (
99
+ "Here are investing tips:\n"
100
+ "1. Educate yourself with Investopedia or books.\n"
101
+ "2. Open a brokerage account (e.g., Vanguard).\n"
102
+ "3. Start small with ETFs like VOO (~10% avg. return).\n"
103
+ "4. Invest regularly using dollar-cost averaging.\n"
104
+ "5. Diversify to manage risk.\n"
105
+ "Consult a financial planner."
 
106
  ),
107
+ "how to start investing": (
108
+ "Here’s how to start investing:\n"
109
+ "1. Study basics on Investopedia.\n"
110
+ "2. Open a brokerage account (e.g., Fidelity).\n"
111
+ "3. Deposit $100 or more after securing savings.\n"
112
+ "4. Buy an ETF like VOO (~10% avg. return) after research.\n"
113
+ "5. Invest monthly with dollar-cost averaging.\n"
114
+ "Consult a financial planner."
115
  ),
116
+ "investing advice": (
117
+ "Here’s investing advice:\n"
118
+ "1. Learn basics from Investopedia.\n"
119
+ "2. Open a brokerage account (e.g., Vanguard).\n"
120
+ "3. Start with $100 in an ETF like VOO (~10% avg. return).\n"
121
+ "4. Use dollar-cost averaging for regular investments.\n"
122
+ "5. Monitor and diversify your portfolio.\n"
123
+ "Consult a financial planner."
124
  ),
125
+ "steps to invest": (
126
+ "Here are steps to invest:\n"
127
+ "1. Educate yourself using Investopedia.\n"
128
+ "2. Open a brokerage account (e.g., Fidelity).\n"
129
+ "3. Deposit an initial $100 after savings.\n"
130
+ "4. Buy an ETF like VOO (~10% avg. return) after research.\n"
131
+ "5. Use dollar-cost averaging monthly.\n"
132
+ "Consult a financial planner."
133
  ),
134
+ "what is the s&p 500 index fund average growth rate?": (
135
+ "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. "
136
+ "For example, from 2015 to 2025, it averaged ~12% annually. Returns vary yearly due to market conditions. Consult a financial planner."
137
+ )
138
  }
139
 
140
  # Load persistent cache
 
147
  except Exception as e:
148
  logger.warning(f"Failed to load cache.json: {e}")
149
 
150
+ # Load model and tokenizer (use fine-tuned model if available)
151
+ model_name = "./finetuned_model" if os.path.exists("./finetuned_model") else "distilgpt2"
152
  try:
153
  logger.info(f"Loading tokenizer for {model_name}")
154
  tokenizer = AutoTokenizer.from_pretrained(model_name, clean_up_tokenization_spaces=False)
155
+ tokenizer.pad_token = tokenizer.eos_token
156
  logger.info(f"Loading model {model_name}")
157
  with torch.inference_mode():
158
  model = AutoModelForCausalLM.from_pretrained(
 
164
  logger.error(f"Error loading model/tokenizer: {e}")
165
  raise RuntimeError(f"Failed to load model: {str(e)}")
166
 
167
+ # Pre-tokenize prompt prefix
168
  prompt_prefix = (
169
+ "You are FinChat, a financial advisor with expertise in stock market performance. Provide detailed, numbered list advice with clear reasoning for investing prompts, "
170
+ "including historical data when relevant (e.g., S&P 500 returns). Avoid repetition and incomplete answers. Explain why each step or choice is beneficial.\n\n"
171
  "Example 1:\n"
172
+ "Q: What is the S&P 500’s average annual return?\n"
173
+ "A: The S&P 500’s average annual return is ~10–12% over the long term (1927–2025), including dividends.\n"
174
+ "1. This reflects historical data adjusted for inflation and dividends.\n"
175
+ "2. Returns vary yearly (e.g., 16.3% in 2020) due to market conditions.\n"
176
+ "3. ETFs like VOO track this index for broad market exposure.\n\n"
 
 
177
  "Example 2:\n"
178
+ "Q: Can I invest $100 a month?\n"
179
+ "A: Yes, $100 a month is sufficient. Here’s how:\n"
180
+ "1. Open a brokerage account (e.g., Fidelity): No minimums allow small investments.\n"
181
+ "2. Buy fractional ETF shares (e.g., VOO, ~12% avg. return 2015–2025): Diversifies risk.\n"
182
+ "3. Use dollar-cost averaging: Reduces market timing risks.\n\n"
183
  "Q: "
184
  )
185
+ prefix_tokens = tokenizer(prompt_prefix, return_tensors="pt", truncation=True, max_length=512).to(device)
186
+
187
+ # Substring matching for cache
188
+ def get_closest_cache_key(message, cache_keys):
189
+ message = message.lower().strip()
190
+ for key in cache_keys:
191
+ if key in message:
192
+ return key
193
+ return None
194
 
195
+ # Define chat function
196
+ def chat_with_model(user_input, history=None, is_processing=False):
197
  try:
198
  start_time = time.time()
199
  logger.info(f"Processing user input: {user_input}")
200
+ is_processing = True
201
+ logger.info("Showing loading animation")
202
+
203
+ # Normalize and check cache
204
+ cache_key = user_input.lower().strip()
205
+ cache_keys = list(response_cache.keys())
206
+ closest_key = cache_key if cache_key in response_cache else get_closest_cache_key(cache_key, cache_keys)
207
+ if closest_key:
208
+ logger.info(f"Cache hit for: {closest_key}")
209
+ response = response_cache[closest_key]
210
  logger.info(f"Chatbot response: {response}")
211
  history = history or []
212
  history.append({"role": "user", "content": user_input})
213
  history.append({"role": "assistant", "content": response})
214
  end_time = time.time()
215
  logger.info(f"Response time: {end_time - start_time:.2f} seconds")
216
+ return response, history, False, ""
217
+
218
+ # Skip model for short prompts
219
  if len(user_input.strip()) <= 5:
220
  logger.info("Short prompt, returning default response")
221
  response = "Hello! I'm FinChat, your financial advisor. Ask about investing!"
 
225
  history.append({"role": "assistant", "content": response})
226
  end_time = time.time()
227
  logger.info(f"Response time: {end_time - start_time:.2f} seconds")
228
+ return response, history, False, ""
229
 
230
+ # Construct prompt
231
  full_prompt = prompt_prefix + user_input + "\nA:"
232
+ try:
233
+ inputs = tokenizer(full_prompt, return_tensors="pt", truncation=True, max_length=512).to(device)
234
+ except Exception as e:
235
+ logger.error(f"Error tokenizing input: {e}")
236
+ response = f"Error: Failed to process input: {str(e)}"
237
+ logger.info(f"Chatbot response: {response}")
238
+ history = history or []
239
+ history.append({"role": "user", "content": user_input})
240
+ history.append({"role": "assistant", "content": response})
241
+ end_time = time.time()
242
+ logger.info(f"Response time: {end_time - start_time:.2f} seconds")
243
+ return response, history, False, ""
244
+
245
+ # Generate response
246
  with torch.inference_mode():
247
+ logger.info("Generating response with model")
248
  gen_start_time = time.time()
249
  outputs = model.generate(
250
  **inputs,
251
+ max_new_tokens=50,
252
  min_length=20,
253
+ do_sample=False,
254
  repetition_penalty=1.2,
255
  pad_token_id=tokenizer.eos_token_id
256
  )
257
  gen_end_time = time.time()
258
  logger.info(f"Generation time: {gen_end_time - gen_start_time:.2f} seconds")
 
259
  response = tokenizer.decode(outputs[0], skip_special_tokens=True)
260
  response = response[len(full_prompt):].strip() if response.startswith(full_prompt) else response
261
  logger.info(f"Chatbot response: {response}")
262
+
263
+ # Update cache
264
+ response_cache[cache_key] = response
265
  logger.info("Cache miss, added to in-memory cache")
266
+
267
+ # Update history
268
  history = history or []
269
  history.append({"role": "user", "content": user_input})
270
  history.append({"role": "assistant", "content": response})
271
  torch.cuda.empty_cache()
272
  end_time = time.time()
273
+ logger.info(f"Response time: {end_time - start_time:.2f} seconds")
274
+ return response, history, False, ""
275
+
276
  except Exception as e:
277
  logger.error(f"Error generating response: {e}")
278
  response = f"Error: {str(e)}"
 
280
  history = history or []
281
  history.append({"role": "user", "content": user_input})
282
  history.append({"role": "assistant", "content": response})
283
+ end_time = time.time()
284
+ logger.info(f"Response time: {end_time - start_time:.2f} seconds")
285
+ return response, history, False, ""
286
 
287
+ # Save cache on exit
288
+ def save_cache():
289
+ try:
290
+ with open(cache_file, 'w') as f:
291
+ json.dump(response_cache, f, indent=2)
292
+ logger.info("Saved cache to cache.json")
293
+ except Exception as e:
294
+ logger.warning(f"Failed to save cache.json: {e}")
295
+
296
+ # Create Gradio interface with loading animation
297
+ logger.info("Initializing Gradio interface")
298
+ try:
299
+ with gr.Blocks(
300
+ title="FinChat: An LLM based on distilgpt2 model",
301
+ css="""
302
+ .loader {
303
+ border: 5px solid #f3f3f3;
304
+ border-top: 5px solid #3498db;
305
+ border-radius: 50%;
306
+ width: 30px;
307
+ height: 30px;
308
+ animation: spin 1s linear infinite;
309
+ margin: 10px auto;
310
+ display: block;
311
+ }
312
+ @keyframes spin {
313
+ 0% { transform: rotate(0deg); }
314
+ 100% { transform: rotate(360deg); }
315
+ }
316
+ .hidden { display: none; }
317
  """
318
+ ) as interface:
319
+ gr.Markdown(
320
+ """
321
+ # FinChat: An LLM based on distilgpt2 model
322
+ FinChat provides financial advice using the lightweight distilgpt2 model, optimized for fast, detailed responses.
323
+ Ask about investing strategies, ETFs, stocks, or budgeting to get started!
324
+ """
325
+ )
326
+ chatbot = gr.Chatbot(type="messages")
327
+ msg = gr.Textbox(label="Your message")
328
+ submit = gr.Button("Send")
329
+ clear = gr.Button("Clear")
330
+ loading = gr.HTML('<div class="loader hidden"></div>', label="Loading")
331
+ is_processing = gr.State(value=False)
332
 
333
+ def submit_message(user_input, history, is_processing):
334
+ response, updated_history, new_processing, clear_input = chat_with_model(user_input, history, is_processing)
335
+ loader_html = '<div class="loader"></div>' if new_processing else '<div class="loader hidden"></div>'
336
+ return clear_input, updated_history, loader_html, new_processing
337
+
338
+ submit.click(
339
+ fn=submit_message,
340
+ inputs=[msg, chatbot, is_processing],
341
+ outputs=[msg, chatbot, loading, is_processing]
342
+ )
343
+ clear.click(
344
+ fn=lambda: ("", [], '<div class="loader hidden"></div>', False),
345
+ outputs=[msg, chatbot, loading, is_processing]
346
+ )
347
+ logger.info("Gradio interface initialized successfully")
348
+ except Exception as e:
349
+ logger.error(f"Error initializing Gradio interface: {e}")
350
+ raise
351
 
352
  # Launch interface (conditional for Spaces)
353
  if __name__ == "__main__" and not os.getenv("HF_SPACE"):
 
357
  except Exception as e:
358
  logger.error(f"Error launching interface: {e}")
359
  raise
360
+ finally:
361
+ save_cache()
362
  else:
363
+ logger.info("Running in Hugging Face Spaces, interface defined but not launched")
364
+ import atexit
365
+ atexit.register(save_cache)