youngtsai commited on
Commit
0569047
·
1 Parent(s): 01aa382
Files changed (1) hide show
  1. app.py +194 -40
app.py CHANGED
@@ -307,7 +307,7 @@ def update_file_on_drive(service, file_id, file_content):
307
  print(f"文件已更新,文件ID: {updated_file['id']}")
308
 
309
 
310
- # ---- Main Functions ----
311
  def process_file(password, file):
312
  verify_password(password)
313
 
@@ -347,6 +347,8 @@ def docx_to_text(file):
347
  doc = Document(file)
348
  return "\n".join([para.text for para in doc.paragraphs])
349
 
 
 
350
  def format_seconds_to_time(seconds):
351
  """将秒数格式化为 时:分:秒 的形式"""
352
  hours = int(seconds // 3600)
@@ -617,12 +619,16 @@ def screenshot_youtube_video(youtube_id, snapshot_sec):
617
 
618
  return screenshot_path
619
 
 
 
620
  def process_web_link(link):
621
  # 抓取和解析网页内容
622
  response = requests.get(link)
623
  soup = BeautifulSoup(response.content, 'html.parser')
624
  return soup.get_text()
625
 
 
 
626
  def get_mind_map(video_id, df_string, source):
627
  if source == "gcs":
628
  print("===get_mind_map on gcs===")
@@ -903,6 +909,145 @@ def change_questions(password, df_string):
903
  print("=====get_questions=====")
904
  return q1, q2, q3
905
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
906
  def respond(password, user_message, data, chat_history, socratic_mode=False):
907
  verify_password(password)
908
 
@@ -1281,7 +1426,6 @@ def chat_with_youtube_transcript(password, youtube_id, thread_id, trascript, use
1281
  # 返回聊天历史和空字符串清空输入框
1282
  return "", chat_history, thread.id
1283
 
1284
-
1285
  def poll_run_status(run_id, thread_id, timeout=600, poll_interval=5):
1286
  """
1287
  Polls the status of a Run and handles different statuses appropriately.
@@ -1411,20 +1555,8 @@ with gr.Blocks() as demo:
1411
  groq_send_button = gr.Button("Send")
1412
 
1413
  with gr.Column(scale=3):
1414
- with gr.Tab("圖文"):
1415
- transcript_html = gr.HTML(label="YouTube Transcript and Video")
1416
- with gr.Tab("投影片"):
1417
- slide_image = gr.Image()
1418
- slide_text = gr.Textbox()
1419
- with gr.Row():
1420
- prev_button = gr.Button("Previous")
1421
- next_button = gr.Button("Next")
1422
- prev_button.click(fn=prev_slide, inputs=[], outputs=[slide_image, slide_text])
1423
- next_button.click(fn=next_slide, inputs=[], outputs=[slide_image, slide_text])
1424
  with gr.Tab("逐字稿"):
1425
  simple_html_content = gr.HTML(label="Simple Transcript")
1426
- with gr.Tab("本文"):
1427
- df_string_output = gr.Textbox(lines=40, label="Data Text")
1428
  with gr.Tab("重點"):
1429
  df_summarise = gr.Textbox(container=True, show_copy_button=True, lines=40)
1430
  with gr.Tab("問題"):
@@ -1434,41 +1566,58 @@ with gr.Blocks() as demo:
1434
  btn_3 = gr.Button()
1435
  gr.Markdown("## 重新生成問題")
1436
  btn_create_question = gr.Button("Create Questions")
1437
- with gr.Tab("markdown"):
1438
- gr.Markdown("## 請複製以下 markdown 並貼到你的心智圖工具中,建議使用:https://markmap.js.org/repl")
1439
- mind_map = gr.Textbox(container=True, show_copy_button=True, lines=40, elem_id="mind_map_markdown")
1440
  with gr.Tab("心智圖",elem_id="mind_map_tab"):
1441
  mind_map_html = gr.HTML()
1442
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1443
  with gr.Tab("教師版"):
1444
  with gr.Row():
1445
  gr.Markdown("## 教育評量饗宴")
1446
  with gr.Row():
1447
- with gr.Column(scale=2):
1448
- with gr.Tab("認知階層評量題目"):
1449
- cognitive_level_content = gr.Textbox(label="輸入學習目標與內容")
1450
- cognitive_level_content_btn = gr.Button("生成評量題目")
 
 
 
 
1451
  with gr.Tab("素養導向閱讀題組"):
1452
  literacy_oriented_reading_content = gr.Textbox(label="輸入閱讀材料")
1453
  literacy_oriented_reading_content_btn = gr.Button("生成閱讀理解題")
1454
- with gr.Tab("學習單"):
1455
- worksheet_content = gr.Textbox(label="輸入學習單內容")
1456
- worksheet_content_btn = gr.Button("生成學習單")
1457
- with gr.Tab("自我評估"):
1458
- self_assessment_content = gr.Textbox(label="輸入自評問卷或檢查表")
1459
- self_assessment_content_btn = gr.Button("生成自評問卷")
1460
- with gr.Tab("自我反思評量"):
1461
- self_reflection_content = gr.Textbox(label="輸入自我反思活動")
1462
- self_reflection_content_btn = gr.Button("生成自我反思活動")
1463
- with gr.Tab("後設認知"):
1464
- metacognition_content = gr.Textbox(label="輸入後設認知相關問題")
1465
- metacognition_content_btn = gr.Button("生成後設認知問題")
1466
- with gr.Column(scale=3):
1467
  # 生成對應不同模式的結果
1468
- exam_result = gr.Textbox("生成結果")
1469
-
1470
-
1471
-
 
1472
  # 傳統模式
1473
  # send_button.click(
1474
  # respond,
@@ -1559,8 +1708,13 @@ with gr.Blocks() as demo:
1559
  # 教師版 學習單
1560
  worksheet_content_btn.click(
1561
  generate_worksheet,
1562
- inputs=[password, worksheet_content],
1563
- outputs=[exam_result]
 
 
 
 
 
1564
  )
1565
 
1566
  demo.launch(allowed_paths=["videos"])
 
307
  print(f"文件已更新,文件ID: {updated_file['id']}")
308
 
309
 
310
+ # ---- Text file ----
311
  def process_file(password, file):
312
  verify_password(password)
313
 
 
347
  doc = Document(file)
348
  return "\n".join([para.text for para in doc.paragraphs])
349
 
350
+
351
+ # ---- YouTube link ----
352
  def format_seconds_to_time(seconds):
353
  """将秒数格式化为 时:分:秒 的形式"""
354
  hours = int(seconds // 3600)
 
619
 
620
  return screenshot_path
621
 
622
+
623
+ # ---- Web ----
624
  def process_web_link(link):
625
  # 抓取和解析网页内容
626
  response = requests.get(link)
627
  soup = BeautifulSoup(response.content, 'html.parser')
628
  return soup.get_text()
629
 
630
+
631
+ # ---- LLM Generator ----
632
  def get_mind_map(video_id, df_string, source):
633
  if source == "gcs":
634
  print("===get_mind_map on gcs===")
 
909
  print("=====get_questions=====")
910
  return q1, q2, q3
911
 
912
+ # --- 學習單 ---
913
+ def generate_worksheet(password, df_string):
914
+ verify_password(password)
915
+
916
+ # df_string delete embed_url, screenshot_path
917
+ df_string_json = json.loads(df_string)
918
+ for entry in df_string_json:
919
+ entry.pop('embed_url', None)
920
+ entry.pop('screenshot_path', None)
921
+ df_string_text = json.dumps(df_string_json, ensure_ascii=False, indent=2)
922
+
923
+ worksheet_prompt = get_worksheet_prompt()
924
+
925
+ # 使用 OpenAI 生成基于上传数据的问题
926
+ sys_content = "你是一個擅長資料分析跟影片教學備課的老師,請精讀資料文本,自行判斷資料的種類,使用 zh-TW"
927
+ user_content = f"""
928
+ 這是逐字稿:{df_string_text}
929
+ ---
930
+ 請根據逐字稿進行以下工作:
931
+ 不要提到 【逐字稿】 這個詞,直接給出工作內容即可
932
+ {worksheet_prompt}
933
+ """
934
+ messages = [
935
+ {"role": "system", "content": sys_content},
936
+ {"role": "user", "content": user_content}
937
+ ]
938
+
939
+ print("=====generate_worksheet messages=====")
940
+ print(messages)
941
+ print("=====generate_worksheet messages=====")
942
+
943
+ request_payload = {
944
+ "model": "gpt-4-1106-preview",
945
+ "messages": messages,
946
+ "max_tokens": 4000,
947
+ }
948
+
949
+ response = OPEN_AI_CLIENT.chat.completions.create(**request_payload)
950
+ worksheet = response.choices[0].message.content.strip()
951
+ print("=====worksheet=====")
952
+ print(worksheet)
953
+ print("=====worksheet=====")
954
+ return worksheet, worksheet_prompt
955
+
956
+ def get_worksheet_prompt():
957
+ default_worksheet_prompt = """
958
+ 你是個專業的教師,熟悉布魯姆(Benjamin Bloom, 1964) 的認知理論。布魯姆認為人類的能力,大致可分為三個領域(domains),即認知領域(cognitive domain)、情意領域(affective domain)、技能領域 (psychomotor domain)。
959
+
960
+ 【認知領域】涉及知能及其運作,著重心智、學習以及問題解決的工作。認知目標從簡單的認識或記憶能力到複雜的評鑑能力。大部分的教育目標都屬於這個領域。認知領域的目標分為六個層次,每個層次代表不同的心智功能。
961
+ - 📖 知識:在認知目標中知識是最低層次的能力,包括名詞、事實、規則和原理原則等的認識和記憶。用來表示此種能力的行為動詞有:指出、寫出、界定、說明、舉例、命名、認明等。例:能在地圖上指出長江流經的省分。
962
+ - 🤔 理解:理解是指能把握所學過知識或概念的意義,包含轉譯、解釋、推論等能力。代表此能力的行為動詞有:解釋、說明、區別、舉例、摘要、歸納等。例:能解釋光合作用。
963
+ - 🛠️ 應用:應用是指將所學到的規則、方法、步驟、原理、原則和概念,應用到新情境的能力。用來表示此能力的行為動詞有:預測、證明、解決、修改、表現、應用等。例:學生能預測抽出容器內之氣體對容器的影響。
964
+ - 🔍 分析:分析是指將所學到的概念或原則,分析為各個構成的部分,或找出各部分之間的相互關係,包括要素、關係及組織原理等的分析。用以表示此種能力的行為動詞有:選出、分析、判斷:區分、指出某些組成要素、指出某些的相互關係等。例:讀完某篇文章後,學生能區分事實和意見。
965
+ - 🌐 綜合:綜合是指將所學到的片斷概念或知識、原理原則或事實,統整成新的整體。用來表示此種能力的行為動詞有:設計、組織、綜合、創造、歸納、聯合等。例:讀完一篇有關防治汙染的文章後,學生能綜合防治汙染的各種方法。
966
+ - 🏅 評鑑:評鑑是認知目標中最高層次的能力,指依據某項標準做價值的判斷的能力。用來表示此能力的行為動詞有:評鑑、判斷、評論、比較、批��等。例:學生能評斷辯論中的謬論。
967
+
968
+ 學習單包含以下的內容,將以布魯姆教育目標來建構提問的架構;請用 markdown 格式來呈現,題目和題目之間要換行,並加上 point 符號,像是 "-" 或是 "1." 等等。
969
+ - 📝 主題:請使用上傳檔案的檔名作為標題
970
+ - 🔑 重點: 和影片有關重要知識摘要
971
+ - 💭 概念:概念性問題 - 布魯姆的知識層級;數學知識的建構
972
+ - 📊 計算:程序性問題 - 布魯姆的理解層級;和影片相同的例題,類似的練習題 → 計算與步驟操作
973
+ - 🚀 延伸與應用 - 布魯姆的應用、分析、綜合、評鑑層級 → 延伸思考與應用
974
+
975
+ 其中,「重點」的題目請用挖空的填空題;在「計算」的程序性問題請以單選題或填空題的形式來建立,需要 3 個題目;「延伸與應用」請使用問答題的形式來建立,一題即可。
976
+
977
+ 這是範例格式:
978
+ ### 主題:【概念】認識公里
979
+ 【情境描述】
980
+ 狐狸貓和家人出遊,過程中認識測量較長距離的單位「公里」。
981
+
982
+ **【影片重點】**
983
+ 公里是用來測量長距離的單位,通常用於測量很遠的距離。
984
+ 1公里等於___公尺,也稱為千米。
985
+ 公里的英文簡寫是 ____。
986
+
987
+ **【概念】**
988
+ 請問公里通常用於測量什麼類型的距離?
989
+ 如果一圈操場是200公尺,那跑5圈是多少公尺?多少公里?
990
+ 為什麼我們需要使用公里這個單位來測量距離?
991
+
992
+ **【計算】**
993
+ 一圈操場是200公尺,跑10圈是多少公里?(A) 1公里 (B) 2公里 (C) 3公里 (D) 4公里
994
+ 如果你跑了5圈操場,運動手環上會顯示你跑了多少公里?
995
+ 6000公尺等於多少公里?
996
+
997
+ **【延伸與應用】**
998
+ 假設你參加一場慈善路跑活動,全程是5公里。如果你已經跑了3公里,還剩下多少公里?你覺得這樣的活動對你的體能有什麼影響?
999
+ """
1000
+
1001
+ return default_worksheet_prompt
1002
+
1003
+ def generate_exam_fine_tune_result(password, worksheet_prompt, df_string_output, exam_result, exam_result_fine_tune_prompt):
1004
+ verify_password(password)
1005
+
1006
+ # df_string delete embed_url, screenshot_path
1007
+ df_string_json = json.loads(df_string_output)
1008
+ for entry in df_string_json:
1009
+ entry.pop('embed_url', None)
1010
+ entry.pop('screenshot_path', None)
1011
+ df_string_text = json.dumps(df_string_json, ensure_ascii=False, indent=2)
1012
+
1013
+ # 使用 OpenAI 生成基于上传数据的问题
1014
+ sys_content = "你是一個擅長資料分析跟影片教學備課的老師,請精讀資料文本,自行判斷資料的種類,使用 zh-TW"
1015
+ user_content = f"""
1016
+ 這是逐字稿:{df_string_text}
1017
+ ---
1018
+ 這是預設的 prompt
1019
+ {worksheet_prompt}
1020
+ ---
1021
+ 產生了以下的結果:
1022
+ {exam_result}
1023
+ ---
1024
+ 但我不是很滿意,請根據以下的調整,產生新的結果
1025
+ {exam_result_fine_tune_prompt}
1026
+ """
1027
+ messages = [
1028
+ {"role": "system", "content": sys_content},
1029
+ {"role": "user", "content": user_content}
1030
+ ]
1031
+
1032
+ print("=====generate_exam_fine_tune_result messages=====")
1033
+ print(messages)
1034
+ print("=====generate_exam_fine_tune_result messages=====")
1035
+
1036
+ request_payload = {
1037
+ "model": "gpt-4-1106-preview",
1038
+ "messages": messages,
1039
+ "max_tokens": 4000,
1040
+ }
1041
+
1042
+ response = OPEN_AI_CLIENT.chat.completions.create(**request_payload)
1043
+ exam_fine_tune_result = response.choices[0].message.content.strip()
1044
+ print("=====exam_fine_tune_result=====")
1045
+ print(exam_fine_tune_result)
1046
+ print("=====exam_fine_tune_result=====")
1047
+ return exam_fine_tune_result
1048
+
1049
+
1050
+ # ---- Chatbot ----
1051
  def respond(password, user_message, data, chat_history, socratic_mode=False):
1052
  verify_password(password)
1053
 
 
1426
  # 返回聊天历史和空字符串清空输入框
1427
  return "", chat_history, thread.id
1428
 
 
1429
  def poll_run_status(run_id, thread_id, timeout=600, poll_interval=5):
1430
  """
1431
  Polls the status of a Run and handles different statuses appropriately.
 
1555
  groq_send_button = gr.Button("Send")
1556
 
1557
  with gr.Column(scale=3):
 
 
 
 
 
 
 
 
 
 
1558
  with gr.Tab("逐字稿"):
1559
  simple_html_content = gr.HTML(label="Simple Transcript")
 
 
1560
  with gr.Tab("重點"):
1561
  df_summarise = gr.Textbox(container=True, show_copy_button=True, lines=40)
1562
  with gr.Tab("問題"):
 
1566
  btn_3 = gr.Button()
1567
  gr.Markdown("## 重新生成問題")
1568
  btn_create_question = gr.Button("Create Questions")
 
 
 
1569
  with gr.Tab("心智圖",elem_id="mind_map_tab"):
1570
  mind_map_html = gr.HTML()
1571
 
1572
+ with gr.Accordion("See Details", open=False):
1573
+ with gr.Tab("本文"):
1574
+ df_string_output = gr.Textbox(lines=40, label="Data Text")
1575
+ with gr.Tab("圖文"):
1576
+ transcript_html = gr.HTML(label="YouTube Transcript and Video")
1577
+ with gr.Tab("投影片"):
1578
+ slide_image = gr.Image()
1579
+ slide_text = gr.Textbox()
1580
+ with gr.Row():
1581
+ prev_button = gr.Button("Previous")
1582
+ next_button = gr.Button("Next")
1583
+ prev_button.click(fn=prev_slide, inputs=[], outputs=[slide_image, slide_text])
1584
+ next_button.click(fn=next_slide, inputs=[], outputs=[slide_image, slide_text])
1585
+ with gr.Tab("markdown"):
1586
+ gr.Markdown("## 請複製以下 markdown 並貼到你的心智圖工具中,建議使用:https://markmap.js.org/repl")
1587
+ mind_map = gr.Textbox(container=True, show_copy_button=True, lines=40, elem_id="mind_map_markdown")
1588
+
1589
+
1590
  with gr.Tab("教師版"):
1591
  with gr.Row():
1592
  gr.Markdown("## 教育評量饗宴")
1593
  with gr.Row():
1594
+ with gr.Column(scale=1):
1595
+ # with gr.Tab("認知階層評量題目"):
1596
+ # cognitive_level_content = gr.Textbox(label="輸入學習目標與內容")
1597
+ # cognitive_level_content_btn = gr.Button("生成評量題目")
1598
+ with gr.Tab("學習單"):
1599
+ worksheet_content_btn = gr.Button("生成學習單")
1600
+ with gr.Accordion("prompt", open=False):
1601
+ worksheet_prompt = gr.Textbox(label="worksheet_prompt", show_copy_button=True, lines=40)
1602
  with gr.Tab("素養導向閱讀題組"):
1603
  literacy_oriented_reading_content = gr.Textbox(label="輸入閱讀材料")
1604
  literacy_oriented_reading_content_btn = gr.Button("生成閱讀理解題")
1605
+ # with gr.Tab("自我評估"):
1606
+ # self_assessment_content = gr.Textbox(label="輸入自評問卷或檢查表")
1607
+ # self_assessment_content_btn = gr.Button("生成自評問卷")
1608
+ # with gr.Tab("自我反思評量"):
1609
+ # self_reflection_content = gr.Textbox(label="輸入自我反思活動")
1610
+ # self_reflection_content_btn = gr.Button("生成自我反思活動")
1611
+ # with gr.Tab("後設認知"):
1612
+ # metacognition_content = gr.Textbox(label="輸入後設認知相關問題")
1613
+ # metacognition_content_btn = gr.Button("生成後設認知問題")
1614
+ with gr.Column(scale=1):
 
 
 
1615
  # 生成對應不同模式的結果
1616
+ exam_result = gr.Textbox(label="初次生成結果", show_copy_button=True)
1617
+ exam_result_fine_tune_prompt = gr.Textbox(label="根據結果,輸入你想更改的想法")
1618
+ exam_result_fine_tune_btn = gr.Button("微調結果")
1619
+ exam_result_fine_result = gr.Textbox(label="微調結果",show_copy_button=True)
1620
+
1621
  # 傳統模式
1622
  # send_button.click(
1623
  # respond,
 
1708
  # 教師版 學習單
1709
  worksheet_content_btn.click(
1710
  generate_worksheet,
1711
+ inputs=[password, df_string_output],
1712
+ outputs=[exam_result, worksheet_prompt]
1713
+ )
1714
+ exam_result_fine_tune_btn.click(
1715
+ generate_exam_fine_tune_result,
1716
+ inputs=[password, worksheet_prompt, df_string_output, exam_result, exam_result_fine_tune_prompt],
1717
+ outputs=[exam_result_fine_result]
1718
  )
1719
 
1720
  demo.launch(allowed_paths=["videos"])