sammy786 commited on
Commit
7b8affe
Β·
verified Β·
1 Parent(s): 112cabd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +163 -28
app.py CHANGED
@@ -1,6 +1,56 @@
1
  """
2
  Beautiful Gradio interface for credit card recommendations
3
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  from datetime import date
5
  from typing import Optional, Tuple, List, Dict, Any
6
  import gradio as gr
@@ -100,6 +150,13 @@ def get_recommendation(
100
  def get_recommendation_with_ai(user_id, merchant, category, amount):
101
  """Get card recommendation with LLM-powered explanation"""
102
 
 
 
 
 
 
 
 
103
  try:
104
  # Get base recommendation from orchestrator
105
  result = client.get_recommendation(
@@ -110,9 +167,11 @@ def get_recommendation_with_ai(user_id, merchant, category, amount):
110
  )
111
 
112
  if not result.get('success'):
113
- return f"❌ Error: {result.get('error', 'Unknown error')}", None
 
114
 
115
- data = result['data']
 
116
 
117
  # Generate LLM explanation if enabled
118
  ai_explanation = ""
@@ -125,9 +184,9 @@ def get_recommendation_with_ai(user_id, merchant, category, amount):
125
  merchant=merchant,
126
  category=category,
127
  amount=float(amount),
128
- warnings=data.get('warnings'),
129
- annual_potential=data.get('annual_potential'),
130
- alternatives=data.get('alternatives', [])
131
  )
132
  except Exception as e:
133
  print(f"LLM explanation failed: {e}")
@@ -135,12 +194,19 @@ def get_recommendation_with_ai(user_id, merchant, category, amount):
135
 
136
  # Format output with AI explanation
137
  output = f"""
138
- ## 🎯 Recommendation for ${amount} at {merchant}
139
 
140
  ### πŸ’³ Best Card: **{data['recommended_card']}**
141
 
142
  **Rewards Earned:** ${data['rewards_earned']:.2f} ({data['rewards_rate']})
143
 
 
 
 
 
 
 
 
144
  """
145
 
146
  # Add AI explanation if available
@@ -158,32 +224,89 @@ def get_recommendation_with_ai(user_id, merchant, category, amount):
158
  output += f"""
159
  ### πŸ“Š Breakdown
160
 
161
- - **Category:** {category}
162
- - **Annual Potential:** ${data.get('annual_potential', 0):.2f}
163
- - **Optimization Score:** {data.get('optimization_score', 'N/A')}/100
 
164
  """
165
 
166
  # Add warnings
167
- if data.get('warnings'):
168
- output += "\n\n### ⚠️ Warnings\n\n"
169
  for warning in data['warnings']:
170
  output += f"- {warning}\n"
171
 
172
  # Add alternatives
173
- if data.get('alternatives'):
174
  output += "\n\n### πŸ”„ Alternative Options\n\n"
175
  for alt in data['alternatives'][:3]:
176
- output += f"- **{alt['card']}:** ${alt['rewards']:.2f} ({alt['rate']})\n"
 
 
 
177
 
178
- # Create visualization (your existing chart code)
179
  chart = create_rewards_comparison_chart(data)
180
 
181
  return output, chart
182
 
183
  except Exception as e:
184
- return f"❌ Error: {str(e)}", None
185
-
 
 
186
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  def get_analytics_with_insights(user_id):
188
  """Get analytics with LLM-generated insights"""
189
 
@@ -747,26 +870,38 @@ Get AI-powered credit card recommendations that maximize your rewards based on:
747
  )
748
 
749
  def respond(message, chat_history, user_id):
750
- """Handle chat responses"""
751
  if not message.strip():
752
  return "", chat_history
753
 
754
- # Get user context
 
755
  try:
756
  analytics = client.get_user_analytics(user_id)
 
 
 
 
 
 
 
 
 
757
  user_context = {
758
- 'cards': analytics.get('data', {}).get('cards', []),
759
- 'monthly_spending': analytics.get('data', {}).get('total_spending', 0),
760
- 'top_category': analytics.get('data', {}).get('top_category', 'Unknown')
761
  }
762
- except:
763
- user_context = {}
764
 
765
- # Generate AI response
766
- if config.LLM_ENABLED:
767
- bot_response = llm.chat_response(message, user_context, chat_history)
768
- else:
769
- bot_response = "I'm currently in fallback mode. Please ask specific questions about your cards or transactions."
 
 
 
 
770
 
771
  chat_history.append((message, bot_response))
772
  return "", chat_history
 
1
  """
2
  Beautiful Gradio interface for credit card recommendations
3
  """
4
+
5
+ # Add after imports, before client initialization
6
+ from typing import Dict, Any
7
+ import traceback
8
+
9
+
10
+ def safe_get(data: Dict, key: str, default: Any = None) -> Any:
11
+ """Safely get value from dictionary with fallback"""
12
+ try:
13
+ return data.get(key, default)
14
+ except:
15
+ return default
16
+
17
+
18
+ def normalize_recommendation_data(data: Dict) -> Dict:
19
+ """Normalize API response to ensure all required fields exist"""
20
+
21
+ # Extract or compute rewards_earned
22
+ rewards_earned = safe_get(data, 'rewards_earned')
23
+ if rewards_earned is None:
24
+ amount = safe_get(data, 'amount', 0)
25
+ rewards_rate = safe_get(data, 'rewards_rate', '0x points')
26
+
27
+ try:
28
+ if 'x' in str(rewards_rate):
29
+ multiplier = float(rewards_rate.split('x')[0])
30
+ rewards_earned = amount * (multiplier / 100)
31
+ elif '%' in str(rewards_rate):
32
+ multiplier = float(rewards_rate.replace('%', '').split()[0])
33
+ rewards_earned = amount * (multiplier / 100)
34
+ else:
35
+ rewards_earned = 0
36
+ except:
37
+ rewards_earned = 0
38
+
39
+ return {
40
+ 'recommended_card': safe_get(data, 'recommended_card', 'Unknown Card'),
41
+ 'rewards_earned': round(float(rewards_earned), 2),
42
+ 'rewards_rate': safe_get(data, 'rewards_rate', 'N/A'),
43
+ 'merchant': safe_get(data, 'merchant', 'Unknown Merchant'),
44
+ 'category': safe_get(data, 'category', 'Unknown'),
45
+ 'amount': float(safe_get(data, 'amount', 0)),
46
+ 'annual_potential': float(safe_get(data, 'annual_potential', rewards_earned * 12)),
47
+ 'optimization_score': int(safe_get(data, 'optimization_score', 75)),
48
+ 'reasoning': safe_get(data, 'reasoning', 'Optimal choice for this category'),
49
+ 'warnings': safe_get(data, 'warnings', []),
50
+ 'alternatives': safe_get(data, 'alternatives', []),
51
+ 'mock_data': safe_get(data, 'mock_data', False)
52
+ }
53
+
54
  from datetime import date
55
  from typing import Optional, Tuple, List, Dict, Any
56
  import gradio as gr
 
150
  def get_recommendation_with_ai(user_id, merchant, category, amount):
151
  """Get card recommendation with LLM-powered explanation"""
152
 
153
+ # Validate inputs
154
+ if not merchant or not merchant.strip():
155
+ return "❌ Please enter a merchant name.", None
156
+
157
+ if amount <= 0:
158
+ return "❌ Please enter a valid amount greater than $0.", None
159
+
160
  try:
161
  # Get base recommendation from orchestrator
162
  result = client.get_recommendation(
 
167
  )
168
 
169
  if not result.get('success'):
170
+ error_msg = result.get('error', 'Unknown error')
171
+ return f"❌ Error: {error_msg}", None
172
 
173
+ # Normalize the data to ensure all fields exist
174
+ data = normalize_recommendation_data(result.get('data', {}))
175
 
176
  # Generate LLM explanation if enabled
177
  ai_explanation = ""
 
184
  merchant=merchant,
185
  category=category,
186
  amount=float(amount),
187
+ warnings=data['warnings'] if data['warnings'] else None,
188
+ annual_potential=data['annual_potential'],
189
+ alternatives=data['alternatives']
190
  )
191
  except Exception as e:
192
  print(f"LLM explanation failed: {e}")
 
194
 
195
  # Format output with AI explanation
196
  output = f"""
197
+ ## 🎯 Recommendation for ${amount:.2f} at {merchant}
198
 
199
  ### πŸ’³ Best Card: **{data['recommended_card']}**
200
 
201
  **Rewards Earned:** ${data['rewards_earned']:.2f} ({data['rewards_rate']})
202
 
203
+ """
204
+
205
+ # Add mock data indicator
206
+ if data.get('mock_data'):
207
+ output += """
208
+ > ⚠️ **Demo Mode:** Using sample data. Connect to orchestrator for real recommendations.
209
+
210
  """
211
 
212
  # Add AI explanation if available
 
224
  output += f"""
225
  ### πŸ“Š Breakdown
226
 
227
+ - **Category:** {data['category']}
228
+ - **Merchant:** {data['merchant']}
229
+ - **Annual Potential:** ${data['annual_potential']:.2f}
230
+ - **Optimization Score:** {data['optimization_score']}/100
231
  """
232
 
233
  # Add warnings
234
+ if data['warnings']:
235
+ output += "\n\n### ⚠️ Important Warnings\n\n"
236
  for warning in data['warnings']:
237
  output += f"- {warning}\n"
238
 
239
  # Add alternatives
240
+ if data['alternatives']:
241
  output += "\n\n### πŸ”„ Alternative Options\n\n"
242
  for alt in data['alternatives'][:3]:
243
+ alt_rewards = safe_get(alt, 'rewards', 0)
244
+ alt_rate = safe_get(alt, 'rate', 'N/A')
245
+ alt_card = safe_get(alt, 'card', 'Unknown')
246
+ output += f"- **{alt_card}:** ${alt_rewards:.2f} ({alt_rate})\n"
247
 
248
+ # Create visualization
249
  chart = create_rewards_comparison_chart(data)
250
 
251
  return output, chart
252
 
253
  except Exception as e:
254
+ import traceback
255
+ error_details = traceback.format_exc()
256
+ print(f"Recommendation error: {error_details}")
257
+ return f"❌ Error: {str(e)}\n\nPlease check your API connection or try again.", None
258
 
259
+ def create_rewards_comparison_chart(data: Dict) -> go.Figure:
260
+ """Create rewards comparison chart"""
261
+
262
+ try:
263
+ # Prepare data for chart
264
+ cards = [data['recommended_card']]
265
+ rewards = [data['rewards_earned']]
266
+
267
+ # Add alternatives
268
+ for alt in data.get('alternatives', [])[:3]:
269
+ cards.append(safe_get(alt, 'card', 'Unknown'))
270
+ rewards.append(float(safe_get(alt, 'rewards', 0)))
271
+
272
+ # Create bar chart
273
+ fig = go.Figure(data=[
274
+ go.Bar(
275
+ x=cards,
276
+ y=rewards,
277
+ marker=dict(
278
+ color=['#667eea'] + ['#a0aec0'] * (len(cards) - 1),
279
+ line=dict(color='white', width=2)
280
+ ),
281
+ text=[f'${r:.2f}' for r in rewards],
282
+ textposition='outside',
283
+ )
284
+ ])
285
+
286
+ fig.update_layout(
287
+ title='Rewards Comparison',
288
+ xaxis_title='Credit Card',
289
+ yaxis_title='Rewards Earned ($)',
290
+ template='plotly_white',
291
+ height=400,
292
+ showlegend=False,
293
+ margin=dict(t=50, b=50, l=50, r=50)
294
+ )
295
+
296
+ return fig
297
+
298
+ except Exception as e:
299
+ print(f"Chart creation error: {e}")
300
+ # Return empty chart with error message
301
+ fig = go.Figure()
302
+ fig.add_annotation(
303
+ text=f"Error creating chart: {str(e)}",
304
+ xref="paper", yref="paper",
305
+ x=0.5, y=0.5, showarrow=False,
306
+ font=dict(size=14, color="red")
307
+ )
308
+ return fig
309
+
310
  def get_analytics_with_insights(user_id):
311
  """Get analytics with LLM-generated insights"""
312
 
 
870
  )
871
 
872
  def respond(message, chat_history, user_id):
873
+ """Handle chat responses with error handling"""
874
  if not message.strip():
875
  return "", chat_history
876
 
877
+ # Get user context with error handling
878
+ user_context = {}
879
  try:
880
  analytics = client.get_user_analytics(user_id)
881
+ if analytics.get('success'):
882
+ data = analytics.get('data', {})
883
+ user_context = {
884
+ 'cards': safe_get(data, 'cards', ['Amex Gold', 'Chase Sapphire Reserve']),
885
+ 'monthly_spending': safe_get(data, 'total_spending', 0),
886
+ 'top_category': safe_get(data, 'top_category', 'Groceries')
887
+ }
888
+ except Exception as e:
889
+ print(f"Error getting user context: {e}")
890
  user_context = {
891
+ 'cards': ['Amex Gold', 'Chase Sapphire Reserve'],
892
+ 'monthly_spending': 3450.75,
893
+ 'top_category': 'Groceries'
894
  }
 
 
895
 
896
+ # Generate AI response with error handling
897
+ try:
898
+ if config.LLM_ENABLED:
899
+ bot_response = llm.chat_response(message, user_context, chat_history)
900
+ else:
901
+ bot_response = "I'm currently in fallback mode. Ask me about specific cards or categories!"
902
+ except Exception as e:
903
+ print(f"Chat error: {e}")
904
+ bot_response = f"I encountered an error. Please try asking your question differently."
905
 
906
  chat_history.append((message, bot_response))
907
  return "", chat_history