Spaces:
Running
on
Zero
Running
on
Zero
Update app.py
Browse files
app.py
CHANGED
@@ -12,6 +12,9 @@ from data_manager import get_dog_description, UserPreferences, get_breed_recomme
|
|
12 |
from history_manager import UserHistoryManager
|
13 |
from search_history import create_history_tab
|
14 |
from styles import get_css_styles
|
|
|
|
|
|
|
15 |
from urllib.parse import quote
|
16 |
from ultralytics import YOLO
|
17 |
import asyncio
|
@@ -750,269 +753,65 @@ with gr.Blocks(css=get_css_styles()) as iface:
|
|
750 |
</header>
|
751 |
""")
|
752 |
|
753 |
-
|
754 |
-
with gr.
|
755 |
-
#
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
label="Select Second Breed",
|
790 |
-
value="Border_Collie"
|
791 |
-
)
|
792 |
-
|
793 |
-
compare_btn = gr.Button("Compare Breeds")
|
794 |
-
comparison_output = gr.HTML(label="Comparison Results")
|
795 |
-
|
796 |
-
def show_comparison(breed1, breed2):
|
797 |
-
if not breed1 or not breed2:
|
798 |
-
return "Please select two breeds to compare"
|
799 |
-
|
800 |
-
breed1_info = get_dog_description(breed1)
|
801 |
-
breed2_info = get_dog_description(breed2)
|
802 |
-
|
803 |
-
html_output = f"""
|
804 |
-
<div class="dog-info-card">
|
805 |
-
<div class="comparison-grid" style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
|
806 |
-
<div class="breed-info">
|
807 |
-
<h2 class="section-title">
|
808 |
-
<span class="icon">🐕</span> {breed1.replace('_', ' ')}
|
809 |
-
</h2>
|
810 |
-
<div class="info-section">
|
811 |
-
<div class="info-item">
|
812 |
-
<span class="tooltip">
|
813 |
-
<span class="icon">📏</span>
|
814 |
-
<span class="label">Size:</span>
|
815 |
-
<span class="value">{breed1_info['Size']}</span>
|
816 |
-
</span>
|
817 |
-
</div>
|
818 |
-
<div class="info-item">
|
819 |
-
<span class="tooltip">
|
820 |
-
<span class="icon">🏃</span>
|
821 |
-
<span class="label">Exercise Needs:</span>
|
822 |
-
<span class="value">{breed1_info['Exercise Needs']}</span>
|
823 |
-
</span>
|
824 |
-
</div>
|
825 |
-
<div class="info-item">
|
826 |
-
<span class="tooltip">
|
827 |
-
<span class="icon">✂️</span>
|
828 |
-
<span class="label">Grooming:</span>
|
829 |
-
<span class="value">{breed1_info['Grooming Needs']}</span>
|
830 |
-
</span>
|
831 |
-
</div>
|
832 |
-
<div class="info-item">
|
833 |
-
<span class="tooltip">
|
834 |
-
<span class="icon">👨👩👧👦</span>
|
835 |
-
<span class="label">Good with Children:</span>
|
836 |
-
<span class="value">{breed1_info['Good with Children']}</span>
|
837 |
-
</span>
|
838 |
-
</div>
|
839 |
-
</div>
|
840 |
-
</div>
|
841 |
-
|
842 |
-
<div class="breed-info">
|
843 |
-
<h2 class="section-title">
|
844 |
-
<span class="icon">🐕</span> {breed2.replace('_', ' ')}
|
845 |
-
</h2>
|
846 |
-
<div class="info-section">
|
847 |
-
<div class="info-item">
|
848 |
-
<span class="tooltip">
|
849 |
-
<span class="icon">📏</span>
|
850 |
-
<span class="label">Size:</span>
|
851 |
-
<span class="value">{breed2_info['Size']}</span>
|
852 |
-
</span>
|
853 |
-
</div>
|
854 |
-
<div class="info-item">
|
855 |
-
<span class="tooltip">
|
856 |
-
<span class="icon">🏃</span>
|
857 |
-
<span class="label">Exercise Needs:</span>
|
858 |
-
<span class="value">{breed2_info['Exercise Needs']}</span>
|
859 |
-
</span>
|
860 |
-
</div>
|
861 |
-
<div class="info-item">
|
862 |
-
<span class="tooltip">
|
863 |
-
<span class="icon">✂️</span>
|
864 |
-
<span class="label">Grooming:</span>
|
865 |
-
<span class="value">{breed2_info['Grooming Needs']}</span>
|
866 |
-
</span>
|
867 |
-
</div>
|
868 |
-
<div class="info-item">
|
869 |
-
<span class="tooltip">
|
870 |
-
<span class="icon">👨👩👧👦</span>
|
871 |
-
<span class="label">Good with Children:</span>
|
872 |
-
<span class="value">{breed2_info['Good with Children']}</span>
|
873 |
-
</span>
|
874 |
-
</div>
|
875 |
-
</div>
|
876 |
-
</div>
|
877 |
-
</div>
|
878 |
-
</div>
|
879 |
-
"""
|
880 |
-
return html_output
|
881 |
-
|
882 |
-
compare_btn.click(
|
883 |
-
show_comparison,
|
884 |
-
inputs=[breed1_dropdown, breed2_dropdown],
|
885 |
-
outputs=comparison_output
|
886 |
)
|
887 |
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
with gr.Column():
|
895 |
-
living_space = gr.Radio(
|
896 |
-
choices=["apartment", "house_small", "house_large"],
|
897 |
-
label="What type of living space do you have?",
|
898 |
-
info="Choose your current living situation",
|
899 |
-
value="apartment"
|
900 |
-
)
|
901 |
-
|
902 |
-
exercise_time = gr.Slider(
|
903 |
-
minimum=0,
|
904 |
-
maximum=180,
|
905 |
-
value=60,
|
906 |
-
label="Daily exercise time (minutes)",
|
907 |
-
info="Consider walks, play time, and training"
|
908 |
-
)
|
909 |
-
|
910 |
-
grooming_commitment = gr.Radio(
|
911 |
-
choices=["low", "medium", "high"],
|
912 |
-
label="Grooming commitment level",
|
913 |
-
info="Low: monthly, Medium: weekly, High: daily",
|
914 |
-
value="medium"
|
915 |
-
)
|
916 |
-
|
917 |
-
with gr.Column():
|
918 |
-
experience_level = gr.Radio(
|
919 |
-
choices=["beginner", "intermediate", "advanced"],
|
920 |
-
label="Dog ownership experience",
|
921 |
-
info="Be honest - this helps find the right match",
|
922 |
-
value="beginner"
|
923 |
-
)
|
924 |
-
|
925 |
-
has_children = gr.Checkbox(
|
926 |
-
label="Have children at home",
|
927 |
-
info="Helps recommend child-friendly breeds"
|
928 |
-
)
|
929 |
-
|
930 |
-
noise_tolerance = gr.Radio(
|
931 |
-
choices=["low", "medium", "high"],
|
932 |
-
label="Noise tolerance level",
|
933 |
-
info="Some breeds are more vocal than others",
|
934 |
-
value="medium"
|
935 |
-
)
|
936 |
-
|
937 |
-
|
938 |
-
# 設置按鈕的點擊事件
|
939 |
-
get_recommendations_btn = gr.Button("Find My Perfect Match! 🔍", variant="primary")
|
940 |
-
recommendation_output = gr.HTML(label="Breed Recommendations")
|
941 |
-
|
942 |
-
def on_find_match_click(*args):
|
943 |
-
try:
|
944 |
-
user_prefs = UserPreferences(
|
945 |
-
living_space=args[0],
|
946 |
-
exercise_time=args[1],
|
947 |
-
grooming_commitment=args[2],
|
948 |
-
experience_level=args[3],
|
949 |
-
has_children=args[4],
|
950 |
-
noise_tolerance=args[5],
|
951 |
-
space_for_play=True if args[0] != "apartment" else False,
|
952 |
-
other_pets=False,
|
953 |
-
climate="moderate"
|
954 |
-
)
|
955 |
-
|
956 |
-
# 取得推薦結果
|
957 |
-
recommendations = get_breed_recommendations(user_prefs)
|
958 |
-
|
959 |
-
print("Debug - Recommendations received:")
|
960 |
-
for rec in recommendations:
|
961 |
-
print(f"#{rec['rank']} {rec['breed']}: {rec['final_score']:.4f}")
|
962 |
-
|
963 |
-
# 修改這裡:確保保存完整的推薦資訊
|
964 |
-
history_results = [{
|
965 |
-
'breed': rec['breed'],
|
966 |
-
'rank': rec['rank'],
|
967 |
-
'overall_score': rec['final_score'], # 使用 final_score
|
968 |
-
'base_score': rec['base_score'],
|
969 |
-
'bonus_score': rec['bonus_score'],
|
970 |
-
'scores': rec['scores']
|
971 |
-
} for rec in recommendations]
|
972 |
-
|
973 |
-
print("Debug - Preparing to save history:")
|
974 |
-
for res in history_results:
|
975 |
-
print(f"Saving #{res['rank']} {res['breed']}: {res['overall_score']:.4f}")
|
976 |
-
|
977 |
-
|
978 |
-
history_component.save_search(
|
979 |
-
user_preferences={
|
980 |
-
'living_space': args[0],
|
981 |
-
'exercise_time': args[1],
|
982 |
-
'grooming_commitment': args[2],
|
983 |
-
'experience_level': args[3],
|
984 |
-
'has_children': args[4],
|
985 |
-
'noise_tolerance': args[5]
|
986 |
-
},
|
987 |
-
results=history_results
|
988 |
-
)
|
989 |
-
|
990 |
-
return format_recommendation_html(recommendations)
|
991 |
-
|
992 |
-
except Exception as e:
|
993 |
-
print(f"Error in find match: {str(e)}")
|
994 |
-
import traceback
|
995 |
-
print(traceback.format_exc())
|
996 |
-
return "Error getting recommendations"
|
997 |
-
|
998 |
-
get_recommendations_btn.click(
|
999 |
-
fn=on_find_match_click,
|
1000 |
-
inputs=[
|
1001 |
-
living_space,
|
1002 |
-
exercise_time,
|
1003 |
-
grooming_commitment,
|
1004 |
-
experience_level,
|
1005 |
-
has_children,
|
1006 |
-
noise_tolerance
|
1007 |
-
],
|
1008 |
-
outputs=recommendation_output
|
1009 |
)
|
1010 |
|
1011 |
-
|
|
|
1012 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1013 |
|
1014 |
-
|
1015 |
|
1016 |
if __name__ == "__main__":
|
1017 |
-
|
1018 |
-
iface.launch(share=True)
|
|
|
12 |
from history_manager import UserHistoryManager
|
13 |
from search_history import create_history_tab
|
14 |
from styles import get_css_styles
|
15 |
+
from breed_detection import create_detection_tab
|
16 |
+
from breed_comparison import create_comparison_tab
|
17 |
+
from breed_recommendation import create_recommendation_tab
|
18 |
from urllib.parse import quote
|
19 |
from ultralytics import YOLO
|
20 |
import asyncio
|
|
|
753 |
</header>
|
754 |
""")
|
755 |
|
756 |
+
def main():
|
757 |
+
with gr.Blocks(css=get_css_styles()) as iface:
|
758 |
+
# Header HTML
|
759 |
+
gr.HTML("""
|
760 |
+
<header style='text-align: center; padding: 20px; margin-bottom: 20px;'>
|
761 |
+
<h1 style='font-size: 2.5em; margin-bottom: 10px; color: #2D3748;'>
|
762 |
+
🐾 PawMatch AI
|
763 |
+
</h1>
|
764 |
+
<h2 style='font-size: 1.2em; font-weight: normal; color: #4A5568; margin-top: 5px;'>
|
765 |
+
Your Smart Dog Breed Guide
|
766 |
+
</h2>
|
767 |
+
<div style='width: 50px; height: 3px; background: linear-gradient(90deg, #4299e1, #48bb78); margin: 15px auto;'></div>
|
768 |
+
<p style='color: #718096; font-size: 0.9em;'>
|
769 |
+
Powered by AI • Breed Recognition • Smart Matching • Companion Guide
|
770 |
+
</p>
|
771 |
+
</header>
|
772 |
+
""")
|
773 |
+
|
774 |
+
# 先創建歷史組件實例(但不創建標籤頁)
|
775 |
+
history_component = create_history_component()
|
776 |
+
|
777 |
+
with gr.Tabs():
|
778 |
+
# 1. 品種檢測標籤頁
|
779 |
+
example_images = [
|
780 |
+
'Border_Collie.jpg',
|
781 |
+
'Golden_Retriever.jpeg',
|
782 |
+
'Saint_Bernard.jpeg',
|
783 |
+
'Samoyed.jpg',
|
784 |
+
'French_Bulldog.jpeg'
|
785 |
+
]
|
786 |
+
detection_components = create_detection_tab(predict, example_images)
|
787 |
+
|
788 |
+
# 2. 品種比較標籤頁
|
789 |
+
comparison_components = create_comparison_tab(
|
790 |
+
dog_breeds=dog_breeds,
|
791 |
+
get_dog_description=get_dog_description
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
792 |
)
|
793 |
|
794 |
+
# 3. 品種推薦標籤頁
|
795 |
+
recommendation_components = create_recommendation_tab(
|
796 |
+
UserPreferences=UserPreferences,
|
797 |
+
get_breed_recommendations=get_breed_recommendations,
|
798 |
+
format_recommendation_html=format_recommendation_html,
|
799 |
+
history_component=history_component
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
800 |
)
|
801 |
|
802 |
+
# 4. 最後創建歷史記錄標籤頁
|
803 |
+
create_history_tab(history_component)
|
804 |
|
805 |
+
# Footer
|
806 |
+
gr.HTML('''
|
807 |
+
For more details on this project and other work, feel free to visit my GitHub
|
808 |
+
<a href="https://github.com/Eric-Chung-0511/Learning-Record/tree/main/Data%20Science%20Projects/Dog_Breed_Classifier">
|
809 |
+
Dog Breed Classifier
|
810 |
+
</a>
|
811 |
+
''')
|
812 |
|
813 |
+
return iface
|
814 |
|
815 |
if __name__ == "__main__":
|
816 |
+
iface = main()
|
817 |
+
iface.launch(share=True)
|