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' , [])
# 顯示時間戳記和搜尋類型
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' )}
"""
# 關鍵修改:確保結果部分始終顯示
if results: # 只有在有結果時才顯示結果區域
html += """
Top 15 Breed Matches:
"""
# 顯示每個推薦結果
for i, result in enumerate (results[: 15 ], 1 ):
breed = result.get( 'breed' , 'Unknown breed' )
score = result.get( 'overall_score' , 0 ) # 改用overall_score
if isinstance (score, ( int , float )): # 確保分數是數字
score = float (score) * 100 # 轉換為百分比
html += f"""
#{i}
{breed.replace('_', ' ')}
{score:.1f}%
"""
html += """
"""
html += "
" # 關閉history-entry div
html += "
" # 關閉history-container div
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 :
"""
儲存搜尋結果到歷史記錄
這個方法負責處理搜尋結果的保存,並確保只保存前15個最相關的推薦結果。
在儲存之前,會處理結果資料確保格式正確且包含所需的所有資訊。
Args:
user_preferences: 使用者偏好設定(僅用於criteria搜尋)
包含所有搜尋條件如居住空間、運動時間等
results: 推薦結果列表
包含所有推薦的狗品種及其評分
search_type: 搜尋類型("criteria" 或"description")
用於標識搜尋方式
description: 用戶輸入的描述(僅用於description搜尋)
用於自然語言搜尋時的描述文本
Returns:
bool: 表示保存是否成功
"""
# 首先確保結果不為空且為列表
if results and isinstance (results, list ):
# 只取前15個結果
processed_results = []
for result in results[: 15 ]: # 限制為前15個結果
# 確保每個結果都包含必要的信息
if isinstance (result, dict ):
processed_result = {
'breed' : result.get( 'breed' , 'Unknown' ),
'overall_score' : result.get( 'overall_score' , result.get( 'final_score' , 0 )),
'rank' : result.get( 'rank' , 0 ),
'base_score' : result.get( 'base_score' , 0 ),
'bonus_score' : result.get( 'bonus_score' , 0 ),
'scores' : result.get( 'scores' , {})
}
processed_results.append(processed_result)
else :
# 如果沒有結果,創建空列表
processed_results = []
# 調用history_manager 的save_history 方法保存處理過的結果
return self.history_manager.save_history(
user_preferences=user_preferences,
results=processed_results, # 使用處理過的結果
search_type= 'criteria'
)
def create_history_component ():
"""只建立實例"""
return SearchHistoryComponent()
def create_history_tab ( history_component: SearchHistoryComponent ):
"""創建歷史紀錄的頁面
Args:
history_component:
"""
with gr.TabItem( "Recommendation Search History" ):
gr.HTML( """