SarahXia0405 commited on
Commit
a0d1f21
·
verified ·
1 Parent(s): 014686d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +217 -37
app.py CHANGED
@@ -294,11 +294,6 @@ def format_references(
294
  根据当前使用的 rag_chunks,生成一个简短的 reference 列表:
295
  - 按文件名分组
296
  - 每个文件列出若干个 section
297
-
298
- 期望 rag_engine 在每个 chunk 中填入:
299
- chunk["source_file"] -> 文件名
300
- chunk["section"] -> 段落 / section 描述(如 "Section 3.2 – Risk taxonomy")
301
- 若未提供,将回退为 "Unknown file" / "Related section"。
302
  """
303
  if not rag_chunks:
304
  return ""
@@ -306,7 +301,7 @@ def format_references(
306
  refs_by_file: Dict[str, List[str]] = defaultdict(list)
307
 
308
  for chunk in rag_chunks:
309
- file_name = chunk.get("source_file") or "Unknown file"
310
  section = chunk.get("section") or "Related section"
311
  if section not in refs_by_file[file_name]:
312
  refs_by_file[file_name].append(section)
@@ -330,7 +325,6 @@ def format_references(
330
  return "\n".join(lines)
331
 
332
 
333
-
334
  def is_academic_query(message: str) -> bool:
335
  """
336
  判断当前学生输入是否是“学术/课程相关”问题。
@@ -343,7 +337,6 @@ def is_academic_query(message: str) -> bool:
343
  if not m:
344
  return False
345
 
346
- # 归一化一下空格
347
  m = " ".join(m.split())
348
 
349
  # 1) 典型闲聊词
@@ -356,11 +349,10 @@ def is_academic_query(message: str) -> bool:
356
  }
357
  tokens = m.split()
358
 
359
- # 如果全是闲聊词而且没有问号 → 视为非学术问题
360
  if "?" not in m and all(t in smalltalk_tokens for t in tokens):
361
  return False
362
 
363
- # 2) 典型「自我介绍 / 工具说明」类问题,也视为非学术问题
364
  meta_phrases = [
365
  "who are you",
366
  "what are you",
@@ -375,22 +367,18 @@ def is_academic_query(message: str) -> bool:
375
  "what is this app",
376
  "what is this tool",
377
  "what is clare",
378
- "who is clare"
379
  ]
380
  if any(p in m for p in meta_phrases):
381
  return False
382
 
383
- # 3) 很短又没有问号的输入,大概率不是严肃学术问题
384
  if len(tokens) <= 2 and "?" not in m:
385
  return False
386
 
387
- # 其他情况默认当作学术/课程相关问题
388
  return True
389
 
390
 
391
-
392
-
393
-
394
  # ================== Gradio App ==================
395
  with gr.Blocks(
396
  title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
@@ -402,6 +390,10 @@ with gr.Blocks(
402
  cognitive_state_state = gr.State({"confusion": 0, "mastery": 0})
403
  rag_chunks_state = gr.State(preloaded_chunks or [])
404
 
 
 
 
 
405
  # 用户状态(登录)
406
  user_name_state = gr.State("")
407
  user_id_state = gr.State("")
@@ -532,7 +524,7 @@ with gr.Blocks(
532
  # === Center Main ===
533
  with gr.Column(scale=3):
534
 
535
- # 1) Instruction + Chat 在最上方
536
  gr.Markdown(
537
  """
538
  <div style="background-color:#f9fafb; padding:10px; border-radius:5px; margin-top:10px; font-size:0.9em; color:#555;">
@@ -550,6 +542,31 @@ with gr.Blocks(
550
  show_label=False,
551
  bubble_full_width=False,
552
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
553
  user_input = gr.Textbox(
554
  label="Your Input",
555
  placeholder="Please log in on the right before asking Clare anything...",
@@ -559,7 +576,7 @@ with gr.Blocks(
559
  interactive=False,
560
  )
561
 
562
- # 2) Upload / File type / Memory Line 放到聊天框下面
563
  with gr.Row():
564
  with gr.Column(scale=2):
565
  syllabus_file = gr.File(
@@ -691,6 +708,11 @@ with gr.Blocks(
691
  learning_mode: gr.update(interactive=False),
692
  model_name: gr.update(interactive=False),
693
  docs_btn: gr.update(interactive=False),
 
 
 
 
 
694
  }
695
 
696
  info_html = f"""
@@ -721,6 +743,11 @@ with gr.Blocks(
721
  learning_mode: gr.update(interactive=True),
722
  model_name: gr.update(interactive=False),
723
  docs_btn: gr.update(interactive=True),
 
 
 
 
 
724
  }
725
 
726
  login_confirm_btn.click(
@@ -745,6 +772,11 @@ with gr.Blocks(
745
  learning_mode,
746
  model_name,
747
  docs_btn,
 
 
 
 
 
748
  ],
749
  )
750
 
@@ -773,6 +805,11 @@ with gr.Blocks(
773
  language_preference: gr.update(interactive=False),
774
  learning_mode: gr.update(interactive=False),
775
  docs_btn: gr.update(interactive=False),
 
 
 
 
 
776
  }
777
 
778
  logout_btn.click(
@@ -797,6 +834,11 @@ with gr.Blocks(
797
  language_preference,
798
  learning_mode,
799
  docs_btn,
 
 
 
 
 
800
  ],
801
  )
802
 
@@ -874,7 +916,7 @@ with gr.Blocks(
874
  weaknesses or [],
875
  cognitive_state or {"confusion": 0, "mastery": 0},
876
  )
877
- return "", new_history, weaknesses, cognitive_state, new_status
878
 
879
  resolved_lang = detect_language(message or "", lang_pref)
880
 
@@ -884,14 +926,13 @@ with gr.Blocks(
884
  weaknesses or [],
885
  cognitive_state or {"confusion": 0, "mastery": 0},
886
  )
887
- return "", chat_history, weaknesses, cognitive_state, new_status
888
 
889
  # 更新学生状态
890
  weaknesses = update_weaknesses_from_message(message, weaknesses or [])
891
  cognitive_state = update_cognitive_state_from_message(message, cognitive_state)
892
 
893
- # RAG 始终基于 (预加载 Module10 + 可选上传)
894
- # 只对“学术/课程相关”问题调用 RAG;闲聊不查文档,也不打 reference
895
  if is_academic_query(message):
896
  rag_context_text, rag_used_chunks = retrieve_relevant_chunks(
897
  message, rag_chunks or []
@@ -899,8 +940,6 @@ with gr.Blocks(
899
  else:
900
  rag_context_text, rag_used_chunks = "", []
901
 
902
-
903
- # 计时
904
  start_ts = time.time()
905
  answer, new_history = chat_with_clare(
906
  message=message,
@@ -912,28 +951,27 @@ with gr.Blocks(
912
  course_outline=course_outline,
913
  weaknesses=weaknesses,
914
  cognitive_state=cognitive_state,
915
- rag_context=rag_context_text, # 这里传检索文本
916
  )
917
  end_ts = time.time()
918
  latency_ms = (end_ts - start_ts) * 1000.0
919
 
920
- # === 在这里附上 References(只在学术问题上附 ===
921
- ref_text = ""
922
  if is_academic_query(message) and rag_used_chunks:
923
  ref_text = format_references(rag_used_chunks)
 
 
924
 
925
  if ref_text and new_history:
926
  last_user, last_assistant = new_history[-1]
927
  if "References (RAG context used):" not in (last_assistant or ""):
928
  last_assistant = f"{last_assistant}\n\n{ref_text}"
929
  new_history[-1] = [last_user, last_assistant]
930
- answer = last_assistant # 同步给日志
931
- # ============================================
932
 
933
  # 日志
934
  student_id = user_id_val or "ANON"
935
  experiment_id = "RESP_AI_W10"
936
-
937
  try:
938
  log_event(
939
  {
@@ -953,9 +991,9 @@ with gr.Blocks(
953
  print("log_event error:", e)
954
 
955
  new_status = render_session_status(mode_val, weaknesses, cognitive_state)
956
- return "", new_history, weaknesses, cognitive_state, new_status
957
-
958
 
 
 
959
 
960
  user_input.submit(
961
  respond,
@@ -972,7 +1010,15 @@ with gr.Blocks(
972
  doc_type,
973
  user_id_state,
974
  ],
975
- [user_input, chatbot, weakness_state, cognitive_state_state, session_status],
 
 
 
 
 
 
 
 
976
  )
977
 
978
  # ===== Micro-Quiz: 直接在主 Chatbot 里进行 =====
@@ -1031,13 +1077,10 @@ with gr.Blocks(
1031
  resolved_lang = lang_pref
1032
 
1033
  start_ts = time.time()
1034
-
1035
-
1036
  quiz_ctx_text, _quiz_ctx_chunks = retrieve_relevant_chunks(
1037
  "Module 10 quiz", rag_chunks or []
1038
  )
1039
 
1040
-
1041
  answer, new_history = chat_with_clare(
1042
  message=quiz_instruction,
1043
  history=chat_history,
@@ -1094,6 +1137,141 @@ with gr.Blocks(
1094
  [chatbot, weakness_state, cognitive_state_state, session_status],
1095
  )
1096
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1097
  # ===== Export / Summary =====
1098
  export_btn.click(
1099
  lambda h, c, m, w, cog: export_conversation(h, c, m, w, cog),
@@ -1120,7 +1298,7 @@ with gr.Blocks(
1120
  def clear_all():
1121
  empty_state = {"confusion": 0, "mastery": 0}
1122
  default_status = render_session_status("Concept Explainer", [], empty_state)
1123
- return [], [], empty_state, [], "", default_status
1124
 
1125
  clear_btn.click(
1126
  clear_all,
@@ -1132,6 +1310,8 @@ with gr.Blocks(
1132
  rag_chunks_state,
1133
  result_display,
1134
  session_status,
 
 
1135
  ],
1136
  queue=False,
1137
  )
 
294
  根据当前使用的 rag_chunks,生成一个简短的 reference 列表:
295
  - 按文件名分组
296
  - 每个文件列出若干个 section
 
 
 
 
 
297
  """
298
  if not rag_chunks:
299
  return ""
 
301
  refs_by_file: Dict[str, List[str]] = defaultdict(list)
302
 
303
  for chunk in rag_chunks:
304
+ file_name = chunk.get("source_file") or "module10_responsible_ai.pdf"
305
  section = chunk.get("section") or "Related section"
306
  if section not in refs_by_file[file_name]:
307
  refs_by_file[file_name].append(section)
 
325
  return "\n".join(lines)
326
 
327
 
 
328
  def is_academic_query(message: str) -> bool:
329
  """
330
  判断当前学生输入是否是“学术/课程相关”问题。
 
337
  if not m:
338
  return False
339
 
 
340
  m = " ".join(m.split())
341
 
342
  # 1) 典型闲聊词
 
349
  }
350
  tokens = m.split()
351
 
 
352
  if "?" not in m and all(t in smalltalk_tokens for t in tokens):
353
  return False
354
 
355
+ # 2) 自我介绍 / 工具说明
356
  meta_phrases = [
357
  "who are you",
358
  "what are you",
 
367
  "what is this app",
368
  "what is this tool",
369
  "what is clare",
370
+ "who is clare",
371
  ]
372
  if any(p in m for p in meta_phrases):
373
  return False
374
 
375
+ # 3) 很短又没有问号,大概率不是学术问题
376
  if len(tokens) <= 2 and "?" not in m:
377
  return False
378
 
 
379
  return True
380
 
381
 
 
 
 
382
  # ================== Gradio App ==================
383
  with gr.Blocks(
384
  title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
 
390
  cognitive_state_state = gr.State({"confusion": 0, "mastery": 0})
391
  rag_chunks_state = gr.State(preloaded_chunks or [])
392
 
393
+ # 最近一次回答(用于每条回答的 thumbs / 详细反馈)
394
+ last_question_state = gr.State("")
395
+ last_answer_state = gr.State("")
396
+
397
  # 用户状态(登录)
398
  user_name_state = gr.State("")
399
  user_id_state = gr.State("")
 
524
  # === Center Main ===
525
  with gr.Column(scale=3):
526
 
527
+ # Instruction + Chat
528
  gr.Markdown(
529
  """
530
  <div style="background-color:#f9fafb; padding:10px; border-radius:5px; margin-top:10px; font-size:0.9em; color:#555;">
 
542
  show_label=False,
543
  bubble_full_width=False,
544
  )
545
+
546
+ # === Feedback on last answer ===
547
+ gr.Markdown("#### Rate Clare’s last answer")
548
+ with gr.Row():
549
+ thumb_up_btn = gr.Button(
550
+ "👍 Helpful", size="sm", interactive=False
551
+ )
552
+ thumb_down_btn = gr.Button(
553
+ "👎 Not helpful", size="sm", interactive=False
554
+ )
555
+
556
+ feedback_toggle_btn = gr.Button(
557
+ "Give detailed feedback", size="sm", variant="secondary", interactive=False
558
+ )
559
+ feedback_text = gr.Textbox(
560
+ label="What worked well or what was wrong?",
561
+ placeholder="Optional: describe what you liked / what was confusing or incorrect.",
562
+ lines=3,
563
+ visible=False,
564
+ )
565
+ feedback_submit_btn = gr.Button(
566
+ "Submit Feedback", size="sm", variant="primary", visible=False, interactive=False
567
+ )
568
+
569
+ # 用户输入
570
  user_input = gr.Textbox(
571
  label="Your Input",
572
  placeholder="Please log in on the right before asking Clare anything...",
 
576
  interactive=False,
577
  )
578
 
579
+ # Upload / File type / Memory Line
580
  with gr.Row():
581
  with gr.Column(scale=2):
582
  syllabus_file = gr.File(
 
708
  learning_mode: gr.update(interactive=False),
709
  model_name: gr.update(interactive=False),
710
  docs_btn: gr.update(interactive=False),
711
+ thumb_up_btn: gr.update(interactive=False),
712
+ thumb_down_btn: gr.update(interactive=False),
713
+ feedback_toggle_btn: gr.update(interactive=False),
714
+ feedback_text: gr.update(visible=False, value=""),
715
+ feedback_submit_btn: gr.update(interactive=False, visible=False),
716
  }
717
 
718
  info_html = f"""
 
743
  learning_mode: gr.update(interactive=True),
744
  model_name: gr.update(interactive=False),
745
  docs_btn: gr.update(interactive=True),
746
+ thumb_up_btn: gr.update(interactive=True),
747
+ thumb_down_btn: gr.update(interactive=True),
748
+ feedback_toggle_btn: gr.update(interactive=True),
749
+ feedback_text: gr.update(visible=False, value=""),
750
+ feedback_submit_btn: gr.update(interactive=True, visible=False),
751
  }
752
 
753
  login_confirm_btn.click(
 
772
  learning_mode,
773
  model_name,
774
  docs_btn,
775
+ thumb_up_btn,
776
+ thumb_down_btn,
777
+ feedback_toggle_btn,
778
+ feedback_text,
779
+ feedback_submit_btn,
780
  ],
781
  )
782
 
 
805
  language_preference: gr.update(interactive=False),
806
  learning_mode: gr.update(interactive=False),
807
  docs_btn: gr.update(interactive=False),
808
+ thumb_up_btn: gr.update(interactive=False),
809
+ thumb_down_btn: gr.update(interactive=False),
810
+ feedback_toggle_btn: gr.update(interactive=False),
811
+ feedback_text: gr.update(visible=False, value=""),
812
+ feedback_submit_btn: gr.update(interactive=False, visible=False),
813
  }
814
 
815
  logout_btn.click(
 
834
  language_preference,
835
  learning_mode,
836
  docs_btn,
837
+ thumb_up_btn,
838
+ thumb_down_btn,
839
+ feedback_toggle_btn,
840
+ feedback_text,
841
+ feedback_submit_btn,
842
  ],
843
  )
844
 
 
916
  weaknesses or [],
917
  cognitive_state or {"confusion": 0, "mastery": 0},
918
  )
919
+ return "", new_history, weaknesses, cognitive_state, new_status, "", ""
920
 
921
  resolved_lang = detect_language(message or "", lang_pref)
922
 
 
926
  weaknesses or [],
927
  cognitive_state or {"confusion": 0, "mastery": 0},
928
  )
929
+ return "", chat_history, weaknesses, cognitive_state, new_status, "", ""
930
 
931
  # 更新学生状态
932
  weaknesses = update_weaknesses_from_message(message, weaknesses or [])
933
  cognitive_state = update_cognitive_state_from_message(message, cognitive_state)
934
 
935
+ # RAG:只对学术问题启用
 
936
  if is_academic_query(message):
937
  rag_context_text, rag_used_chunks = retrieve_relevant_chunks(
938
  message, rag_chunks or []
 
940
  else:
941
  rag_context_text, rag_used_chunks = "", []
942
 
 
 
943
  start_ts = time.time()
944
  answer, new_history = chat_with_clare(
945
  message=message,
 
951
  course_outline=course_outline,
952
  weaknesses=weaknesses,
953
  cognitive_state=cognitive_state,
954
+ rag_context=rag_context_text,
955
  )
956
  end_ts = time.time()
957
  latency_ms = (end_ts - start_ts) * 1000.0
958
 
959
+ # 只在学术问题上附 References
 
960
  if is_academic_query(message) and rag_used_chunks:
961
  ref_text = format_references(rag_used_chunks)
962
+ else:
963
+ ref_text = ""
964
 
965
  if ref_text and new_history:
966
  last_user, last_assistant = new_history[-1]
967
  if "References (RAG context used):" not in (last_assistant or ""):
968
  last_assistant = f"{last_assistant}\n\n{ref_text}"
969
  new_history[-1] = [last_user, last_assistant]
970
+ answer = last_assistant
 
971
 
972
  # 日志
973
  student_id = user_id_val or "ANON"
974
  experiment_id = "RESP_AI_W10"
 
975
  try:
976
  log_event(
977
  {
 
991
  print("log_event error:", e)
992
 
993
  new_status = render_session_status(mode_val, weaknesses, cognitive_state)
 
 
994
 
995
+ # 将当前这一轮的 Q/A 存入 state,后面 thumbs / 详细反馈用
996
+ return "", new_history, weaknesses, cognitive_state, new_status, message, answer
997
 
998
  user_input.submit(
999
  respond,
 
1010
  doc_type,
1011
  user_id_state,
1012
  ],
1013
+ [
1014
+ user_input,
1015
+ chatbot,
1016
+ weakness_state,
1017
+ cognitive_state_state,
1018
+ session_status,
1019
+ last_question_state,
1020
+ last_answer_state,
1021
+ ],
1022
  )
1023
 
1024
  # ===== Micro-Quiz: 直接在主 Chatbot 里进行 =====
 
1077
  resolved_lang = lang_pref
1078
 
1079
  start_ts = time.time()
 
 
1080
  quiz_ctx_text, _quiz_ctx_chunks = retrieve_relevant_chunks(
1081
  "Module 10 quiz", rag_chunks or []
1082
  )
1083
 
 
1084
  answer, new_history = chat_with_clare(
1085
  message=quiz_instruction,
1086
  history=chat_history,
 
1137
  [chatbot, weakness_state, cognitive_state_state, session_status],
1138
  )
1139
 
1140
+ # ===== Feedback Handlers =====
1141
+ def show_feedback_box():
1142
+ """
1143
+ 点击 'Give detailed feedback' 时显示文本框 + 提交按钮
1144
+ """
1145
+ return {
1146
+ feedback_text: gr.update(visible=True),
1147
+ feedback_submit_btn: gr.update(visible=True),
1148
+ }
1149
+
1150
+ feedback_toggle_btn.click(
1151
+ show_feedback_box,
1152
+ None,
1153
+ [feedback_text, feedback_submit_btn],
1154
+ )
1155
+
1156
+ def send_thumb_up(last_q, last_a, user_id_val, mode_val, model_name_val, lang_pref):
1157
+ if not last_q and not last_a:
1158
+ print("No last QA to log for thumbs_up.")
1159
+ return
1160
+ try:
1161
+ log_event(
1162
+ {
1163
+ "experiment_id": "RESP_AI_W10",
1164
+ "student_id": user_id_val or "ANON",
1165
+ "event_type": "thumbs_up",
1166
+ "timestamp": time.time(),
1167
+ "question": last_q,
1168
+ "answer": last_a,
1169
+ "model_name": model_name_val,
1170
+ "language": lang_pref,
1171
+ "learning_mode": mode_val,
1172
+ }
1173
+ )
1174
+ print("[Feedback] thumbs_up logged.")
1175
+ except Exception as e:
1176
+ print("thumb_up log error:", e)
1177
+
1178
+ def send_thumb_down(last_q, last_a, user_id_val, mode_val, model_name_val, lang_pref):
1179
+ if not last_q and not last_a:
1180
+ print("No last QA to log for thumbs_down.")
1181
+ return
1182
+ try:
1183
+ log_event(
1184
+ {
1185
+ "experiment_id": "RESP_AI_W10",
1186
+ "student_id": user_id_val or "ANON",
1187
+ "event_type": "thumbs_down",
1188
+ "timestamp": time.time(),
1189
+ "question": last_q,
1190
+ "answer": last_a,
1191
+ "model_name": model_name_val,
1192
+ "language": lang_pref,
1193
+ "learning_mode": mode_val,
1194
+ }
1195
+ )
1196
+ print("[Feedback] thumbs_down logged.")
1197
+ except Exception as e:
1198
+ print("thumb_down log error:", e)
1199
+
1200
+ thumb_up_btn.click(
1201
+ send_thumb_up,
1202
+ [
1203
+ last_question_state,
1204
+ last_answer_state,
1205
+ user_id_state,
1206
+ learning_mode,
1207
+ model_name,
1208
+ language_preference,
1209
+ ],
1210
+ [],
1211
+ )
1212
+
1213
+ thumb_down_btn.click(
1214
+ send_thumb_down,
1215
+ [
1216
+ last_question_state,
1217
+ last_answer_state,
1218
+ user_id_state,
1219
+ learning_mode,
1220
+ model_name,
1221
+ language_preference,
1222
+ ],
1223
+ [],
1224
+ )
1225
+
1226
+ def submit_detailed_feedback(
1227
+ text, last_q, last_a, user_id_val, mode_val, model_name_val, lang_pref
1228
+ ):
1229
+ if not text or not text.strip():
1230
+ # 提示:请先填写再提交(用 placeholder 提醒)
1231
+ return gr.update(
1232
+ value="",
1233
+ placeholder="Please enter some feedback before submitting.",
1234
+ )
1235
+
1236
+ try:
1237
+ log_event(
1238
+ {
1239
+ "experiment_id": "RESP_AI_W10",
1240
+ "student_id": user_id_val or "ANON",
1241
+ "event_type": "detailed_feedback",
1242
+ "timestamp": time.time(),
1243
+ "question": last_q,
1244
+ "answer": last_a,
1245
+ "feedback_text": text.strip(),
1246
+ "model_name": model_name_val,
1247
+ "language": lang_pref,
1248
+ "learning_mode": mode_val,
1249
+ }
1250
+ )
1251
+ print("[Feedback] detailed_feedback logged.")
1252
+ except Exception as e:
1253
+ print("detailed_feedback log error:", e)
1254
+
1255
+ # 清空文本框,并显示感谢(用 placeholder)
1256
+ return gr.update(
1257
+ value="",
1258
+ placeholder="Thanks! Your feedback has been recorded.",
1259
+ )
1260
+
1261
+ feedback_submit_btn.click(
1262
+ submit_detailed_feedback,
1263
+ [
1264
+ feedback_text,
1265
+ last_question_state,
1266
+ last_answer_state,
1267
+ user_id_state,
1268
+ learning_mode,
1269
+ model_name,
1270
+ language_preference,
1271
+ ],
1272
+ [feedback_text],
1273
+ )
1274
+
1275
  # ===== Export / Summary =====
1276
  export_btn.click(
1277
  lambda h, c, m, w, cog: export_conversation(h, c, m, w, cog),
 
1298
  def clear_all():
1299
  empty_state = {"confusion": 0, "mastery": 0}
1300
  default_status = render_session_status("Concept Explainer", [], empty_state)
1301
+ return [], [], empty_state, [], "", default_status, "", ""
1302
 
1303
  clear_btn.click(
1304
  clear_all,
 
1310
  rag_chunks_state,
1311
  result_display,
1312
  session_status,
1313
+ last_question_state,
1314
+ last_answer_state,
1315
  ],
1316
  queue=False,
1317
  )