Spaces:
Running
Running
update
Browse files- app.py +158 -110
- educational_material.py +136 -55
app.py
CHANGED
@@ -30,8 +30,6 @@ from educational_material import EducationalMaterial
|
|
30 |
from storage_service import GoogleCloudStorage
|
31 |
|
32 |
|
33 |
-
|
34 |
-
|
35 |
is_env_local = os.getenv("IS_ENV_LOCAL", "false") == "true"
|
36 |
print(f"is_env_local: {is_env_local}")
|
37 |
|
@@ -375,7 +373,7 @@ def generate_transcription(video_id):
|
|
375 |
file=audio_file,
|
376 |
response_format="verbose_json",
|
377 |
timestamp_granularities=["segment"],
|
378 |
-
prompt="
|
379 |
)
|
380 |
|
381 |
# get segments
|
@@ -858,6 +856,7 @@ def generate_summarise(df_string):
|
|
858 |
如果是資料類型,請提估欄位敘述、資料樣態與資料分析,告訴學生這張表的意義,以及可能的結論與對應方式
|
859 |
|
860 |
如果是影片類型,請提估影片內容,告訴學生這部影片的意義,
|
|
|
861 |
小範圍切出不同段落的相對應時間軸的重點摘要,最多不超過五段
|
862 |
注意不要遺漏任何一段時間軸的內容
|
863 |
格式為 【start - end】: 摘要
|
@@ -866,9 +865,9 @@ def generate_summarise(df_string):
|
|
866 |
整體格式為:
|
867 |
🗂️ 1. 內容類型:?
|
868 |
📚 2. 整體摘要
|
869 |
-
🔖 3.
|
870 |
-
🔑 4.
|
871 |
-
💡 5.
|
872 |
❓ 6. 延伸小問題
|
873 |
"""
|
874 |
|
@@ -1305,102 +1304,128 @@ def chat_with_youtube_transcript(password, youtube_id, thread_id, trascript, use
|
|
1305 |
error_msg = "你的訊息太長了,請縮短訊息長度至五百字以內"
|
1306 |
raise gr.Error(error_msg)
|
1307 |
|
1308 |
-
|
1309 |
-
|
1310 |
-
|
1311 |
-
|
1312 |
-
|
1313 |
-
|
1314 |
-
|
1315 |
-
|
1316 |
-
|
1317 |
-
|
1318 |
-
|
1319 |
-
|
1320 |
-
|
1321 |
-
|
1322 |
-
|
1323 |
-
|
1324 |
-
|
1325 |
-
|
1326 |
-
|
1327 |
-
|
1328 |
-
|
1329 |
-
|
1330 |
-
|
1331 |
-
|
1332 |
-
|
1333 |
-
|
1334 |
-
|
1335 |
-
|
1336 |
-
|
1337 |
-
|
1338 |
-
|
1339 |
-
entry
|
1340 |
-
|
1341 |
-
|
1342 |
-
|
1343 |
-
|
1344 |
-
|
1345 |
-
|
1346 |
-
|
1347 |
-
|
1348 |
-
|
1349 |
-
|
1350 |
-
|
1351 |
-
|
1352 |
-
|
1353 |
-
|
1354 |
-
|
1355 |
-
|
1356 |
-
|
1357 |
-
|
1358 |
-
|
1359 |
-
|
1360 |
-
|
1361 |
-
|
|
|
1362 |
|
1363 |
-
|
1364 |
-
|
1365 |
-
|
1366 |
-
|
1367 |
-
|
1368 |
-
|
1369 |
-
|
1370 |
-
|
1371 |
-
|
1372 |
-
|
1373 |
-
|
1374 |
-
|
1375 |
-
|
1376 |
|
1377 |
-
|
1378 |
-
|
1379 |
-
|
1380 |
-
|
1381 |
-
|
1382 |
-
|
1383 |
|
1384 |
-
|
1385 |
-
|
1386 |
-
|
1387 |
-
|
1388 |
-
|
1389 |
-
|
1390 |
-
|
1391 |
-
|
1392 |
-
|
1393 |
|
1394 |
-
|
1395 |
-
|
1396 |
-
|
1397 |
-
|
1398 |
-
|
1399 |
-
|
|
|
|
|
|
|
1400 |
|
1401 |
# 返回聊天历史和空字符串清空输入框
|
1402 |
return "", chat_history, thread.id
|
1403 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1404 |
def poll_run_status(run_id, thread_id, timeout=600, poll_interval=5):
|
1405 |
"""
|
1406 |
Polls the status of a Run and handles different statuses appropriately.
|
@@ -1586,22 +1611,24 @@ with gr.Blocks() as demo:
|
|
1586 |
with gr.Tab("心智圖",elem_id="mind_map_tab"):
|
1587 |
mind_map_html = gr.HTML()
|
1588 |
with gr.Column(scale=2):
|
1589 |
-
gr.
|
1590 |
-
|
1591 |
-
|
1592 |
-
|
1593 |
-
|
1594 |
-
|
1595 |
-
|
1596 |
-
|
1597 |
-
|
1598 |
-
|
1599 |
-
|
1600 |
-
|
1601 |
-
|
1602 |
-
|
1603 |
-
|
1604 |
-
|
|
|
|
|
1605 |
|
1606 |
with gr.Tab("教師版"):
|
1607 |
with gr.Row():
|
@@ -1625,10 +1652,17 @@ with gr.Blocks() as demo:
|
|
1625 |
lesson_plan_btn = gr.Button("生成課程計畫 📕")
|
1626 |
with gr.Accordion("prompt", open=False):
|
1627 |
lesson_plan_prompt = gr.Textbox(label="worksheet_prompt", show_copy_button=True, lines=40)
|
|
|
|
|
|
|
|
|
|
|
|
|
1628 |
|
1629 |
with gr.Tab("素養導向閱讀題組"):
|
1630 |
literacy_oriented_reading_content = gr.Textbox(label="輸入閱讀材料")
|
1631 |
literacy_oriented_reading_content_btn = gr.Button("生成閱讀理解題")
|
|
|
1632 |
# with gr.Tab("自我評估"):
|
1633 |
# self_assessment_content = gr.Textbox(label="輸入自評問卷或檢查表")
|
1634 |
# self_assessment_content_btn = gr.Button("生成自評問卷")
|
@@ -1664,11 +1698,20 @@ with gr.Blocks() as demo:
|
|
1664 |
# outputs=[msg, chatbot, thread_id]
|
1665 |
# )
|
1666 |
# chat_with_youtube_transcript
|
|
|
|
|
1667 |
send_button.click(
|
1668 |
chat_with_youtube_transcript,
|
1669 |
inputs=[password, video_id, thread_id, df_string_output, msg, chatbot, socratic_mode_btn],
|
1670 |
outputs=[msg, chatbot, thread_id]
|
1671 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1672 |
# GROQ 模式
|
1673 |
groq_send_button.click(
|
1674 |
chat_with_groq,
|
@@ -1760,6 +1803,11 @@ with gr.Blocks() as demo:
|
|
1760 |
inputs=[password, df_string_output, content_topic, content_grade, content_level, lesson_plan_time, lesson_plan_content_type_name],
|
1761 |
outputs=[exam_result, lesson_plan_prompt, exam_result_prompt]
|
1762 |
)
|
|
|
|
|
|
|
|
|
|
|
1763 |
|
1764 |
# 生成結果微調
|
1765 |
exam_result_fine_tune_btn.click(
|
|
|
30 |
from storage_service import GoogleCloudStorage
|
31 |
|
32 |
|
|
|
|
|
33 |
is_env_local = os.getenv("IS_ENV_LOCAL", "false") == "true"
|
34 |
print(f"is_env_local: {is_env_local}")
|
35 |
|
|
|
373 |
file=audio_file,
|
374 |
response_format="verbose_json",
|
375 |
timestamp_granularities=["segment"],
|
376 |
+
prompt="如果逐字稿有中文,請使用繁體中文 zh-TW",
|
377 |
)
|
378 |
|
379 |
# get segments
|
|
|
856 |
如果是資料類型,請提估欄位敘述、資料樣態與資料分析,告訴學生這張表的意義,以及可能的結論與對應方式
|
857 |
|
858 |
如果是影片類型,請提估影片內容,告訴學生這部影片的意義,
|
859 |
+
整體摘要在一百字以內
|
860 |
小範圍切出不同段落的相對應時間軸的重點摘要,最多不超過五段
|
861 |
注意不要遺漏任何一段時間軸的內容
|
862 |
格式為 【start - end】: 摘要
|
|
|
865 |
整體格式為:
|
866 |
🗂️ 1. 內容類型:?
|
867 |
📚 2. 整體摘要
|
868 |
+
🔖 3. 重點概念
|
869 |
+
🔑 4. 關鍵時刻
|
870 |
+
💡 5. 為什麼我們要學這個?
|
871 |
❓ 6. 延伸小問題
|
872 |
"""
|
873 |
|
|
|
1304 |
error_msg = "你的訊息太長了,請縮短訊息長度至五百字以內"
|
1305 |
raise gr.Error(error_msg)
|
1306 |
|
1307 |
+
try:
|
1308 |
+
assistant_id = "asst_kmvZLNkDUYaNkMNtZEAYxyPq"
|
1309 |
+
client = OPEN_AI_CLIENT
|
1310 |
+
|
1311 |
+
# 從 file 拿逐字稿資料
|
1312 |
+
# instructions = f"""
|
1313 |
+
# 你是一個擅長資料分析跟影片教學的老師,user 為學生
|
1314 |
+
# 請根據 assistant beta 的上傳資料
|
1315 |
+
# 如果 file 內有找到 file.content["{youtube_id}"] 為資料文本,自行判斷資料的種類,
|
1316 |
+
# 如果沒有資料,請告訴用戶沒有逐字稿資料,但仍然可以進行對話,使用台灣人的口與表達,及繁體中文 zh-TW
|
1317 |
+
# 請嚴格執行,只根據 file.content["{youtube_id}"] 為資料文本,沒有就是沒有資料,不要引用其他資料
|
1318 |
+
|
1319 |
+
# 如果是影片類型,不用解釋逐字稿格式,直接回答學生問題
|
1320 |
+
# socratic_mode = {socratic_mode}
|
1321 |
+
# 如果 socratic_mode = True,
|
1322 |
+
# - 請用蘇格拉底式的提問方式,引導學生思考,並且給予學生一些提示
|
1323 |
+
# - 不要直接給予答案,讓學生自己思考
|
1324 |
+
# - 但可以給予一些提示跟引導,例如給予影片的時間軸,讓學生自己去找答案
|
1325 |
+
# - 在你回答的開頭標註【蘇格拉底助教:{youtube_id} 】
|
1326 |
+
# 如果 socratic_mode = False,
|
1327 |
+
# - 直接回答學生問題
|
1328 |
+
# - 在你回答的開頭標註【一般學習精靈:{youtube_id} 】
|
1329 |
+
# 如果學生問了一些問題你無法判斷,請告訴學生你無法判斷,並建議學生可以問其他問題
|
1330 |
+
# 或者你可以反問學生一些問題,幫助學生更好的理解資料
|
1331 |
+
# 如果學生的問題與資料文本無關,請告訴學生你無法回答超出範圍的問題
|
1332 |
+
# 最後只要是參考逐字稿資料,請在回答的最後標註【參考資料:(分):(秒)】
|
1333 |
+
# """
|
1334 |
+
|
1335 |
+
# 直接安排逐字稿資料 in instructions
|
1336 |
+
trascript_json = json.loads(trascript)
|
1337 |
+
# 移除 embed_url, screenshot_path
|
1338 |
+
for entry in trascript_json:
|
1339 |
+
entry.pop('embed_url', None)
|
1340 |
+
entry.pop('screenshot_path', None)
|
1341 |
+
trascript_text = json.dumps(trascript_json, ensure_ascii=False, indent=2)
|
1342 |
+
|
1343 |
+
instructions = f"""
|
1344 |
+
逐字稿資料:{trascript_text}
|
1345 |
+
-------------------------------------
|
1346 |
+
你是一個擅長資料分析跟影片教學的老師,user 為學生
|
1347 |
+
如果是影片類型,不用解釋逐字稿格式,直接回答學生問題
|
1348 |
+
socratic_mode = {socratic_mode}
|
1349 |
+
如果 socratic_mode = True,
|
1350 |
+
- 請用蘇格拉底式的提問方式,引導學生思考,並且給予學生一些提示
|
1351 |
+
- 不要直接給予答案,讓學生自己思考
|
1352 |
+
- 但可以給予一些提示跟引導,例如給予影片的時間軸,讓學生自己去找答案
|
1353 |
+
- 在你回答的開頭標註【蘇格拉底助教:{youtube_id} 】
|
1354 |
+
如果 socratic_mode = False,
|
1355 |
+
- 直接回答學生問題
|
1356 |
+
- 在你回答的開頭標註【一般學習精靈:{youtube_id} 】
|
1357 |
+
如果學生問了一些問題你無法判斷,請告訴學生你無法判斷,並建議學生可以問其他問題
|
1358 |
+
或者你可以反問學生一些問題,幫助學生更好的理解資料
|
1359 |
+
如果學生的問題與資料文本無關,請告訴學生你無法回答超出範圍的問題
|
1360 |
+
最後只要是參考逐字稿資料,請在回答的最後標註【參考資料:(分):(秒)】
|
1361 |
+
"""
|
1362 |
|
1363 |
+
# 创建线程
|
1364 |
+
if not thread_id:
|
1365 |
+
thread = client.beta.threads.create()
|
1366 |
+
thread_id = thread.id
|
1367 |
+
else:
|
1368 |
+
thread = client.beta.threads.retrieve(thread_id)
|
1369 |
+
|
1370 |
+
# 向线程添加用户的消息
|
1371 |
+
client.beta.threads.messages.create(
|
1372 |
+
thread_id=thread.id,
|
1373 |
+
role="user",
|
1374 |
+
content=user_message
|
1375 |
+
)
|
1376 |
|
1377 |
+
# 运行助手,生成响应
|
1378 |
+
run = client.beta.threads.runs.create(
|
1379 |
+
thread_id=thread.id,
|
1380 |
+
assistant_id=assistant_id,
|
1381 |
+
instructions=instructions,
|
1382 |
+
)
|
1383 |
|
1384 |
+
# 等待助手响应,设定最大等待时间为 30 秒
|
1385 |
+
run_status = poll_run_status(run.id, thread.id, timeout=30)
|
1386 |
+
# 获取助手的响应消息
|
1387 |
+
if run_status == "completed":
|
1388 |
+
messages = client.beta.threads.messages.list(thread_id=thread.id)
|
1389 |
+
# [MessageContentText(text=Text(annotations=[], value='您好!有什麼我可以幫助您的嗎?如果有任何問題或需要指導,請隨時告訴我!'), type='text')]
|
1390 |
+
response_text = messages.data[0].content[0].text.value
|
1391 |
+
else:
|
1392 |
+
response_text = "學習精靈有點累,請稍後再試!"
|
1393 |
|
1394 |
+
# 更新聊天历史
|
1395 |
+
new_chat_history = (user_message, response_text)
|
1396 |
+
if chat_history is None:
|
1397 |
+
chat_history = [new_chat_history]
|
1398 |
+
else:
|
1399 |
+
chat_history.append(new_chat_history)
|
1400 |
+
except Exception as e:
|
1401 |
+
print(f"Error: {e}")
|
1402 |
+
raise gr.Error(f"Error: {e}")
|
1403 |
|
1404 |
# 返回聊天历史和空字符串清空输入框
|
1405 |
return "", chat_history, thread.id
|
1406 |
|
1407 |
+
def process_open_ai_audio_to_chatbot(password, audio_url):
|
1408 |
+
verify_password(password)
|
1409 |
+
if audio_url:
|
1410 |
+
with open(audio_url, "rb") as audio_file:
|
1411 |
+
file_size = os.path.getsize(audio_url)
|
1412 |
+
if file_size > 2000000:
|
1413 |
+
raise gr.Error("檔案大小超過,請不要超過 60秒")
|
1414 |
+
else:
|
1415 |
+
response = OPEN_AI_CLIENT.audio.transcriptions.create(
|
1416 |
+
model="whisper-1",
|
1417 |
+
file=audio_file,
|
1418 |
+
response_format="text"
|
1419 |
+
)
|
1420 |
+
# response 拆解 dict
|
1421 |
+
print("=== response ===")
|
1422 |
+
print(response)
|
1423 |
+
print("=== response ===")
|
1424 |
+
else:
|
1425 |
+
response = ""
|
1426 |
+
|
1427 |
+
return response
|
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.
|
|
|
1611 |
with gr.Tab("心智圖",elem_id="mind_map_tab"):
|
1612 |
mind_map_html = gr.HTML()
|
1613 |
with gr.Column(scale=2):
|
1614 |
+
with gr.Tab("OPENAI"):
|
1615 |
+
gr.Markdown("## OPEN AI 模式")
|
1616 |
+
chatbot = gr.Chatbot(avatar_images=["https://junyi-avatar.s3.ap-northeast-1.amazonaws.com/live/%20%20foxcat-star-18.png?v=20231113095823614", "https://junyitopicimg.s3.amazonaws.com/s4byy--icon.jpe?v=20200513013523726"], label="OPEN AI 模式")
|
1617 |
+
thread_id = gr.Textbox(label="thread_id", visible=False)
|
1618 |
+
socratic_mode_btn = gr.Checkbox(label="蘇格拉底家教助理模式", value=True)
|
1619 |
+
openai_chatbot_audio_input = gr.Audio(sources=["microphone"], type="filepath")
|
1620 |
+
msg = gr.Textbox(label="Message")
|
1621 |
+
send_button = gr.Button("Send")
|
1622 |
+
with gr.Tab("GROQ"):
|
1623 |
+
gr.Markdown("## GROQ 模式")
|
1624 |
+
groq_chatbot = gr.Chatbot(label="groq mode chatbot")
|
1625 |
+
groq_msg = gr.Textbox(label="Message")
|
1626 |
+
groq_send_button = gr.Button("Send")
|
1627 |
+
with gr.Tab("JUTOR"):
|
1628 |
+
gr.Markdown("## JUTOR API 模式")
|
1629 |
+
jutor_chatbot = gr.Chatbot(label="jutor mode chatbot")
|
1630 |
+
jutor_msg = gr.Textbox(label="Message")
|
1631 |
+
jutor_send_button = gr.Button("Send")
|
1632 |
|
1633 |
with gr.Tab("教師版"):
|
1634 |
with gr.Row():
|
|
|
1652 |
lesson_plan_btn = gr.Button("生成課程計畫 📕")
|
1653 |
with gr.Accordion("prompt", open=False):
|
1654 |
lesson_plan_prompt = gr.Textbox(label="worksheet_prompt", show_copy_button=True, lines=40)
|
1655 |
+
with gr.Tab("出場券"):
|
1656 |
+
exit_ticket_content_type_name = gr.Textbox(value="exit_ticket", visible=False)
|
1657 |
+
exit_ticket_time = gr.Slider(label="選擇出場券時間(分鐘)", minimum=5, maximum=10, step=1, value=8)
|
1658 |
+
exit_ticket_btn = gr.Button("生成出場券 🎟️")
|
1659 |
+
with gr.Accordion("prompt", open=False):
|
1660 |
+
exit_ticket_prompt = gr.Textbox(label="worksheet_prompt", show_copy_button=True, lines=40)
|
1661 |
|
1662 |
with gr.Tab("素養導向閱讀題組"):
|
1663 |
literacy_oriented_reading_content = gr.Textbox(label="輸入閱讀材料")
|
1664 |
literacy_oriented_reading_content_btn = gr.Button("生成閱讀理解題")
|
1665 |
+
|
1666 |
# with gr.Tab("自我評估"):
|
1667 |
# self_assessment_content = gr.Textbox(label="輸入自評問卷或檢查表")
|
1668 |
# self_assessment_content_btn = gr.Button("生成自評問卷")
|
|
|
1698 |
# outputs=[msg, chatbot, thread_id]
|
1699 |
# )
|
1700 |
# chat_with_youtube_transcript
|
1701 |
+
|
1702 |
+
# OPENAI 模式
|
1703 |
send_button.click(
|
1704 |
chat_with_youtube_transcript,
|
1705 |
inputs=[password, video_id, thread_id, df_string_output, msg, chatbot, socratic_mode_btn],
|
1706 |
outputs=[msg, chatbot, thread_id]
|
1707 |
)
|
1708 |
+
openai_chatbot_audio_input.change(
|
1709 |
+
process_open_ai_audio_to_chatbot,
|
1710 |
+
inputs=[password, openai_chatbot_audio_input],
|
1711 |
+
outputs=[msg]
|
1712 |
+
)
|
1713 |
+
|
1714 |
+
|
1715 |
# GROQ 模式
|
1716 |
groq_send_button.click(
|
1717 |
chat_with_groq,
|
|
|
1803 |
inputs=[password, df_string_output, content_topic, content_grade, content_level, lesson_plan_time, lesson_plan_content_type_name],
|
1804 |
outputs=[exam_result, lesson_plan_prompt, exam_result_prompt]
|
1805 |
)
|
1806 |
+
exit_ticket_btn.click(
|
1807 |
+
on_generate_ai_content,
|
1808 |
+
inputs=[password, df_string_output, content_topic, content_grade, content_level, exit_ticket_time, exit_ticket_content_type_name],
|
1809 |
+
outputs=[exam_result, exit_ticket_prompt, exam_result_prompt]
|
1810 |
+
)
|
1811 |
|
1812 |
# 生成結果微調
|
1813 |
exam_result_fine_tune_btn.click(
|
educational_material.py
CHANGED
@@ -45,6 +45,8 @@ class EducationalMaterial:
|
|
45 |
return self._generate_worksheet_prompt()
|
46 |
elif self.content_type == 'lesson_plan':
|
47 |
return self._generate_lesson_plan_prompt()
|
|
|
|
|
48 |
|
49 |
def _generate_worksheet_prompt(self):
|
50 |
bloom_worksheet_prompt = """
|
@@ -189,60 +191,83 @@ class EducationalMaterial:
|
|
189 |
return worksheet_prompt
|
190 |
|
191 |
def _generate_lesson_plan_prompt(self):
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
# 規則如下,請嚴格遵守
|
198 |
-
# 1. 請使用 zh-TW
|
199 |
-
# 2. 該換行就換行,盡量滿足 word .doc 的格式
|
200 |
-
# 3. 【課程大綱】的工作項目請嚴格遵守【課程時間】的時間長度,總和時間不要超過或不足
|
201 |
-
# 4. 時間安排盡量以五分鐘的倍數為一個單位
|
202 |
-
# 5. 並且根據課程目標安排教學內容
|
203 |
-
|
204 |
-
# 範例:
|
205 |
-
# 【課程主題】計算面積的創意設計
|
206 |
-
|
207 |
-
# 【課程目標】
|
208 |
-
# - 理解不同形狀(正方形、長方形、三角形)的面積計算方法。
|
209 |
-
# - 學會如何通過對摺改變形狀並計算新形狀的面積。
|
210 |
-
# - 鼓勵創造力和實際操作,將數學知識應用於創作中。
|
211 |
-
|
212 |
-
# 【年級】國小三年級
|
213 |
-
|
214 |
-
# 【難度】基礎
|
215 |
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
|
247 |
lesson_plan_5E_prompt = """
|
248 |
你是一位專業教師,
|
@@ -323,10 +348,63 @@ class EducationalMaterial:
|
|
323 |
- 形成性評估:探索和細化階段的觀察以及討論和演示將深入了解學生對相同分母分數加法和減法的理解。
|
324 |
- 總結性評估:收集並審查學生的工作表和任務卡,以評估他們解決涉及具有相同分母的分數的加法和減法問題的能力。
|
325 |
"""
|
326 |
-
lesson_plan_prompt =
|
327 |
|
328 |
return lesson_plan_prompt
|
329 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
330 |
def create_ai_content(self, ai_client, request_payload):
|
331 |
user_content = self.build_user_content()
|
332 |
messages = self.build_messages(user_content)
|
@@ -339,7 +417,9 @@ class EducationalMaterial:
|
|
339 |
if self.content_type == 'worksheet':
|
340 |
specific_feature_text = f"理論模型: {self.specific_feature}"
|
341 |
elif self.content_type == 'lesson_plan':
|
342 |
-
specific_feature_text = f"時間: {self.specific_feature}分鐘"
|
|
|
|
|
343 |
|
344 |
# 根据属性构建用户内容
|
345 |
user_content = f"""
|
@@ -352,6 +432,7 @@ class EducationalMaterial:
|
|
352 |
請根據逐字稿進行以下工作:
|
353 |
不要提到 【逐字稿】 這個詞,直接給出工作內容即可
|
354 |
如果是中文素材,請嚴格使用 zh-TW
|
|
|
355 |
{self.generate_content_prompt()}
|
356 |
"""
|
357 |
print("====User content====")
|
|
|
45 |
return self._generate_worksheet_prompt()
|
46 |
elif self.content_type == 'lesson_plan':
|
47 |
return self._generate_lesson_plan_prompt()
|
48 |
+
elif self.content_type == 'exit_ticket':
|
49 |
+
return self._generate_exit_ticket_prompt()
|
50 |
|
51 |
def _generate_worksheet_prompt(self):
|
52 |
bloom_worksheet_prompt = """
|
|
|
191 |
return worksheet_prompt
|
192 |
|
193 |
def _generate_lesson_plan_prompt(self):
|
194 |
+
lesson_plan_ADDIE_prompt = """
|
195 |
+
你是一位專業教師,
|
196 |
+
請根據以上要教學的項目細節(主題、年級、課程時間、課程目標)
|
197 |
+
幫我安排一個 lesson plan
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
|
199 |
+
規則如下,請嚴格遵守
|
200 |
+
1. 請使用繁體中文溝通 zh-TW,並使用台灣人的用語
|
201 |
+
2. 該換行就換行,盡量滿足 word .doc 的格式
|
202 |
+
3. 【課程大綱】的工作項目請嚴格遵守【課程時間】的時間長度,總和時間不要超過或不足
|
203 |
+
4. 時間安排盡量以五分鐘的倍數為一個單位
|
204 |
+
5. 並且根據課程目標安排教學內容
|
205 |
+
Step1. 你是一個精通於課程設計的老師,能夠運用 ADDIE 教學策略來設計一門適合學生的課程。
|
206 |
+
Step2. 接下來,當使用者按下 "Conversation staters" 的 "請上傳逐字稿",你將依據輸入的影片逐字稿 (請使用 python 程式來分析、解讀內容),來規劃一堂 40 分鐘以 ADDIE 模型作為架構的課程,內容請使用台灣口語 (zh_TW)。
|
207 |
+
- 以下是 ADDIE 的說明:
|
208 |
+
|
209 |
+
ADDIE 教學設計模式是一種廣泛應用於教育和訓練領域的系統化教學設計流程。ADDIE 代表分析(Analysis)、設計(Design)、開發(Development)、實施(Implementation)、評估(Evaluation)五個階段:
|
210 |
+
1. 分析(Analysis)階段:在這一階段,設計者需評估教學需求和學習者的背景,包括學習者的知識水平、學習風格及教學目標等。
|
211 |
+
2. 設計(Design)階段:基於分析階段的資料,開始構��教學計劃,包括課程目標、教學策略、內容架構、評估方法等。
|
212 |
+
a. 轉化課程目標為:單元目標和表現的結果
|
213 |
+
b. 決定可以涵括這些目標的主題或單元,計算實際實施教學時會花費的時間
|
214 |
+
c. 依課程目標安排課程順序
|
215 |
+
d. 設計教學的單元,並確認在這些單元中所要達到的主要目標
|
216 |
+
e. 規劃各單元的學習活動
|
217 |
+
f. 發展特定的評量以確認學生的學習情況
|
218 |
+
3. 開發(Development)階段:這個階段主要是製作教學材料,如課程內容、學習活動、多媒體素材等。
|
219 |
+
4. 實施(Implementation)階段:在此階段,實際執行教學計劃,這包括教授課程、指導學習者及管理學習過程。
|
220 |
+
|
221 |
+
5 評估(Evaluation)階段:評估整個教學設計和實施的有效性,這不僅包括學習成果的評估,還要檢視整個教學過程的有效性與可改進之處。
|
222 |
+
a. 教材:是否達到教學目標?
|
223 |
+
b. 過程:設計過程中的品質是否OK?
|
224 |
+
c. 學習者的反應/感受
|
225 |
+
d. 學習者在學習後達成之成就
|
226 |
+
e. 教學實施的結果
|
227 |
+
|
228 |
+
Step3. 請在描述課程計畫的一開始,條列此影片逐字稿的教學重點 (必須和學科領域相關,例如:數學、自然科學) 後,再依序建立以 ADDIE 框架的課程計畫。
|
229 |
+
Step4. 請在「設計」和「實施」階段請使用合適的範例做說明。
|
230 |
+
Step5. 請使用 Markdown 語法,標題與段落文字的字級需有所區隔。
|
231 |
+
|
232 |
+
example:
|
233 |
+
# 課程設計:面積的實測與估測
|
234 |
+
|
235 |
+
# 教學重點
|
236 |
+
1. 面積的概念:解釋什麼是面積,以及它在日常生活中的應用。
|
237 |
+
2. 面積的計算:教授如何計算不同形狀的面積(例如矩形、三角形)。
|
238 |
+
3. 實測與估測的區別:比較實際測量面積和估算面積的不同方法。
|
239 |
+
4. 應用實例:使用日常生活中的例子,例如給麥麥的生日卡片大小的比較,來說明面積的重要性。
|
240 |
+
|
241 |
+
# 分析(Analysis)
|
242 |
+
- 目標學習者:小學高年級學生。
|
243 |
+
- 學習需求:理解面積概念,掌握基本面積計算方法。
|
244 |
+
- 學習風格:結合視覺教材和互動活動。
|
245 |
+
|
246 |
+
# 設計(Design)
|
247 |
+
- 課程目標:學生能夠理解面積概念,並能透過實際操作學會估算和計算面積。
|
248 |
+
- 學習單元:(a)面積基礎概念(b)計算面積(c)實測與估測的比較。
|
249 |
+
- 教學策略:透過互動遊戲、案例討論和實作活動進行教學。
|
250 |
+
- 評估方法:透過小測驗和課堂參與情況進行評估。
|
251 |
+
|
252 |
+
# 開發(Development)
|
253 |
+
- 教材準備:準備視覺化教學幻燈片,設計互動遊戲和實作活動。
|
254 |
+
- 教學活動:設計面積估測遊戲,讓學生在實際操作中學習。
|
255 |
+
|
256 |
+
# 實施(Implementation)
|
257 |
+
- 課程時間分配:(a)面積基礎概念(10分鐘)(b)計算面積(15分鐘)(c)實測與估測比較(10分鐘)(d)總結與回顧(5分鐘)。
|
258 |
+
- 教學範例:
|
259 |
+
- 面積基礎概念:介紹面積是如何在日常生活中應用,例如計算桌布的大小。
|
260 |
+
- 計算面積:透過計算教室黑板或門的面積來教學。
|
261 |
+
- 實測與估測比較:讓學生估計並實際測量教室中物品的面積,比較結果。
|
262 |
+
|
263 |
+
# 評估(Evaluation)
|
264 |
+
- 教材評估:確保教材能清楚傳達面積概念。
|
265 |
+
- 學習者反應:觀察學生參與情況,收集反饋以改善教學。
|
266 |
+
- 學習成就:透過小測驗評估學生對面積概念的理解。
|
267 |
+
- 教學實施結果:評估課程的整體有效性,並根據學生的學習成果進行調整。
|
268 |
+
|
269 |
+
這個課程計畫將幫助學生透過互動和實作活動來深入理解面積的概念和計算方法
|
270 |
+
"""
|
271 |
|
272 |
lesson_plan_5E_prompt = """
|
273 |
你是一位專業教師,
|
|
|
348 |
- 形成性評估:探索和細化階段的觀察以及討論和演示將深入了解學生對相同分母分數加法和減法的理解。
|
349 |
- 總結性評估:收集並審查學生的工作表和任務卡,以評估他們解決涉及具有相同分母的分數的加法和減法問題的能力。
|
350 |
"""
|
351 |
+
lesson_plan_prompt = lesson_plan_ADDIE_prompt
|
352 |
|
353 |
return lesson_plan_prompt
|
354 |
|
355 |
+
def _generate_exit_ticket_prompt(self):
|
356 |
+
exit_ticket_prompt = """
|
357 |
+
你是一位專業教師,
|
358 |
+
請根據以上要教學的項目細節及逐字稿
|
359 |
+
在一節課結束前用上述的時間(10分鐘內)
|
360 |
+
運用出場券 (exit ticket) 來檢核學生的學習是否有對上學習目標,有哪些知識點或技能還不熟悉
|
361 |
+
目的是讓教學更加精準;出場券能夠檢視每一堂課的學習成效,從學生的答題狀況,
|
362 |
+
可以觀察班上有多少比例學生沒學會,沒學會的地方又是什麼。
|
363 |
+
|
364 |
+
規則如下,請嚴格遵守:
|
365 |
+
1. 內容請使用台灣口語的繁體中文 (zh_TW),不可以使用大陸用語,也不可以使用簡體字。
|
366 |
+
2. 該換行就換行,盡量滿足 word .doc 的格式
|
367 |
+
3. 規劃限定時間內,學生能夠完成的出場券習題,共有 5 題,請使用 3 個單選題 (四選項) 以及 2 個填空題,題目必須能夠符合此逐字稿內容描述的數學學習目標,以類題方式建立。
|
368 |
+
4. 此出場券習題最末請公布各題的答案。
|
369 |
+
|
370 |
+
example:
|
371 |
+
出場券習題:公里、公尺和公分的換算
|
372 |
+
選擇題(請從四個選項中選出一個正確答案)
|
373 |
+
|
374 |
+
1. 1公里等於多少公尺?
|
375 |
+
A) 100公尺
|
376 |
+
B) 1000公尺
|
377 |
+
C) 10,000公尺
|
378 |
+
D) 100公分
|
379 |
+
|
380 |
+
2. 5公尺等於多少公分?
|
381 |
+
A) 50公分
|
382 |
+
B) 500公分
|
383 |
+
C) 5,000公分
|
384 |
+
D) 50,000公分
|
385 |
+
|
386 |
+
3. 如果你走了2.5公里的路程,這段路程等於多少公尺?
|
387 |
+
A) 250公尺
|
388 |
+
B) 2,500公尺
|
389 |
+
C) 25,000公尺
|
390 |
+
D) 250,000公尺
|
391 |
+
|
392 |
+
填空題
|
393 |
+
1. 100公分等於___公尺?(請填入數字)
|
394 |
+
2. 1公尺等於___公分?(請填入數字)
|
395 |
+
|
396 |
+
|
397 |
+
答案公布
|
398 |
+
答案:B) 1000公尺
|
399 |
+
答案:B) 500公分
|
400 |
+
答案:B) 2,500公尺
|
401 |
+
答案:A) 3公尺
|
402 |
+
答案:1公尺
|
403 |
+
|
404 |
+
這套出場券習題旨在幫助學生掌握公里、公尺、和公分之間的換算關係,通過實際的例子加深學生對這些單位之間轉換的理解。
|
405 |
+
"""
|
406 |
+
return exit_ticket_prompt
|
407 |
+
|
408 |
def create_ai_content(self, ai_client, request_payload):
|
409 |
user_content = self.build_user_content()
|
410 |
messages = self.build_messages(user_content)
|
|
|
417 |
if self.content_type == 'worksheet':
|
418 |
specific_feature_text = f"理論模型: {self.specific_feature}"
|
419 |
elif self.content_type == 'lesson_plan':
|
420 |
+
specific_feature_text = f"時間: {self.specific_feature} 分鐘"
|
421 |
+
elif self.content_type == 'exit_ticket':
|
422 |
+
specific_feature_text = f"時間: {self.specific_feature} 分鐘"
|
423 |
|
424 |
# 根据属性构建用户内容
|
425 |
user_content = f"""
|
|
|
432 |
請根據逐字稿進行以下工作:
|
433 |
不要提到 【逐字稿】 這個詞,直接給出工作內容即可
|
434 |
如果是中文素材,請嚴格使用 zh-TW
|
435 |
+
請用 {self.grade} 年級的口吻,不要用太難的詞彙
|
436 |
{self.generate_content_prompt()}
|
437 |
"""
|
438 |
print("====User content====")
|