youngtsai commited on
Commit
2bac9cd
·
1 Parent(s): 0569047
Files changed (1) hide show
  1. app.py +278 -66
app.py CHANGED
@@ -65,6 +65,8 @@ OPEN_AI_CLIENT = OpenAI(api_key=OPEN_AI_KEY)
65
  GROQ_API_KEY = os.getenv("GROQ_API_KEY")
66
  GROQ_CLIENT = Groq(api_key=GROQ_API_KEY)
67
 
 
 
68
  DRIVE_KEY = os.getenv("GOOGLE_APPLICATION_CREDENTIALS_JSON")
69
  GCS_KEY = os.getenv("GOOGLE_APPLICATION_CREDENTIALS_JSON")
70
 
@@ -475,9 +477,23 @@ def process_transcript_and_screenshots_on_gcs(video_id):
475
  # get_mind_map(video_id, transcript_text, source)
476
  # print("===確認其他衍生文件 end ===")
477
 
 
478
  # 處理截圖
479
  for entry in transcript:
480
  if 'img_file_id' not in entry:
 
 
 
 
 
 
 
 
 
 
 
 
 
481
  screenshot_path = screenshot_youtube_video(video_id, entry['start'])
482
  screenshot_blob_name = f"{video_id}/{video_id}_{entry['start']}.jpg"
483
  img_file_id = upload_img_and_get_public_url(gcs_client, bucket_name, screenshot_blob_name, screenshot_path)
@@ -503,7 +519,6 @@ def process_youtube_link(password, link):
503
  video_id = extract_youtube_id(link)
504
  global VIDEO_ID
505
  VIDEO_ID = video_id
506
- download_youtube_video(video_id, output_path=OUTPUT_PATH)
507
 
508
  try:
509
  # transcript = process_transcript_and_screenshots(video_id)
@@ -560,6 +575,8 @@ def process_youtube_link(password, link):
560
  mind_map_json = get_mind_map(video_id, formatted_simple_transcript, source)
561
  mind_map = mind_map_json["mind_map"]
562
  mind_map_html = get_mind_map_html(mind_map)
 
 
563
 
564
  # 确保返回与 UI 组件预期匹配的输出
565
  return video_id, \
@@ -573,7 +590,8 @@ def process_youtube_link(password, link):
573
  html_content, \
574
  simple_html_content, \
575
  first_image, \
576
- first_text,
 
577
 
578
  def format_transcript_to_html(formatted_transcript):
579
  html_content = ""
@@ -629,6 +647,78 @@ def process_web_link(link):
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===")
@@ -910,7 +1000,7 @@ def change_questions(password, df_string):
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
@@ -920,15 +1010,21 @@ def generate_worksheet(password, df_string):
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 = [
@@ -953,8 +1049,8 @@ def generate_worksheet(password, df_string):
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
  【認知領域】涉及知能及其運作,著重心智、學習以及問題解決的工作。認知目標從簡單的認識或記憶能力到複雜的評鑑能力。大部分的教育目標都屬於這個領域。認知領域的目標分為六個層次,每個層次代表不同的心智功能。
@@ -965,41 +1061,135 @@ def get_worksheet_prompt():
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
 
@@ -1196,27 +1386,23 @@ def respond_with_jutor_chat(password, user_message, data, chat_history, socratic
1196
  else:
1197
  pass
1198
 
1199
- # 构造请求体
1200
- request_payload = {
1201
- "endpoint": "https://api.openai.com/v1/chat/completions",
1202
- "http_method": "POST",
 
 
 
1203
  "data": {
1204
- "model": "gpt-4-1106-preview", # 或其他模型
1205
  "messages": messages,
1206
- "max_tokens": 4000 # 設定一個較大的值,可根據需要調整
 
 
 
1207
  }
1208
  }
1209
 
1210
- # 发送请求到远程API
1211
- response = requests.post(
1212
- "https://www.junyiacademy.com/api/v2/jutor/chat", # 你的远程API URL
1213
- headers={
1214
- "Content-Type": "application/json",
1215
- # 如果API需要XSRF token或其他认证信息,请在这里添加
1216
- # 'X-KA-FKey': xsrfToken
1217
- },
1218
- json=request_payload # 使用json参数直接发送JSON格式的数据
1219
- )
1220
 
1221
  if response.status_code == 200:
1222
  # 处理响应数据
@@ -1542,21 +1728,9 @@ with gr.Blocks() as demo:
1542
  web_link = gr.Textbox(label="Enter Web Page Link", visible=False)
1543
  with gr.Tab("學生版"):
1544
  with gr.Row():
1545
- with gr.Column(scale=2):
1546
- gr.Markdown("## OPEN AI 模式")
1547
- chatbot = gr.Chatbot()
1548
- thread_id = gr.Textbox(label="thread_id", visible=False)
1549
- socratic_mode_btn = gr.Checkbox(label="蘇格拉底家教助理模式", value=False)
1550
- msg = gr.Textbox(label="Message")
1551
- send_button = gr.Button("Send")
1552
- gr.Markdown("## GROQ 模式")
1553
- groq_chatbot = gr.Chatbot(label="groq mode chatbot")
1554
- groq_msg = gr.Textbox(label="Message")
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,12 +1740,12 @@ with gr.Blocks() as demo:
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("投影片"):
@@ -1585,7 +1759,25 @@ with gr.Blocks() as demo:
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():
@@ -1595,7 +1787,11 @@ with gr.Blocks() as demo:
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)
@@ -1629,6 +1825,12 @@ with gr.Blocks() as demo:
1629
  # btn_2.click(respond, inputs=[btn_2, df_string_output, chatbot, socratic_mode_btn], outputs=[msg, chatbot])
1630
  # btn_3.click(respond, inputs=[btn_3, df_string_output, chatbot, socratic_mode_btn], outputs=[msg, chatbot])
1631
 
 
 
 
 
 
 
1632
  # chat_with_youtube_transcript
1633
  send_button.click(
1634
  chat_with_youtube_transcript,
@@ -1641,6 +1843,14 @@ with gr.Blocks() as demo:
1641
  inputs=[password, groq_msg, df_string_output, groq_chatbot, socratic_mode_btn],
1642
  outputs=[groq_msg, groq_chatbot]
1643
  )
 
 
 
 
 
 
 
 
1644
  # 连接按钮点击事件
1645
  btn_1.click(
1646
  chat_with_youtube_transcript,
@@ -1679,9 +1889,10 @@ with gr.Blocks() as demo:
1679
  transcript_html,
1680
  simple_html_content,
1681
  slide_image,
1682
- slide_text
1683
- ]
1684
- )
 
1685
 
1686
  youtube_link_btn.click(
1687
  process_youtube_link,
@@ -1698,9 +1909,10 @@ with gr.Blocks() as demo:
1698
  transcript_html,
1699
  simple_html_content,
1700
  slide_image,
1701
- slide_text
1702
- ]
1703
- )
 
1704
 
1705
  # 当输入网页链接时触发
1706
  # web_link.change(process_web_link, inputs=web_link, outputs=[btn_1, btn_2, btn_3, df_summarise, df_string_output])
@@ -1708,7 +1920,7 @@ with gr.Blocks() as demo:
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(
 
65
  GROQ_API_KEY = os.getenv("GROQ_API_KEY")
66
  GROQ_CLIENT = Groq(api_key=GROQ_API_KEY)
67
 
68
+ JUTOR_CHAT_KEY = os.getenv("JUTOR_CHAT_KEY")
69
+
70
  DRIVE_KEY = os.getenv("GOOGLE_APPLICATION_CREDENTIALS_JSON")
71
  GCS_KEY = os.getenv("GOOGLE_APPLICATION_CREDENTIALS_JSON")
72
 
 
477
  # get_mind_map(video_id, transcript_text, source)
478
  # print("===確認其他衍生文件 end ===")
479
 
480
+
481
  # 處理截圖
482
  for entry in transcript:
483
  if 'img_file_id' not in entry:
484
+ # 檢查 OUTPUT_PATH 是否存在 video_id.mp4
485
+ video_path = f'{OUTPUT_PATH}/{video_id}.mp4'
486
+ if not os.path.exists(video_path):
487
+ # try 5 times 如果都失敗就 raise
488
+ for i in range(5):
489
+ try:
490
+ download_youtube_video(video_id)
491
+ break
492
+ except Exception as e:
493
+ if i == 4:
494
+ raise gr.Error(f"下载视频失败: {str(e)}")
495
+ time.sleep(5)
496
+ # 截图
497
  screenshot_path = screenshot_youtube_video(video_id, entry['start'])
498
  screenshot_blob_name = f"{video_id}/{video_id}_{entry['start']}.jpg"
499
  img_file_id = upload_img_and_get_public_url(gcs_client, bucket_name, screenshot_blob_name, screenshot_path)
 
519
  video_id = extract_youtube_id(link)
520
  global VIDEO_ID
521
  VIDEO_ID = video_id
 
522
 
523
  try:
524
  # transcript = process_transcript_and_screenshots(video_id)
 
575
  mind_map_json = get_mind_map(video_id, formatted_simple_transcript, source)
576
  mind_map = mind_map_json["mind_map"]
577
  mind_map_html = get_mind_map_html(mind_map)
578
+ reading_passage_json = get_reading_passage(video_id, formatted_simple_transcript, source)
579
+ reading_passage = reading_passage_json["reading_passage"]
580
 
581
  # 确保返回与 UI 组件预期匹配的输出
582
  return video_id, \
 
590
  html_content, \
591
  simple_html_content, \
592
  first_image, \
593
+ first_text, \
594
+ reading_passage
595
 
596
  def format_transcript_to_html(formatted_transcript):
597
  html_content = ""
 
647
 
648
 
649
  # ---- LLM Generator ----
650
+ def get_reading_passage(video_id, df_string, source):
651
+ if source == "gcs":
652
+ print("===get_reading_passage on gcs===")
653
+ gcs_client = init_gcs_client(GCS_KEY)
654
+ bucket_name = 'video_ai_assistant'
655
+ file_name = f'{video_id}_reading_passage.json'
656
+ blob_name = f"{video_id}/{file_name}"
657
+ # 检查 reading_passage 是否存在
658
+ is_file_exists = gcs_check_file_exists(gcs_client, bucket_name, blob_name)
659
+ if not is_file_exists:
660
+ reading_passage = generate_reading_passage(df_string)
661
+ reading_passage_json = {"reading_passage": str(reading_passage)}
662
+ reading_passage_text = json.dumps(reading_passage_json, ensure_ascii=False, indent=2)
663
+ upload_file_to_gcs_with_json_string(gcs_client, bucket_name, blob_name, reading_passage_text)
664
+ print("reading_passage已上传到GCS")
665
+ else:
666
+ # reading_passage已存在,下载内容
667
+ print("reading_passage已存在于GCS中")
668
+ reading_passage_text = download_blob_to_string(gcs_client, bucket_name, blob_name)
669
+ reading_passage_json = json.loads(reading_passage_text)
670
+
671
+ elif source == "drive":
672
+ print("===get_reading_passage on drive===")
673
+ service = init_drive_service()
674
+ parent_folder_id = '1GgI4YVs0KckwStVQkLa1NZ8IpaEMurkL'
675
+ folder_id = create_folder_if_not_exists(service, video_id, parent_folder_id)
676
+ file_name = f'{video_id}_reading_passage.json'
677
+
678
+ # 检查 reading_passage 是否存在
679
+ exists, file_id = check_file_exists(service, folder_id, file_name)
680
+ if not exists:
681
+ reading_passage = generate_reading_passage(df_string)
682
+ reading_passage_json = {"reading_passage": str(reading_passage)}
683
+ reading_passage_text = json.dumps(reading_passage_json, ensure_ascii=False, indent=2)
684
+ upload_content_directly(service, file_name, folder_id, reading_passage_text)
685
+ print("reading_passage已上傳到Google Drive")
686
+ else:
687
+ # reading_passage已存在,下载内容
688
+ print("reading_passage已存在于Google Drive中")
689
+ reading_passage_text = download_file_as_string(service, file_id)
690
+
691
+ return reading_passage_json
692
+
693
+ def generate_reading_passage(df_string):
694
+ # 使用 OpenAI 生成基于上传数据的问题
695
+ sys_content = "你是一個擅長資料分析跟影片教學��老師,user 為學生,請精讀資料文本,自行判斷資料的種類,使用 zh-TW"
696
+ user_content = f"""
697
+ 請根據 {df_string}
698
+ 文本自行判斷資料的種類
699
+ 幫我組合成 Reading Passage
700
+ 並潤稿讓文句通順
701
+ 請一定要使用 zh-TW
702
+ """
703
+ messages = [
704
+ {"role": "system", "content": sys_content},
705
+ {"role": "user", "content": user_content}
706
+ ]
707
+
708
+ request_payload = {
709
+ "model": "gpt-4-1106-preview",
710
+ "messages": messages,
711
+ "max_tokens": 4000,
712
+ }
713
+
714
+ response = OPEN_AI_CLIENT.chat.completions.create(**request_payload)
715
+ reading_passage = response.choices[0].message.content.strip()
716
+ print("=====reading_passage=====")
717
+ print(reading_passage)
718
+ print("=====reading_passage=====")
719
+
720
+ return reading_passage
721
+
722
  def get_mind_map(video_id, df_string, source):
723
  if source == "gcs":
724
  print("===get_mind_map on gcs===")
 
1000
  return q1, q2, q3
1001
 
1002
  # --- 學習單 ---
1003
+ def generate_worksheet(password, df_string, worksheet_topic, worksheet_grade, worksheet_level, worksheet_algorithm):
1004
  verify_password(password)
1005
 
1006
  # df_string delete embed_url, screenshot_path
 
1010
  entry.pop('screenshot_path', None)
1011
  df_string_text = json.dumps(df_string_json, ensure_ascii=False, indent=2)
1012
 
1013
+ worksheet_prompt = get_worksheet_prompt(worksheet_algorithm)
1014
 
1015
  # 使用 OpenAI 生成基于上传数据的问题
1016
  sys_content = "你是一個擅長資料分析跟影片教學備課的老師,請精讀資料文本,自行判斷資料的種類,使用 zh-TW"
1017
  user_content = f"""
1018
  這是逐字稿:{df_string_text}
1019
  ---
1020
+ 這是學習單模型:{worksheet_algorithm}
1021
+ 這是學習單科目:{worksheet_topic}
1022
+ 這是學習單年級:{worksheet_grade}
1023
+ 這是學習單難度:{worksheet_level}
1024
+
1025
  請根據逐字稿進行以下工作:
1026
  不要提到 【逐字稿】 這個詞,直接給出工作內容即可
1027
+ 如果是中文素材,請嚴格使用 zh-TW
1028
  {worksheet_prompt}
1029
  """
1030
  messages = [
 
1049
  print("=====worksheet=====")
1050
  return worksheet, worksheet_prompt
1051
 
1052
+ def get_worksheet_prompt(algorithm="Bloom認知階層理論"):
1053
+ bloom_worksheet_prompt = """
1054
  你是個專業的教師,熟悉布魯姆(Benjamin Bloom, 1964) 的認知理論。布魯姆認為人類的能力,大致可分為三個領域(domains),即認知領域(cognitive domain)、情意領域(affective domain)、技能領域 (psychomotor domain)。
1055
 
1056
  【認知領域】涉及知能及其運作,著重心智、學習以及問題解決的工作。認知目標從簡單的認識或記憶能力到複雜的評鑑能力。大部分的教育目標都屬於這個領域。認知領域的目標分為六個層次,每個層次代表不同的心智功能。
 
1061
  - 🌐 綜合:綜合是指將所學到的片斷概念或知識、原理原則或事實,統整成新的整體。用來表示此種能力的行為動詞有:設計、組織、綜合、創造、歸納、聯合等。例:讀完一篇有關防治汙染的文章後,學生能綜合防治汙染的各種方法。
1062
  - 🏅 評鑑:評鑑是認知目標中最高層次的能力,指依據某項標準做價值的判斷的能力。用來表示此能力的行為動詞有:評鑑、判斷、評論、比較、批判等。例:學生能評斷辯論中的謬論。
1063
 
1064
+ 學習單包含以下的內容,將以布魯姆教育目標來建構提問的架構;請用 markdown 格式來呈現。
1065
  - 📝 主題:請使用上傳檔案的檔名作為標題
1066
  - 🔑 重點: 和影片有關重要知識摘要
1067
  - 💭 概念:概念性問題 - 布魯姆的知識層級;數學知識的建構
1068
  - 📊 計算:程序性問題 - 布魯姆的理解層級;和影片相同的例題,類似的練習題 → 計算與步驟操作
1069
  - 🚀 延伸與應用 - 布魯姆的應用、分析、綜合、評鑑層級 → 延伸思考與應用
1070
 
1071
+ 其中,「重點」的題目請用挖空的填空題;在「計算」的程序性問題請以單選題或填空題的形式來建立,需要 3 個題目;「延伸與應用���請使用問答題的形式來建立,一題即可。
1072
+ 題目和題目之間要換行,並加上 point 符號,像是 "-" 或是 "1." 等等
1073
 
1074
  這是範例格式:
1075
+ 🌐 主題:【概念】認識公里
1076
+
1077
+ 🎓【對象】
1078
+ 科目: 數學
1079
+ 年級: 三年級
1080
+ 難度: 基礎
1081
+
1082
+ 🏞️【情境描述】
1083
  狐狸貓和家人出遊,過程中認識測量較長距離的單位「公里」。
1084
 
1085
+ 🔑【影片重點】
1086
+ - 公里是用來測量長距離的單位,通常用於測量很遠的距離。
1087
+ - 1公里等於___公尺,也稱為千米。
1088
+ - 公里的英文簡寫是 ____。
1089
 
1090
+ 🌟【概念】
1091
+ - 請問公里通常用於測量什麼類型的距離?
1092
+ - 如果一圈操場是200公尺,那跑5圈是多少公尺?多少公里?
1093
+ - 為什麼我們需要使用公里這個單位來測量距離?
1094
 
1095
+ 🔢【計算】
1096
+ 1. 一圈操場是200公尺,跑10圈是多少公里?(A) 1公里 (B) 2公里 (C) 3公里 (D) 4公里
1097
+ 2. 如果你跑了5圈操場,運動手環上會顯示你跑了多少公里?
1098
+ 3. 6000公尺等於多少公里?
1099
 
1100
+ 💡【延伸與應用】
1101
+ - 假設你參加一場慈善路跑活動,全程是5公里。如果你已經跑了3公里,還剩下多少公里?你覺得這樣的活動對你的體能有什麼影響?
1102
  """
1103
 
1104
+ Polya_worksheet_prompt = """
1105
+ 你是個專業的教師,熟悉 George Polya(1945) 的數學問題解決策略。
1106
+ Polya提出了一個四步驟的數學問題解決策略,在他影響深遠的經典著作 How to solve it《如何解題》中指出解難過程可分為四個階段:
1107
+ (1) 理解問題 (understanding the problem)
1108
+ (2) 設計解題策略 (devising a plan)
1109
+ (3) 按步解題 (carrying out the plan)
1110
+ (4) 回顧解答 (looking back) (edited)
1111
+
1112
+ 請以此設計學習單並依據文本跟難度給予題目
1113
+ 請一定要使用 zh-TW
1114
+
1115
+ 這是範例格式:
1116
+ 🌐 主題:【概念】認識公里
1117
+
1118
+ 🎓【對象】
1119
+ 科目: 數學
1120
+ 年級: 三年級
1121
+ 難度: 基礎
1122
+
1123
+ 🏞️【情境描述】
1124
+ 狐狸貓和家人出遊,過程中認識測量較長距離的單位「公里」。
1125
 
1126
+ ❓【給出問題】
1127
+ - 如果日月潭環潭自行車道共30公里,狐狸貓騎行了13.7公里後休息,剩餘多少公里尚未騎行?
1128
+
1129
+ 🤔【理解問題】
1130
+ 首先,我們必須完全理解問題的所有細節。在此情境中,我們需要釐清以下幾點:
1131
+ - 日月潭環潭自行車道的總長度為30公里。
1132
+ - 狐狸貓已經騎行了13.7公里。
1133
+ - 我們的目標是計算狐狸貓還剩下多少公里未騎行。
1134
+
1135
+ 🧭【設計解題策略】
1136
+ 接下來,根據我們對問題的理解來設計解決問題的計劃。在此步驟中,我們決定採用哪種策略來解決問題。對於這個問題,最直接的計劃是使用算術減法:
1137
+ - 總公里數(30公里)減去已騎行的公里數(13.7公里)。
1138
+
1139
+ 📝【按步解題】
1140
+ 按照設計的計劃執行解題步驟。在這裡我們執行減法運算:
1141
+ 30−13.7=16.3
1142
+ 這意味著狐狸貓還有16.3公里未騎行。
1143
+
1144
+ ✨【回顧解答】
1145
+ 最後,解題完成後,我們回顧和反思整個解題過程。在這一步,我們驗證計算的結果是否符合邏輯,是否正確解決了原問題。
1146
+ 同時,考慮是否有更有效或簡便的方法來解決類似的問題。在這個例子中,使用直接減法是最簡單直接的方法。
1147
+ 但在其他情境下,可能需要考慮使用圖形、表格或代數表達式等其他策略來解決問題。
1148
+ """
1149
+
1150
+ # CRA教學法
1151
+ cra_worksheet_prompt = """
1152
+ 你是個專業的教師,熟悉CRA教學法,CRA教學法是一種教學策略,
1153
+ CRA正是一種用來促進學生學習和記憶數學的三步教學法,它闡明瞭用這種方式進行教學的具體步驟。
1154
+ CRA的三個步驟互相依賴,運用CRA能建立起一種概念結構,從而形成知識的意義關聯。
1155
+ CRA策略的第一個階段, 即實例(C)階段,是一個“做”的階段。在這一階段,教師用加工材料建模,這些材料包括彩色圓片、立方體、十進位積木、六形六色積木,以及分數積木,等等。在使用這些材料時,必須考慮到兒童的視覺、觸覺及動感經驗。
1156
+ 階段二,即描述(R)階段,是一個“看”的階段。在這一-階段,具體的模型被改成了圖片展示,教師可用手繪圖片或貼紙來對概念進行解釋。
1157
+ 最後一個階段,即抽象(A)階段,是一個抽象的“符號”階段, 在這一階段, 教師使用數字、字母等數學符號(如:2, 6, 3x, +,-等)來進行教學。
1158
+ 運用CRA的前提是學生在學習“規則”前必須學會概念。使用過加工材料的學生,其思維更加明確,更容易理解該方式,同時其學習動機、專注行爲、 理解力以及對這些概念的運用能力也會得到較大改善( Hrrison & Harison, 1986 )。
1159
+ CRA策略可以有效地幫助學生理解以下幾個概念:早期數量關係、位值、計算、分數、小數、測量、幾何、貨幣、百分數、數基、應用題、概率以及統計等
1160
+ 這是範例格式:
1161
+ 🌐 主題:【概念】認識公里
1162
+
1163
+ 🎓【對象】
1164
+ 科目: 數學
1165
+ 年級: 三年級
1166
+ 難度: 基礎
1167
+
1168
+ 【實例(C)階段】
1169
+ 1. 用彩色圓片來解釋什麼是分數?
1170
+ 2. 用立方體來解釋什麼是體積?
1171
+ 3. 用十進位積木來解釋什麼是小數?
1172
+
1173
+ 【描述(R)階段】
1174
+ 1. 用手繪圖片來解釋什麼是分數?
1175
+ 2. 用貼紙來解釋什麼是體積?
1176
+ 3. 用手繪圖片來解釋什麼是小數?
1177
+
1178
+ 【抽象(A)階段】
1179
+ 1. 用數字來解釋什麼是分數?
1180
+ 2. 用字母來解釋什麼是體積?
1181
+ 3. 用數字來解釋什麼是小數?
1182
+
1183
+ """
1184
+
1185
+ case = {
1186
+ "Bloom認知階層理論": bloom_worksheet_prompt,
1187
+ "Polya數學解題法": Polya_worksheet_prompt,
1188
+ "CRA教學法": cra_worksheet_prompt
1189
+ }
1190
+
1191
+ return case[algorithm]
1192
+
1193
  def generate_exam_fine_tune_result(password, worksheet_prompt, df_string_output, exam_result, exam_result_fine_tune_prompt):
1194
  verify_password(password)
1195
 
 
1386
  else:
1387
  pass
1388
 
1389
+ messages.append({"role": "user", "content": user_message})
1390
+ api_endpoint = "https://ci-live-feat-video-ai-dot-junyiacademy.appspot.com/api/v2/jutor/hf-chat"
1391
+ headers = {
1392
+ "Content-Type": "application/json",
1393
+ "x-api-key": JUTOR_CHAT_KEY,
1394
+ }
1395
+ data = {
1396
  "data": {
 
1397
  "messages": messages,
1398
+ "max_tokens": 512,
1399
+ "temperature": 0.9,
1400
+ "model": "gpt-4-1106-preview",
1401
+ "stream": False,
1402
  }
1403
  }
1404
 
1405
+ response = requests.post(api_endpoint, headers=headers, data=json.dumps(data))
 
 
 
 
 
 
 
 
 
1406
 
1407
  if response.status_code == 200:
1408
  # 处理响应数据
 
1728
  web_link = gr.Textbox(label="Enter Web Page Link", visible=False)
1729
  with gr.Tab("學生版"):
1730
  with gr.Row():
 
 
 
 
 
 
 
 
 
 
 
 
1731
  with gr.Column(scale=3):
1732
+ with gr.Tab("文章模式"):
1733
+ reading_passage = gr.Textbox(label="Reading Passage", lines=40)
1734
  with gr.Tab("重點"):
1735
  df_summarise = gr.Textbox(container=True, show_copy_button=True, lines=40)
1736
  with gr.Tab("問題"):
 
1740
  btn_3 = gr.Button()
1741
  gr.Markdown("## 重新生成問題")
1742
  btn_create_question = gr.Button("Create Questions")
1743
+
 
 
1744
  with gr.Accordion("See Details", open=False):
1745
  with gr.Tab("本文"):
1746
  df_string_output = gr.Textbox(lines=40, label="Data Text")
1747
+ with gr.Tab("逐字稿"):
1748
+ simple_html_content = gr.HTML(label="Simple Transcript")
1749
  with gr.Tab("圖文"):
1750
  transcript_html = gr.HTML(label="YouTube Transcript and Video")
1751
  with gr.Tab("投影片"):
 
1759
  with gr.Tab("markdown"):
1760
  gr.Markdown("## 請複製以下 markdown 並貼到你的心智圖工具中,建議使用:https://markmap.js.org/repl")
1761
  mind_map = gr.Textbox(container=True, show_copy_button=True, lines=40, elem_id="mind_map_markdown")
1762
+ with gr.Tab("心智圖",elem_id="mind_map_tab"):
1763
+ mind_map_html = gr.HTML()
1764
+ with gr.Column(scale=2):
1765
+ gr.Markdown("## OPEN AI 模式")
1766
+ chatbot = gr.Chatbot(avatar_images=["https://assets-global.website-files.com/6405517ab71c76a232456561/6405517ab71c7635804565a3_%E9%A0%AD%E8%B2%BC%20_%E8%80%81%E5%B8%AB%20.png", "https://junyitopicimg.s3.amazonaws.com/s4byy--icon.jpe?v=20200513013523726"], label="OPEN AI 模式")
1767
+ thread_id = gr.Textbox(label="thread_id", visible=False)
1768
+ socratic_mode_btn = gr.Checkbox(label="蘇格拉底家教助理模式", value=True)
1769
+ msg = gr.Textbox(label="Message")
1770
+ send_button = gr.Button("Send")
1771
 
1772
+ gr.Markdown("## GROQ 模式")
1773
+ groq_chatbot = gr.Chatbot(label="groq mode chatbot")
1774
+ groq_msg = gr.Textbox(label="Message")
1775
+ groq_send_button = gr.Button("Send")
1776
+
1777
+ gr.Markdown("## JUTOR API 模式")
1778
+ jutor_chatbot = gr.Chatbot(label="jutor mode chatbot")
1779
+ jutor_msg = gr.Textbox(label="Message")
1780
+ jutor_send_button = gr.Button("Send")
1781
 
1782
  with gr.Tab("教師版"):
1783
  with gr.Row():
 
1787
  # with gr.Tab("認知階層評量題目"):
1788
  # cognitive_level_content = gr.Textbox(label="輸入學習目標與內容")
1789
  # cognitive_level_content_btn = gr.Button("生成評量題目")
1790
+ with gr.Tab("學習單"):
1791
+ worksheet_topic = gr.Dropdown(label="選擇學習單主題", choices=["數學", "自然", "國文", "英文", "社會"], value="數學")
1792
+ worksheet_grade = gr.Dropdown(label="選擇學習單年級", choices=["一年級", "二年級", "三年級", "四年級", "五年級", "六年級", "七年級", "八年級", "九年級", "十年級", "十一年級", "十二年級"], value="三年級")
1793
+ worksheet_level = gr.Dropdown(label="選擇學習單難度", choices=["基礎", "中級", "進階"], value="基礎")
1794
+ worksheet_algorithm = gr.Dropdown(label="選擇學習單理論", choices=["Bloom認知階層理論", "Polya數學解題法", "CRA教學法"], value="Bloom認知階層理論")
1795
  worksheet_content_btn = gr.Button("生成學習單")
1796
  with gr.Accordion("prompt", open=False):
1797
  worksheet_prompt = gr.Textbox(label="worksheet_prompt", show_copy_button=True, lines=40)
 
1825
  # btn_2.click(respond, inputs=[btn_2, df_string_output, chatbot, socratic_mode_btn], outputs=[msg, chatbot])
1826
  # btn_3.click(respond, inputs=[btn_3, df_string_output, chatbot, socratic_mode_btn], outputs=[msg, chatbot])
1827
 
1828
+ # chat_with_youtube_transcript
1829
+ # send_button.click(
1830
+ # chat_with_youtube_transcript,
1831
+ # inputs=[password, video_id, thread_id, df_string_output, msg, chatbot, socratic_mode_btn],
1832
+ # outputs=[msg, chatbot, thread_id]
1833
+ # )
1834
  # chat_with_youtube_transcript
1835
  send_button.click(
1836
  chat_with_youtube_transcript,
 
1843
  inputs=[password, groq_msg, df_string_output, groq_chatbot, socratic_mode_btn],
1844
  outputs=[groq_msg, groq_chatbot]
1845
  )
1846
+ # JUTOR API 模式
1847
+ jutor_send_button.click(
1848
+ respond_with_jutor_chat,
1849
+ inputs=[password, jutor_msg, df_string_output, jutor_chatbot, socratic_mode_btn],
1850
+ outputs=[jutor_msg, jutor_chatbot]
1851
+ )
1852
+
1853
+
1854
  # 连接按钮点击事件
1855
  btn_1.click(
1856
  chat_with_youtube_transcript,
 
1889
  transcript_html,
1890
  simple_html_content,
1891
  slide_image,
1892
+ slide_text,
1893
+ reading_passage
1894
+ ]
1895
+ )
1896
 
1897
  youtube_link_btn.click(
1898
  process_youtube_link,
 
1909
  transcript_html,
1910
  simple_html_content,
1911
  slide_image,
1912
+ slide_text,
1913
+ reading_passage
1914
+ ]
1915
+ )
1916
 
1917
  # 当输入网页链接时触发
1918
  # web_link.change(process_web_link, inputs=web_link, outputs=[btn_1, btn_2, btn_3, df_summarise, df_string_output])
 
1920
  # 教師版 學習單
1921
  worksheet_content_btn.click(
1922
  generate_worksheet,
1923
+ inputs=[password, df_string_output, worksheet_topic, worksheet_grade, worksheet_level, worksheet_algorithm],
1924
  outputs=[exam_result, worksheet_prompt]
1925
  )
1926
  exam_result_fine_tune_btn.click(