Spaces:
Running
Running
update
Browse files
app.py
CHANGED
@@ -6,6 +6,8 @@ from docx import Document
|
|
6 |
import os
|
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
|
@@ -713,6 +715,12 @@ def generate_reading_passage(df_string):
|
|
713 |
|
714 |
return reading_passage
|
715 |
|
|
|
|
|
|
|
|
|
|
|
|
|
716 |
def get_mind_map(video_id, df_string, source):
|
717 |
if source == "gcs":
|
718 |
print("===get_mind_map on gcs===")
|
@@ -1025,6 +1033,18 @@ def generate_exam_fine_tune_result(password, exam_result_prompt , df_string_outp
|
|
1025 |
ai_content = material.send_ai_request(OPEN_AI_CLIENT, request_payload)
|
1026 |
return ai_content
|
1027 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1028 |
# ---- Chatbot ----
|
1029 |
def respond(password, user_message, data, chat_history, socratic_mode=False):
|
1030 |
verify_password(password)
|
@@ -1296,7 +1316,7 @@ def chat_with_groq(password, user_message, data, chat_history, socratic_mode=Fal
|
|
1296 |
# 返回聊天历史和空字符串清空输入框
|
1297 |
return "", chat_history
|
1298 |
|
1299 |
-
def
|
1300 |
verify_password(password)
|
1301 |
|
1302 |
# 先計算 user_message 是否超過 500 個字
|
@@ -1304,6 +1324,11 @@ def chat_with_youtube_transcript(password, youtube_id, thread_id, trascript, use
|
|
1304 |
error_msg = "你的訊息太長了,請縮短訊息長度至五百字以內"
|
1305 |
raise gr.Error(error_msg)
|
1306 |
|
|
|
|
|
|
|
|
|
|
|
1307 |
try:
|
1308 |
assistant_id = "asst_kmvZLNkDUYaNkMNtZEAYxyPq"
|
1309 |
client = OPEN_AI_CLIENT
|
@@ -1346,18 +1371,24 @@ def chat_with_youtube_transcript(password, youtube_id, thread_id, trascript, use
|
|
1346 |
你是一個擅長資料分析跟影片教學的老師,user 為學生
|
1347 |
如果是影片類型,不用解釋逐字稿格式,直接回答學生問題
|
1348 |
socratic_mode = {socratic_mode}
|
1349 |
-
|
1350 |
- 請用蘇格拉底式的提問方式,引導學生思考,並且給予學生一些提示
|
|
|
1351 |
- 不要直接給予答案,讓學生自己思考
|
1352 |
- 但可以給予一些提示跟引導,例如給予影片的時間軸,讓學生自己去找答案
|
1353 |
- 在你回答的開頭標註【蘇格拉底助教:{youtube_id} 】
|
1354 |
-
|
1355 |
-
|
|
|
1356 |
- 在你回答的開頭標註【一般學習精靈:{youtube_id} 】
|
|
|
1357 |
如果學生問了一些問題你無法判斷,請告訴學生你無法判斷,並建議學生可以問其他問題
|
1358 |
-
|
1359 |
-
|
1360 |
-
|
|
|
|
|
|
|
1361 |
"""
|
1362 |
|
1363 |
# 创建线程
|
@@ -1371,7 +1402,7 @@ def chat_with_youtube_transcript(password, youtube_id, thread_id, trascript, use
|
|
1371 |
client.beta.threads.messages.create(
|
1372 |
thread_id=thread.id,
|
1373 |
role="user",
|
1374 |
-
content=user_message
|
1375 |
)
|
1376 |
|
1377 |
# 运行助手,生成响应
|
@@ -1580,6 +1611,8 @@ with gr.Blocks() as demo:
|
|
1580 |
with gr.Column(scale=3):
|
1581 |
with gr.Tab("文章模式"):
|
1582 |
reading_passage = gr.Textbox(label="Reading Passage", lines=40)
|
|
|
|
|
1583 |
with gr.Tab("重點"):
|
1584 |
df_summarise = gr.Textbox(container=True, show_copy_button=True, lines=40)
|
1585 |
with gr.Tab("問題"):
|
@@ -1675,33 +1708,17 @@ with gr.Blocks() as demo:
|
|
1675 |
with gr.Column(scale=2):
|
1676 |
# 生成對應不同模式的結果
|
1677 |
exam_result_prompt = gr.Textbox(visible=False)
|
1678 |
-
exam_result = gr.Textbox(label="初次生成結果", show_copy_button=True)
|
1679 |
exam_result_fine_tune_prompt = gr.Textbox(label="根據結果,輸入你想更改的想法")
|
1680 |
exam_result_fine_tune_btn = gr.Button("微調結果")
|
1681 |
exam_result_fine_result = gr.Textbox(label="微調結果",show_copy_button=True)
|
1682 |
-
|
1683 |
-
|
1684 |
-
|
1685 |
-
|
1686 |
-
# inputs=[msg, df_string_output, chatbot, socratic_mode_btn],
|
1687 |
-
# outputs=[msg, chatbot]
|
1688 |
-
# )
|
1689 |
-
# # 连接按钮点击事件
|
1690 |
-
# btn_1.click(respond, inputs=[btn_1, df_string_output, chatbot, socratic_mode_btn], outputs=[msg, chatbot])
|
1691 |
-
# btn_2.click(respond, inputs=[btn_2, df_string_output, chatbot, socratic_mode_btn], outputs=[msg, chatbot])
|
1692 |
-
# btn_3.click(respond, inputs=[btn_3, df_string_output, chatbot, socratic_mode_btn], outputs=[msg, chatbot])
|
1693 |
-
|
1694 |
-
# chat_with_youtube_transcript
|
1695 |
-
# send_button.click(
|
1696 |
-
# chat_with_youtube_transcript,
|
1697 |
-
# inputs=[password, video_id, thread_id, df_string_output, msg, chatbot, socratic_mode_btn],
|
1698 |
-
# outputs=[msg, chatbot, thread_id]
|
1699 |
-
# )
|
1700 |
-
# chat_with_youtube_transcript
|
1701 |
-
|
1702 |
# OPENAI 模式
|
1703 |
send_button.click(
|
1704 |
-
|
1705 |
inputs=[password, video_id, thread_id, df_string_output, msg, chatbot, socratic_mode_btn],
|
1706 |
outputs=[msg, chatbot, thread_id]
|
1707 |
)
|
@@ -1710,8 +1727,6 @@ with gr.Blocks() as demo:
|
|
1710 |
inputs=[password, openai_chatbot_audio_input],
|
1711 |
outputs=[msg]
|
1712 |
)
|
1713 |
-
|
1714 |
-
|
1715 |
# GROQ 模式
|
1716 |
groq_send_button.click(
|
1717 |
chat_with_groq,
|
@@ -1725,20 +1740,19 @@ with gr.Blocks() as demo:
|
|
1725 |
outputs=[jutor_msg, jutor_chatbot]
|
1726 |
)
|
1727 |
|
1728 |
-
|
1729 |
# 连接按钮点击事件
|
1730 |
btn_1.click(
|
1731 |
-
|
1732 |
inputs=[password, video_id, thread_id, df_string_output, btn_1, chatbot, socratic_mode_btn],
|
1733 |
outputs=[msg, chatbot, thread_id]
|
1734 |
)
|
1735 |
btn_2.click(
|
1736 |
-
|
1737 |
inputs=[password, video_id, thread_id, df_string_output, btn_2, chatbot, socratic_mode_btn],
|
1738 |
outputs=[msg, chatbot, thread_id]
|
1739 |
)
|
1740 |
btn_3.click(
|
1741 |
-
|
1742 |
inputs=[password, video_id, thread_id, df_string_output, btn_3, chatbot, socratic_mode_btn],
|
1743 |
outputs=[msg, chatbot, thread_id]
|
1744 |
)
|
@@ -1792,6 +1806,13 @@ with gr.Blocks() as demo:
|
|
1792 |
# 当输入网页链接时触发
|
1793 |
# web_link.change(process_web_link, inputs=web_link, outputs=[btn_1, btn_2, btn_3, df_summarise, df_string_output])
|
1794 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1795 |
# 教師版 學習單
|
1796 |
worksheet_content_btn.click(
|
1797 |
on_generate_ai_content,
|
@@ -1815,6 +1836,12 @@ with gr.Blocks() as demo:
|
|
1815 |
inputs=[password, exam_result_prompt, df_string_output, exam_result, exam_result_fine_tune_prompt],
|
1816 |
outputs=[exam_result_fine_result]
|
1817 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
1818 |
|
1819 |
demo.load(
|
1820 |
init_params,
|
|
|
6 |
import os
|
7 |
from openai import OpenAI
|
8 |
from groq import Groq
|
9 |
+
from docx import Document
|
10 |
+
from gtts import gTTS
|
11 |
|
12 |
from youtube_transcript_api import YouTubeTranscriptApi
|
13 |
from youtube_transcript_api._errors import NoTranscriptFound
|
|
|
715 |
|
716 |
return reading_passage
|
717 |
|
718 |
+
def text_to_speech(video_id, text):
|
719 |
+
tts = gTTS(text, lang='en')
|
720 |
+
filename = f'{video_id}_reading_passage.mp3'
|
721 |
+
tts.save(filename)
|
722 |
+
return filename
|
723 |
+
|
724 |
def get_mind_map(video_id, df_string, source):
|
725 |
if source == "gcs":
|
726 |
print("===get_mind_map on gcs===")
|
|
|
1033 |
ai_content = material.send_ai_request(OPEN_AI_CLIENT, request_payload)
|
1034 |
return ai_content
|
1035 |
|
1036 |
+
def create_word(content):
|
1037 |
+
unique_filename = str(uuid.uuid4())
|
1038 |
+
word_file_path = f"/tmp/{unique_filename}.docx"
|
1039 |
+
doc = Document()
|
1040 |
+
doc.add_paragraph(content)
|
1041 |
+
doc.save(word_file_path)
|
1042 |
+
return word_file_path
|
1043 |
+
|
1044 |
+
def download_exam_result(content):
|
1045 |
+
word_path = create_word(content)
|
1046 |
+
return word_path
|
1047 |
+
|
1048 |
# ---- Chatbot ----
|
1049 |
def respond(password, user_message, data, chat_history, socratic_mode=False):
|
1050 |
verify_password(password)
|
|
|
1316 |
# 返回聊天历史和空字符串清空输入框
|
1317 |
return "", chat_history
|
1318 |
|
1319 |
+
def chat_with_opan_ai_assistant(password, youtube_id, thread_id, trascript, user_message, chat_history, socratic_mode=False):
|
1320 |
verify_password(password)
|
1321 |
|
1322 |
# 先計算 user_message 是否超過 500 個字
|
|
|
1324 |
error_msg = "你的訊息太長了,請縮短訊息長度至五百字以內"
|
1325 |
raise gr.Error(error_msg)
|
1326 |
|
1327 |
+
# 如果 chat_history 超過 10 則訊息,直接 return "對話超過上限"
|
1328 |
+
if chat_history is not None and len(chat_history) > 10:
|
1329 |
+
error_msg = "此次對話超過上限"
|
1330 |
+
raise gr.Error(error_msg)
|
1331 |
+
|
1332 |
try:
|
1333 |
assistant_id = "asst_kmvZLNkDUYaNkMNtZEAYxyPq"
|
1334 |
client = OPEN_AI_CLIENT
|
|
|
1371 |
你是一個擅長資料分析跟影片教學的老師,user 為學生
|
1372 |
如果是影片類型,不用解釋逐字稿格式,直接回答學生問題
|
1373 |
socratic_mode = {socratic_mode}
|
1374 |
+
if socratic_mode is True,
|
1375 |
- 請用蘇格拉底式的提問方式,引導學生思考,並且給予學生一些提示
|
1376 |
+
- 一次只問一個問題,字數在100字以內
|
1377 |
- 不要直接給予答案,讓學生自己思考
|
1378 |
- 但可以給予一些提示跟引導,例如給予影片的時間軸,讓學生自己去找答案
|
1379 |
- 在你回答的開頭標註【蘇格拉底助教:{youtube_id} 】
|
1380 |
+
|
1381 |
+
if socratic_mode is False,
|
1382 |
+
- 直接回答學生問題,字數在100字以內
|
1383 |
- 在你回答的開頭標註【一般學習精靈:{youtube_id} 】
|
1384 |
+
|
1385 |
如果學生問了一些問題你無法判斷,請告訴學生你無法判斷,並建議學生可以問其他問題
|
1386 |
+
或者你可以反問學生一些問題,幫助學生更好的理解資料,字數在100字以內
|
1387 |
+
如果學生的問題與資料文本無關,請告訴學生你「無法回答超出範圍的問題」,並告訴他可以怎麼問什麼樣的問題(一個就好)
|
1388 |
+
只要是參考逐字稿資料,請在回答的最後標註【參考資料:(分):(秒)】
|
1389 |
+
請一定要用繁體中文回答 zh-TW,並用台灣人的口語表達
|
1390 |
+
回答範圍一定要在逐字稿資料內,不要引用其他資料,請嚴格執行
|
1391 |
+
並在重複問句後給予學生鼓勵,讓學生有學習的動力
|
1392 |
"""
|
1393 |
|
1394 |
# 创建线程
|
|
|
1402 |
client.beta.threads.messages.create(
|
1403 |
thread_id=thread.id,
|
1404 |
role="user",
|
1405 |
+
content=user_message + "(請一定要用繁體中文回答 zh-TW,並用台灣人的口語表達,回答時不要特別說明這是台灣人的語氣)"
|
1406 |
)
|
1407 |
|
1408 |
# 运行助手,生成响应
|
|
|
1611 |
with gr.Column(scale=3):
|
1612 |
with gr.Tab("文章模式"):
|
1613 |
reading_passage = gr.Textbox(label="Reading Passage", lines=40)
|
1614 |
+
reading_passage_speak_button = gr.Button("Speak", visible=False)
|
1615 |
+
reading_passage_audio_output = gr.Audio(label="Audio Output", visible=False)
|
1616 |
with gr.Tab("重點"):
|
1617 |
df_summarise = gr.Textbox(container=True, show_copy_button=True, lines=40)
|
1618 |
with gr.Tab("問題"):
|
|
|
1708 |
with gr.Column(scale=2):
|
1709 |
# 生成對應不同模式的結果
|
1710 |
exam_result_prompt = gr.Textbox(visible=False)
|
1711 |
+
exam_result = gr.Textbox(label="初次生成結果", show_copy_button=True, interactive=True)
|
1712 |
exam_result_fine_tune_prompt = gr.Textbox(label="根據結果,輸入你想更改的想法")
|
1713 |
exam_result_fine_tune_btn = gr.Button("微調結果")
|
1714 |
exam_result_fine_result = gr.Textbox(label="微調結果",show_copy_button=True)
|
1715 |
+
|
1716 |
+
download_exam_result_button = gr.Button("下载结果")
|
1717 |
+
exam_result_word_link = gr.File(label="Download Word")
|
1718 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1719 |
# OPENAI 模式
|
1720 |
send_button.click(
|
1721 |
+
chat_with_opan_ai_assistant,
|
1722 |
inputs=[password, video_id, thread_id, df_string_output, msg, chatbot, socratic_mode_btn],
|
1723 |
outputs=[msg, chatbot, thread_id]
|
1724 |
)
|
|
|
1727 |
inputs=[password, openai_chatbot_audio_input],
|
1728 |
outputs=[msg]
|
1729 |
)
|
|
|
|
|
1730 |
# GROQ 模式
|
1731 |
groq_send_button.click(
|
1732 |
chat_with_groq,
|
|
|
1740 |
outputs=[jutor_msg, jutor_chatbot]
|
1741 |
)
|
1742 |
|
|
|
1743 |
# 连接按钮点击事件
|
1744 |
btn_1.click(
|
1745 |
+
chat_with_opan_ai_assistant,
|
1746 |
inputs=[password, video_id, thread_id, df_string_output, btn_1, chatbot, socratic_mode_btn],
|
1747 |
outputs=[msg, chatbot, thread_id]
|
1748 |
)
|
1749 |
btn_2.click(
|
1750 |
+
chat_with_opan_ai_assistant,
|
1751 |
inputs=[password, video_id, thread_id, df_string_output, btn_2, chatbot, socratic_mode_btn],
|
1752 |
outputs=[msg, chatbot, thread_id]
|
1753 |
)
|
1754 |
btn_3.click(
|
1755 |
+
chat_with_opan_ai_assistant,
|
1756 |
inputs=[password, video_id, thread_id, df_string_output, btn_3, chatbot, socratic_mode_btn],
|
1757 |
outputs=[msg, chatbot, thread_id]
|
1758 |
)
|
|
|
1806 |
# 当输入网页链接时触发
|
1807 |
# web_link.change(process_web_link, inputs=web_link, outputs=[btn_1, btn_2, btn_3, df_summarise, df_string_output])
|
1808 |
|
1809 |
+
# 文章模式
|
1810 |
+
reading_passage_speak_button.click(
|
1811 |
+
text_to_speech,
|
1812 |
+
inputs=[video_id, reading_passage],
|
1813 |
+
outputs=reading_passage_audio_output
|
1814 |
+
)
|
1815 |
+
|
1816 |
# 教師版 學習單
|
1817 |
worksheet_content_btn.click(
|
1818 |
on_generate_ai_content,
|
|
|
1836 |
inputs=[password, exam_result_prompt, df_string_output, exam_result, exam_result_fine_tune_prompt],
|
1837 |
outputs=[exam_result_fine_result]
|
1838 |
)
|
1839 |
+
download_exam_result_button.click(
|
1840 |
+
download_exam_result,
|
1841 |
+
inputs=[exam_result],
|
1842 |
+
outputs=[exam_result_word_link]
|
1843 |
+
)
|
1844 |
+
|
1845 |
|
1846 |
demo.load(
|
1847 |
init_params,
|