import streamlit as st import json import os from datetime import datetime from calendar_rag import ( create_default_config, AcademicCalendarRAG, PipelineConfig ) # Custom CSS for enhanced styling def load_custom_css(): st.markdown(""" """, unsafe_allow_html=True) # Page config st.set_page_config( page_title="Academic Calendar Assistant", page_icon="📅", layout="wide", initial_sidebar_state="collapsed" ) # Load custom CSS load_custom_css() # Initialize session state if 'pipeline' not in st.session_state: st.session_state.pipeline = None if 'chat_history' not in st.session_state: st.session_state.chat_history = [] if 'feedback_data' not in st.session_state: st.session_state.feedback_data = [] def initialize_pipeline(): """Initialize RAG pipeline with configurations""" try: openai_api_key = os.getenv('OPENAI_API_KEY') or st.secrets['OPENAI_API_KEY'] config = create_default_config(openai_api_key) config.localization.enable_thai_normalization = True config.retriever.top_k = 5 config.model.temperature = 0.3 pipeline = AcademicCalendarRAG(config) with open("calendar.json", "r", encoding="utf-8") as f: calendar_data = json.load(f) pipeline.load_data(calendar_data) return pipeline except Exception as e: st.error(f"Error initializing pipeline: {str(e)}") return None def save_feedback_to_json(): """Save feedback data to a JSON file""" try: # Get current directory current_dir = os.path.dirname(os.path.abspath(__file__)) file_path = os.path.join(current_dir, 'feedback_data.json') # Log the attempt st.write(f"Attempting to save feedback to: {file_path}") # Create directory if it doesn't exist os.makedirs(current_dir, exist_ok=True) # Save the file with open(file_path, "w", encoding="utf-8") as f: json.dump( st.session_state.feedback_data, f, ensure_ascii=False, indent=2 ) # Verify file was created if os.path.exists(file_path): st.write(f"✅ Feedback saved successfully to {file_path}") st.write(f"Current feedback data: {st.session_state.feedback_data}") return True else: st.error("File was not created despite no errors") return False except Exception as e: st.error(f"Error saving feedback: {str(e)}") st.write(f"Current directory: {current_dir}") st.write(f"Current feedback data: {st.session_state.feedback_data}") return False def add_feedback(query: str, answer: str, is_correct: bool): """Add feedback entry to session state and save to JSON""" feedback_entry = { "timestamp": datetime.now().isoformat(), "query": query, "answer": answer, "is_correct": is_correct } st.session_state.feedback_data.append(feedback_entry) save_feedback_to_json() def evaluate_answer(query: str, answer: str): """Display evaluation buttons for the answer""" col1, col2, col3 = st.columns([1, 1, 4]) with col1: if st.button("✅ ถูกต้อง", type="primary", key=f"correct_{len(st.session_state.chat_history)}"): add_feedback(query, answer, True) st.success("บันทึกผลการประเมินแล้ว") return True with col2: if st.button("❌ ไม่ถูกต้อง", type="secondary", key=f"incorrect_{len(st.session_state.chat_history)}"): add_feedback(query, answer, False) st.error("บันทึกผลการประเมินแล้ว") return True return False def display_chat_history(): """Display chat history with enhanced styling""" for i, (role, message) in enumerate(st.session_state.chat_history): if role == "user": st.markdown(f"""
🧑 คำถาม:
{message}
""", unsafe_allow_html=True) else: st.markdown(f"""
🤖 คำตอบ:
{message}
""", unsafe_allow_html=True) # Add evaluation buttons after each assistant response if i == len(st.session_state.chat_history) - 1: # Only for the latest answer user_query = st.session_state.chat_history[i-1][1] # Get the corresponding user query evaluate_answer(user_query, message) def add_to_history(role: str, message: str): """Add message to chat history""" st.session_state.chat_history.append((role, message)) def main(): # Header with animation st.markdown("""

🎓 ระบบค้นหาข้อมูลปฏิทินการศึกษา

""", unsafe_allow_html=True) # Initialize pipeline if needed if st.session_state.pipeline is None: with st.spinner("กำลังเริ่มต้นระบบ..."): st.session_state.pipeline = initialize_pipeline() # Create two columns with better proportions chat_col, info_col = st.columns([7, 3]) with chat_col: # Add a subtle container for the chat interface with st.container(): # Display chat history display_chat_history() # Main query interface with enhanced styling st.markdown("
", unsafe_allow_html=True) query = st.text_input( "โปรดระบุคำถามเกี่ยวกับปฏิทินการศึกษา:", placeholder="เช่น: วันสุดท้ายของการสอบปากเปล่าในภาคเรียนที่ 1/2567 คือวันที่เท่าไร?", key="query_input" ) # Button layout with enhanced styling col1, col2, col3 = st.columns([1, 1, 4]) with col1: send_query = st.button("📤 ส่งคำถาม", type="primary", use_container_width=True) with col2: if st.button("🗑️ ล้างประวัติ", type="secondary", use_container_width=True): st.session_state.chat_history = [] st.rerun() # Process query if send_query and query: if st.session_state.pipeline is None: st.error("❌ ไม่สามารถเชื่อมต่อกับระบบได้ กรุณาลองใหม่อีกครั้ง") return add_to_history("user", query) try: with st.spinner("🔍 กำลังค้นหาคำตอบ..."): result = st.session_state.pipeline.process_query(query) add_to_history("assistant", result["answer"]) # Enhanced expandable sections with st.expander("📚 แสดงข้อมูลอ้างอิง", expanded=False): for i, doc in enumerate(result["documents"], 1): st.markdown(f"""
เอกสารที่ {i}:
{doc.content}
""", unsafe_allow_html=True) with st.expander("🔍 รายละเอียดการวิเคราะห์คำถาม", expanded=False): st.json(result["query_info"]) st.rerun() except Exception as e: st.error(f"❌ เกิดข้อผิดพลาด: {str(e)}") elif send_query and not query: st.warning("⚠️ กรุณาระบุคำถาม") with info_col: # Enhanced system information section st.markdown("""

ℹ️ เกี่ยวกับระบบ

ระบบนี้ใช้เทคโนโลยี RAG (Retrieval-Augmented Generation) ในการค้นหาและตอบคำถามเกี่ยวกับปฏิทินการศึกษา

สามารถสอบถามข้อมูลเกี่ยวกับ:

""", unsafe_allow_html=True) # Enhanced system status section st.markdown("""

🔄 สถานะระบบ

⏰ เวลาปัจจุบัน:
{}

📡 สถานะระบบ:
{} {}

""".format( datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "status-online" if st.session_state.pipeline else "status-offline", "🟢" if st.session_state.pipeline else "🔴", "พร้อมใช้งาน" if st.session_state.pipeline else "ไม่พร้อมใช้งาน" ), unsafe_allow_html=True) if __name__ == "__main__": main()