DawnC commited on
Commit
505d2dd
1 Parent(s): 1c0e3dc

Upload 5 files

Browse files
breed_comparison.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+
3
+ def create_comparison_tab(dog_breeds, get_dog_description):
4
+ """创建品种比较标签页
5
+
6
+ Args:
7
+ dog_breeds: 狗品种列表
8
+ get_dog_description: 获取品种描述的函数
9
+ """
10
+ with gr.TabItem("Breed Comparison"):
11
+ gr.HTML("<p style='text-align: center;'>Select two dog breeds to compare their characteristics and care requirements.</p>")
12
+
13
+ with gr.Row():
14
+ breed1_dropdown = gr.Dropdown(
15
+ choices=dog_breeds,
16
+ label="Select First Breed",
17
+ value="Golden_Retriever"
18
+ )
19
+ breed2_dropdown = gr.Dropdown(
20
+ choices=dog_breeds,
21
+ label="Select Second Breed",
22
+ value="Border_Collie"
23
+ )
24
+
25
+ compare_btn = gr.Button("Compare Breeds")
26
+ comparison_output = gr.HTML(label="Comparison Results")
27
+
28
+ def show_comparison(breed1, breed2):
29
+ if not breed1 or not breed2:
30
+ return "Please select two breeds to compare"
31
+
32
+ breed1_info = get_dog_description(breed1)
33
+ breed2_info = get_dog_description(breed2)
34
+
35
+ html_output = f"""
36
+ <div class="dog-info-card">
37
+ <div class="comparison-grid" style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
38
+ <div class="breed-info">
39
+ <h2 class="section-title">
40
+ <span class="icon">🐕</span> {breed1.replace('_', ' ')}
41
+ </h2>
42
+ <div class="info-section">
43
+ <div class="info-item">
44
+ <span class="tooltip">
45
+ <span class="icon">📏</span>
46
+ <span class="label">Size:</span>
47
+ <span class="value">{breed1_info['Size']}</span>
48
+ </span>
49
+ </div>
50
+ <div class="info-item">
51
+ <span class="tooltip">
52
+ <span class="icon">🏃</span>
53
+ <span class="label">Exercise Needs:</span>
54
+ <span class="value">{breed1_info['Exercise Needs']}</span>
55
+ </span>
56
+ </div>
57
+ <div class="info-item">
58
+ <span class="tooltip">
59
+ <span class="icon">✂️</span>
60
+ <span class="label">Grooming:</span>
61
+ <span class="value">{breed1_info['Grooming Needs']}</span>
62
+ </span>
63
+ </div>
64
+ <div class="info-item">
65
+ <span class="tooltip">
66
+ <span class="icon">👨‍👩‍👧‍👦</span>
67
+ <span class="label">Good with Children:</span>
68
+ <span class="value">{breed1_info['Good with Children']}</span>
69
+ </span>
70
+ </div>
71
+ </div>
72
+ </div>
73
+
74
+ <div class="breed-info">
75
+ <h2 class="section-title">
76
+ <span class="icon">🐕</span> {breed2.replace('_', ' ')}
77
+ </h2>
78
+ <div class="info-section">
79
+ <div class="info-item">
80
+ <span class="tooltip">
81
+ <span class="icon">📏</span>
82
+ <span class="label">Size:</span>
83
+ <span class="value">{breed2_info['Size']}</span>
84
+ </span>
85
+ </div>
86
+ <div class="info-item">
87
+ <span class="tooltip">
88
+ <span class="icon">🏃</span>
89
+ <span class="label">Exercise Needs:</span>
90
+ <span class="value">{breed2_info['Exercise Needs']}</span>
91
+ </span>
92
+ </div>
93
+ <div class="info-item">
94
+ <span class="tooltip">
95
+ <span class="icon">✂️</span>
96
+ <span class="label">Grooming:</span>
97
+ <span class="value">{breed2_info['Grooming Needs']}</span>
98
+ </span>
99
+ </div>
100
+ <div class="info-item">
101
+ <span class="tooltip">
102
+ <span class="icon">👨‍👩‍👧‍👦</span>
103
+ <span class="label">Good with Children:</span>
104
+ <span class="value">{breed2_info['Good with Children']}</span>
105
+ </span>
106
+ </div>
107
+ </div>
108
+ </div>
109
+ </div>
110
+ </div>
111
+ """
112
+ return html_output
113
+
114
+ compare_btn.click(
115
+ show_comparison,
116
+ inputs=[breed1_dropdown, breed2_dropdown],
117
+ outputs=comparison_output
118
+ )
119
+
120
+ return {
121
+ 'breed1_dropdown': breed1_dropdown,
122
+ 'breed2_dropdown': breed2_dropdown,
123
+ 'compare_btn': compare_btn,
124
+ 'comparison_output': comparison_output
125
+ }
breed_detection.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from PIL import Image
3
+
4
+ def create_detection_tab(predict_fn, example_images):
5
+ """创建品种识别标签页
6
+
7
+ Args:
8
+ predict_fn: 预测函数
9
+ example_images: 示例图片路径列表
10
+ """
11
+ with gr.TabItem("Breed Detection"):
12
+ gr.HTML("<p style='text-align: center;'>Upload a picture of a dog, and the model will predict its breed and provide detailed information!</p>")
13
+ gr.HTML("<p style='text-align: center; color: #666; font-size: 0.9em;'>Note: The model's predictions may not always be 100% accurate, and it is recommended to use the results as a reference.</p>")
14
+
15
+ with gr.Row():
16
+ input_image = gr.Image(label="Upload a dog image", type="pil")
17
+ output_image = gr.Image(label="Annotated Image")
18
+
19
+ output = gr.HTML(label="Prediction Results")
20
+ initial_state = gr.State()
21
+
22
+ input_image.change(
23
+ predict_fn,
24
+ inputs=input_image,
25
+ outputs=[output, output_image, initial_state]
26
+ )
27
+
28
+ gr.Examples(
29
+ examples=example_images,
30
+ inputs=input_image
31
+ )
32
+
33
+ return {
34
+ 'input_image': input_image,
35
+ 'output_image': output_image,
36
+ 'output': output,
37
+ 'initial_state': initial_state
38
+ }
breed_recommendation.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+
3
+ def create_recommendation_tab(UserPreferences, get_breed_recommendations, format_recommendation_html, history_component):
4
+ """创建品种推荐标签页
5
+
6
+ Args:
7
+ UserPreferences: 用户偏好类
8
+ get_breed_recommendations: 获取品种推荐的函数
9
+ format_recommendation_html: 格式化推荐结果的函数
10
+ history_component: 历史记录组件
11
+ """
12
+ with gr.TabItem("Breed Recommendation"):
13
+ gr.HTML("<p style='text-align: center;'>Tell us about your lifestyle, and we'll recommend the perfect dog breeds for you!</p>")
14
+
15
+ with gr.Row():
16
+ with gr.Column():
17
+ living_space = gr.Radio(
18
+ choices=["apartment", "house_small", "house_large"],
19
+ label="What type of living space do you have?",
20
+ info="Choose your current living situation",
21
+ value="apartment"
22
+ )
23
+
24
+ exercise_time = gr.Slider(
25
+ minimum=0,
26
+ maximum=180,
27
+ value=60,
28
+ label="Daily exercise time (minutes)",
29
+ info="Consider walks, play time, and training"
30
+ )
31
+
32
+ grooming_commitment = gr.Radio(
33
+ choices=["low", "medium", "high"],
34
+ label="Grooming commitment level",
35
+ info="Low: monthly, Medium: weekly, High: daily",
36
+ value="medium"
37
+ )
38
+
39
+ with gr.Column():
40
+ experience_level = gr.Radio(
41
+ choices=["beginner", "intermediate", "advanced"],
42
+ label="Dog ownership experience",
43
+ info="Be honest - this helps find the right match",
44
+ value="beginner"
45
+ )
46
+
47
+ has_children = gr.Checkbox(
48
+ label="Have children at home",
49
+ info="Helps recommend child-friendly breeds"
50
+ )
51
+
52
+ noise_tolerance = gr.Radio(
53
+ choices=["low", "medium", "high"],
54
+ label="Noise tolerance level",
55
+ info="Some breeds are more vocal than others",
56
+ value="medium"
57
+ )
58
+
59
+ get_recommendations_btn = gr.Button("Find My Perfect Match! 🔍", variant="primary")
60
+ recommendation_output = gr.HTML(label="Breed Recommendations")
61
+
62
+ def on_find_match_click(*args):
63
+ try:
64
+ user_prefs = UserPreferences(
65
+ living_space=args[0],
66
+ exercise_time=args[1],
67
+ grooming_commitment=args[2],
68
+ experience_level=args[3],
69
+ has_children=args[4],
70
+ noise_tolerance=args[5],
71
+ space_for_play=True if args[0] != "apartment" else False,
72
+ other_pets=False,
73
+ climate="moderate"
74
+ )
75
+
76
+ recommendations = get_breed_recommendations(user_prefs)
77
+
78
+ history_results = [{
79
+ 'breed': rec['breed'],
80
+ 'rank': rec['rank'],
81
+ 'overall_score': rec['final_score'],
82
+ 'base_score': rec['base_score'],
83
+ 'bonus_score': rec['bonus_score'],
84
+ 'scores': rec['scores']
85
+ } for rec in recommendations]
86
+
87
+ # 保存到历史记录
88
+ history_component.save_search(
89
+ user_preferences={
90
+ 'living_space': args[0],
91
+ 'exercise_time': args[1],
92
+ 'grooming_commitment': args[2],
93
+ 'experience_level': args[3],
94
+ 'has_children': args[4],
95
+ 'noise_tolerance': args[5]
96
+ },
97
+ results=history_results
98
+ )
99
+
100
+ return format_recommendation_html(recommendations)
101
+
102
+ except Exception as e:
103
+ print(f"Error in find match: {str(e)}")
104
+ import traceback
105
+ print(traceback.format_exc())
106
+ return "Error getting recommendations"
107
+
108
+ get_recommendations_btn.click(
109
+ fn=on_find_match_click,
110
+ inputs=[
111
+ living_space,
112
+ exercise_time,
113
+ grooming_commitment,
114
+ experience_level,
115
+ has_children,
116
+ noise_tolerance
117
+ ],
118
+ outputs=recommendation_output
119
+ )
120
+
121
+ return {
122
+ 'living_space': living_space,
123
+ 'exercise_time': exercise_time,
124
+ 'grooming_commitment': grooming_commitment,
125
+ 'experience_level': experience_level,
126
+ 'has_children': has_children,
127
+ 'noise_tolerance': noise_tolerance,
128
+ 'get_recommendations_btn': get_recommendations_btn,
129
+ 'recommendation_output': recommendation_output
130
+ }
history_manager.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from datetime import datetime
3
+ import json
4
+ import os
5
+ import pytz
6
+ import traceback
7
+
8
+ class UserHistoryManager:
9
+ def __init__(self):
10
+ """初始化歷史紀錄管理器"""
11
+ self.history_file = "user_history.json"
12
+ print(f"Initializing UserHistoryManager with file: {os.path.abspath(self.history_file)}")
13
+ self._init_file()
14
+
15
+ def _init_file(self):
16
+ """初始化JSON檔案"""
17
+ try:
18
+ if not os.path.exists(self.history_file):
19
+ print(f"Creating new history file: {self.history_file}")
20
+ with open(self.history_file, 'w', encoding='utf-8') as f:
21
+ json.dump([], f)
22
+ else:
23
+ print(f"History file exists: {self.history_file}")
24
+ # 驗證檔案內容
25
+ with open(self.history_file, 'r', encoding='utf-8') as f:
26
+ data = json.load(f)
27
+ print(f"Current history entries: {len(data)}")
28
+ except Exception as e:
29
+ print(f"Error in _init_file: {str(e)}")
30
+ print(traceback.format_exc())
31
+
32
+
33
+ def save_history(self, user_preferences: dict, results: list) -> bool:
34
+ """儲存搜尋歷史,使用台北時間"""
35
+ try:
36
+ print("\nSaving history:")
37
+ print("Results to save:", results)
38
+
39
+ # 使用 pytz 創建台北時區
40
+ taipei_tz = pytz.timezone('Asia/Taipei')
41
+ # 獲取當前時間並轉換為台北時間
42
+ taipei_time = datetime.now(taipei_tz)
43
+
44
+ history_entry = {
45
+ "timestamp": taipei_time.strftime("%Y-%m-%d %H:%M:%S"),
46
+ "preferences": user_preferences,
47
+ "results": results
48
+ }
49
+
50
+ with open(self.history_file, 'r', encoding='utf-8') as f:
51
+ history = json.load(f)
52
+
53
+ # 添加新紀錄
54
+ history.append(history_entry)
55
+
56
+ # 限制保存最近的20筆記錄
57
+ if len(history) > 20:
58
+ history = history[-20:]
59
+
60
+ with open(self.history_file, 'w', encoding='utf-8') as f:
61
+ json.dump(history, f, ensure_ascii=False, indent=2)
62
+
63
+ return True
64
+ except Exception as e:
65
+ print(f"Error saving history: {str(e)}")
66
+ return False
67
+
68
+ def get_history(self) -> list:
69
+ """獲取搜尋歷史"""
70
+ try:
71
+ print("Attempting to read history") # Debug
72
+ with open(self.history_file, 'r', encoding='utf-8') as f:
73
+ data = json.load(f)
74
+ print(f"Read {len(data)} history entries") # Debug
75
+ return data if isinstance(data, list) else []
76
+ except Exception as e:
77
+ print(f"Error reading history: {str(e)}")
78
+ print(traceback.format_exc())
79
+ return []
80
+
81
+ def clear_all_history(self) -> bool:
82
+ """清除所有歷史紀錄"""
83
+ try:
84
+ print("Attempting to clear all history") # Debug
85
+ with open(self.history_file, 'w', encoding='utf-8') as f:
86
+ json.dump([], f)
87
+ print("History cleared successfully") # Debug
88
+ return True
89
+ except Exception as e:
90
+ print(f"Error clearing history: {str(e)}")
91
+ print(traceback.format_exc())
92
+ return False
search_history.py ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import traceback
3
+ from typing import Optional, Dict, List
4
+ from history_manager import UserHistoryManager
5
+
6
+ class SearchHistoryComponent:
7
+ def __init__(self):
8
+ """初始化搜索歷史組件"""
9
+ self.history_manager = UserHistoryManager()
10
+
11
+ def format_history_html(self, history_data: Optional[List[Dict]] = None) -> str:
12
+ """將歷史記錄格式化為HTML"""
13
+ try:
14
+ if history_data is None:
15
+ history_data = self.history_manager.get_history()
16
+
17
+ if not history_data:
18
+ return """
19
+ <div style='text-align: center; padding: 20px; color: #666;'>
20
+ No search history yet. Try making some breed recommendations!
21
+ </div>
22
+ """
23
+
24
+ html = "<div class='history-container'>"
25
+
26
+ for entry in reversed(history_data):
27
+ timestamp = entry.get('timestamp', 'Unknown time')
28
+ prefs = entry.get('preferences', {})
29
+ results = entry.get('results', [])
30
+
31
+ html += f"""
32
+ <div class="history-entry">
33
+ <div class="history-header">
34
+ <span class="timestamp">🕒 {timestamp}</span>
35
+ </div>
36
+
37
+ <div class="params-list">
38
+ <h4>Search Parameters:</h4>
39
+ <ul>
40
+ <li><span class="param-label">Living Space:</span> {prefs.get('living_space', 'N/A')}</li>
41
+ <li><span class="param-label">Exercise Time:</span> {prefs.get('exercise_time', 'N/A')} minutes</li>
42
+ <li><span class="param-label">Grooming:</span> {prefs.get('grooming_commitment', 'N/A')}</li>
43
+ <li><span class="param-label">Experience:</span> {prefs.get('experience_level', 'N/A')}</li>
44
+ <li><span class="param-label">Children at Home:</span> {"Yes" if prefs.get('has_children') else "No"}</li>
45
+ <li><span class="param-label">Noise Tolerance:</span> {prefs.get('noise_tolerance', 'N/A')}</li>
46
+ </ul>
47
+ </div>
48
+
49
+ <div class="results-list">
50
+ <h4>Top 5 Breed Matches:</h4>
51
+ <div class="breed-list">
52
+ """
53
+
54
+ if results:
55
+ for i, result in enumerate(results[:5], 1):
56
+ breed_name = result.get('breed', 'Unknown breed').replace('_', ' ')
57
+ score = result.get('overall_score', result.get('final_score', 0))
58
+ html += f"""
59
+ <div class="breed-item">
60
+ <div class="breed-info">
61
+ <span class="breed-rank">#{i}</span>
62
+ <span class="breed-name">{breed_name}</span>
63
+ <span class="breed-score">{score*100:.1f}%</span>
64
+ </div>
65
+ </div>
66
+ """
67
+
68
+ html += """
69
+ </div>
70
+ </div>
71
+ </div>
72
+ """
73
+
74
+ html += "</div>"
75
+ return html
76
+
77
+ except Exception as e:
78
+ print(f"Error formatting history: {str(e)}")
79
+ print(traceback.format_exc())
80
+ return f"""
81
+ <div style='text-align: center; padding: 20px; color: #dc2626;'>
82
+ Error formatting history. Please try refreshing the page.
83
+ <br>Error details: {str(e)}
84
+ </div>
85
+ """
86
+
87
+ def clear_history(self) -> str:
88
+ """清除所有搜尋歷史"""
89
+ try:
90
+ success = self.history_manager.clear_all_history()
91
+ print(f"Clear history result: {success}")
92
+ return self.format_history_html()
93
+ except Exception as e:
94
+ print(f"Error in clear_history: {str(e)}")
95
+ print(traceback.format_exc())
96
+ return "Error clearing history"
97
+
98
+ def refresh_history(self) -> str:
99
+ """刷新歷史記錄顯示"""
100
+ try:
101
+ return self.format_history_html()
102
+ except Exception as e:
103
+ print(f"Error in refresh_history: {str(e)}")
104
+ return "Error refreshing history"
105
+
106
+ def save_search(self, user_preferences: dict, results: list) -> bool:
107
+ """保存搜索結果"""
108
+ return self.history_manager.save_history(user_preferences, results)
109
+
110
+ def create_history_component():
111
+ """只创建历史组件实例,不创建UI"""
112
+ return SearchHistoryComponent()
113
+
114
+ def create_history_tab(history_component: SearchHistoryComponent):
115
+ """创建历史记录标签页
116
+
117
+ Args:
118
+ history_component: 已创建的历史组件实例
119
+ """
120
+ with gr.TabItem("Recommendation Search History"):
121
+ gr.HTML("""
122
+ <div style='text-align: center; padding: 20px;'>
123
+ <h3 style='color: #2D3748; margin-bottom: 10px;'>Search History</h3>
124
+ <p style='color: #4A5568;'>View your previous breed recommendations and search preferences</p>
125
+ </div>
126
+ """)
127
+
128
+ with gr.Row():
129
+ with gr.Column(scale=4):
130
+ history_display = gr.HTML()
131
+
132
+ with gr.Row():
133
+ with gr.Column(scale=1):
134
+ clear_history_btn = gr.Button(
135
+ "🗑️ Clear History",
136
+ variant="secondary",
137
+ size="sm"
138
+ )
139
+ with gr.Column(scale=1):
140
+ refresh_btn = gr.Button(
141
+ "🔄 Refresh",
142
+ variant="secondary",
143
+ size="sm"
144
+ )
145
+
146
+ history_display.value = history_component.format_history_html()
147
+
148
+ clear_history_btn.click(
149
+ fn=history_component.clear_history,
150
+ outputs=[history_display],
151
+ api_name="clear_history"
152
+ )
153
+
154
+ refresh_btn.click(
155
+ fn=history_component.refresh_history,
156
+ outputs=[history_display],
157
+ api_name="refresh_history"
158
+ )