CelagenexResearch commited on
Commit
40f4896
Β·
verified Β·
1 Parent(s): daa408f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +274 -53
app.py CHANGED
@@ -10,6 +10,7 @@ from transformers import (
10
  CLIPProcessor, CLIPModel,
11
  AutoProcessor
12
  )
 
13
 
14
  # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
15
  # CONFIG: set your HF token here or via env var HF_TOKEN
@@ -114,10 +115,11 @@ BREED_LIFESPAN = {
114
  "wire-haired fox terrier": 13.5, "yorkshire terrier": 13.3
115
  }
116
 
117
- # 4. VetMetrica HRQOL Framework
118
  HRQOL_QUESTIONNAIRE = {
119
  "vitality": {
120
- "title": "πŸ”‹ Vitality & Energy",
 
121
  "questions": [
122
  {
123
  "id": "vitality_energy",
@@ -131,7 +133,7 @@ HRQOL_QUESTIONNAIRE = {
131
  ]
132
  },
133
  {
134
- "id": "vitality_play",
135
  "text": "How often does your dog seek out play or interaction?",
136
  "options": [
137
  "Always seeks play/interaction",
@@ -157,6 +159,7 @@ HRQOL_QUESTIONNAIRE = {
157
  },
158
  "comfort": {
159
  "title": "😌 Comfort & Pain Management",
 
160
  "questions": [
161
  {
162
  "id": "comfort_activities",
@@ -196,6 +199,7 @@ HRQOL_QUESTIONNAIRE = {
196
  },
197
  "emotional_wellbeing": {
198
  "title": "😊 Emotional Wellbeing",
 
199
  "questions": [
200
  {
201
  "id": "emotion_mood",
@@ -235,6 +239,7 @@ HRQOL_QUESTIONNAIRE = {
235
  },
236
  "alertness": {
237
  "title": "🧠 Alertness & Cognition",
 
238
  "questions": [
239
  {
240
  "id": "alert_awareness",
@@ -478,9 +483,41 @@ def get_healthspan_grade(score):
478
  else:
479
  return "Critical (F)"
480
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481
  def comprehensive_healthspan_analysis(input_type, image_input, video_input, breed, age, *hrqol_responses):
482
  """Combine image/video analysis with HRQOL assessment based on input type"""
483
 
 
 
 
 
 
 
484
  # Determine which input to use based on dropdown selection
485
  if input_type == "Image Analysis":
486
  selected_media = image_input
@@ -489,14 +526,17 @@ def comprehensive_healthspan_analysis(input_type, image_input, video_input, bree
489
  selected_media = video_input
490
  media_type = "video"
491
  else:
492
- return "❌ **Error**: Please select an input type."
 
493
 
494
  if selected_media is None:
495
- return f"❌ **Error**: Please provide a {media_type} for analysis."
 
496
 
497
  # Check if questionnaire is completed
498
  if not hrqol_responses or all(not r for r in hrqol_responses):
499
- return "❌ **Error**: Please complete the HRQOL questionnaire before analysis."
 
500
 
501
  # Build HRQOL responses dictionary
502
  response_keys = []
@@ -695,7 +735,7 @@ def comprehensive_healthspan_analysis(input_type, image_input, video_input, bree
695
  </div>
696
  """
697
 
698
- return report_html
699
 
700
  def update_media_input(input_type):
701
  """Update the visibility of media inputs based on dropdown selection"""
@@ -704,38 +744,147 @@ def update_media_input(input_type):
704
  else: # Video Analysis
705
  return gr.update(visible=False), gr.update(visible=True)
706
 
707
- # Gradio Interface
708
- with gr.Blocks(title="🐢 VetMetrica HRQOL Dog Health Analyzer", theme=gr.themes.Soft()) as demo:
709
- gr.Markdown("""
710
- # πŸ• **VetMetricaΒ© HRQOL Dog Health & Age Analyzer**
711
- ### AI-powered comprehensive analysis using validated Health-Related Quality of Life metrics
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
712
  """)
713
 
714
  with gr.Row():
715
- # Left Column - Media Input with Dropdown
716
  with gr.Column(scale=1):
717
- gr.Markdown("### πŸ“Έ **Media Input Selection**")
 
 
 
 
 
 
718
 
719
- # Streamlined dropdown with only 2 options
720
  input_type_dropdown = gr.Dropdown(
721
  choices=["Image Analysis", "Video Analysis"],
722
- label="Select Analysis Type",
723
  value="Image Analysis",
724
- interactive=True
 
725
  )
726
 
727
- # Media input components with webcam access for both
728
  image_input = gr.Image(
729
  type="pil",
730
- label="Upload Dog Photo or Use Webcam",
731
  visible=True,
732
- sources=["upload", "webcam"] # Enable webcam for images
 
733
  )
734
 
735
  video_input = gr.Video(
736
- label="Upload Video (10-30 seconds) or Record with Webcam",
737
  visible=False,
738
- sources=["upload", "webcam"] # Enable webcam for videos
 
739
  )
740
 
741
  # Update visibility based on dropdown selection
@@ -745,73 +894,145 @@ with gr.Blocks(title="🐢 VetMetrica HRQOL Dog Health Analyzer", theme=gr.theme
745
  outputs=[image_input, video_input]
746
  )
747
 
748
- gr.Markdown("### βš™οΈ **Optional Information**")
 
 
 
 
 
 
 
 
749
  breed_input = gr.Dropdown(
750
  STANFORD_BREEDS,
751
- label="Dog Breed (Auto-detected if not specified)",
752
  value=None,
753
- allow_custom_value=True
 
754
  )
755
  age_input = gr.Number(
756
- label="Chronological Age (years)",
757
  precision=1,
758
  value=None,
759
  minimum=0,
760
  maximum=25
761
  )
762
 
763
- # Right Column - HRQOL Questionnaire
764
  with gr.Column(scale=1):
765
- gr.Markdown("### πŸ“‹ **VetMetricaΒ© HRQOL Assessment** (Required)")
766
- gr.Markdown("*Complete all sections for accurate healthspan analysis*")
 
 
 
 
 
 
 
 
767
 
768
  hrqol_inputs = []
769
 
770
  for domain_key, domain_data in HRQOL_QUESTIONNAIRE.items():
 
 
 
 
 
 
 
 
 
 
 
 
771
  with gr.Accordion(domain_data["title"], open=True):
772
  for question in domain_data["questions"]:
773
- radio = gr.Radio(
 
774
  choices=question["options"],
775
  label=question["text"],
776
  value=None,
777
- interactive=True
 
778
  )
779
- hrqol_inputs.append(radio)
 
 
 
 
 
780
 
781
- # Analysis Button
782
  analyze_button = gr.Button(
783
- "πŸ”¬ **Analyze Comprehensive Healthspan**",
784
  variant="primary",
785
  size="lg",
786
- scale=1
787
  )
788
 
789
- # Results
790
- gr.Markdown("### πŸ“Š **Comprehensive HRQOL Analysis Report**")
 
 
 
 
 
 
 
 
 
791
  output_report = gr.HTML()
792
 
793
- # Connect analysis function
794
  analyze_button.click(
795
  fn=comprehensive_healthspan_analysis,
796
  inputs=[input_type_dropdown, image_input, video_input, breed_input, age_input] + hrqol_inputs,
797
  outputs=output_report
798
  )
799
 
800
- gr.Markdown("""
801
- ---
802
- ### πŸ”¬ **About VetMetricaΒ© HRQOL Framework**
803
-
804
- This tool integrates the validated **VetMetricaΒ© Health-Related Quality of Life** framework with advanced AI analysis:
805
-
806
- - **🎯 Evidence-Based Assessment**: Uses clinically validated HRQOL domains (Vitality, Comfort, Emotional Wellbeing, Alertness)
807
- - **πŸ€– AI-Powered Analysis**: Combines CLIP vision models with BiomedCLIP for medical insights
808
- - **πŸ“Š Comprehensive Scoring**: Generates composite healthspan scores normalized by breed and age
809
- - **πŸ“ΈπŸŽ₯ Multi-Modal Input**: Both image and video analysis support upload and real-time webcam capture
810
- - **πŸ“ˆ Personalized Insights**: Provides domain-specific recommendations based on assessment results
811
-
812
- **πŸ”¬ Scientific Validation**: Based on peer-reviewed research in veterinary medicine and validated against clinical outcomes.
813
-
814
- **⚠️ Medical Disclaimer**: This tool provides educational insights only. Always consult a qualified veterinarian for professional medical advice.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
815
  """)
816
 
817
  if __name__ == "__main__":
 
10
  CLIPProcessor, CLIPModel,
11
  AutoProcessor
12
  )
13
+ import time
14
 
15
  # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
16
  # CONFIG: set your HF token here or via env var HF_TOKEN
 
115
  "wire-haired fox terrier": 13.5, "yorkshire terrier": 13.3
116
  }
117
 
118
+ # 4. VetMetrica HRQOL Framework with dropdown options
119
  HRQOL_QUESTIONNAIRE = {
120
  "vitality": {
121
+ "title": "πŸ”‹ Vitality & Energy Assessment",
122
+ "description": "Evaluate your dog's energy levels and enthusiasm for activities",
123
  "questions": [
124
  {
125
  "id": "vitality_energy",
 
133
  ]
134
  },
135
  {
136
+ "id": "vitality_play",
137
  "text": "How often does your dog seek out play or interaction?",
138
  "options": [
139
  "Always seeks play/interaction",
 
159
  },
160
  "comfort": {
161
  "title": "😌 Comfort & Pain Management",
162
+ "description": "Assess signs of discomfort, pain, or mobility issues",
163
  "questions": [
164
  {
165
  "id": "comfort_activities",
 
199
  },
200
  "emotional_wellbeing": {
201
  "title": "😊 Emotional Wellbeing",
202
+ "description": "Evaluate mood, anxiety levels, and social engagement",
203
  "questions": [
204
  {
205
  "id": "emotion_mood",
 
239
  },
240
  "alertness": {
241
  "title": "🧠 Alertness & Cognition",
242
+ "description": "Assess cognitive function, awareness, and responsiveness",
243
  "questions": [
244
  {
245
  "id": "alert_awareness",
 
483
  else:
484
  return "Critical (F)"
485
 
486
+ def show_loading():
487
+ """Display loading animation"""
488
+ return """
489
+ <div style="text-align: center; padding: 40px;">
490
+ <div style="display: inline-block; width: 40px; height: 40px; border: 4px solid #f3f3f3; border-top: 4px solid #667eea; border-radius: 50%; animation: spin 1s linear infinite;"></div>
491
+ <style>
492
+ @keyframes spin {
493
+ 0% { transform: rotate(0deg); }
494
+ 100% { transform: rotate(360deg); }
495
+ }
496
+ </style>
497
+ <h3 style="color: #667eea; margin-top: 20px;">πŸ”¬ Analyzing Your Dog's Health...</h3>
498
+ <p style="color: #666;">Please wait while we process the image/video and questionnaire data.</p>
499
+ <div style="background: #f0f0f0; border-radius: 20px; padding: 10px; margin: 20px auto; width: 300px;">
500
+ <div style="background: linear-gradient(90deg, #667eea, #764ba2); height: 6px; border-radius: 10px; width: 0%; animation: progress 3s ease-in-out infinite;"></div>
501
+ </div>
502
+ <style>
503
+ @keyframes progress {
504
+ 0% { width: 0%; }
505
+ 50% { width: 80%; }
506
+ 100% { width: 100%; }
507
+ }
508
+ </style>
509
+ </div>
510
+ """
511
+
512
  def comprehensive_healthspan_analysis(input_type, image_input, video_input, breed, age, *hrqol_responses):
513
  """Combine image/video analysis with HRQOL assessment based on input type"""
514
 
515
+ # Show loading first
516
+ yield show_loading()
517
+
518
+ # Simulate processing time
519
+ time.sleep(2)
520
+
521
  # Determine which input to use based on dropdown selection
522
  if input_type == "Image Analysis":
523
  selected_media = image_input
 
526
  selected_media = video_input
527
  media_type = "video"
528
  else:
529
+ yield "❌ **Error**: Please select an input type."
530
+ return
531
 
532
  if selected_media is None:
533
+ yield f"❌ **Error**: Please provide a {media_type} for analysis."
534
+ return
535
 
536
  # Check if questionnaire is completed
537
  if not hrqol_responses or all(not r for r in hrqol_responses):
538
+ yield "❌ **Error**: Please complete the HRQOL questionnaire before analysis."
539
+ return
540
 
541
  # Build HRQOL responses dictionary
542
  response_keys = []
 
735
  </div>
736
  """
737
 
738
+ yield report_html
739
 
740
  def update_media_input(input_type):
741
  """Update the visibility of media inputs based on dropdown selection"""
 
744
  else: # Video Analysis
745
  return gr.update(visible=False), gr.update(visible=True)
746
 
747
+ # Custom CSS for enhanced styling
748
+ custom_css = """
749
+ /* Enhanced gradient background */
750
+ .gradio-container {
751
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
752
+ min-height: 100vh;
753
+ }
754
+
755
+ /* Card styling */
756
+ .input-card, .questionnaire-card {
757
+ background: white;
758
+ border-radius: 15px;
759
+ padding: 25px;
760
+ box-shadow: 0 8px 25px rgba(0,0,0,0.1);
761
+ margin: 10px;
762
+ border: 1px solid #e0e6ed;
763
+ }
764
+
765
+ /* Header styling */
766
+ .main-header {
767
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
768
+ color: white;
769
+ text-align: center;
770
+ padding: 30px;
771
+ border-radius: 15px;
772
+ margin-bottom: 30px;
773
+ box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
774
+ }
775
+
776
+ /* Button styling */
777
+ .analyze-button {
778
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
779
+ border: none;
780
+ color: white;
781
+ padding: 15px 30px;
782
+ font-size: 16px;
783
+ font-weight: 600;
784
+ border-radius: 25px;
785
+ cursor: pointer;
786
+ transition: all 0.3s ease;
787
+ box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
788
+ }
789
+
790
+ .analyze-button:hover {
791
+ transform: translateY(-2px);
792
+ box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
793
+ }
794
+
795
+ /* Accordion styling */
796
+ .accordion-header {
797
+ background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
798
+ border: 1px solid #dee2e6;
799
+ border-radius: 8px;
800
+ padding: 15px;
801
+ margin: 10px 0;
802
+ cursor: pointer;
803
+ transition: all 0.3s ease;
804
+ }
805
+
806
+ .accordion-header:hover {
807
+ background: linear-gradient(135deg, #e9ecef 0%, #dee2e6 100%);
808
+ transform: translateY(-1px);
809
+ }
810
+
811
+ /* Dropdown styling */
812
+ .gr-dropdown {
813
+ border-radius: 8px;
814
+ border: 2px solid #e0e6ed;
815
+ transition: border-color 0.3s ease;
816
+ }
817
+
818
+ .gr-dropdown:focus {
819
+ border-color: #667eea;
820
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
821
+ }
822
+
823
+ /* Progress animation */
824
+ @keyframes pulse {
825
+ 0% { opacity: 1; }
826
+ 50% { opacity: 0.5; }
827
+ 100% { opacity: 1; }
828
+ }
829
+
830
+ .loading-pulse {
831
+ animation: pulse 2s infinite;
832
+ }
833
+ """
834
+
835
+ # Gradio Interface with Enhanced UI
836
+ with gr.Blocks(
837
+ title="🐢 VetMetrica HRQOL Dog Health Analyzer",
838
+ theme=gr.themes.Soft(),
839
+ css=custom_css
840
+ ) as demo:
841
+
842
+ # Main Header
843
+ gr.HTML("""
844
+ <div class="main-header">
845
+ <h1 style="margin: 0; font-size: 2.5em; text-shadow: 2px 2px 4px rgba(0,0,0,0.3);">
846
+ πŸ• VetMetricaΒ© HRQOL Dog Health & Age Analyzer
847
+ </h1>
848
+ <p style="margin: 15px 0 0 0; font-size: 1.2em; opacity: 0.9;">
849
+ AI-powered comprehensive analysis using validated Health-Related Quality of Life metrics
850
+ </p>
851
+ </div>
852
  """)
853
 
854
  with gr.Row():
855
+ # Left Column - Enhanced Media Input
856
  with gr.Column(scale=1):
857
+ gr.HTML("""
858
+ <div class="input-card">
859
+ <h2 style="color: #667eea; margin: 0 0 20px 0; text-align: center;">
860
+ πŸ“Έ Media Input Selection
861
+ </h2>
862
+ </div>
863
+ """)
864
 
865
+ # Enhanced dropdown with better styling
866
  input_type_dropdown = gr.Dropdown(
867
  choices=["Image Analysis", "Video Analysis"],
868
+ label="πŸ” Select Analysis Type",
869
  value="Image Analysis",
870
+ interactive=True,
871
+ elem_classes=["gr-dropdown"]
872
  )
873
 
874
+ # Media input components with enhanced labels
875
  image_input = gr.Image(
876
  type="pil",
877
+ label="πŸ“· Upload Dog Photo or Use Webcam",
878
  visible=True,
879
+ sources=["upload", "webcam"],
880
+ height=300
881
  )
882
 
883
  video_input = gr.Video(
884
+ label="πŸŽ₯ Upload Video (10-30 seconds) or Record with Webcam",
885
  visible=False,
886
+ sources=["upload", "webcam"],
887
+ height=300
888
  )
889
 
890
  # Update visibility based on dropdown selection
 
894
  outputs=[image_input, video_input]
895
  )
896
 
897
+ # Enhanced optional information section
898
+ gr.HTML("""
899
+ <div style="margin: 20px 0;">
900
+ <h3 style="color: #667eea; text-align: center; margin-bottom: 15px;">
901
+ βš™οΈ Optional Information
902
+ </h3>
903
+ </div>
904
+ """)
905
+
906
  breed_input = gr.Dropdown(
907
  STANFORD_BREEDS,
908
+ label="πŸ• Dog Breed (Auto-detected if not specified)",
909
  value=None,
910
+ allow_custom_value=True,
911
+ elem_classes=["gr-dropdown"]
912
  )
913
  age_input = gr.Number(
914
+ label="πŸ“… Chronological Age (years)",
915
  precision=1,
916
  value=None,
917
  minimum=0,
918
  maximum=25
919
  )
920
 
921
+ # Right Column - Enhanced HRQOL Questionnaire
922
  with gr.Column(scale=1):
923
+ gr.HTML("""
924
+ <div class="questionnaire-card">
925
+ <h2 style="color: #667eea; margin: 0 0 10px 0; text-align: center;">
926
+ πŸ“‹ VetMetricaΒ© HRQOL Assessment
927
+ </h2>
928
+ <p style="text-align: center; color: #666; font-style: italic; margin-bottom: 20px;">
929
+ Complete all sections for accurate healthspan analysis
930
+ </p>
931
+ </div>
932
+ """)
933
 
934
  hrqol_inputs = []
935
 
936
  for domain_key, domain_data in HRQOL_QUESTIONNAIRE.items():
937
+ # Enhanced accordion header
938
+ gr.HTML(f"""
939
+ <div class="accordion-header">
940
+ <h3 style="margin: 0; color: #333;">
941
+ {domain_data['title']}
942
+ </h3>
943
+ <p style="margin: 5px 0 0 0; color: #666; font-size: 0.9em;">
944
+ {domain_data['description']}
945
+ </p>
946
+ </div>
947
+ """)
948
+
949
  with gr.Accordion(domain_data["title"], open=True):
950
  for question in domain_data["questions"]:
951
+ # Enhanced dropdown for each question
952
+ dropdown = gr.Dropdown(
953
  choices=question["options"],
954
  label=question["text"],
955
  value=None,
956
+ interactive=True,
957
+ elem_classes=["gr-dropdown"]
958
  )
959
+ hrqol_inputs.append(dropdown)
960
+
961
+ # Enhanced Analysis Button
962
+ gr.HTML("""
963
+ <div style="text-align: center; margin: 30px 0;">
964
+ """)
965
 
 
966
  analyze_button = gr.Button(
967
+ "πŸ”¬ Analyze Comprehensive Healthspan",
968
  variant="primary",
969
  size="lg",
970
+ elem_classes=["analyze-button"]
971
  )
972
 
973
+ gr.HTML("</div>")
974
+
975
+ # Enhanced Results Section
976
+ gr.HTML("""
977
+ <div style="text-align: center; margin: 30px 0 10px 0;">
978
+ <h2 style="color: #667eea; margin: 0;">
979
+ πŸ“Š Comprehensive HRQOL Analysis Report
980
+ </h2>
981
+ </div>
982
+ """)
983
+
984
  output_report = gr.HTML()
985
 
986
+ # Connect analysis function with loading
987
  analyze_button.click(
988
  fn=comprehensive_healthspan_analysis,
989
  inputs=[input_type_dropdown, image_input, video_input, breed_input, age_input] + hrqol_inputs,
990
  outputs=output_report
991
  )
992
 
993
+ # Enhanced About Section
994
+ gr.HTML("""
995
+ <div style="background: white; border-radius: 15px; padding: 25px; margin: 30px 0; box-shadow: 0 4px 15px rgba(0,0,0,0.1);">
996
+ <h2 style="color: #667eea; text-align: center; margin-bottom: 20px;">
997
+ πŸ”¬ About VetMetricaΒ© HRQOL Framework
998
+ </h2>
999
+
1000
+ <p style="text-align: center; margin-bottom: 25px; color: #666; font-size: 1.1em;">
1001
+ This tool integrates the validated <strong>VetMetricaΒ© Health-Related Quality of Life</strong> framework with advanced AI analysis:
1002
+ </p>
1003
+
1004
+ <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin: 25px 0;">
1005
+ <div style="text-align: center; padding: 20px; background: #f8f9fa; border-radius: 10px;">
1006
+ <div style="font-size: 2em; margin-bottom: 10px;">🎯</div>
1007
+ <h4 style="color: #667eea; margin-bottom: 10px;">Evidence-Based Assessment</h4>
1008
+ <p style="color: #666; font-size: 0.9em;">Uses clinically validated HRQOL domains (Vitality, Comfort, Emotional Wellbeing, Alertness)</p>
1009
+ </div>
1010
+
1011
+ <div style="text-align: center; padding: 20px; background: #f8f9fa; border-radius: 10px;">
1012
+ <div style="font-size: 2em; margin-bottom: 10px;">πŸ€–</div>
1013
+ <h4 style="color: #667eea; margin-bottom: 10px;">AI-Powered Analysis</h4>
1014
+ <p style="color: #666; font-size: 0.9em;">Combines CLIP vision models with BiomedCLIP for medical insights</p>
1015
+ </div>
1016
+
1017
+ <div style="text-align: center; padding: 20px; background: #f8f9fa; border-radius: 10px;">
1018
+ <div style="font-size: 2em; margin-bottom: 10px;">πŸ“Š</div>
1019
+ <h4 style="color: #667eea; margin-bottom: 10px;">Comprehensive Scoring</h4>
1020
+ <p style="color: #666; font-size: 0.9em;">Generates composite healthspan scores normalized by breed and age</p>
1021
+ </div>
1022
+
1023
+ <div style="text-align: center; padding: 20px; background: #f8f9fa; border-radius: 10px;">
1024
+ <div style="font-size: 2em; margin-bottom: 10px;">πŸ“ΈπŸŽ₯</div>
1025
+ <h4 style="color: #667eea; margin-bottom: 10px;">Multi-Modal Input</h4>
1026
+ <p style="color: #666; font-size: 0.9em;">Both image and video analysis support upload and real-time webcam capture</p>
1027
+ </div>
1028
+ </div>
1029
+
1030
+ <div style="background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 8px; padding: 15px; margin: 20px 0;">
1031
+ <p style="margin: 0; color: #856404; text-align: center;">
1032
+ <strong>⚠️ Medical Disclaimer:</strong> This tool provides educational insights only. Always consult a qualified veterinarian for professional medical advice.
1033
+ </p>
1034
+ </div>
1035
+ </div>
1036
  """)
1037
 
1038
  if __name__ == "__main__":