youngtsai commited on
Commit
a00cecb
·
1 Parent(s): 2bac9cd
Files changed (1) hide show
  1. app.py +149 -249
app.py CHANGED
@@ -7,15 +7,17 @@ import os
7
  from openai import OpenAI
8
  from groq import Groq
9
 
10
- import json
11
-
12
  from youtube_transcript_api import YouTubeTranscriptApi
13
  from youtube_transcript_api._errors import NoTranscriptFound
14
-
15
 
16
  from moviepy.editor import VideoFileClip
17
  from pytube import YouTube
18
  import os
 
 
 
 
19
 
20
  from google.cloud import storage
21
  from google.oauth2 import service_account
@@ -24,11 +26,13 @@ from googleapiclient.http import MediaFileUpload
24
  from googleapiclient.http import MediaIoBaseDownload
25
  from googleapiclient.http import MediaIoBaseUpload
26
 
27
- import io
28
- import time
 
 
 
29
 
30
 
31
- from urllib.parse import urlparse, parse_qs
32
 
33
 
34
  # 假设您的环境变量或Secret的名称是GOOGLE_APPLICATION_CREDENTIALS_JSON
@@ -381,6 +385,47 @@ def get_transcript(video_id):
381
  continue # 當前語言的字幕沒有找到,繼續嘗試下一個語言
382
  return None # 所有嘗試都失敗,返回None
383
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
384
  def process_transcript_and_screenshots(video_id):
385
  print("====process_transcript_and_screenshots====")
386
 
@@ -457,7 +502,13 @@ def process_transcript_and_screenshots_on_gcs(video_id):
457
  is_transcript_exists = gcs_check_file_exists(gcs_client, bucket_name, transcript_blob_name)
458
  if not is_transcript_exists:
459
  # 从YouTube获取逐字稿并上传
460
- transcript = get_transcript(video_id)
 
 
 
 
 
 
461
  if transcript:
462
  print("成功獲取字幕")
463
  else:
@@ -999,243 +1050,36 @@ def change_questions(password, df_string):
999
  print("=====get_questions=====")
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
1007
- df_string_json = json.loads(df_string)
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
- 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 = [
1031
- {"role": "system", "content": sys_content},
1032
- {"role": "user", "content": user_content}
1033
- ]
1034
-
1035
- print("=====generate_worksheet messages=====")
1036
- print(messages)
1037
- print("=====generate_worksheet messages=====")
1038
 
 
 
 
 
 
 
 
 
1039
  request_payload = {
1040
- "model": "gpt-4-1106-preview",
1041
  "messages": messages,
1042
- "max_tokens": 4000,
1043
  }
 
 
1044
 
1045
- response = OPEN_AI_CLIENT.chat.completions.create(**request_payload)
1046
- worksheet = response.choices[0].message.content.strip()
1047
- print("=====worksheet=====")
1048
- print(worksheet)
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
- 【認知領域】涉及知能及其運作,著重心智、學習以及問題解決的工作。認知目標從簡單的認識或記憶能力到複雜的評鑑能力。大部分的教育目標都屬於這個領域。認知領域的目標分為六個層次,每個層次代表不同的心智功能。
1057
- - 📖 知識:在認知目標中知識是最低層次的能力,包括名詞、事實、規則和原理原則等的認識和記憶。用來表示此種能力的行為動詞有:指出、寫出、界定、說明、舉例、命名、認明等。例:能在地圖上指出長江流經的省分。
1058
- - 🤔 理解:理解是指能把握所學過知識或概念的意義,包含轉譯、解釋、推論等能力。代表此能力的行為動詞有:解釋、說明、區別、舉例、摘要、歸納等。例:能解釋光合作用。
1059
- - 🛠️ 應用:應用是指將所學到的規則、方法、步驟、原理、原則和概念,應用到新情境的能力。用來表示此能力的行為動詞有:預測、證明、解決、修改、表現、應用等。例:學生能預測抽出容器內之氣體對容器的影響。
1060
- - 🔍 分析:分析是指將所學到的概念或原則,分析為各個構成的部分,或找出各部分之間的相互關係,包括要素、關係及組織原理等的分析。用以表示此種能力的行為動詞有:選出、分析、判斷:區分、指出某些組成要素、指出某些的相互關係等。例:讀完某篇文章後,學生能區分事實和意見。
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
-
1196
- # df_string delete embed_url, screenshot_path
1197
- df_string_json = json.loads(df_string_output)
1198
- for entry in df_string_json:
1199
- entry.pop('embed_url', None)
1200
- entry.pop('screenshot_path', None)
1201
- df_string_text = json.dumps(df_string_json, ensure_ascii=False, indent=2)
1202
-
1203
- # 使用 OpenAI 生成基于上传数据的问题
1204
- sys_content = "你是一個擅長資料分析跟影片教學備課的老師,請精讀資料文本,自行判斷資料的種類,使用 zh-TW"
1205
- user_content = f"""
1206
- 這是逐字稿:{df_string_text}
1207
- ---
1208
- 這是預設的 prompt
1209
- {worksheet_prompt}
1210
- ---
1211
- 產生了以下的結果:
1212
- {exam_result}
1213
- ---
1214
- 但我不是很滿意,請根據以下的調整,產生新的結果
1215
- {exam_result_fine_tune_prompt}
1216
- """
1217
- messages = [
1218
- {"role": "system", "content": sys_content},
1219
- {"role": "user", "content": user_content}
1220
- ]
1221
-
1222
- print("=====generate_exam_fine_tune_result messages=====")
1223
- print(messages)
1224
- print("=====generate_exam_fine_tune_result messages=====")
1225
-
1226
  request_payload = {
1227
- "model": "gpt-4-1106-preview",
1228
  "messages": messages,
1229
- "max_tokens": 4000,
1230
  }
1231
-
1232
- response = OPEN_AI_CLIENT.chat.completions.create(**request_payload)
1233
- exam_fine_tune_result = response.choices[0].message.content.strip()
1234
- print("=====exam_fine_tune_result=====")
1235
- print(exam_fine_tune_result)
1236
- print("=====exam_fine_tune_result=====")
1237
- return exam_fine_tune_result
1238
-
1239
 
1240
  # ---- Chatbot ----
1241
  def respond(password, user_message, data, chat_history, socratic_mode=False):
@@ -1689,6 +1533,41 @@ def next_slide():
1689
  return update_slide(1)
1690
 
1691
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1692
 
1693
  HEAD = """
1694
  <meta charset="UTF-8">
@@ -1720,11 +1599,11 @@ HEAD = """
1720
 
1721
  with gr.Blocks() as demo:
1722
  with gr.Row():
1723
- password = gr.Textbox(label="Password", type="password", elem_id="password_input")
1724
  file_upload = gr.File(label="Upload your CSV or Word file", visible=False)
1725
- youtube_link = gr.Textbox(label="Enter YouTube Link", elem_id="youtube_link_input")
1726
  video_id = gr.Textbox(label="video_id", visible=False)
1727
- youtube_link_btn = gr.Button("Submit_YouTube_Link")
1728
  web_link = gr.Textbox(label="Enter Web Page Link", visible=False)
1729
  with gr.Tab("學生版"):
1730
  with gr.Row():
@@ -1781,20 +1660,27 @@ with gr.Blocks() as demo:
1781
 
1782
  with gr.Tab("教師版"):
1783
  with gr.Row():
1784
- gr.Markdown("## 教育評量饗宴")
 
 
1785
  with gr.Row():
1786
  with gr.Column(scale=1):
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)
 
 
 
 
 
 
 
1798
  with gr.Tab("素養導向閱讀題組"):
1799
  literacy_oriented_reading_content = gr.Textbox(label="輸入閱讀材料")
1800
  literacy_oriented_reading_content_btn = gr.Button("生成閱讀理解題")
@@ -1807,8 +1693,9 @@ with gr.Blocks() as demo:
1807
  # with gr.Tab("後設認知"):
1808
  # metacognition_content = gr.Textbox(label="輸入後設認知相關問題")
1809
  # metacognition_content_btn = gr.Button("生成後設認知問題")
1810
- with gr.Column(scale=1):
1811
  # 生成對應不同模式的結果
 
1812
  exam_result = gr.Textbox(label="初次生成結果", show_copy_button=True)
1813
  exam_result_fine_tune_prompt = gr.Textbox(label="根據結果,輸入你想更改的想法")
1814
  exam_result_fine_tune_btn = gr.Button("微調結果")
@@ -1919,14 +1806,27 @@ with gr.Blocks() as demo:
1919
 
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(
1927
  generate_exam_fine_tune_result,
1928
- inputs=[password, worksheet_prompt, df_string_output, exam_result, exam_result_fine_tune_prompt],
1929
  outputs=[exam_result_fine_result]
1930
  )
1931
 
 
 
 
 
 
 
1932
  demo.launch(allowed_paths=["videos"])
 
7
  from openai import OpenAI
8
  from groq import Groq
9
 
 
 
10
  from youtube_transcript_api import YouTubeTranscriptApi
11
  from youtube_transcript_api._errors import NoTranscriptFound
12
+ import yt_dlp
13
 
14
  from moviepy.editor import VideoFileClip
15
  from pytube import YouTube
16
  import os
17
+ import io
18
+ import time
19
+ import json
20
+ from urllib.parse import urlparse, parse_qs
21
 
22
  from google.cloud import storage
23
  from google.oauth2 import service_account
 
26
  from googleapiclient.http import MediaIoBaseDownload
27
  from googleapiclient.http import MediaIoBaseUpload
28
 
29
+ from educational_material import EducationalMaterial
30
+
31
+
32
+
33
+
34
 
35
 
 
36
 
37
 
38
  # 假设您的环境变量或Secret的名称是GOOGLE_APPLICATION_CREDENTIALS_JSON
 
385
  continue # 當前語言的字幕沒有找到,繼續嘗試下一個語言
386
  return None # 所有嘗試都失敗,返回None
387
 
388
+ def generate_transcription(video_id):
389
+ youtube_url = f'https://www.youtube.com/watch?v={video_id}'
390
+ codec_name = "mp3"
391
+ ydl_opts = {
392
+ 'format': 'bestaudio/best',
393
+ 'postprocessors': [{
394
+ 'key': 'FFmpegExtractAudio',
395
+ 'preferredcodec': codec_name,
396
+ 'preferredquality': '192'
397
+ }],
398
+ 'outtmpl': f'{video_id}.%(ext)s',
399
+ }
400
+ print("===download video mp3===")
401
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
402
+ ydl.download([youtube_url])
403
+
404
+ audio_path = f'{video_id}.{codec_name}'
405
+
406
+ print("===transcription by open ai===")
407
+ with open(audio_path, "rb") as audio_file:
408
+ srt_content = OPEN_AI_CLIENT.audio.transcriptions.create(
409
+ model="whisper-1",
410
+ file=audio_file,
411
+ response_format="verbose_json",
412
+ timestamp_granularities=["segment"],
413
+ prompt="Transcribe the following audio file. if chinese, please using 'language: zh-TW' in the prompt.",
414
+ )
415
+
416
+ # get segments
417
+ segments = srt_content.segments
418
+ transcription = [
419
+ {
420
+ "text": item["text"],
421
+ "start": int(item["start"]),
422
+ "duration": int(item["end"] - item["start"])
423
+ }
424
+ for item in segments
425
+ ]
426
+ return transcription
427
+
428
+
429
  def process_transcript_and_screenshots(video_id):
430
  print("====process_transcript_and_screenshots====")
431
 
 
502
  is_transcript_exists = gcs_check_file_exists(gcs_client, bucket_name, transcript_blob_name)
503
  if not is_transcript_exists:
504
  # 从YouTube获取逐字稿并上传
505
+ try:
506
+ transcript = get_transcript(video_id)
507
+ except:
508
+ # call open ai whisper
509
+ print("===call open ai whisper===")
510
+ transcript = generate_transcription(video_id)
511
+
512
  if transcript:
513
  print("成功獲取字幕")
514
  else:
 
1050
  print("=====get_questions=====")
1051
  return q1, q2, q3
1052
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1053
 
1054
+ # AI 生成教學素材
1055
+ def on_generate_ai_content(password, df_string, topic, grade, level, specific_feature, content_type):
1056
+ verify_password(password)
1057
+ material = EducationalMaterial(df_string, topic, grade, level, specific_feature, content_type)
1058
+ prompt = material.generate_content_prompt()
1059
+ user_content = material.build_user_content()
1060
+ messages = material.build_messages(user_content)
1061
+ ai_model_name = "gpt-4-1106-preview"
1062
  request_payload = {
1063
+ "model": ai_model_name,
1064
  "messages": messages,
1065
+ "max_tokens": 4000 # 举例,实际上您可能需要更详细的配置
1066
  }
1067
+ ai_content = material.send_ai_request(OPEN_AI_CLIENT, request_payload)
1068
+ return ai_content, prompt, prompt
1069
 
1070
+ def generate_exam_fine_tune_result(password, exam_result_prompt , df_string_output, exam_result, exam_result_fine_tune_prompt):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1071
  verify_password(password)
1072
+ material = EducationalMaterial(df_string_output, "", "", "", "", "")
1073
+ user_content = material.build_fine_tune_user_content(exam_result_prompt, exam_result, exam_result_fine_tune_prompt)
1074
+ messages = material.build_messages(user_content)
1075
+ ai_model_name = "gpt-4-1106-preview"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1076
  request_payload = {
1077
+ "model": ai_model_name,
1078
  "messages": messages,
1079
+ "max_tokens": 4000 # 举例,实际上您可能需要更详细的配置
1080
  }
1081
+ ai_content = material.send_ai_request(OPEN_AI_CLIENT, request_payload)
1082
+ return ai_content
 
 
 
 
 
 
1083
 
1084
  # ---- Chatbot ----
1085
  def respond(password, user_message, data, chat_history, socratic_mode=False):
 
1533
  return update_slide(1)
1534
 
1535
 
1536
+ IS_PASSWORD_SHOW = True
1537
+ IS_YOUTUBE_LINK_SHOW = True
1538
+ IS_YOUTUBE_LINK_BTN_SHOW = True
1539
+
1540
+ def init_params(text, request: gr.Request):
1541
+ if request:
1542
+ print("Request headers dictionary:", request.headers)
1543
+ print("IP address:", request.client.host)
1544
+ print("Query parameters:", dict(request.query_params))
1545
+ # url = request.url
1546
+ print("Request URL:", request.url)
1547
+
1548
+ # if youtube_link in query_params
1549
+ if "youtube_id" in request.query_params:
1550
+ youtube_id = request.query_params["youtube_id"]
1551
+ youtube_link = f"https://www.youtube.com/watch?v={youtube_id}"
1552
+ print(f"youtube_link: {youtube_link}")
1553
+ else:
1554
+ youtube_link = ""
1555
+ print("youtube_link not in query_params")
1556
+
1557
+ origin = request.headers.get("origin", "")
1558
+ if "junyiacademy" in origin:
1559
+ password_text = "6161"
1560
+ global IS_PASSWORD_SHOW
1561
+ global IS_YOUTUBE_LINK_SHOW
1562
+ global IS_YOUTUBE_LINK_BTN_SHOW
1563
+ IS_PASSWORD_SHOW = False
1564
+ IS_YOUTUBE_LINK_SHOW = False
1565
+ IS_YOUTUBE_LINK_BTN_SHOW = False
1566
+
1567
+ else:
1568
+ password_text = ""
1569
+
1570
+ return password_text, youtube_link
1571
 
1572
  HEAD = """
1573
  <meta charset="UTF-8">
 
1599
 
1600
  with gr.Blocks() as demo:
1601
  with gr.Row():
1602
+ password = gr.Textbox(label="Password", type="password", elem_id="password_input", visible=IS_PASSWORD_SHOW)
1603
  file_upload = gr.File(label="Upload your CSV or Word file", visible=False)
1604
+ youtube_link = gr.Textbox(label="Enter YouTube Link", elem_id="youtube_link_input", visible=IS_YOUTUBE_LINK_SHOW)
1605
  video_id = gr.Textbox(label="video_id", visible=False)
1606
+ youtube_link_btn = gr.Button("Submit_YouTube_Link", elem_id="youtube_link_btn", visible=IS_YOUTUBE_LINK_BTN_SHOW)
1607
  web_link = gr.Textbox(label="Enter Web Page Link", visible=False)
1608
  with gr.Tab("學生版"):
1609
  with gr.Row():
 
1660
 
1661
  with gr.Tab("教師版"):
1662
  with gr.Row():
1663
+ content_topic = gr.Dropdown(label="選擇主題", choices=["數學", "自然", "國文", "英文", "社會"], value="數學")
1664
+ content_grade = gr.Dropdown(label="選擇年級", choices=["一年級", "二年級", "三年級", "四年級", "五年級", "六年級", "七年級", "八年級", "九年級", "十年級", "十一年級", "十二年級"], value="三年級")
1665
+ content_level = gr.Dropdown(label="差異化教學", choices=["基礎", "中級", "進階"], value="基礎")
1666
  with gr.Row():
1667
  with gr.Column(scale=1):
1668
  # with gr.Tab("認知階層評量題目"):
1669
  # cognitive_level_content = gr.Textbox(label="輸入學習目標與內容")
1670
  # cognitive_level_content_btn = gr.Button("生成評量題目")
1671
  with gr.Tab("學習單"):
1672
+ worksheet_content_type_name = gr.Textbox(value="worksheet", visible=False)
1673
+ worksheet_algorithm = gr.Dropdown(label="選擇教學策略或理論", choices=["Bloom認知階層理論", "Polya數學解題法", "CRA教學法"], value="Bloom認知階層理論")
1674
+ worksheet_content_btn = gr.Button("生成學習單 📄")
 
 
1675
  with gr.Accordion("prompt", open=False):
1676
  worksheet_prompt = gr.Textbox(label="worksheet_prompt", show_copy_button=True, lines=40)
1677
+ with gr.Tab("課程計畫"):
1678
+ lesson_plan_content_type_name = gr.Textbox(value="lesson_plan", visible=False)
1679
+ lesson_plan_time = gr.Slider(label="選擇課程時間(分鐘)", minimum=10, maximum=120, step=5, value=40)
1680
+ lesson_plan_btn = gr.Button("生成課程計畫")
1681
+ with gr.Accordion("prompt", open=False):
1682
+ lesson_plan_prompt = gr.Textbox(label="worksheet_prompt", show_copy_button=True, lines=40)
1683
+
1684
  with gr.Tab("素養導向閱讀題組"):
1685
  literacy_oriented_reading_content = gr.Textbox(label="輸入閱讀材料")
1686
  literacy_oriented_reading_content_btn = gr.Button("生成閱讀理解題")
 
1693
  # with gr.Tab("後設認知"):
1694
  # metacognition_content = gr.Textbox(label="輸入後設認知相關問題")
1695
  # metacognition_content_btn = gr.Button("生成後設認知問題")
1696
+ with gr.Column(scale=2):
1697
  # 生成對應不同模式的結果
1698
+ exam_result_prompt = gr.Textbox(visible=False)
1699
  exam_result = gr.Textbox(label="初次生成結果", show_copy_button=True)
1700
  exam_result_fine_tune_prompt = gr.Textbox(label="根據結果,輸入你想更改的想法")
1701
  exam_result_fine_tune_btn = gr.Button("微調結果")
 
1806
 
1807
  # 教師版 學習單
1808
  worksheet_content_btn.click(
1809
+ on_generate_ai_content,
1810
+ inputs=[password, df_string_output, content_topic, content_grade, content_level, worksheet_algorithm, worksheet_content_type_name],
1811
+ outputs=[exam_result, worksheet_prompt, exam_result_prompt]
1812
+ )
1813
+ lesson_plan_btn.click(
1814
+ on_generate_ai_content,
1815
+ inputs=[password, df_string_output, content_topic, content_grade, content_level, lesson_plan_time, lesson_plan_content_type_name],
1816
+ outputs=[exam_result, lesson_plan_prompt, exam_result_prompt]
1817
  )
1818
+
1819
+ # 生成結果微調
1820
  exam_result_fine_tune_btn.click(
1821
  generate_exam_fine_tune_result,
1822
+ inputs=[password, exam_result_prompt, df_string_output, exam_result, exam_result_fine_tune_prompt],
1823
  outputs=[exam_result_fine_result]
1824
  )
1825
 
1826
+ demo.load(
1827
+ init_params,
1828
+ inputs =[youtube_link],
1829
+ outputs = [password , youtube_link]
1830
+ )
1831
+
1832
  demo.launch(allowed_paths=["videos"])