siyah1 commited on
Commit
a5405ac
·
verified ·
1 Parent(s): 32d19ef

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +220 -217
app.py CHANGED
@@ -280,250 +280,274 @@ class SocioCareAIPreconsultation:
280
  self.demo = self._create_interface()
281
 
282
  def _create_interface(self):
283
- # Custom CSS for better styling
284
  custom_css = """
285
  <style>
286
- .sociocare-header {
287
- background: linear-gradient(135deg, #2c5aa0 0%, #4a90e2 50%, #7bb3f0 100%);
288
- padding: 2rem;
289
- border-radius: 20px;
290
- margin-bottom: 2rem;
291
- box-shadow: 0 10px 30px rgba(44, 90, 160, 0.3);
292
- text-align: center;
293
- position: relative;
294
- overflow: hidden;
295
  }
296
 
297
- .sociocare-header::before {
298
- content: '';
299
- position: absolute;
300
- top: -50%;
301
- left: -50%;
302
- width: 200%;
303
- height: 200%;
304
- background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
305
- animation: pulse 4s ease-in-out infinite;
306
  }
307
 
308
- @keyframes pulse {
309
- 0%, 100% { transform: scale(1); opacity: 0.5; }
310
- 50% { transform: scale(1.05); opacity: 0.8; }
311
- }
312
-
313
- .sociocare-title {
314
- color: white;
315
- font-size: 2.5rem;
316
- font-weight: 700;
317
- margin-bottom: 0.5rem;
318
- text-shadow: 0 2px 4px rgba(0,0,0,0.3);
319
- position: relative;
320
- z-index: 1;
321
  }
322
 
323
- .sociocare-subtitle {
324
- color: #e8f4fd;
325
- font-size: 1.2rem;
326
- margin-bottom: 1rem;
327
- font-weight: 400;
328
  position: relative;
329
- z-index: 1;
 
 
 
330
  }
331
 
332
- .sociocare-disclaimer {
333
- color: #b8daf7;
334
- font-size: 0.95rem;
335
- font-weight: 300;
336
- position: relative;
337
- z-index: 1;
 
 
338
  }
339
 
340
- .info-card {
341
- background: linear-gradient(135deg, #f8fbff 0%, #e8f4fd 100%);
342
- padding: 1.5rem;
343
- border-radius: 16px;
344
- border: 1px solid #d1e7f5;
345
- box-shadow: 0 4px 20px rgba(44, 90, 160, 0.1);
346
- margin-bottom: 1.5rem;
347
- transition: transform 0.3s ease, box-shadow 0.3s ease;
348
  }
349
 
350
- .info-card:hover {
351
- transform: translateY(-2px);
352
- box-shadow: 0 6px 25px rgba(44, 90, 160, 0.15);
 
 
353
  }
354
 
355
- .info-card h3 {
356
- color: #2c5aa0;
357
- margin-top: 0;
358
- margin-bottom: 1rem;
359
- font-size: 1.3rem;
360
- font-weight: 600;
361
- display: flex;
362
- align-items: center;
363
- gap: 0.5rem;
364
- }
 
 
365
 
366
- .info-card ul {
367
- color: #4a6b8a;
368
- line-height: 1.7;
369
- margin-bottom: 0;
370
  }
371
 
372
- .info-card li {
373
- margin-bottom: 0.5rem;
374
- padding-left: 0.5rem;
375
  }
376
 
377
- .warning-card {
378
- background: linear-gradient(135deg, #fff8e1 0%, #ffeaa7 100%);
379
- border: 1px solid #ffcc02;
380
- border-left: 4px solid #ff9800;
 
 
 
 
 
 
 
 
 
 
 
381
  }
382
 
383
- .warning-card h3 {
384
- color: #e65100;
 
 
 
 
 
 
 
385
  }
386
 
387
- .warning-card p {
388
- color: #bf360c;
389
- line-height: 1.6;
390
  }
391
 
392
- .emergency-card {
393
- background: linear-gradient(135deg, #e8f5e8 0%, #c8e6c9 100%);
394
- padding: 1.5rem;
395
- border-radius: 16px;
396
- border: 1px solid #81c784;
397
- border-left: 4px solid #4caf50;
398
- margin-top: 1.5rem;
 
399
  text-align: center;
400
- }
401
-
402
- .emergency-card p {
403
- color: #1b5e20;
404
  margin-bottom: 0.5rem;
405
- font-weight: 500;
406
  }
407
 
408
- .voice-section {
409
- background: linear-gradient(135deg, #ffffff 0%, #f8fbff 100%);
410
- padding: 2rem;
411
- border-radius: 20px;
412
- border: 2px solid #e3f2fd;
413
- box-shadow: 0 8px 32px rgba(44, 90, 160, 0.1);
 
414
  }
415
 
416
- .voice-title {
417
- color: #2c5aa0;
418
- font-size: 1.5rem;
419
- font-weight: 600;
420
- margin-bottom: 1rem;
421
- text-align: center;
422
  display: flex;
 
423
  align-items: center;
424
- justify-content: center;
425
- gap: 0.5rem;
426
  }
427
 
428
- .feature-grid {
429
- display: grid;
430
- grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
431
- gap: 1rem;
432
- margin-bottom: 1.5rem;
 
 
433
  }
434
 
435
- .feature-item {
436
- background: #f8fbff;
437
- padding: 1rem;
438
- border-radius: 12px;
439
- border: 1px solid #e1f5fe;
440
- text-align: center;
441
- transition: all 0.3s ease;
 
 
 
 
 
442
  }
443
 
444
- .feature-item:hover {
445
- background: #e8f4fd;
446
- border-color: #b3e5fc;
447
  }
448
 
449
- .feature-icon {
450
- font-size: 2rem;
451
- margin-bottom: 0.5rem;
452
- display: block;
 
 
 
 
 
453
  }
454
 
455
- .feature-text {
456
- color: #2c5aa0;
457
- font-weight: 500;
458
  font-size: 0.9rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
459
  }
460
  </style>
461
  """
462
 
463
- with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo:
464
- gr.HTML("""
465
- <div class="sociocare-header">
466
- <h1 class="sociocare-title">🏥 SocioCare AI Preconsultation</h1>
467
- <p class="sociocare-subtitle">Advanced AI-Powered Health Assessment & Guidance</p>
468
- <p class="sociocare-disclaimer">⚠️ Preliminary health assessment • Not a substitute for professional medical advice</p>
469
- </div>
470
- """)
471
-
472
- with gr.Row():
473
- with gr.Column(scale=5):
474
- gr.HTML("""
475
- <div class="info-card">
476
- <h3>🎯 How Your Preconsultation Works</h3>
477
- <ul>
478
- <li><strong>Start Your Session:</strong> Click "Begin Preconsultation" to activate voice interaction</li>
479
- <li><strong>Describe Your Concerns:</strong> Speak clearly about your symptoms, health concerns, or questions</li>
480
- <li><strong>Interactive Assessment:</strong> SocioCare AI will ask follow-up questions to better understand your condition</li>
481
- <li><strong>Receive Guidance:</strong> Get preliminary health insights and next-step recommendations</li>
482
- <li><strong>Ask Questions:</strong> Feel free to ask for clarification or additional information</li>
483
- </ul>
484
- </div>
485
- """)
486
-
487
- gr.HTML("""
488
- <div class="feature-grid">
489
- <div class="feature-item">
490
- <span class="feature-icon">🎤</span>
491
- <div class="feature-text">Voice-Activated<br>Assessment</div>
492
- </div>
493
- <div class="feature-item">
494
- <span class="feature-icon">🧠</span>
495
- <div class="feature-text">AI-Powered<br>Analysis</div>
496
- </div>
497
- <div class="feature-item">
498
- <span class="feature-icon">⚡</span>
499
- <div class="feature-text">Real-Time<br>Responses</div>
500
- </div>
501
- <div class="feature-item">
502
- <span class="feature-icon">🔒</span>
503
- <div class="feature-text">Secure &<br>Private</div>
504
- </div>
505
- </div>
506
- """)
507
-
508
- gr.HTML("""
509
- <div class="info-card warning-card">
510
- <h3>⚠️ Important Medical Disclaimer</h3>
511
- <p style="margin-bottom: 1rem;">
512
- SocioCare AI provides preliminary health assessment and general medical information only.
513
- This service is designed to help you understand your symptoms and guide you toward appropriate care.
514
- </p>
515
- <p style="margin-bottom: 0;">
516
- <strong>Always consult with qualified healthcare professionals for diagnosis, treatment, and comprehensive medical care.</strong>
517
- </p>
518
  </div>
519
- """)
520
-
521
- with gr.Column(scale=6):
522
- gr.HTML('<div class="voice-section">')
523
- gr.HTML('<h2 class="voice-title">🎙️ Voice Preconsultation Portal</h2>')
524
-
 
 
 
 
 
525
  webrtc = WebRTC(
526
- label="Click to Begin Your Preconsultation",
527
  modality="audio",
528
  mode="send-receive",
529
  rtc_configuration=get_rtc_configuration(),
@@ -537,34 +561,13 @@ class SocioCareAIPreconsultation:
537
  concurrency_limit=3,
538
  )
539
 
 
540
  gr.HTML("""
541
- <div style="margin-top: 1.5rem; padding: 1rem; background: #f0f8ff; border-radius: 12px; border: 1px solid #b3e5fc;">
542
- <p style="color: #1976d2; margin-bottom: 0.5rem; font-weight: 500; text-align: center;">
543
- 💡 <strong>Tips for Best Results:</strong>
544
- </p>
545
- <ul style="color: #1976d2; font-size: 0.9rem; line-height: 1.5; margin-bottom: 0;">
546
- <li>Speak in a quiet environment</li>
547
- <li>Describe symptoms clearly and in detail</li>
548
- <li>Mention symptom duration and severity</li>
549
- <li>Be honest about your medical history</li>
550
- </ul>
551
  </div>
552
  """)
553
- gr.HTML('</div>')
554
-
555
- gr.HTML("""
556
- <div class="emergency-card">
557
- <p style="margin-bottom: 1rem;">
558
- <strong>🚨 Emergency Services:</strong> If you're experiencing a medical emergency, call your local emergency number (911, 999, 112) immediately.
559
- </p>
560
- <p style="margin-bottom: 1rem;">
561
- <strong>🔒 Privacy Protection:</strong> Your voice consultation is not recorded or stored. All interactions are secure and confidential.
562
- </p>
563
- <p style="margin-bottom: 0;">
564
- <strong>⏰ Session Duration:</strong> Each preconsultation session lasts up to 10 minutes. You can start a new session anytime.
565
- </p>
566
- </div>
567
- """)
568
 
569
  return demo
570
 
@@ -590,7 +593,7 @@ class SocioCareAIPreconsultation:
590
  print("Could not find an available port. Please set the PORT environment variable.")
591
  return
592
 
593
- print(f"Starting SocioCare AI Preconsultation server on port {port}")
594
 
595
  self.demo.launch(
596
  server_name="0.0.0.0",
 
280
  self.demo = self._create_interface()
281
 
282
  def _create_interface(self):
283
+ # Modern dark theme CSS matching the image
284
  custom_css = """
285
  <style>
286
+ /* Global dark theme */
287
+ .gradio-container {
288
+ background: linear-gradient(135deg, #0F0C29 0%, #24243e 50%, #302B63 100%) !important;
289
+ min-height: 100vh;
 
 
 
 
 
290
  }
291
 
292
+ .dark {
293
+ background: linear-gradient(135deg, #0F0C29 0%, #24243e 50%, #302B63 100%) !important;
 
 
 
 
 
 
 
294
  }
295
 
296
+ /* Main container */
297
+ .main-container {
298
+ display: flex;
299
+ flex-direction: column;
300
+ align-items: center;
301
+ justify-content: center;
302
+ min-height: 90vh;
303
+ padding: 2rem;
 
 
 
 
 
304
  }
305
 
306
+ /* AI Icon and waves container */
307
+ .ai-icon-container {
 
 
 
308
  position: relative;
309
+ margin-bottom: 3rem;
310
+ display: flex;
311
+ flex-direction: column;
312
+ align-items: center;
313
  }
314
 
315
+ /* Audio waves */
316
+ .audio-waves {
317
+ display: flex;
318
+ align-items: center;
319
+ justify-content: center;
320
+ gap: 4px;
321
+ margin-bottom: 2rem;
322
+ height: 60px;
323
  }
324
 
325
+ .wave-dot {
326
+ width: 6px;
327
+ height: 6px;
328
+ background: #667EEA;
329
+ border-radius: 50%;
330
+ animation: pulse 2s ease-in-out infinite;
331
+ opacity: 0.6;
 
332
  }
333
 
334
+ .wave-bar {
335
+ width: 4px;
336
+ background: linear-gradient(to top, #667EEA, #764BA2);
337
+ border-radius: 2px;
338
+ animation: wave 1.5s ease-in-out infinite;
339
  }
340
 
341
+ .wave-bar:nth-child(1) { height: 20px; animation-delay: 0s; }
342
+ .wave-bar:nth-child(2) { height: 35px; animation-delay: 0.1s; }
343
+ .wave-bar:nth-child(3) { height: 45px; animation-delay: 0.2s; }
344
+ .wave-bar:nth-child(4) { height: 60px; animation-delay: 0.3s; }
345
+ .wave-bar:nth-child(5) { height: 50px; animation-delay: 0.4s; }
346
+ .wave-bar:nth-child(6) { height: 40px; animation-delay: 0.5s; }
347
+ .wave-bar:nth-child(7) { height: 55px; animation-delay: 0.6s; }
348
+ .wave-bar:nth-child(8) { height: 35px; animation-delay: 0.7s; }
349
+ .wave-bar:nth-child(9) { height: 25px; animation-delay: 0.8s; }
350
+ .wave-bar:nth-child(10) { height: 40px; animation-delay: 0.9s; }
351
+ .wave-bar:nth-child(11) { height: 50px; animation-delay: 1s; }
352
+ .wave-bar:nth-child(12) { height: 30px; animation-delay: 1.1s; }
353
 
354
+ @keyframes wave {
355
+ 0%, 100% { transform: scaleY(0.5); opacity: 0.7; }
356
+ 50% { transform: scaleY(1); opacity: 1; }
 
357
  }
358
 
359
+ @keyframes pulse {
360
+ 0%, 100% { opacity: 0.4; transform: scale(1); }
361
+ 50% { opacity: 1; transform: scale(1.2); }
362
  }
363
 
364
+ /* AI Icon */
365
+ .ai-icon {
366
+ width: 120px;
367
+ height: 120px;
368
+ background: linear-gradient(135deg, #667EEA 0%, #764BA2 100%);
369
+ border-radius: 24px;
370
+ display: flex;
371
+ align-items: center;
372
+ justify-content: center;
373
+ font-size: 3rem;
374
+ color: white;
375
+ box-shadow: 0 20px 40px rgba(102, 126, 234, 0.3);
376
+ margin-bottom: 2rem;
377
+ position: relative;
378
+ overflow: hidden;
379
  }
380
 
381
+ .ai-icon::before {
382
+ content: '';
383
+ position: absolute;
384
+ top: 0;
385
+ left: 0;
386
+ right: 0;
387
+ bottom: 0;
388
+ background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.1) 50%, transparent 70%);
389
+ animation: shimmer 3s ease-in-out infinite;
390
  }
391
 
392
+ @keyframes shimmer {
393
+ 0% { transform: translateX(-100%); }
394
+ 100% { transform: translateX(100%); }
395
  }
396
 
397
+ /* Title */
398
+ .ai-title {
399
+ font-size: 2.5rem;
400
+ font-weight: 700;
401
+ background: linear-gradient(135deg, #667EEA 0%, #764BA2 100%);
402
+ -webkit-background-clip: text;
403
+ -webkit-text-fill-color: transparent;
404
+ background-clip: text;
405
  text-align: center;
 
 
 
 
406
  margin-bottom: 0.5rem;
407
+ letter-spacing: -0.02em;
408
  }
409
 
410
+ /* Subtitle */
411
+ .ai-subtitle {
412
+ color: #A0AEC0;
413
+ font-size: 1.1rem;
414
+ text-align: center;
415
+ margin-bottom: 3rem;
416
+ font-weight: 400;
417
  }
418
 
419
+ /* WebRTC component styling */
420
+ .webrtc-container {
 
 
 
 
421
  display: flex;
422
+ flex-direction: column;
423
  align-items: center;
424
+ gap: 1rem;
 
425
  }
426
 
427
+ /* Hide default gradio elements */
428
+ .gradio-container .wrap,
429
+ .gradio-container .container,
430
+ footer {
431
+ background: transparent !important;
432
+ border: none !important;
433
+ box-shadow: none !important;
434
  }
435
 
436
+ /* Custom button styling for WebRTC */
437
+ button {
438
+ background: linear-gradient(135deg, #667EEA 0%, #764BA2 100%) !important;
439
+ border: none !important;
440
+ border-radius: 50px !important;
441
+ padding: 1rem 2rem !important;
442
+ color: white !important;
443
+ font-weight: 600 !important;
444
+ font-size: 1.1rem !important;
445
+ cursor: pointer !important;
446
+ transition: all 0.3s ease !important;
447
+ box-shadow: 0 10px 30px rgba(102, 126, 234, 0.3) !important;
448
  }
449
 
450
+ button:hover {
451
+ transform: translateY(-2px) !important;
452
+ box-shadow: 0 15px 35px rgba(102, 126, 234, 0.4) !important;
453
  }
454
 
455
+ /* Status indicators */
456
+ .status-dot {
457
+ width: 12px;
458
+ height: 12px;
459
+ border-radius: 50%;
460
+ background: #4ADE80;
461
+ box-shadow: 0 0 20px rgba(74, 222, 128, 0.5);
462
+ animation: pulse 2s ease-in-out infinite;
463
+ margin-right: 0.5rem;
464
  }
465
 
466
+ .status-text {
467
+ color: #E2E8F0;
 
468
  font-size: 0.9rem;
469
+ display: flex;
470
+ align-items: center;
471
+ justify-content: center;
472
+ margin-top: 1rem;
473
+ }
474
+
475
+ /* Hide default gradio styling */
476
+ .gradio-container .block {
477
+ background: transparent !important;
478
+ border: none !important;
479
+ box-shadow: none !important;
480
+ }
481
+
482
+ /* Responsive design */
483
+ @media (max-width: 768px) {
484
+ .ai-icon {
485
+ width: 100px;
486
+ height: 100px;
487
+ font-size: 2.5rem;
488
+ }
489
+
490
+ .ai-title {
491
+ font-size: 2rem;
492
+ }
493
+
494
+ .audio-waves {
495
+ height: 50px;
496
+ gap: 3px;
497
+ }
498
+
499
+ .wave-bar {
500
+ width: 3px;
501
+ }
502
  }
503
  </style>
504
  """
505
 
506
+ with gr.Blocks(theme=gr.themes.Glass(), css=custom_css) as demo:
507
+ with gr.Column(elem_classes=["main-container"]):
508
+ # Audio waves visualization
509
+ gr.HTML("""
510
+ <div class="audio-waves">
511
+ <div class="wave-dot"></div>
512
+ <div class="wave-dot"></div>
513
+ <div class="wave-dot"></div>
514
+ <div class="wave-bar"></div>
515
+ <div class="wave-bar"></div>
516
+ <div class="wave-bar"></div>
517
+ <div class="wave-bar"></div>
518
+ <div class="wave-bar"></div>
519
+ <div class="wave-bar"></div>
520
+ <div class="wave-bar"></div>
521
+ <div class="wave-bar"></div>
522
+ <div class="wave-bar"></div>
523
+ <div class="wave-bar"></div>
524
+ <div class="wave-bar"></div>
525
+ <div class="wave-bar"></div>
526
+ <div class="wave-dot"></div>
527
+ <div class="wave-dot"></div>
528
+ <div class="wave-dot"></div>
529
+ </div>
530
+ """)
531
+
532
+ # AI Icon
533
+ gr.HTML("""
534
+ <div class="ai-icon-container">
535
+ <div class="ai-icon">
536
+ AI✨
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
537
  </div>
538
+ </div>
539
+ """)
540
+
541
+ # Title and Subtitle
542
+ gr.HTML("""
543
+ <h1 class="ai-title">AI Voice Agent</h1>
544
+ <p class="ai-subtitle">By SocioCare</p>
545
+ """)
546
+
547
+ # WebRTC Component
548
+ with gr.Column(elem_classes=["webrtc-container"]):
549
  webrtc = WebRTC(
550
+ label="",
551
  modality="audio",
552
  mode="send-receive",
553
  rtc_configuration=get_rtc_configuration(),
 
561
  concurrency_limit=3,
562
  )
563
 
564
+ # Status indicator
565
  gr.HTML("""
566
+ <div class="status-text">
567
+ <span class="status-dot"></span>
568
+ Ready to assist with your health consultation
 
 
 
 
 
 
 
569
  </div>
570
  """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
571
 
572
  return demo
573
 
 
593
  print("Could not find an available port. Please set the PORT environment variable.")
594
  return
595
 
596
+ print(f"Starting AI Voice Agent server on port {port}")
597
 
598
  self.demo.launch(
599
  server_name="0.0.0.0",