JirasakJo commited on
Commit
9467d9b
·
verified ·
1 Parent(s): be01a92

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +292 -49
app.py CHANGED
@@ -1,30 +1,97 @@
1
  import streamlit as st
2
  import json
3
  import os
 
4
  from datetime import datetime, timedelta
 
5
  from huggingface_hub import HfApi
6
  from pathlib import Path
7
  from calendar_rag import (
8
  create_default_config,
9
  AcademicCalendarRAG,
 
10
  )
11
 
12
  # Custom CSS for enhanced styling
13
  def load_custom_css():
14
  st.markdown("""
15
  <style>
16
- /* General styling */
17
- body { font-family: "Arial", sans-serif; line-height: 1.6; }
18
- .main { padding: 2rem; }
19
- h1 { text-align: center; border-bottom: 3px solid #1E3A8A; padding-bottom: 1rem; }
20
- .chat-message { padding: 1rem; margin: 1rem 0; border-radius: 8px; }
21
- .user-message { background-color: #F3F4F6; }
22
- .assistant-message { background-color: #EFF6FF; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  </style>
24
  """, unsafe_allow_html=True)
25
 
26
  def initialize_pipeline():
27
- """Initialize the RAG pipeline."""
28
  try:
29
  openai_api_key = os.getenv('OPENAI_API_KEY') or st.secrets['OPENAI_API_KEY']
30
  config = create_default_config(openai_api_key)
@@ -32,26 +99,54 @@ def initialize_pipeline():
32
  config.retriever.top_k = 5
33
  config.model.temperature = 0.3
34
  pipeline = AcademicCalendarRAG(config)
 
35
  with open("calendar.json", "r", encoding="utf-8") as f:
36
  calendar_data = json.load(f)
37
  pipeline.load_data(calendar_data)
 
38
  return pipeline
 
39
  except Exception as e:
40
  st.error(f"Error initializing pipeline: {str(e)}")
41
  return None
42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  def save_qa_history(history_entry):
44
- """Save QA history to file and upload to Hugging Face."""
45
  try:
 
46
  history_file = Path("qa_history.json")
 
 
47
  if history_file.exists():
48
  with open(history_file, "r", encoding="utf-8") as f:
49
- history_data = json.load(f) or []
 
 
 
50
  else:
51
  history_data = []
 
 
52
  history_data.append(history_entry)
53
- with open(history_file, "w", encoding="utf-8") as f:
 
 
54
  json.dump(history_data, f, ensure_ascii=False, indent=2)
 
 
55
  hf_token = os.getenv('HF_TOKEN') or st.secrets['HF_TOKEN']
56
  api = HfApi(token=hf_token)
57
  api.upload_file(
@@ -63,75 +158,223 @@ def save_qa_history(history_entry):
63
  except Exception as e:
64
  st.error(f"Error saving QA history: {str(e)}")
65
 
66
- def add_to_qa_history(query, answer):
67
- """Add a QA pair to history and save it."""
68
  history_entry = {
69
  "timestamp": (datetime.now() + timedelta(hours=7)).isoformat(),
70
  "query": query,
71
- "answer": answer,
72
  }
 
73
  save_qa_history(history_entry)
 
74
 
75
- def add_to_history(role, message):
76
- """Update the chat history dynamically."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  st.session_state.chat_history.append((role, message))
78
-
 
 
 
 
 
 
79
  def display_chat_history():
80
- """Display chat history dynamically."""
81
- for role, message in st.session_state.chat_history:
82
  if role == "user":
83
  st.markdown(f"""
84
  <div class="chat-message user-message">
85
- <strong>🧑 คำถาม:</strong><br>{message}
 
86
  </div>
87
  """, unsafe_allow_html=True)
88
- elif role == "assistant":
89
  st.markdown(f"""
90
  <div class="chat-message assistant-message">
91
- <strong>🤖 คำตอบ:</strong><br>{message}
 
92
  </div>
93
  """, unsafe_allow_html=True)
94
 
95
  def main():
96
- # Page setup
97
  st.set_page_config(
98
  page_title="Academic Calendar Assistant",
99
  page_icon="📅",
100
  layout="wide",
 
101
  )
 
 
102
  load_custom_css()
103
 
104
  # Initialize session state
105
  if 'pipeline' not in st.session_state:
106
- st.session_state.pipeline = initialize_pipeline()
 
107
  if 'chat_history' not in st.session_state:
108
  st.session_state.chat_history = []
109
 
110
- st.title("🎓 ระบบค้นหาข้อมูลปฏิทินการศึกษา")
111
-
112
- # Chat interface
113
- query = st.text_input("โปรดระบุคำถามเกี่ยวกับปฏิทินการศึกษา:", "")
114
- send_query = st.button("📤 ส่งคำถาม")
115
- clear_history = st.button("🗑️ ล้างประวัติ")
116
-
117
- # Handle sending query
118
- if send_query and query:
119
- add_to_history("user", query)
120
- try:
121
- result = st.session_state.pipeline.process_query(query)
122
- answer = result["answer"]
123
- add_to_history("assistant", answer)
124
- add_to_qa_history(query, answer)
125
- except Exception as e:
126
- st.error(f"Error processing query: {str(e)}")
127
-
128
- # Handle clearing history
129
- if clear_history:
130
- st.session_state.chat_history = []
131
- st.success("ล้างประวัติสำเร็จ!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
 
133
- # Display chat history
134
- display_chat_history()
 
 
 
135
 
136
  if __name__ == "__main__":
137
- main()
 
1
  import streamlit as st
2
  import json
3
  import os
4
+ import time
5
  from datetime import datetime, timedelta
6
+ import subprocess
7
  from huggingface_hub import HfApi
8
  from pathlib import Path
9
  from calendar_rag import (
10
  create_default_config,
11
  AcademicCalendarRAG,
12
+ PipelineConfig
13
  )
14
 
15
  # Custom CSS for enhanced styling
16
  def load_custom_css():
17
  st.markdown("""
18
  <style>
19
+ /* General body styling */
20
+ body {
21
+ font-family: "Arial", sans-serif !important;
22
+ color: #000000 !important;
23
+ background-color: white !important;
24
+ line-height: 1.7 !important;
25
+ }
26
+
27
+ /* Main container styling */
28
+ .main {
29
+ padding: 2rem;
30
+ color: #000000;
31
+ background-color: white;
32
+ }
33
+
34
+ /* Headers styling */
35
+ h1 {
36
+ color: #000000;
37
+ font-size: 2.8rem !important;
38
+ font-weight: 700 !important;
39
+ margin-bottom: 1.5rem !important;
40
+ text-align: center;
41
+ padding: 1rem 0;
42
+ border-bottom: 3px solid #1E3A8A;
43
+ }
44
+
45
+ h3, h4 {
46
+ color: #000000;
47
+ font-weight: 600 !important;
48
+ font-size: 1.6rem !important;
49
+ margin-top: 1.5rem !important;
50
+ }
51
+
52
+ /* Chat message styling */
53
+ .chat-message {
54
+ padding: 1.5rem;
55
+ border-radius: 10px;
56
+ margin: 1rem 0;
57
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
58
+ font-size: 1.1rem !important;
59
+ line-height: 1.6 !important;
60
+ font-family: "Arial", sans-serif !important;
61
+ color: #000000 !important;
62
+ }
63
+
64
+ .user-message {
65
+ background-color: #F3F4F6 !important;
66
+ }
67
+
68
+ .assistant-message {
69
+ background-color: #EFF6FF !important;
70
+ }
71
+
72
+ /* Status indicators */
73
+ .status-indicator {
74
+ padding: 0.5rem 1rem;
75
+ border-radius: 6px;
76
+ font-weight: 500;
77
+ font-size: 1.2rem;
78
+ color: #000000;
79
+ }
80
+
81
+ .status-online {
82
+ background-color: #DEF7EC;
83
+ color: #03543F;
84
+ }
85
+
86
+ .status-offline {
87
+ background-color: #FDE8E8;
88
+ color: rgb(255, 255, 255);
89
+ }
90
  </style>
91
  """, unsafe_allow_html=True)
92
 
93
  def initialize_pipeline():
94
+ """Initialize RAG pipeline with configurations"""
95
  try:
96
  openai_api_key = os.getenv('OPENAI_API_KEY') or st.secrets['OPENAI_API_KEY']
97
  config = create_default_config(openai_api_key)
 
99
  config.retriever.top_k = 5
100
  config.model.temperature = 0.3
101
  pipeline = AcademicCalendarRAG(config)
102
+
103
  with open("calendar.json", "r", encoding="utf-8") as f:
104
  calendar_data = json.load(f)
105
  pipeline.load_data(calendar_data)
106
+
107
  return pipeline
108
+
109
  except Exception as e:
110
  st.error(f"Error initializing pipeline: {str(e)}")
111
  return None
112
 
113
+ def load_qa_history():
114
+ """Load QA history from local JSON file"""
115
+ try:
116
+ history_file = Path("qa_history.json")
117
+ if history_file.exists():
118
+ with open(history_file, "r", encoding="utf-8") as f:
119
+ return json.load(f)
120
+ return []
121
+ except Exception as e:
122
+ st.error(f"Error loading QA history: {str(e)}")
123
+ return []
124
+
125
+
126
  def save_qa_history(history_entry):
127
+ """Save QA history entry to local JSON file and push to Hugging Face"""
128
  try:
129
+
130
  history_file = Path("qa_history.json")
131
+
132
+ # Initialize or load existing history
133
  if history_file.exists():
134
  with open(history_file, "r", encoding="utf-8") as f:
135
+ try:
136
+ history_data = json.load(f)
137
+ except json.JSONDecodeError:
138
+ history_data = []
139
  else:
140
  history_data = []
141
+
142
+ # Append new entry
143
  history_data.append(history_entry)
144
+
145
+ # Save updated history
146
+ with open("qa_history.json", "w", encoding="utf-8") as f:
147
  json.dump(history_data, f, ensure_ascii=False, indent=2)
148
+
149
+ # Push to Hugging Face
150
  hf_token = os.getenv('HF_TOKEN') or st.secrets['HF_TOKEN']
151
  api = HfApi(token=hf_token)
152
  api.upload_file(
 
158
  except Exception as e:
159
  st.error(f"Error saving QA history: {str(e)}")
160
 
161
+ def add_to_qa_history(query: str, answer: str):
162
+ """Add new QA pair to history"""
163
  history_entry = {
164
  "timestamp": (datetime.now() + timedelta(hours=7)).isoformat(),
165
  "query": query,
166
+ "answer": answer
167
  }
168
+
169
  save_qa_history(history_entry)
170
+ return history_entry
171
 
172
+ def clear_qa_history():
173
+ """Clear QA history file"""
174
+ try:
175
+ # Write empty list to history file
176
+ with open("qa_history.json", "w", encoding="utf-8") as f:
177
+ json.dump([], f, ensure_ascii=False, indent=2)
178
+
179
+ # Push to Hugging Face
180
+ hf_token = os.getenv('HF_TOKEN') or st.secrets['HF_TOKEN']
181
+ api = HfApi(token=hf_token)
182
+ api.upload_file(
183
+ path_or_fileobj="qa_history.json",
184
+ path_in_repo="qa_history.json",
185
+ repo_id="JirasakJo/Questions_Graduate_Studies_Calendar_2024",
186
+ repo_type="space"
187
+ )
188
+ except Exception as e:
189
+ st.error(f"Error clearing QA history: {str(e)}")
190
+
191
+ def add_to_history(role: str, message: str):
192
+ """Add message to chat history and save if it's a complete QA pair"""
193
  st.session_state.chat_history.append((role, message))
194
+
195
+ # If this is an assistant response, save the QA pair
196
+ if role == "assistant" and len(st.session_state.chat_history) >= 2:
197
+ # Get the corresponding user query (previous message)
198
+ user_query = st.session_state.chat_history[-2][1]
199
+ add_to_qa_history(user_query, message)
200
+
201
  def display_chat_history():
202
+ """Display chat history with enhanced styling"""
203
+ for i, (role, message) in enumerate(st.session_state.chat_history):
204
  if role == "user":
205
  st.markdown(f"""
206
  <div class="chat-message user-message">
207
+ <strong>🧑 คำถาม:</strong><br>
208
+ {message}
209
  </div>
210
  """, unsafe_allow_html=True)
211
+ else:
212
  st.markdown(f"""
213
  <div class="chat-message assistant-message">
214
+ <strong>🤖 คำตอบ:</strong><br>
215
+ {message}
216
  </div>
217
  """, unsafe_allow_html=True)
218
 
219
  def main():
220
+ # Page config
221
  st.set_page_config(
222
  page_title="Academic Calendar Assistant",
223
  page_icon="📅",
224
  layout="wide",
225
+ initial_sidebar_state="collapsed"
226
  )
227
+
228
+ # Load custom CSS
229
  load_custom_css()
230
 
231
  # Initialize session state
232
  if 'pipeline' not in st.session_state:
233
+ st.session_state.pipeline = None
234
+
235
  if 'chat_history' not in st.session_state:
236
  st.session_state.chat_history = []
237
 
238
+ # Load QA history at startup
239
+ if 'qa_history_loaded' not in st.session_state:
240
+ st.session_state.qa_history_loaded = True
241
+ load_qa_history()
242
+
243
+ # Header
244
+ st.markdown("""
245
+ <div style="text-align: center; padding: 2rem 0;">
246
+ <h1>🎓 ระบบค้นหาข้อมูลปฏิทินการศึกษา</h1>
247
+ </div>
248
+ """, unsafe_allow_html=True)
249
+
250
+ # Initialize pipeline
251
+ if st.session_state.pipeline is None:
252
+ with st.spinner("กำลังเริ่มต้นระบบ..."):
253
+ st.session_state.pipeline = initialize_pipeline()
254
+
255
+ chat_col, info_col = st.columns([7, 3])
256
+
257
+ with chat_col:
258
+ with st.container():
259
+ # Display chat history
260
+ display_chat_history()
261
+
262
+ # Query input section
263
+ st.markdown("""
264
+ <label for="query_input" style="font-size: 1.2rem; font-weight: bold; color: black;">
265
+ <span style="color: white; background-color: yellow; padding: 0 0.2rem;">โปรดระบุคำถามเกี่ยวกับ ปฏิทินการศึกษา:</span>
266
+ </label>
267
+ """, unsafe_allow_html=True)
268
+
269
+ query = st.text_input(
270
+ "",
271
+ placeholder="เช่น: วันสุดท้ายของการสอบปากเปล่าในภาคเรียนที่ 1/2567 คือวันที่เท่าไร?",
272
+ key="query_input"
273
+ )
274
+
275
+ # Button layout
276
+ col1, col2, col3 = st.columns([1, 1, 4])
277
+
278
+ with col1:
279
+ send_query = st.button(
280
+ "📤 ส่งคำถาม",
281
+ type="primary",
282
+ use_container_width=True,
283
+ key="send_query_button"
284
+ )
285
+
286
+ with col2:
287
+ clear_history = st.button(
288
+ "🗑️ ล้างประวัติ",
289
+ type="secondary",
290
+ use_container_width=True,
291
+ key="clear_history_button"
292
+ )
293
+
294
+ # Process query
295
+ if send_query and query:
296
+ if st.session_state.pipeline is None:
297
+ st.error("❌ ไม่สามารถเชื่อมต่อกับระบบได้ กรุณาลองใหม่อีกครั้ง")
298
+ return
299
+
300
+ add_to_history("user", query)
301
+
302
+ try:
303
+ with st.spinner("🔍 กำลังค้นหาคำตอบ..."):
304
+ result = st.session_state.pipeline.process_query(query)
305
+ add_to_history("assistant", result["answer"])
306
+
307
+ with st.expander("📚 แสดงข้อมูลอ้างอิง", expanded=False):
308
+ for i, doc in enumerate(result["documents"], 1):
309
+ st.markdown(f"""
310
+ <div style="padding: 1rem; background-color: #F9FAFB; border-radius: 8px; margin: 0.5rem 0;">
311
+ <strong>เอกสารที่ {i}:</strong><br>
312
+ {doc.content}
313
+ </div>
314
+ """, unsafe_allow_html=True)
315
+
316
+ with st.expander("🔍 รายละเอียดการวิเคราะห์คำถาม", expanded=False):
317
+ st.json(result["query_info"])
318
+
319
+ st.rerun()
320
+
321
+ except Exception as e:
322
+ st.error(f"❌ เกิดข้อผิดพลาด: {str(e)}")
323
+
324
+ elif send_query and not query:
325
+ st.warning("⚠️ กรุณาระบุคำถาม")
326
+
327
+ # Clear history
328
+ if clear_history:
329
+ st.session_state.chat_history = []
330
+ save_qa_history([]) # Clear saved history
331
+ st.rerun()
332
+
333
+ with info_col:
334
+ # System information
335
+ st.markdown("""
336
+ <div style="background-color: #F9FAFB; padding: 1.5rem; border-radius: 12px; margin-bottom: 2rem;">
337
+ <h3 style="color: #1E3A8A;">ℹ️ เกี่ยวกับระบบ</h3>
338
+ <p style="color: #ff0015;">
339
+ ระบบนี้ใช้เทคโนโลยี <strong>RAG (Retrieval-Augmented Generation)</strong>
340
+ ในการค้นหาและตอบคำถามเกี่ยวกับปฏิทินการศึกษา
341
+ </p>
342
+ <h4 style="color: #1E3A8A; margin-top: 1rem;">สามารถสอบถามข้อมูลเกี่ยวกับ:</h4>
343
+ <ul style="list-style-type: none; padding-left: 0;">
344
+ <li>📅 กำหนดการต่างๆ ในปฏิทินการศึกษา</li>
345
+ <li>🎯 วันสำคัญและกิจกรรม</li>
346
+ <li>📝 การลงทะเบียนเรียน</li>
347
+ <li>📚 กำหนดการสอบ</li>
348
+ <li>🏖️ วันหยุดการศึกษา</li>
349
+ </ul>
350
+ </div>
351
+ """, unsafe_allow_html=True)
352
+
353
+ # System status
354
+ st.markdown("""
355
+ <div style="background-color: #f9fafb; padding: 1.5rem; border-radius: 12px;">
356
+ <h3 style="color: #1E3A8A;">🔄 สถานะระบบ</h3>
357
+ <div style="margin-top: 1rem;">
358
+ <p><strong>⏰ เวลาปัจจุบัน:</strong><br>
359
+ {}</p>
360
+ <p><strong>📡 สถานะระบบ:</strong><br>
361
+ <span class="status-indicator {}">
362
+ {} {}
363
+ </span></p>
364
+ </div>
365
+ </div>
366
+ """.format(
367
+ (datetime.now() + timedelta(hours=6)).strftime('%Y-%m-%d %H:%M:%S'),
368
+ "status-online" if st.session_state.pipeline else "status-offline",
369
+ "🟢" if st.session_state.pipeline else "🔴",
370
+ "พร้อมใช้งาน" if st.session_state.pipeline else "ไม่พร้อมใช้งาน"
371
+ ), unsafe_allow_html=True)
372
 
373
+ # Handle clear history action
374
+ if clear_history:
375
+ st.session_state.chat_history = []
376
+ clear_qa_history()
377
+ st.rerun()
378
 
379
  if __name__ == "__main__":
380
+ main()