SarahXia0405 commited on
Commit
f30f379
·
verified ·
1 Parent(s): 9994155

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -27
app.py CHANGED
@@ -2,6 +2,7 @@ import os
2
  import time
3
  import base64
4
  import requests
 
5
  from typing import List, Dict, Tuple, Optional
6
 
7
  import gradio as gr
@@ -285,6 +286,50 @@ def log_event(data: Dict):
285
  print("GSheet log exception:", e)
286
 
287
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  # ================== Gradio App ==================
289
  with gr.Blocks(
290
  title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
@@ -299,6 +344,7 @@ with gr.Blocks(
299
  # 用户状态(登录)
300
  user_name_state = gr.State("")
301
  user_id_state = gr.State("")
 
302
  # --- Header ---
303
  with gr.Row(elem_classes="header-container"):
304
  with gr.Column(scale=3):
@@ -422,7 +468,6 @@ with gr.Blocks(
422
  """
423
  )
424
 
425
-
426
  # === Center Main ===
427
  with gr.Column(scale=3):
428
 
@@ -504,7 +549,6 @@ with gr.Blocks(
504
  )
505
  session_status = gr.Markdown(visible=False)
506
 
507
-
508
  # === Right Sidebar ===
509
  with gr.Column(scale=1, min_width=180):
510
  with gr.Group(elem_classes="login-panel"):
@@ -803,6 +847,16 @@ with gr.Blocks(
803
  end_ts = time.time()
804
  latency_ms = (end_ts - start_ts) * 1000.0
805
 
 
 
 
 
 
 
 
 
 
 
806
  student_id = user_id_val or "ANON"
807
  experiment_id = "RESP_AI_W10"
808
 
@@ -872,33 +926,32 @@ with gr.Blocks(
872
  )
873
 
874
  quiz_instruction = (
875
- "We are running a short micro-quiz session based ONLY on **Module 10 – "
876
- "Responsible AI (Alto, 2024, Chapter 12)** and the pre-loaded materials.\n\n"
877
- "Step 1 – Before asking any content question:\n"
878
- "• First ask me which quiz style I prefer right now:\n"
879
- " - (1) Multiple-choice questions\n"
880
- " - (2) Short-answer / open-ended questions\n"
881
- "• Ask me explicitly: \"Which quiz style do you prefer now: 1) Multiple-choice or 2) Short-answer? "
882
- "Please reply with 1 or 2.\"\n"
883
- "• Do NOT start a content question until I have answered 1 or 2.\n\n"
884
- "Step 2 – After I choose the style:\n"
885
- "• If I choose 1 (multiple-choice):\n"
886
- " - Ask ONE multiple-choice question at a time, based on Module 10 concepts "
887
- "(Responsible AI definition, risk types, mitigation layers, EU AI Act, etc.).\n"
888
- " - Provide 3–4 options (A, B, C, D) and make only one option clearly correct.\n"
889
- "• If I choose 2 (short-answer):\n"
890
- " - Ask ONE short-answer question at a time, also based on Module 10 concepts.\n"
891
- " - Do NOT show the answer when you ask the question.\n\n"
892
- "Step 3 – For each answer I give:\n"
893
- "• Grade my answer (correct / partially correct / incorrect).\n"
894
- "• Give a brief explanation and the correct answer.\n"
895
- "• Then ask if I want another question of the SAME style.\n"
896
- "• Continue this pattern until I explicitly say to stop.\n\n"
897
- "Please start by asking me which quiz style I prefer (1 = multiple-choice, 2 = short-answer). "
898
- "Do not ask any content question before I choose."
899
  )
900
 
901
-
902
  resolved_lang = lang_pref
903
 
904
  start_ts = time.time()
 
2
  import time
3
  import base64
4
  import requests
5
+ from collections import defaultdict
6
  from typing import List, Dict, Tuple, Optional
7
 
8
  import gradio as gr
 
286
  print("GSheet log exception:", e)
287
 
288
 
289
+ # ===== Reference Formatting Helper =====
290
+ def format_references(
291
+ rag_chunks: List[Dict], max_files: int = 2, max_sections_per_file: int = 3
292
+ ) -> str:
293
+ """
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 ""
305
+
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)
313
+
314
+ if not refs_by_file:
315
+ return ""
316
+
317
+ lines = ["**References (RAG context used):**"]
318
+ for i, (file_name, sections) in enumerate(refs_by_file.items()):
319
+ if i >= max_files:
320
+ break
321
+ short_sections = sections[:max_sections_per_file]
322
+ if short_sections:
323
+ section_str = "; ".join(short_sections)
324
+ lines.append(f"- *{file_name}* — {section_str}")
325
+ else:
326
+ lines.append(f"- *{file_name}*")
327
+
328
+ if len(lines) == 1:
329
+ return ""
330
+ return "\n".join(lines)
331
+
332
+
333
  # ================== Gradio App ==================
334
  with gr.Blocks(
335
  title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
 
344
  # 用户状态(登录)
345
  user_name_state = gr.State("")
346
  user_id_state = gr.State("")
347
+
348
  # --- Header ---
349
  with gr.Row(elem_classes="header-container"):
350
  with gr.Column(scale=3):
 
468
  """
469
  )
470
 
 
471
  # === Center Main ===
472
  with gr.Column(scale=3):
473
 
 
549
  )
550
  session_status = gr.Markdown(visible=False)
551
 
 
552
  # === Right Sidebar ===
553
  with gr.Column(scale=1, min_width=180):
554
  with gr.Group(elem_classes="login-panel"):
 
847
  end_ts = time.time()
848
  latency_ms = (end_ts - start_ts) * 1000.0
849
 
850
+ # === 在这里附上 References ===
851
+ ref_text = format_references(rag_context)
852
+ if ref_text and new_history:
853
+ last_user, last_assistant = new_history[-1]
854
+ if "References (RAG context used):" not in (last_assistant or ""):
855
+ last_assistant = f"{last_assistant}\n\n{ref_text}"
856
+ new_history[-1] = [last_user, last_assistant]
857
+ answer = last_assistant # 同步给日志
858
+ # ==============================
859
+
860
  student_id = user_id_val or "ANON"
861
  experiment_id = "RESP_AI_W10"
862
 
 
926
  )
927
 
928
  quiz_instruction = (
929
+ "We are running a short micro-quiz session based ONLY on **Module 10 – "
930
+ "Responsible AI (Alto, 2024, Chapter 12)** and the pre-loaded materials.\n\n"
931
+ "Step 1 – Before asking any content question:\n"
932
+ "• First ask me which quiz style I prefer right now:\n"
933
+ " - (1) Multiple-choice questions\n"
934
+ " - (2) Short-answer / open-ended questions\n"
935
+ "• Ask me explicitly: \"Which quiz style do you prefer now: 1) Multiple-choice or 2) Short-answer? "
936
+ "Please reply with 1 or 2.\"\n"
937
+ "• Do NOT start a content question until I have answered 1 or 2.\n\n"
938
+ "Step 2 – After I choose the style:\n"
939
+ "• If I choose 1 (multiple-choice):\n"
940
+ " - Ask ONE multiple-choice question at a time, based on Module 10 concepts "
941
+ "(Responsible AI definition, risk types, mitigation layers, EU AI Act, etc.).\n"
942
+ " - Provide 3–4 options (A, B, C, D) and make only one option clearly correct.\n"
943
+ "• If I choose 2 (short-answer):\n"
944
+ " - Ask ONE short-answer question at a time, also based on Module 10 concepts.\n"
945
+ " - Do NOT show the answer when you ask the question.\n\n"
946
+ "Step 3 – For each answer I give:\n"
947
+ "• Grade my answer (correct / partially correct / incorrect).\n"
948
+ "• Give a brief explanation and the correct answer.\n"
949
+ "• Then ask if I want another question of the SAME style.\n"
950
+ "• Continue this pattern until I explicitly say to stop.\n\n"
951
+ "Please start by asking me which quiz style I prefer (1 = multiple-choice, 2 = short-answer). "
952
+ "Do not ask any content question before I choose."
953
  )
954
 
 
955
  resolved_lang = lang_pref
956
 
957
  start_ts = time.time()