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)
|