Devavrat28 commited on
Commit
b944845
Β·
verified Β·
1 Parent(s): 46de2c7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +211 -172
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py - Enhanced Professional UI with Fixed Dropdowns
2
  import gradio as gr
3
  import requests
4
  import json
@@ -7,13 +7,15 @@ import aiohttp
7
  from typing import Optional
8
  from fpdf import FPDF
9
 
10
- # Update this to your new optimized Modal URL
11
- MODAL_URL = "https://devsam2898--personal-investment-strategist-fixed-web.modal.run/strategy"
12
- HEALTH_URL = "https://devsam2898--personal-investment-strategist-fixed-web.modal.run/health"
13
- TEST_URL = "https://devsam2898--personal-investment-strategist-fixed-web.modal.run/test"
 
 
14
 
15
  async def get_investment_strategy_async(age_group, income, expenses, current_assets, current_liabilities, risk_profile, goal, timeframe, country):
16
- """Async version with better timeout handling and assets/liabilities support"""
17
 
18
  # Input validation
19
  if not all([age_group, income, expenses, risk_profile, goal, timeframe, country]):
@@ -40,29 +42,31 @@ async def get_investment_strategy_async(age_group, income, expenses, current_ass
40
  if expenses_val >= income_val:
41
  return "⚠️ **Warning**: Your expenses are equal to or exceed your income. Consider budgeting advice before investing."
42
 
 
 
 
 
43
  payload = {
44
- "profile": {
45
- "age_group": age_group,
46
- "income": income_val,
47
- "expenses": expenses_val,
48
- "current_assets": assets_val,
49
- "current_liabilities": liabilities_val,
50
- "risk_profile": risk_profile,
51
- "goal": goal,
52
- "timeframe": timeframe,
53
- "country": country
54
- }
55
  }
56
 
57
  try:
58
- print(f"πŸš€ Sending request to: {MODAL_URL}")
59
 
60
  # Use aiohttp for better async handling
61
- timeout = aiohttp.ClientTimeout(total=150) # 2.5 minute timeout
62
 
63
  async with aiohttp.ClientSession(timeout=timeout) as session:
64
  async with session.post(
65
- MODAL_URL,
66
  json=payload,
67
  headers={
68
  'Content-Type': 'application/json',
@@ -76,12 +80,17 @@ async def get_investment_strategy_async(age_group, income, expenses, current_ass
76
  result = await response.json()
77
  strategy = result.get("strategy", "No strategy returned.")
78
  status = result.get("status", "unknown")
 
79
 
80
- # Add status indicator
81
- if status == "basic":
82
- prefix = "## πŸ“Š Your Investment Strategy (Rule-Based)\n*AI service was unavailable, using optimized rule-based strategy*\n\n"
 
 
 
 
83
  else:
84
- prefix = "## πŸ“Š Your Personalized Investment Strategy\n*Powered by AI*\n\n"
85
 
86
  return f"{prefix}{strategy}"
87
  else:
@@ -91,28 +100,29 @@ async def get_investment_strategy_async(age_group, income, expenses, current_ass
91
  except asyncio.TimeoutError:
92
  return """⏱️ **Request Timeout**
93
 
94
- The AI service is taking longer than expected. This could be due to:
95
- - High server load
96
- - Cold start (first request after idle period)
97
- - Network connectivity issues
 
98
 
99
  **What to try:**
100
- 1. Wait 30 seconds and try again
101
- 2. Simplify your goal description
102
- 3. Check if the service is healthy using the 'Test Service' button"""
103
 
104
  except aiohttp.ClientError as e:
105
  return f"""πŸ”Œ **Connection Error**
106
 
107
- Unable to connect to the backend service.
108
 
109
  **Possible causes:**
110
- - Service is starting up (cold start)
111
  - Network connectivity issues
112
- - Service is temporarily down
113
 
114
  **What to try:**
115
- 1. Wait 1-2 minutes and try again
116
  2. Check service health with 'Test Service' button
117
  3. Refresh the page
118
 
@@ -139,56 +149,90 @@ def get_investment_strategy(age_group, income, expenses, current_assets, current
139
  return f"❌ **Error**: {str(e)}"
140
 
141
  async def test_service_async():
142
- """Test service connectivity"""
143
  try:
144
  timeout = aiohttp.ClientTimeout(total=30)
145
 
146
  async with aiohttp.ClientSession(timeout=timeout) as session:
147
- # Test health endpoint first
148
  try:
149
  async with session.get(HEALTH_URL) as response:
150
  if response.status == 200:
151
  health_data = await response.json()
152
- health_status = f"βœ… Service is healthy\n- Status: {health_data.get('status')}\n- Timestamp: {health_data.get('timestamp')}"
 
 
 
153
  else:
154
  health_status = f"⚠️ Health check returned status {response.status}"
155
  except Exception as e:
156
  health_status = f"❌ Health check failed: {str(e)}"
157
 
158
- # Test strategy endpoint with sample data
159
  try:
160
- async with session.get(TEST_URL) as response:
161
  if response.status == 200:
162
- test_data = await response.json()
163
- test_status = f"βœ… Test endpoint working\n- Result: {test_data.get('test_result')}"
 
 
 
164
  else:
165
- test_status = f"⚠️ Test endpoint returned status {response.status}"
166
  except Exception as e:
167
- test_status = f"❌ Test endpoint failed: {str(e)}"
168
 
169
- return f"""## πŸ” Service Status Check
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
- **Health Check:**
172
  {health_status}
173
 
174
- **Functionality Test:**
175
- {test_status}
 
 
 
176
 
177
- **Service URL:** {MODAL_URL}
 
 
 
 
 
 
 
178
 
179
  *Last checked: {asyncio.get_event_loop().time()}*"""
180
 
181
  except Exception as e:
182
  return f"""❌ **Service Test Failed**
183
 
184
- Unable to connect to the service.
185
 
186
  Error: {str(e)}
187
 
188
  **Troubleshooting:**
189
  1. Check if the Modal deployment is running
190
- 2. Verify the service URL is correct
191
- 3. Check network connectivity"""
 
192
 
193
  def test_service():
194
  """Sync wrapper for service test"""
@@ -200,8 +244,53 @@ def test_service():
200
  return result
201
  except Exception as e:
202
  return f"❌ **Test Error**: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
 
204
  def generate_pdf(strategy):
 
205
  pdf = FPDF()
206
  pdf.add_page()
207
  pdf.set_font("Arial", size=12)
@@ -216,10 +305,11 @@ def generate_pdf(strategy):
216
  return pdf_output
217
 
218
  def download_strategy(strategy):
 
219
  pdf_path = generate_pdf(strategy)
220
  return pdf_path
221
 
222
- # Fixed CSS - Removed problematic dropdown overrides
223
  custom_css = """
224
  /* Global container styling */
225
  .gradio-container {
@@ -283,15 +373,7 @@ custom_css = """
283
  z-index: 1;
284
  }
285
 
286
- /* Icon styling */
287
- .finance-icon {
288
- font-size: 4rem;
289
- margin-bottom: 1rem;
290
- position: relative;
291
- z-index: 1;
292
- }
293
-
294
- /* Form sections */
295
  .form-section {
296
  background: white !important;
297
  border-radius: 16px !important;
@@ -317,7 +399,7 @@ custom_css = """
317
  gap: 0.75rem !important;
318
  }
319
 
320
- /* Input styling - only for textboxes and numbers, NOT dropdowns */
321
  input[type="text"], input[type="number"], textarea {
322
  border-radius: 12px !important;
323
  border: 2px solid #e5e7eb !important;
@@ -332,11 +414,6 @@ input[type="text"]:focus, input[type="number"]:focus, textarea:focus {
332
  outline: none !important;
333
  }
334
 
335
- /* Minimal dropdown styling - let Gradio handle the functionality */
336
- .gradio-dropdown {
337
- margin-bottom: 1rem !important;
338
- }
339
-
340
  /* Button styling */
341
  .primary-btn {
342
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
@@ -374,6 +451,16 @@ input[type="text"]:focus, input[type="number"]:focus, textarea:focus {
374
  box-shadow: 0 12px 32px rgba(100, 116, 139, 0.4) !important;
375
  }
376
 
 
 
 
 
 
 
 
 
 
 
377
  /* Output area styling */
378
  .output-area {
379
  background: white !important;
@@ -400,44 +487,6 @@ input[type="text"]:focus, input[type="number"]:focus, textarea:focus {
400
  margin-bottom: 1rem !important;
401
  }
402
 
403
- /* Radio button styling */
404
- .gradio-radio {
405
- gap: 1rem !important;
406
- }
407
-
408
- .gradio-radio label {
409
- background: white !important;
410
- border: 2px solid #e5e7eb !important;
411
- border-radius: 12px !important;
412
- padding: 1rem !important;
413
- transition: all 0.3s ease !important;
414
- cursor: pointer !important;
415
- }
416
-
417
- .gradio-radio label:hover {
418
- border-color: #667eea !important;
419
- background: #f8fafc !important;
420
- }
421
-
422
- .gradio-radio input:checked + label {
423
- border-color: #667eea !important;
424
- background: linear-gradient(135deg, #667eea10, #764ba210) !important;
425
- color: #1e3c72 !important;
426
- }
427
-
428
- /* Progress indicator */
429
- .loading-indicator {
430
- background: linear-gradient(90deg, #667eea, #764ba2, #667eea) !important;
431
- background-size: 200% 100% !important;
432
- animation: gradient 2s ease infinite !important;
433
- }
434
-
435
- @keyframes gradient {
436
- 0% { background-position: 0% 50%; }
437
- 50% { background-position: 100% 50%; }
438
- 100% { background-position: 0% 50%; }
439
- }
440
-
441
  /* Responsive design */
442
  @media (max-width: 768px) {
443
  .finance-header h1 {
@@ -453,29 +502,12 @@ input[type="text"]:focus, input[type="number"]:focus, textarea:focus {
453
  padding: 1.5rem !important;
454
  }
455
  }
456
-
457
- /* Chart and finance icons */
458
- .finance-bg {
459
- position: relative;
460
- overflow: hidden;
461
- }
462
-
463
- .finance-bg::after {
464
- content: "πŸ“ˆπŸ“ŠπŸ’°πŸ¦πŸ’³πŸ“‹";
465
- position: absolute;
466
- top: -20px;
467
- right: -20px;
468
- font-size: 6rem;
469
- opacity: 0.05;
470
- z-index: 0;
471
- transform: rotate(12deg);
472
- }
473
  """
474
 
475
  # Create the enhanced interface
476
  with gr.Blocks(
477
  theme=gr.themes.Soft(primary_hue="blue", secondary_hue="slate"),
478
- title="πŸ’Ό Vittaśāstra - AI Strategist",
479
  css=custom_css
480
  ) as interface:
481
 
@@ -484,10 +516,10 @@ with gr.Blocks(
484
  gr.HTML("""
485
  <div style="text-align: center; position: relative; z-index: 1;">
486
  <div class="finance-icon">πŸ’Ό</div>
487
- <h1>Vittaśāstra - AI Strategist</h1>
488
  <p>Professional-Grade Investment Strategy Generator</p>
489
  <div style="margin-top: 1rem; font-size: 0.95rem; opacity: 0.8;">
490
- πŸ€– Powered by Advanced AI β€’ πŸ”’ Secure & Private β€’ πŸ“Š Data-Driven Insights
491
  </div>
492
  </div>
493
  """)
@@ -495,6 +527,13 @@ with gr.Blocks(
495
  with gr.Row(elem_classes="main-content"):
496
  with gr.Column():
497
 
 
 
 
 
 
 
 
498
  # Personal Information Section
499
  with gr.Group(elem_classes="form-section"):
500
  gr.HTML("<h3>πŸ‘€ Personal Profile</h3>")
@@ -516,7 +555,6 @@ with gr.Blocks(
516
  show_label=True
517
  )
518
 
519
-
520
  # Financial Information Section
521
  with gr.Group(elem_classes="form-section"):
522
  gr.HTML("<h3>πŸ’° Financial Overview</h3>")
@@ -553,7 +591,8 @@ with gr.Blocks(
553
  gr.HTML("""
554
  <div style="background: linear-gradient(90deg, #10b981, #059669); color: white;
555
  padding: 1rem; border-radius: 8px; margin-top: 1rem; font-size: 0.9rem;">
556
- πŸ’‘ <strong>Quick Tip:</strong> A healthy savings rate is typically 20% or more of your income. Consider your net worth (assets - liabilities) for better strategy planning.
 
557
  </div>
558
  """)
559
 
@@ -586,82 +625,70 @@ with gr.Blocks(
586
  with gr.Row():
587
  with gr.Column(scale=3):
588
  submit_btn = gr.Button(
589
- "πŸš€ Generate My Investment Strategy",
590
  variant="primary",
591
  size="lg",
592
  elem_classes="primary-btn"
593
  )
594
  with gr.Column(scale=1):
595
  test_btn = gr.Button(
596
- "πŸ” Test Service",
 
 
 
 
 
 
 
597
  variant="secondary",
598
  size="lg",
599
  elem_classes="secondary-btn"
600
  )
601
 
602
- # Tips Section
603
  with gr.Group(elem_classes="tips-section"):
604
  gr.HTML("""
605
- <h4>πŸ’‘ Pro Tips for Better Results</h4>
606
- <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1rem; margin-top: 1rem;">
607
  <div style="display: flex; align-items: start; gap: 0.5rem;">
608
- <span style="color: #10b981; font-size: 1.2rem;">βœ“</span>
609
- <span><strong>Be Specific:</strong> Detailed goals lead to better recommendations</span>
610
  </div>
611
  <div style="display: flex; align-items: start; gap: 0.5rem;">
612
- <span style="color: #10b981; font-size: 1.2rem;">βœ“</span>
613
- <span><strong>Realistic Timeline:</strong> Match your goals with appropriate timeframes</span>
614
  </div>
615
  <div style="display: flex; align-items: start; gap: 0.5rem;">
616
- <span style="color: #10b981; font-size: 1.2rem;">βœ“</span>
617
- <span><strong>Know Your Risk:</strong> Be honest about your comfort level</span>
618
  </div>
619
  <div style="display: flex; align-items: start; gap: 0.5rem;">
620
- <span style="color: #10b981; font-size: 1.2rem;">βœ“</span>
621
- <span><strong>Include Assets & Debts:</strong> Complete financial picture enables better advice</span>
622
  </div>
623
  </div>
624
  """)
625
 
626
  # Output Section
627
- # with gr.Group(elem_classes="output-area"):
628
- # output = gr.Markdown(
629
- # value="""
630
- # ## 🎯 Ready to Get Started?
631
-
632
- # Fill out your each and every financial profile above and click **"Generate My Investment Strategy"** to receive:
633
-
634
- # πŸ“‹ **Personalized Investment Plan**
635
- # πŸ“Š **Asset Allocation Recommendations**
636
- # 🏦 **Account Type Suggestions**
637
- # πŸ’‘ **Tax Optimization Strategies**
638
- # πŸ“ˆ **Risk Management Advice**
639
- # πŸ’³ **Debt Management Guidance**
640
-
641
- # *Your data is processed securely and never stored permanently.*
642
- # """,
643
- # elem_id="strategy-output"
644
- # )
645
  with gr.Group(elem_classes="output-area"):
646
  output = gr.Markdown(
647
  value="""
648
- ## 🎯 Ready to Get Started?
649
 
650
- Fill out your each and every financial profile above and click **"Generate My Investment Strategy"** to receive:
651
 
652
- πŸ“‹ **Personalized Investment Plan**
653
- πŸ“Š **Asset Allocation Recommendations**
654
- 🏦 **Account Type Suggestions**
655
- πŸ’‘ **Tax Optimization Strategies**
656
- πŸ“ˆ **Risk Management Advice**
657
- πŸ’³ **Debt Management Guidance**
658
 
659
- *Your data is processed securely and never stored permanently.*
660
  """,
661
  elem_id="strategy-output"
662
  )
663
  download_btn = gr.Button("πŸ“₯ Download Strategy as PDF", variant="secondary", elem_classes="secondary-btn")
664
-
665
 
666
  # Event handlers
667
  submit_btn.click(
@@ -676,11 +703,23 @@ with gr.Blocks(
676
  outputs=output,
677
  show_progress=True
678
  )
 
 
 
 
 
 
679
 
680
  download_btn.click(
681
- fn=download_strategy,
682
- inputs=output,
683
- outputs=gr.File(label="Download PDF")
 
 
 
 
 
 
684
  )
685
 
686
  if __name__ == "__main__":
 
1
+ # app.py - Updated for New Modal Backend
2
  import gradio as gr
3
  import requests
4
  import json
 
7
  from typing import Optional
8
  from fpdf import FPDF
9
 
10
+ # Update these URLs to match your new Modal deployment
11
+ MODAL_BASE_URL = "https://your-app-name--personal-investment-strategist-enhanced-web.modal.run"
12
+ STRATEGY_URL = f"{MODAL_BASE_URL}/generate_strategy"
13
+ HEALTH_URL = f"{MODAL_BASE_URL}/health"
14
+ MARKET_DATA_URL = f"{MODAL_BASE_URL}/market_data"
15
+ COUNTRY_ANALYSIS_URL = f"{MODAL_BASE_URL}/country_analysis"
16
 
17
  async def get_investment_strategy_async(age_group, income, expenses, current_assets, current_liabilities, risk_profile, goal, timeframe, country):
18
+ """Updated async function for new Modal backend structure"""
19
 
20
  # Input validation
21
  if not all([age_group, income, expenses, risk_profile, goal, timeframe, country]):
 
42
  if expenses_val >= income_val:
43
  return "⚠️ **Warning**: Your expenses are equal to or exceed your income. Consider budgeting advice before investing."
44
 
45
+ # Clean country name (remove emoji flags if present)
46
+ clean_country = country.split(' ', 1)[-1] if 'πŸ‡ΊπŸ‡Έ' in country or 'πŸ‡¨πŸ‡¦' in country else country
47
+
48
+ # Updated payload structure to match new Modal backend
49
  payload = {
50
+ "age_group": age_group,
51
+ "income": income_val,
52
+ "expenses": expenses_val,
53
+ "current_assets": assets_val,
54
+ "current_liabilities": liabilities_val,
55
+ "risk_profile": risk_profile,
56
+ "goal": goal,
57
+ "timeframe": timeframe,
58
+ "country": clean_country
 
 
59
  }
60
 
61
  try:
62
+ print(f"πŸš€ Sending request to: {STRATEGY_URL}")
63
 
64
  # Use aiohttp for better async handling
65
+ timeout = aiohttp.ClientTimeout(total=180) # 3 minute timeout for comprehensive analysis
66
 
67
  async with aiohttp.ClientSession(timeout=timeout) as session:
68
  async with session.post(
69
+ STRATEGY_URL,
70
  json=payload,
71
  headers={
72
  'Content-Type': 'application/json',
 
80
  result = await response.json()
81
  strategy = result.get("strategy", "No strategy returned.")
82
  status = result.get("status", "unknown")
83
+ processing_time = result.get("processing_time", 0)
84
 
85
+ # Add enhanced status indicator
86
+ if status == "success":
87
+ prefix = f"## πŸ’Ό Your Comprehensive Investment Strategy\n*✨ AI-Powered Analysis Complete (Generated in {processing_time:.1f}s)*\n\n"
88
+ elif status == "validation_error":
89
+ return f"❌ **Validation Error**\n\n{strategy}"
90
+ elif status == "llm_error":
91
+ prefix = "## πŸ“Š Your Investment Strategy (Rule-Based Fallback)\n*⚠️ AI service temporarily unavailable, using optimized rule-based strategy*\n\n"
92
  else:
93
+ prefix = "## πŸ“Š Your Investment Strategy\n*Generated using advanced algorithms*\n\n"
94
 
95
  return f"{prefix}{strategy}"
96
  else:
 
100
  except asyncio.TimeoutError:
101
  return """⏱️ **Request Timeout**
102
 
103
+ The comprehensive AI analysis is taking longer than expected. This could be due to:
104
+ - Extensive market data collection and analysis
105
+ - Real-time financial data processing
106
+ - High server load or cold start
107
+ - Complex tax calculations
108
 
109
  **What to try:**
110
+ 1. Wait 1-2 minutes and try again
111
+ 2. Check if the service is healthy using the 'Test Service' button
112
+ 3. Simplify your goal description if very detailed"""
113
 
114
  except aiohttp.ClientError as e:
115
  return f"""πŸ”Œ **Connection Error**
116
 
117
+ Unable to connect to the enhanced backend service.
118
 
119
  **Possible causes:**
120
+ - Service is performing cold start (initial startup)
121
  - Network connectivity issues
122
+ - Enhanced features are initializing
123
 
124
  **What to try:**
125
+ 1. Wait 2-3 minutes and try again (cold start can take time)
126
  2. Check service health with 'Test Service' button
127
  3. Refresh the page
128
 
 
149
  return f"❌ **Error**: {str(e)}"
150
 
151
  async def test_service_async():
152
+ """Enhanced service connectivity test"""
153
  try:
154
  timeout = aiohttp.ClientTimeout(total=30)
155
 
156
  async with aiohttp.ClientSession(timeout=timeout) as session:
157
+ # Test health endpoint
158
  try:
159
  async with session.get(HEALTH_URL) as response:
160
  if response.status == 200:
161
  health_data = await response.json()
162
+ health_status = f"""βœ… **Service is healthy**
163
+ - Status: {health_data.get('status')}
164
+ - Version: {health_data.get('version', 'N/A')}
165
+ - Timestamp: {health_data.get('timestamp')}"""
166
  else:
167
  health_status = f"⚠️ Health check returned status {response.status}"
168
  except Exception as e:
169
  health_status = f"❌ Health check failed: {str(e)}"
170
 
171
+ # Test market data endpoint
172
  try:
173
+ async with session.get(MARKET_DATA_URL) as response:
174
  if response.status == 200:
175
+ market_data = await response.json()
176
+ market_status = f"""βœ… **Market data service working**
177
+ - Status: {market_data.get('status')}
178
+ - Timestamp: {market_data.get('timestamp')}
179
+ - Features: Real-time market data, sector analysis"""
180
  else:
181
+ market_status = f"⚠️ Market data endpoint returned status {response.status}"
182
  except Exception as e:
183
+ market_status = f"❌ Market data test failed: {str(e)}"
184
 
185
+ # Test country analysis endpoint
186
+ try:
187
+ test_payload = {
188
+ "country": "United States",
189
+ "include_tax_calc": False
190
+ }
191
+ async with session.post(COUNTRY_ANALYSIS_URL, json=test_payload) as response:
192
+ if response.status == 200:
193
+ country_data = await response.json()
194
+ country_status = f"""βœ… **Country analysis service working**
195
+ - Status: {country_data.get('status')}
196
+ - Features: Tax analysis, economic data, interest rates"""
197
+ else:
198
+ country_status = f"⚠️ Country analysis returned status {response.status}"
199
+ except Exception as e:
200
+ country_status = f"❌ Country analysis test failed: {str(e)}"
201
+
202
+ return f"""## πŸ” Enhanced Service Status Check
203
 
204
+ **Core Health:**
205
  {health_status}
206
 
207
+ **Market Data Service:**
208
+ {market_status}
209
+
210
+ **Country Analysis Service:**
211
+ {country_status}
212
 
213
+ **Service Features:**
214
+ ✨ Real-time market data via Yahoo Finance
215
+ 🏦 Comprehensive tax analysis for 8+ countries
216
+ πŸ€– AI-powered strategy generation
217
+ πŸ“Š Bullish sector and stock analysis
218
+ 🌍 Country-specific financial context
219
+
220
+ **Service URL:** {MODAL_BASE_URL}
221
 
222
  *Last checked: {asyncio.get_event_loop().time()}*"""
223
 
224
  except Exception as e:
225
  return f"""❌ **Service Test Failed**
226
 
227
+ Unable to connect to the enhanced service.
228
 
229
  Error: {str(e)}
230
 
231
  **Troubleshooting:**
232
  1. Check if the Modal deployment is running
233
+ 2. Verify the service URL is correct: {MODAL_BASE_URL}
234
+ 3. Check network connectivity
235
+ 4. Allow extra time for cold start (enhanced features take longer to initialize)"""
236
 
237
  def test_service():
238
  """Sync wrapper for service test"""
 
244
  return result
245
  except Exception as e:
246
  return f"❌ **Test Error**: {str(e)}"
247
+
248
+ async def get_market_preview_async():
249
+ """Get current market data preview"""
250
+ try:
251
+ timeout = aiohttp.ClientTimeout(total=30)
252
+
253
+ async with aiohttp.ClientSession(timeout=timeout) as session:
254
+ async with session.get(MARKET_DATA_URL) as response:
255
+ if response.status == 200:
256
+ market_data = await response.json()
257
+
258
+ preview = "## πŸ“Š Current Market Snapshot\n\n"
259
+
260
+ # Market indices
261
+ if market_data.get("market_indices"):
262
+ preview += "**Major Indices:**\n"
263
+ for index, data in list(market_data["market_indices"].items())[:4]:
264
+ if not data.get('error'):
265
+ change_emoji = "πŸ“ˆ" if data.get('change_percent', 0) > 0 else "πŸ“‰"
266
+ preview += f"β€’ {change_emoji} {index}: {data.get('current_price', 'N/A'):.2f} ({data.get('change_percent', 0):+.2f}%)\n"
267
+
268
+ # Bullish sectors
269
+ if market_data.get("bullish_sectors", {}).get("bullish_sectors"):
270
+ preview += "\n**πŸš€ Top Performing Sectors:**\n"
271
+ for sector in market_data["bullish_sectors"]["bullish_sectors"][:3]:
272
+ preview += f"β€’ {sector['sector']}: {sector['performance']}\n"
273
+
274
+ preview += f"\n*Updated: {market_data.get('timestamp', 'Unknown')}*"
275
+ return preview
276
+ else:
277
+ return "πŸ“Š **Market data temporarily unavailable**\n\nClick 'Generate Strategy' for comprehensive analysis including current market conditions."
278
+ except Exception as e:
279
+ return "πŸ“Š **Market preview unavailable**\n\nFull market analysis will be included in your personalized strategy."
280
+
281
+ def get_market_preview():
282
+ """Sync wrapper for market preview"""
283
+ try:
284
+ loop = asyncio.new_event_loop()
285
+ asyncio.set_event_loop(loop)
286
+ result = loop.run_until_complete(get_market_preview_async())
287
+ loop.close()
288
+ return result
289
+ except Exception as e:
290
+ return "πŸ“Š **Market preview unavailable**\n\nFull analysis available in strategy generation."
291
 
292
  def generate_pdf(strategy):
293
+ """Generate PDF from strategy"""
294
  pdf = FPDF()
295
  pdf.add_page()
296
  pdf.set_font("Arial", size=12)
 
305
  return pdf_output
306
 
307
  def download_strategy(strategy):
308
+ """Download strategy as PDF"""
309
  pdf_path = generate_pdf(strategy)
310
  return pdf_path
311
 
312
+ # Enhanced CSS with new features
313
  custom_css = """
314
  /* Global container styling */
315
  .gradio-container {
 
373
  z-index: 1;
374
  }
375
 
376
+ /* Enhanced form sections */
 
 
 
 
 
 
 
 
377
  .form-section {
378
  background: white !important;
379
  border-radius: 16px !important;
 
399
  gap: 0.75rem !important;
400
  }
401
 
402
+ /* Input styling - only for textboxes and numbers */
403
  input[type="text"], input[type="number"], textarea {
404
  border-radius: 12px !important;
405
  border: 2px solid #e5e7eb !important;
 
414
  outline: none !important;
415
  }
416
 
 
 
 
 
 
417
  /* Button styling */
418
  .primary-btn {
419
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
 
451
  box-shadow: 0 12px 32px rgba(100, 116, 139, 0.4) !important;
452
  }
453
 
454
+ /* Market preview styling */
455
+ .market-preview {
456
+ background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%) !important;
457
+ border-radius: 16px !important;
458
+ padding: 1.5rem !important;
459
+ margin: 1.5rem 0 !important;
460
+ border-left: 4px solid #0ea5e9 !important;
461
+ font-size: 0.9rem !important;
462
+ }
463
+
464
  /* Output area styling */
465
  .output-area {
466
  background: white !important;
 
487
  margin-bottom: 1rem !important;
488
  }
489
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
490
  /* Responsive design */
491
  @media (max-width: 768px) {
492
  .finance-header h1 {
 
502
  padding: 1.5rem !important;
503
  }
504
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
  """
506
 
507
  # Create the enhanced interface
508
  with gr.Blocks(
509
  theme=gr.themes.Soft(primary_hue="blue", secondary_hue="slate"),
510
+ title="πŸ’Ό Vittaśāstra - AI Strategist Enhanced",
511
  css=custom_css
512
  ) as interface:
513
 
 
516
  gr.HTML("""
517
  <div style="text-align: center; position: relative; z-index: 1;">
518
  <div class="finance-icon">πŸ’Ό</div>
519
+ <h1>Vittaśāstra - AI Strategist Enhanced</h1>
520
  <p>Professional-Grade Investment Strategy Generator</p>
521
  <div style="margin-top: 1rem; font-size: 0.95rem; opacity: 0.8;">
522
+ πŸ€– Enhanced AI Analysis β€’ πŸ“Š Real-Time Market Data β€’ 🏦 Tax Optimization β€’ πŸ”’ Secure & Private
523
  </div>
524
  </div>
525
  """)
 
527
  with gr.Row(elem_classes="main-content"):
528
  with gr.Column():
529
 
530
+ # Market Preview Section
531
+ with gr.Group(elem_classes="market-preview"):
532
+ market_preview = gr.Markdown(
533
+ value="πŸ“Š **Loading current market data...**",
534
+ elem_id="market-preview"
535
+ )
536
+
537
  # Personal Information Section
538
  with gr.Group(elem_classes="form-section"):
539
  gr.HTML("<h3>πŸ‘€ Personal Profile</h3>")
 
555
  show_label=True
556
  )
557
 
 
558
  # Financial Information Section
559
  with gr.Group(elem_classes="form-section"):
560
  gr.HTML("<h3>πŸ’° Financial Overview</h3>")
 
591
  gr.HTML("""
592
  <div style="background: linear-gradient(90deg, #10b981, #059669); color: white;
593
  padding: 1rem; border-radius: 8px; margin-top: 1rem; font-size: 0.9rem;">
594
+ πŸ’‘ <strong>Enhanced Analysis:</strong> The new system provides comprehensive tax optimization,
595
+ real-time market data, and personalized asset allocation based on your complete financial profile.
596
  </div>
597
  """)
598
 
 
625
  with gr.Row():
626
  with gr.Column(scale=3):
627
  submit_btn = gr.Button(
628
+ "πŸš€ Generate Enhanced Investment Strategy",
629
  variant="primary",
630
  size="lg",
631
  elem_classes="primary-btn"
632
  )
633
  with gr.Column(scale=1):
634
  test_btn = gr.Button(
635
+ "πŸ” Test Enhanced Service",
636
+ variant="secondary",
637
+ size="lg",
638
+ elem_classes="secondary-btn"
639
+ )
640
+ with gr.Column(scale=1):
641
+ market_btn = gr.Button(
642
+ "πŸ“Š Refresh Market Data",
643
  variant="secondary",
644
  size="lg",
645
  elem_classes="secondary-btn"
646
  )
647
 
648
+ # Enhanced Tips Section
649
  with gr.Group(elem_classes="tips-section"):
650
  gr.HTML("""
651
+ <h4>✨ Enhanced Features & Pro Tips</h4>
652
+ <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1rem; margin-top: 1rem;">
653
  <div style="display: flex; align-items: start; gap: 0.5rem;">
654
+ <span style="color: #10b981; font-size: 1.2rem;">πŸ“Š</span>
655
+ <span><strong>Real-Time Market Data:</strong> Live analysis of market conditions and sector performance</span>
656
  </div>
657
  <div style="display: flex; align-items: start; gap: 0.5rem;">
658
+ <span style="color: #10b981; font-size: 1.2rem;">🏦</span>
659
+ <span><strong>Tax Optimization:</strong> Country-specific tax strategies and account recommendations</span>
660
  </div>
661
  <div style="display: flex; align-items: start; gap: 0.5rem;">
662
+ <span style="color: #10b981; font-size: 1.2rem;">πŸ€–</span>
663
+ <span><strong>AI-Powered Analysis:</strong> Advanced algorithms for personalized recommendations</span>
664
  </div>
665
  <div style="display: flex; align-items: start; gap: 0.5rem;">
666
+ <span style="color: #10b981; font-size: 1.2rem;">πŸ’Ž</span>
667
+ <span><strong>Complete Financial Picture:</strong> Assets, liabilities, and cash flow analysis</span>
668
  </div>
669
  </div>
670
  """)
671
 
672
  # Output Section
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
673
  with gr.Group(elem_classes="output-area"):
674
  output = gr.Markdown(
675
  value="""
676
+ ## 🎯 Ready for Enhanced Analysis?
677
 
678
+ The enhanced system provides:
679
 
680
+ πŸ“Š **Real-Time Market Analysis** - Current indices, sector performance, bullish stocks
681
+ 🏦 **Comprehensive Tax Optimization** - Country-specific strategies and calculations
682
+ πŸ’Ό **Professional Asset Allocation** - Based on your complete financial profile
683
+ πŸ“ˆ **Advanced Risk Management** - Tailored to your risk tolerance and timeline
684
+ 🌍 **Global Financial Context** - Economic indicators and country-specific advice
685
+ πŸ’‘ **Implementation Roadmap** - Step-by-step action plan
686
 
687
+ *Enhanced with real-time data processing and comprehensive financial analysis.*
688
  """,
689
  elem_id="strategy-output"
690
  )
691
  download_btn = gr.Button("πŸ“₯ Download Strategy as PDF", variant="secondary", elem_classes="secondary-btn")
 
692
 
693
  # Event handlers
694
  submit_btn.click(
 
703
  outputs=output,
704
  show_progress=True
705
  )
706
+
707
+ market_btn.click(
708
+ fn=get_market_preview,
709
+ outputs=market_preview,
710
+ show_progress=True
711
+ )
712
 
713
  download_btn.click(
714
+ fn=download_strategy,
715
+ inputs=output,
716
+ outputs=gr.File(label="Download PDF")
717
+ )
718
+
719
+ # Load market data on startup
720
+ interface.load(
721
+ fn=get_market_preview,
722
+ outputs=market_preview
723
  )
724
 
725
  if __name__ == "__main__":