import gradio as gr
import traceback
from typing import Optional , Dict , List
from history_manager import UserHistoryManager
class SearchHistoryComponent:
def __init__(self):
"""初始化搜尋歷史組件"""
self.history_manager = UserHistoryManager()
def format_history_html(self, history_data: Optional[List[Dict]] = None) -> str:
try:
if history_data is None:
history_data = self.history_manager.get_history()
if not history_data:
return """
"
# 最新的顯示在前面
for entry in reversed(history_data):
timestamp = entry.get('timestamp', 'Unknown time')
search_type = entry.get('search_type', 'criteria')
results = entry.get('results', [])
# 標籤樣式
if search_type == "description":
border_color = "#4299e1"
tag_color = "#4299e1"
tag_bg = "rgba(66, 153, 225, 0.1)"
tag_text = "Description Search"
icon = "🤖"
else:
border_color = "#48bb78"
tag_color = "#48bb78"
tag_bg = "rgba(72, 187, 120, 0.1)"
tag_text = "Criteria Search"
icon = "🔍"
# header
html += f"""
"""
# 參數/描述
if search_type == "criteria":
prefs = entry.get('preferences', {})
html += f"""
Search Parameters:
- Living Space: {prefs.get('living_space', 'N/A')}
- Exercise Time: {prefs.get('exercise_time', 'N/A')} minutes
- Grooming: {prefs.get('grooming_commitment', 'N/A')}
- Size Preference: {prefs.get('size_preference', 'N/A')}
- Experience: {prefs.get('experience_level', 'N/A')}
- Children at Home: {"Yes" if prefs.get('has_children') else "No"}
- Noise Tolerance: {prefs.get('noise_tolerance', 'N/A')}
"""
elif search_type == "description":
description = entry.get('user_description', '')
html += f"""
User Description:
"{description}"
"""
# 結果區
if results:
html += """
Top 15 Breed Matches:
"""
for i, result in enumerate(results[:15], 1):
breed = result.get('breed', 'Unknown breed')
# ★ 分數回退順序:final_score → overall_score → semantic_score
score_val = (
result.get('final_score', None)
if result.get('final_score', None) not in [None, ""]
else result.get('overall_score', None)
)
if score_val in [None, ""]:
score_val = result.get('semantic_score', 0)
try:
score_pct = float(score_val) * 100.0
except Exception:
score_pct = 0.0
html += f"""
#{i}
{breed.replace('_', ' ')}
{score_pct:.1f}%
"""
html += """
"""
html += "
" # 關閉 .history-entry
html += "
" # 關閉 .history-container
return html
except Exception as e:
print(f"Error formatting history: {str(e)}")
print(traceback.format_exc())
return f"""
Error formatting history. Please try refreshing the page.
Error details: {str(e)}
"""
def clear_history(self) -> str:
try:
success = self.history_manager.clear_all_history()
print(f"Clear history result: {success}")
return self.format_history_html()
except Exception as e:
print(f"Error in clear_history: {str(e)}")
print(traceback.format_exc())
return "Error clearing history"
def refresh_history(self) -> str:
try:
return self.format_history_html()
except Exception as e:
print(f"Error in refresh_history: {str(e)}")
return "Error refreshing history"
def save_search(self,
user_preferences: Optional[dict] = None,
results: list = None,
search_type: str = "criteria",
description: str = None) -> bool:
"""參數原樣透傳給 history_manager"""
return self.history_manager.save_history(
user_preferences=user_preferences,
results=results,
search_type=search_type,
description=description,
user_description=description
)
def create_history_component ():
"""只建立實例"""
return SearchHistoryComponent()
def create_history_tab ( history_component: SearchHistoryComponent ):
"""創建歷史紀錄的頁面
Args:
history_component:
"""
with gr.TabItem( "Recommendation Search History" ):
gr.HTML( """