uumerrr684 commited on
Commit
f2d289d
Β·
verified Β·
1 Parent(s): 010f6d4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +364 -441
app.py CHANGED
@@ -1,11 +1,10 @@
1
  #!/usr/bin/env python3
2
  """
3
  Hybrid AI Assistant - General Purpose + Healthcare Billing Expert
4
- Enhanced with Emotional UI and Voice Input
5
  """
6
 
7
  import os
8
- import sys
9
  import json
10
  import logging
11
  import re
@@ -16,15 +15,14 @@ import requests
16
  import gradio as gr
17
  from datetime import datetime
18
  import random
19
- import time
20
-
21
- # Set up environment
22
- os.environ['OPENROUTER_API_KEY'] = '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'
23
 
24
  # Configure logging
25
  logging.basicConfig(level=logging.INFO)
26
  logger = logging.getLogger(__name__)
27
 
 
 
 
28
  # ============= Data Classes =============
29
 
30
  @dataclass
@@ -235,7 +233,7 @@ class SentimentAnalyzer:
235
 
236
  class HybridAIAssistant:
237
  def __init__(self):
238
- self.api_key = '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'
239
  self.billing_db = BillingCodesDB()
240
  self.sentiment_analyzer = SentimentAnalyzer()
241
  self.context = ConversationContext()
@@ -413,35 +411,66 @@ class HybridAIAssistant:
413
  # ============= Global Assistant Instance =============
414
  assistant = HybridAIAssistant()
415
 
416
- # ============= Chat Functions =============
417
 
418
- def respond(message, history):
419
- """Response function for ChatInterface"""
420
- if not message.strip():
421
- return "Feel free to ask me anything! I can help with general questions or healthcare billing codes. 😊"
422
-
423
- # Process message and get sentiment
424
- response, sentiment = assistant.process_message(message)
425
-
426
- # Update UI based on sentiment (this will be handled by JavaScript)
427
- return response
 
 
 
428
 
429
- def process_voice_input(audio):
430
- """Process voice input and return text"""
431
- if audio is None:
432
- return "No audio received. Please try again."
433
-
434
- # For now, return a placeholder message
435
- # In a real implementation, you'd use speech recognition here
436
- return "Voice input processed! (Speech recognition would be implemented here)"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
437
 
438
- def reset_chat():
439
  """Reset the conversation context"""
440
- assistant.reset_context()
441
- return []
 
 
 
 
442
 
443
  # ============= Examples =============
444
-
445
  examples = [
446
  "What is healthcare billing code A0429?",
447
  "Can you explain CPT code 99213 in detail?",
@@ -454,422 +483,316 @@ examples = [
454
  "Write a short poem about nature"
455
  ]
456
 
457
- # ============= Create Interface =============
 
 
 
 
 
 
 
 
 
458
 
459
- def create_interface():
460
- """Create the Gradio ChatInterface with Emotional UI and Voice Input"""
461
-
462
- # Enhanced CSS with emotional UI and voice features
463
- custom_css = """
464
- /* Global Styles */
465
- .gradio-container {
466
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif !important;
467
- max-width: 1200px !important;
468
- margin: auto !important;
469
- background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%) !important;
470
- min-height: 100vh !important;
471
- padding: 1rem !important;
472
- transition: all 0.5s ease !important;
473
- }
474
-
475
- /* Emotional UI Color Schemes */
476
- .sentiment-positive { background: linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%) !important; }
477
- .sentiment-very-positive { background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%) !important; }
478
- .sentiment-negative { background: linear-gradient(135deg, #d299c2 0%, #fef9d7 100%) !important; }
479
- .sentiment-very-negative { background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%) !important; }
480
- .sentiment-anxious { background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%) !important; }
481
- .sentiment-frustrated { background: linear-gradient(135deg, #ff8a80 0%, #ffad80 100%) !important; }
482
- .sentiment-excited { background: linear-gradient(135deg, #ffd89b 0%, #19547b 100%) !important; }
483
- .sentiment-confused { background: linear-gradient(135deg, #a8caba 0%, #5d4e75 100%) !important; }
484
-
485
- /* Enhanced Header with Mood Indicator */
486
- .header-text {
487
- text-align: center;
488
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
489
- color: white;
490
- padding: 3rem 2rem;
491
- border-radius: 20px;
492
- margin-bottom: 2rem;
493
- box-shadow: 0 20px 40px rgba(102, 126, 234, 0.3);
494
- position: relative;
495
- overflow: hidden;
496
- transition: all 0.5s ease;
497
- }
498
-
499
- .header-text::before {
500
- content: '';
501
- position: absolute;
502
- top: -50%;
503
- left: -50%;
504
- width: 200%;
505
- height: 200%;
506
- background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
507
- animation: pulse 4s ease-in-out infinite;
508
- }
509
-
510
- @keyframes pulse {
511
- 0%, 100% { opacity: 0.3; }
512
- 50% { opacity: 0.6; }
513
- }
514
-
515
- /* Mood Indicator */
516
- .mood-indicator {
517
- position: absolute;
518
- top: 1rem;
519
- right: 1rem;
520
- width: 60px;
521
- height: 60px;
522
- border-radius: 50%;
523
- background: rgba(255,255,255,0.2);
524
- backdrop-filter: blur(10px);
525
- display: flex;
526
- align-items: center;
527
- justify-content: center;
528
- font-size: 24px;
529
- transition: all 0.5s ease;
530
- animation: breathe 3s ease-in-out infinite;
531
- }
532
-
533
- @keyframes breathe {
534
- 0%, 100% { transform: scale(1); }
535
- 50% { transform: scale(1.05); }
536
- }
537
-
538
- .mood-positive { background: rgba(132, 250, 176, 0.3) !important; }
539
- .mood-negative { background: rgba(255, 154, 158, 0.3) !important; }
540
- .mood-anxious { background: rgba(255, 236, 210, 0.3) !important; }
541
- .mood-excited { background: rgba(255, 216, 155, 0.3) !important; }
542
-
543
- .header-text h1 {
544
- margin: 0;
545
- font-size: 3rem;
546
- font-weight: 800;
547
- display: flex;
548
- align-items: center;
549
- justify-content: center;
550
- gap: 1rem;
551
- position: relative;
552
- z-index: 1;
553
- text-shadow: 0 2px 4px rgba(0,0,0,0.2);
554
- }
555
-
556
- .header-text p {
557
- margin: 1rem 0 0 0;
558
- font-size: 1.2rem;
559
- opacity: 0.95;
560
- position: relative;
561
- z-index: 1;
562
- font-weight: 300;
563
- }
564
-
565
- .badge {
566
- background: rgba(255,255,255,0.25) !important;
567
- backdrop-filter: blur(10px);
568
- border: 1px solid rgba(255,255,255,0.3);
569
- animation: glow 2s ease-in-out infinite alternate;
570
- }
571
-
572
- @keyframes glow {
573
- from { box-shadow: 0 0 5px rgba(255,255,255,0.3); }
574
- to { box-shadow: 0 0 20px rgba(255,255,255,0.6); }
575
- }
576
-
577
- /* Voice Input Button */
578
- .voice-btn {
579
- background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%) !important;
580
- color: white !important;
581
- border: none !important;
582
- border-radius: 50% !important;
583
- width: 60px !important;
584
- height: 60px !important;
585
- font-size: 24px !important;
586
- margin: 0.5rem !important;
587
- transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) !important;
588
- box-shadow: 0 4px 15px rgba(255, 107, 107, 0.3) !important;
589
- position: relative;
590
- overflow: hidden;
591
- }
592
-
593
- .voice-btn:hover {
594
- transform: scale(1.1) !important;
595
- box-shadow: 0 8px 25px rgba(255, 107, 107, 0.5) !important;
596
- }
597
-
598
- .voice-btn.recording {
599
- animation: recordPulse 1s ease-in-out infinite !important;
600
- background: linear-gradient(135deg, #ff3030 0%, #ff1010 100%) !important;
601
- }
602
-
603
- @keyframes recordPulse {
604
- 0% { box-shadow: 0 0 0 0 rgba(255, 107, 107, 0.7); }
605
- 70% { box-shadow: 0 0 0 20px rgba(255, 107, 107, 0); }
606
- 100% { box-shadow: 0 0 0 0 rgba(255, 107, 107, 0); }
607
- }
608
-
609
- /* Chat Interface Styling with Emotional Feedback */
610
- .gradio-chatinterface {
611
- background: white !important;
612
- border-radius: 20px !important;
613
- box-shadow: 0 25px 50px rgba(0,0,0,0.15) !important;
614
- padding: 2rem !important;
615
- margin: 1rem 0 !important;
616
- backdrop-filter: blur(10px) !important;
617
- transition: all 0.5s ease !important;
618
- }
619
-
620
- .gradio-chatinterface.emotional-positive {
621
- border: 2px solid rgba(132, 250, 176, 0.5) !important;
622
- box-shadow: 0 25px 50px rgba(132, 250, 176, 0.2) !important;
623
- }
624
-
625
- .gradio-chatinterface.emotional-negative {
626
- border: 2px solid rgba(255, 154, 158, 0.5) !important;
627
- box-shadow: 0 25px 50px rgba(255, 154, 158, 0.2) !important;
628
- }
629
-
630
- /* Enhanced Buttons */
631
- .reset-btn {
632
- background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%) !important;
633
- color: white !important;
634
- border: none !important;
635
- border-radius: 12px !important;
636
- padding: 0.75rem 1.5rem !important;
637
- font-weight: 600 !important;
638
- margin: 0.5rem 0 !important;
639
- transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) !important;
640
- box-shadow: 0 4px 15px rgba(255, 107, 107, 0.3) !important;
641
- }
642
-
643
- .reset-btn:hover {
644
- background: linear-gradient(135deg, #ff5252 0%, #d32f2f 100%) !important;
645
- transform: translateY(-2px) scale(1.02) !important;
646
- box-shadow: 0 8px 25px rgba(255, 107, 107, 0.4) !important;
647
- }
648
-
649
- /* Example Buttons Enhancement */
650
- .gradio-chatinterface .examples .example {
651
- background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%) !important;
652
- border: 2px solid #e2e8f0 !important;
653
- border-radius: 15px !important;
654
- padding: 0.75rem 1rem !important;
655
- margin: 0.5rem !important;
656
- transition: all 0.3s ease !important;
657
- box-shadow: 0 2px 8px rgba(0,0,0,0.05) !important;
658
- }
659
-
660
- .gradio-chatinterface .examples .example:hover {
661
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
662
- color: white !important;
663
- border-color: #667eea !important;
664
- transform: translateY(-2px) !important;
665
- box-shadow: 0 8px 20px rgba(102, 126, 234, 0.3) !important;
666
- }
667
-
668
- /* Enhanced Stats Cards */
669
- .stats-container {
670
- display: grid;
671
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
672
- gap: 1.5rem;
673
- margin: 2rem 0;
674
- }
675
-
676
- .stat-card {
677
- background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
678
- border-radius: 16px;
679
- padding: 2rem;
680
- text-align: center;
681
- box-shadow: 0 10px 30px rgba(0,0,0,0.1);
682
- border: 1px solid #e2e8f0;
683
- transition: all 0.3s ease;
684
- position: relative;
685
- overflow: hidden;
686
- }
687
-
688
- .stat-card::before {
689
- content: '';
690
- position: absolute;
691
- top: 0;
692
- left: 0;
693
- right: 0;
694
- height: 4px;
695
- background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
696
- }
697
-
698
- .stat-card:hover {
699
- transform: translateY(-5px);
700
- box-shadow: 0 20px 40px rgba(0,0,0,0.15);
701
- }
702
-
703
- .stat-number {
704
- font-size: 2.5rem;
705
- font-weight: 800;
706
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
707
- -webkit-background-clip: text;
708
- -webkit-text-fill-color: transparent;
709
- background-clip: text;
710
- margin-bottom: 0.5rem;
711
- }
712
-
713
- .stat-label {
714
- color: #64748b;
715
- font-size: 0.9rem;
716
- font-weight: 500;
717
- text-transform: uppercase;
718
- letter-spacing: 1px;
719
- }
720
-
721
- /* Empathy Animations */
722
- @keyframes empathyPulse {
723
- 0%, 100% { transform: scale(1); }
724
- 50% { transform: scale(1.02); }
725
- }
726
-
727
- @keyframes supportGlow {
728
- 0%, 100% { box-shadow: 0 0 10px rgba(102, 126, 234, 0.3); }
729
- 50% { box-shadow: 0 0 20px rgba(102, 126, 234, 0.6); }
730
- }
731
-
732
- .empathy-support {
733
- animation: empathyPulse 2s ease-in-out infinite, supportGlow 3s ease-in-out infinite;
734
- }
735
-
736
- /* Voice Recognition Feedback */
737
- .voice-feedback {
738
- position: fixed;
739
- bottom: 2rem;
740
- right: 2rem;
741
- background: rgba(102, 126, 234, 0.9);
742
- color: white;
743
- padding: 1rem 1.5rem;
744
- border-radius: 50px;
745
- backdrop-filter: blur(10px);
746
- z-index: 1000;
747
- animation: slideInRight 0.3s ease-out;
748
- }
749
-
750
- @keyframes slideInRight {
751
- from { transform: translateX(100%); opacity: 0; }
752
- to { transform: translateX(0); opacity: 1; }
753
- }
754
-
755
- /* Enhanced Accordion */
756
- .gradio-accordion {
757
- background: rgba(255,255,255,0.9) !important;
758
- backdrop-filter: blur(10px) !important;
759
- border-radius: 16px !important;
760
- border: 1px solid rgba(255,255,255,0.2) !important;
761
- box-shadow: 0 8px 25px rgba(0,0,0,0.1) !important;
762
- margin: 1.5rem 0 !important;
763
- }
764
-
765
- /* Feature Cards */
766
- .feature-grid {
767
- display: grid;
768
- grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
769
- gap: 1.5rem;
770
- margin: 2rem 0;
771
- }
772
-
773
- .feature-card {
774
- background: rgba(255,255,255,0.95);
775
- backdrop-filter: blur(10px);
776
- border-radius: 16px;
777
- padding: 1.5rem;
778
- border: 1px solid rgba(255,255,255,0.3);
779
- box-shadow: 0 8px 25px rgba(0,0,0,0.1);
780
- transition: all 0.3s ease;
781
- }
782
-
783
- .feature-card:hover {
784
- transform: translateY(-5px);
785
- box-shadow: 0 15px 35px rgba(0,0,0,0.15);
786
- }
787
-
788
- .feature-icon {
789
  font-size: 2rem;
790
- margin-bottom: 1rem;
791
  }
792
 
793
- .feature-title {
794
- color: #2d3748;
795
- font-size: 1.25rem;
796
- font-weight: 600;
797
- margin-bottom: 0.5rem;
798
  }
799
 
800
- .feature-desc {
801
- color: #64748b;
802
- line-height: 1.6;
803
  }
804
-
805
- /* Responsive Design */
806
- @media (max-width: 768px) {
807
- .gradio-container {
808
- padding: 0.5rem !important;
809
- }
810
-
811
- .header-text h1 {
812
- font-size: 2rem;
813
- flex-direction: column;
814
- gap: 0.5rem;
815
- }
816
-
817
- .header-text {
818
- padding: 2rem 1rem;
819
- }
820
-
821
- .stats-container {
822
- grid-template-columns: repeat(2, 1fr);
823
- gap: 1rem;
824
- }
825
-
826
- .stat-card {
827
- padding: 1.5rem;
828
- }
829
-
830
- .feature-grid {
831
- grid-template-columns: 1fr;
832
- gap: 1rem;
833
- }
834
-
835
- .mood-indicator {
836
- width: 50px;
837
- height: 50px;
838
- font-size: 20px;
839
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
840
 
841
- .voice-btn {
842
- width: 50px !important;
843
- height: 50px !important;
844
- font-size: 20px !important;
845
- }
846
- }
847
-
848
- /* Loading Animation */
849
- @keyframes shimmer {
850
- 0% { background-position: -468px 0; }
851
- 100% { background-position: 468px 0; }
852
- }
853
-
854
- .loading {
855
- animation: shimmer 1.5s ease-in-out infinite;
856
- background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
857
- background-size: 400% 100%;
858
- }
859
-
860
- /* Sentiment-based message styling */
861
- .message-positive {
862
- border-left: 4px solid #84fab0 !important;
863
- background: linear-gradient(135deg, rgba(132, 250, 176, 0.1) 0%, rgba(143, 211, 244, 0.1) 100%) !important;
864
- }
865
-
866
- .message-negative {
867
- border-left: 4px solid #ff9a9e !important;
868
- background: linear-gradient(135deg, rgba(255, 154, 158, 0.1) 0%, rgba(254, 207, 239, 0.1) 100%) !important;
869
- }
870
-
871
- .message-anxious {
872
- border-left: 4px solid #ffecd2 !important;
873
- background: linear-gradient(135deg, rgba(255, 236, 210, 0.1) 0%, rgba(252, 182, 159, 0.1) 100%) !important;
874
- }
875
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  #!/usr/bin/env python3
2
  """
3
  Hybrid AI Assistant - General Purpose + Healthcare Billing Expert
4
+ Enhanced with Emotional UI and Voice Input - HUGGING FACE SPACES VERSION
5
  """
6
 
7
  import os
 
8
  import json
9
  import logging
10
  import re
 
15
  import gradio as gr
16
  from datetime import datetime
17
  import random
 
 
 
 
18
 
19
  # Configure logging
20
  logging.basicConfig(level=logging.INFO)
21
  logger = logging.getLogger(__name__)
22
 
23
+ # Set up environment - Hugging Face Spaces will handle API keys via secrets
24
+ API_KEY = os.getenv('OPENROUTER_API_KEY', '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')
25
+
26
  # ============= Data Classes =============
27
 
28
  @dataclass
 
233
 
234
  class HybridAIAssistant:
235
  def __init__(self):
236
+ self.api_key = API_KEY
237
  self.billing_db = BillingCodesDB()
238
  self.sentiment_analyzer = SentimentAnalyzer()
239
  self.context = ConversationContext()
 
411
  # ============= Global Assistant Instance =============
412
  assistant = HybridAIAssistant()
413
 
414
+ # ============= Chat Functions for Gradio =============
415
 
416
+ def chat_with_assistant(message, history):
417
+ """Main chat function for Gradio ChatInterface"""
418
+ try:
419
+ if not message or not message.strip():
420
+ return "Feel free to ask me anything! I can help with general questions or healthcare billing codes. 😊"
421
+
422
+ # Process message and get response
423
+ response, sentiment = assistant.process_message(message.strip())
424
+ return response
425
+
426
+ except Exception as e:
427
+ logger.error(f"Chat error: {e}")
428
+ return "I apologize, but I encountered an error processing your message. Please try again!"
429
 
430
+ def quick_code_lookup(code):
431
+ """Quick billing code lookup function"""
432
+ try:
433
+ if not code or not code.strip():
434
+ return "Please enter a billing code to look up."
435
+
436
+ info = assistant.billing_db.lookup(code.strip())
437
+ if info:
438
+ result = f"**{info.code} ({info.code_type})**\n\n"
439
+ result += f"**Description:** {info.description}\n\n"
440
+ if info.additional_info:
441
+ result += f"**Details:** {info.additional_info}\n\n"
442
+ if info.category:
443
+ result += f"**Category:** {info.category}"
444
+ return result
445
+ else:
446
+ return f"Code '{code.strip()}' not found in database. Try asking in the chat for more help!"
447
+ except Exception as e:
448
+ logger.error(f"Code lookup error: {e}")
449
+ return "Error looking up code. Please try again."
450
+
451
+ def process_voice_input(audio_file):
452
+ """Process voice input (placeholder for speech recognition)"""
453
+ if audio_file is None:
454
+ return "No audio received. Please try recording again."
455
+
456
+ # Placeholder for speech recognition
457
+ # In a real implementation, you would use libraries like:
458
+ # - speech_recognition
459
+ # - whisper
460
+ # - Google Speech-to-Text API
461
+
462
+ return "Voice input received! (Speech recognition would be implemented here with libraries like Whisper or SpeechRecognition)"
463
 
464
+ def reset_conversation():
465
  """Reset the conversation context"""
466
+ try:
467
+ assistant.reset_context()
468
+ return "βœ… Conversation reset successfully!", ""
469
+ except Exception as e:
470
+ logger.error(f"Reset error: {e}")
471
+ return "Error resetting conversation.", ""
472
 
473
  # ============= Examples =============
 
474
  examples = [
475
  "What is healthcare billing code A0429?",
476
  "Can you explain CPT code 99213 in detail?",
 
483
  "Write a short poem about nature"
484
  ]
485
 
486
+ # ============= Custom CSS for Hugging Face Spaces =============
487
+ custom_css = """
488
+ /* Enhanced Hugging Face Spaces Compatible CSS */
489
+ .gradio-container {
490
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
491
+ max-width: 1200px !important;
492
+ margin: 0 auto !important;
493
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%) !important;
494
+ padding: 1rem !important;
495
+ }
496
 
497
+ /* Header Styling */
498
+ .header-banner {
499
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
500
+ color: white;
501
+ padding: 2rem;
502
+ border-radius: 15px;
503
+ margin-bottom: 1.5rem;
504
+ text-align: center;
505
+ box-shadow: 0 10px 30px rgba(102, 126, 234, 0.3);
506
+ }
507
+
508
+ .header-banner h1 {
509
+ margin: 0;
510
+ font-size: 2.5rem;
511
+ font-weight: 700;
512
+ text-shadow: 0 2px 4px rgba(0,0,0,0.2);
513
+ }
514
+
515
+ .header-banner p {
516
+ margin: 0.5rem 0 0 0;
517
+ font-size: 1.1rem;
518
+ opacity: 0.9;
519
+ }
520
+
521
+ /* Enhanced Buttons */
522
+ .custom-button {
523
+ background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%) !important;
524
+ border: none !important;
525
+ border-radius: 8px !important;
526
+ color: white !important;
527
+ font-weight: 600 !important;
528
+ padding: 0.6rem 1.2rem !important;
529
+ transition: all 0.3s ease !important;
530
+ }
531
+
532
+ .custom-button:hover {
533
+ transform: translateY(-2px) !important;
534
+ box-shadow: 0 4px 12px rgba(255, 107, 107, 0.4) !important;
535
+ }
536
+
537
+ /* Chat Interface */
538
+ .gradio-chatbot {
539
+ border-radius: 15px !important;
540
+ box-shadow: 0 8px 25px rgba(0,0,0,0.1) !important;
541
+ background: white !important;
542
+ }
543
+
544
+ /* Feature Cards */
545
+ .feature-grid {
546
+ display: grid;
547
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
548
+ gap: 1rem;
549
+ margin: 1rem 0;
550
+ }
551
+
552
+ .feature-card {
553
+ background: rgba(255,255,255,0.95);
554
+ padding: 1.5rem;
555
+ border-radius: 12px;
556
+ box-shadow: 0 4px 15px rgba(0,0,0,0.1);
557
+ transition: transform 0.3s ease;
558
+ text-align: center;
559
+ }
560
+
561
+ .feature-card:hover {
562
+ transform: translateY(-5px);
563
+ }
564
+
565
+ .feature-icon {
566
+ font-size: 2rem;
567
+ margin-bottom: 0.5rem;
568
+ }
569
+
570
+ /* Stats */
571
+ .stats-container {
572
+ display: grid;
573
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
574
+ gap: 1rem;
575
+ margin: 1rem 0;
576
+ }
577
+
578
+ .stat-item {
579
+ background: white;
580
+ padding: 1rem;
581
+ border-radius: 10px;
582
+ text-align: center;
583
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
584
+ border-top: 3px solid #667eea;
585
+ }
586
+
587
+ .stat-number {
588
+ font-size: 1.8rem;
589
+ font-weight: bold;
590
+ color: #667eea;
591
+ }
592
+
593
+ .stat-label {
594
+ font-size: 0.8rem;
595
+ color: #666;
596
+ text-transform: uppercase;
597
+ letter-spacing: 1px;
598
+ }
599
+
600
+ /* Responsive Design */
601
+ @media (max-width: 768px) {
602
+ .header-banner h1 {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
603
  font-size: 2rem;
 
604
  }
605
 
606
+ .feature-grid {
607
+ grid-template-columns: 1fr;
 
 
 
608
  }
609
 
610
+ .stats-container {
611
+ grid-template-columns: repeat(2, 1fr);
 
612
  }
613
+ }
614
+ """
615
+
616
+ # ============= Main Gradio Interface =============
617
+
618
+ def create_gradio_interface():
619
+ """Create the main Gradio interface optimized for Hugging Face Spaces"""
620
+
621
+ with gr.Blocks(
622
+ css=custom_css,
623
+ title="πŸ₯ Hybrid AI Assistant - Healthcare Billing Expert",
624
+ theme=gr.themes.Soft()
625
+ ) as demo:
626
+
627
+ # Header Section
628
+ gr.HTML("""
629
+ <div class="header-banner">
630
+ <h1>πŸ₯ Hybrid AI Assistant</h1>
631
+ <p>Your intelligent companion for healthcare billing codes and general assistance</p>
632
+ <div style="margin-top: 1rem;">
633
+ <span style="background: rgba(255,255,255,0.2); padding: 0.3rem 0.8rem; border-radius: 15px; margin: 0 0.25rem; font-size: 0.9rem;">πŸ’¬ General AI</span>
634
+ <span style="background: rgba(255,255,255,0.2); padding: 0.3rem 0.8rem; border-radius: 15px; margin: 0 0.25rem; font-size: 0.9rem;">πŸ₯ Medical Billing</span>
635
+ <span style="background: rgba(255,255,255,0.2); padding: 0.3rem 0.8rem; border-radius: 15px; margin: 0 0.25rem; font-size: 0.9rem;">🎭 Emotional AI</span>
636
+ <span style="background: rgba(255,255,255,0.2); padding: 0.3rem 0.8rem; border-radius: 15px; margin: 0 0.25rem; font-size: 0.9rem;">πŸŽ™οΈ Voice Ready</span>
637
+ </div>
638
+ </div>
639
+ """)
640
+
641
+ # Stats Section
642
+ gr.HTML("""
643
+ <div class="stats-container">
644
+ <div class="stat-item">
645
+ <div class="stat-number">15+</div>
646
+ <div class="stat-label">Billing Codes</div>
647
+ </div>
648
+ <div class="stat-item">
649
+ <div class="stat-number">9</div>
650
+ <div class="stat-label">Sentiment Types</div>
651
+ </div>
652
+ <div class="stat-item">
653
+ <div class="stat-number">24/7</div>
654
+ <div class="stat-label">Available</div>
655
+ </div>
656
+ <div class="stat-item">
657
+ <div class="stat-number">∞</div>
658
+ <div class="stat-label">Conversations</div>
659
+ </div>
660
+ </div>
661
+ """)
662
+
663
+ # Main Chat Interface
664
+ chatbot = gr.ChatInterface(
665
+ chat_with_assistant,
666
+ examples=examples,
667
+ title="",
668
+ description="πŸ’¬ Start chatting! I can help with healthcare billing codes, general questions, and adapt to your emotional tone.",
669
+ submit_btn="Send πŸ“€",
670
+ retry_btn="πŸ”„ Retry",
671
+ undo_btn="↩️ Undo",
672
+ clear_btn="πŸ—‘οΈ Clear"
673
+ )
674
+
675
+ # Additional Tools Section
676
+ with gr.Row():
677
+ with gr.Column(scale=1):
678
+ gr.Markdown("### πŸ₯ Quick Code Lookup")
679
+ code_input = gr.Textbox(
680
+ label="Enter Billing Code",
681
+ placeholder="e.g., A0429, 99213, DRG470...",
682
+ lines=1
683
+ )
684
+ lookup_btn = gr.Button("πŸ” Look up Code", elem_classes=["custom-button"])
685
+ code_output = gr.Textbox(
686
+ label="Code Information",
687
+ placeholder="Code details will appear here...",
688
+ lines=6,
689
+ interactive=False
690
+ )
691
+
692
+ with gr.Column(scale=1):
693
+ gr.Markdown("### πŸŽ™οΈ Voice Input")
694
+ audio_input = gr.Audio(
695
+ sources=["microphone"],
696
+ type="filepath",
697
+ label="Voice Input"
698
+ )
699
+ voice_btn = gr.Button("🎀 Process Voice", elem_classes=["custom-button"])
700
+ voice_output = gr.Textbox(
701
+ label="Voice Processing Result",
702
+ placeholder="Voice processing result will appear here...",
703
+ lines=3,
704
+ interactive=False
705
+ )
706
+
707
+ # Features Section
708
+ gr.HTML("""
709
+ <div class="feature-grid">
710
+ <div class="feature-card">
711
+ <div class="feature-icon">🧠</div>
712
+ <h3>Smart AI Assistant</h3>
713
+ <p>Advanced AI that understands context and provides intelligent responses.</p>
714
+ </div>
715
+ <div class="feature-card">
716
+ <div class="feature-icon">πŸ₯</div>
717
+ <h3>Healthcare Billing Expert</h3>
718
+ <p>Comprehensive database of CPT, HCPCS, ICD-10, and DRG codes.</p>
719
+ </div>
720
+ <div class="feature-card">
721
+ <div class="feature-icon">🎭</div>
722
+ <h3>Emotional Intelligence</h3>
723
+ <p>Adapts responses based on your emotional state and tone.</p>
724
+ </div>
725
+ <div class="feature-card">
726
+ <div class="feature-icon">πŸŽ™οΈ</div>
727
+ <h3>Voice Input Ready</h3>
728
+ <p>Framework for voice processing and hands-free interaction.</p>
729
+ </div>
730
+ </div>
731
+ """)
732
+
733
+ # Control Section
734
+ with gr.Row():
735
+ reset_btn = gr.Button("πŸ”„ Reset Conversation", elem_classes=["custom-button"])
736
+ status_output = gr.Textbox(
737
+ label="Status",
738
+ placeholder="System status will appear here...",
739
+ lines=1,
740
+ interactive=False
741
+ )
742
 
743
+ # Usage Information
744
+ gr.Markdown("""
745
+ ### πŸ’‘ How to Use:
746
+ - **Healthcare Codes**: Mention any billing code (A0429, 99213, etc.) and get detailed information
747
+ - **General Questions**: Ask anything - from recipes to complex topics, I'm here to help!
748
+ - **Emotional Support**: I adapt my tone based on your mood - express how you're feeling
749
+ - **Voice Input**: Use the voice recorder for hands-free interaction (framework ready)
750
+ - **Quick Lookup**: Use the code lookup tool for instant billing code information
751
+
752
+ ### πŸ₯ Supported Code Types:
753
+ - **CPT Codes**: Current Procedural Terminology (99213, 93000, etc.)
754
+ - **HCPCS Codes**: Healthcare Common Procedure Coding (A0429, J3420, etc.)
755
+ - **ICD-10 Codes**: International Classification of Diseases (Z79.899, etc.)
756
+ - **DRG Codes**: Diagnosis Related Groups (DRG470, etc.)
757
+ """)
758
+
759
+ # Event Handlers
760
+ lookup_btn.click(
761
+ quick_code_lookup,
762
+ inputs=[code_input],
763
+ outputs=[code_output]
764
+ )
765
+
766
+ voice_btn.click(
767
+ process_voice_input,
768
+ inputs=[audio_input],
769
+ outputs=[voice_output]
770
+ )
771
+
772
+ reset_btn.click(
773
+ reset_conversation,
774
+ outputs=[status_output, code_output]
775
+ )
776
+
777
+ return demo
778
+
779
+ # ============= Launch Application =============
780
+
781
+ # Create and configure the interface
782
+ demo = create_gradio_interface()
783
+
784
+ # For Hugging Face Spaces, the app will be launched automatically
785
+ # No need for manual demo.launch() in Hugging Face Spaces
786
+ if __name__ == "__main__":
787
+ # This block will be executed when running locally
788
+ # For Hugging Face Spaces, remove this and just export the demo
789
+ demo.launch(
790
+ server_name="0.0.0.0",
791
+ server_port=7860,
792
+ share=True,
793
+ debug=True
794
+ )
795
+
796
+ # For Hugging Face Spaces deployment, export the demo
797
+ # Uncomment the line below when deploying to Hugging Face Spaces
798
+ # demo.queue().launch()