Spaces:
Sleeping
Sleeping
update
Browse files- app.py +131 -3
- local_config.json +0 -23
- requirements.txt +2 -1
app.py
CHANGED
@@ -32,6 +32,7 @@ from googleapiclient.http import MediaIoBaseUpload
|
|
32 |
from educational_material import EducationalMaterial
|
33 |
from storage_service import GoogleCloudStorage
|
34 |
|
|
|
35 |
|
36 |
is_env_local = os.getenv("IS_ENV_LOCAL", "false") == "true"
|
37 |
print(f"is_env_local: {is_env_local}")
|
@@ -45,6 +46,9 @@ if is_env_local:
|
|
45 |
OPEN_AI_KEY = config["OPEN_AI_KEY"]
|
46 |
GROQ_API_KEY = config["GROQ_API_KEY"]
|
47 |
JUTOR_CHAT_KEY = config["JUTOR_CHAT_KEY"]
|
|
|
|
|
|
|
48 |
OUTPUT_PATH = config["OUTPUT_PATH"]
|
49 |
else:
|
50 |
PASSWORD = os.getenv("PASSWORD")
|
@@ -53,6 +57,9 @@ else:
|
|
53 |
OPEN_AI_KEY = os.getenv("OPEN_AI_KEY")
|
54 |
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
|
55 |
JUTOR_CHAT_KEY = os.getenv("JUTOR_CHAT_KEY")
|
|
|
|
|
|
|
56 |
OUTPUT_PATH = 'videos'
|
57 |
|
58 |
TRANSCRIPTS = []
|
@@ -64,6 +71,20 @@ GROQ_CLIENT = Groq(api_key=GROQ_API_KEY)
|
|
64 |
GCS_SERVICE = GoogleCloudStorage(GCS_KEY)
|
65 |
GCS_CLIENT = GCS_SERVICE.client
|
66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
# 驗證 password
|
68 |
def verify_password(password):
|
69 |
if password == PASSWORD:
|
@@ -1615,6 +1636,106 @@ def poll_run_status(run_id, thread_id, timeout=600, poll_interval=5):
|
|
1615 |
|
1616 |
return run.status
|
1617 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1618 |
def update_slide(direction):
|
1619 |
global TRANSCRIPTS
|
1620 |
global CURRENT_INDEX
|
@@ -1743,7 +1864,6 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, seconda
|
|
1743 |
mind_map_html = gr.HTML()
|
1744 |
with gr.Column(scale=2):
|
1745 |
with gr.Tab("OPENAI"):
|
1746 |
-
gr.Markdown("## OPEN AI 模式")
|
1747 |
bot_avatar = "https://junyi-avatar.s3.ap-northeast-1.amazonaws.com/live/%20%20foxcat-star-18.png?v=20231113095823614"
|
1748 |
user_avatar = "https://junyitopicimg.s3.amazonaws.com/s4byy--icon.jpe?v=20200513013523726"
|
1749 |
chatbot = gr.Chatbot(avatar_images=[bot_avatar, user_avatar], label="OPEN AI", show_share_button=False, likeable=True)
|
@@ -1753,15 +1873,17 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, seconda
|
|
1753 |
msg = gr.Textbox(label="Message")
|
1754 |
send_button = gr.Button("Send", variant="primary")
|
1755 |
with gr.Tab("GROQ"):
|
1756 |
-
gr.Markdown("## GROQ 模式")
|
1757 |
groq_chatbot = gr.Chatbot(avatar_images=[bot_avatar, user_avatar], label="groq mode chatbot", show_share_button=False)
|
1758 |
groq_msg = gr.Textbox(label="Message")
|
1759 |
groq_send_button = gr.Button("Send", variant="primary")
|
1760 |
with gr.Tab("JUTOR"):
|
1761 |
-
gr.Markdown("## JUTOR API 模式")
|
1762 |
jutor_chatbot = gr.Chatbot(avatar_images=[bot_avatar, user_avatar], label="jutor mode chatbot", show_share_button=False)
|
1763 |
jutor_msg = gr.Textbox(label="Message")
|
1764 |
jutor_send_button = gr.Button("Send", variant="primary")
|
|
|
|
|
|
|
|
|
1765 |
|
1766 |
with gr.Tab("教師版"):
|
1767 |
with gr.Row():
|
@@ -1873,6 +1995,12 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, seconda
|
|
1873 |
inputs=[password, jutor_msg, df_string_output, jutor_chatbot, socratic_mode_btn],
|
1874 |
outputs=[jutor_msg, jutor_chatbot]
|
1875 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
1876 |
|
1877 |
# 连接按钮点击事件
|
1878 |
chat_with_opan_ai_assistant_input =[password, video_id, thread_id, df_string_output, btn_1, chatbot, content_subject, content_grade, socratic_mode_btn]
|
|
|
32 |
from educational_material import EducationalMaterial
|
33 |
from storage_service import GoogleCloudStorage
|
34 |
|
35 |
+
import boto3
|
36 |
|
37 |
is_env_local = os.getenv("IS_ENV_LOCAL", "false") == "true"
|
38 |
print(f"is_env_local: {is_env_local}")
|
|
|
46 |
OPEN_AI_KEY = config["OPEN_AI_KEY"]
|
47 |
GROQ_API_KEY = config["GROQ_API_KEY"]
|
48 |
JUTOR_CHAT_KEY = config["JUTOR_CHAT_KEY"]
|
49 |
+
AWS_ACCESS_KEY = config["AWS_ACCESS_KEY"]
|
50 |
+
AWS_SECRET_KEY = config["AWS_SECRET_KEY"]
|
51 |
+
AWS_REGION_NAME = config["AWS_REGION_NAME"]
|
52 |
OUTPUT_PATH = config["OUTPUT_PATH"]
|
53 |
else:
|
54 |
PASSWORD = os.getenv("PASSWORD")
|
|
|
57 |
OPEN_AI_KEY = os.getenv("OPEN_AI_KEY")
|
58 |
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
|
59 |
JUTOR_CHAT_KEY = os.getenv("JUTOR_CHAT_KEY")
|
60 |
+
AWS_ACCESS_KEY = os.getenv("AWS_ACCESS_KEY"),
|
61 |
+
AWS_SECRET_KEY = os.getenv("AWS_SECRET_KEY"),
|
62 |
+
AWS_REGION_NAME = 'us-west-2'
|
63 |
OUTPUT_PATH = 'videos'
|
64 |
|
65 |
TRANSCRIPTS = []
|
|
|
71 |
GCS_SERVICE = GoogleCloudStorage(GCS_KEY)
|
72 |
GCS_CLIENT = GCS_SERVICE.client
|
73 |
|
74 |
+
|
75 |
+
|
76 |
+
# 初始化 boto3 session
|
77 |
+
boto3.setup_default_session(
|
78 |
+
aws_access_key_id=AWS_ACCESS_KEY,
|
79 |
+
aws_secret_access_key=AWS_SECRET_KEY,
|
80 |
+
region_name=AWS_REGION_NAME
|
81 |
+
)
|
82 |
+
|
83 |
+
BEDROCK_CLIENT = boto3.client(
|
84 |
+
service_name="bedrock-runtime",
|
85 |
+
region_name=AWS_REGION_NAME
|
86 |
+
)
|
87 |
+
|
88 |
# 驗證 password
|
89 |
def verify_password(password):
|
90 |
if password == PASSWORD:
|
|
|
1636 |
|
1637 |
return run.status
|
1638 |
|
1639 |
+
def chat_with_claude3(password, user_message, data, chat_history, socratic_mode=False):
|
1640 |
+
verify_password(password)
|
1641 |
+
data_json = json.loads(data)
|
1642 |
+
for entry in data_json:
|
1643 |
+
entry.pop('embed_url', None) # Remove 'embed_url' if it exists
|
1644 |
+
entry.pop('screenshot_path', None)
|
1645 |
+
|
1646 |
+
if socratic_mode:
|
1647 |
+
sys_content = f"""
|
1648 |
+
你是一個擅長資料分析跟影片教學的老師,user 為學生
|
1649 |
+
請用 {data} 為資料文本,自行判斷資料的種類,
|
1650 |
+
並進行對話,使用 台灣人的口與表達,及繁體中文zh-TW
|
1651 |
+
請你用蘇格拉底式的提問方式,引導學生思考,並且給予學生一些提示
|
1652 |
+
不要直接給予答案,讓學生自己思考
|
1653 |
+
但可以給予一些提示跟引導,例如給予影片的時間軸,讓學生自己去找答案
|
1654 |
+
|
1655 |
+
如果學生問了一些問題你無法判斷,請告訴學生你無法判斷,並建議學生可以問其他問題
|
1656 |
+
或者你可以問學生一些問題,幫助學生更好的理解資料
|
1657 |
+
|
1658 |
+
如果學生的問題與資料文本無關,請告訴學生你無法回答超出範圍的問題
|
1659 |
+
|
1660 |
+
最後,在你回答的開頭標註【蘇格拉底助教】
|
1661 |
+
"""
|
1662 |
+
else:
|
1663 |
+
sys_content = f"""
|
1664 |
+
你是一個擅長資料分析跟影片教學的老師,user 為學生
|
1665 |
+
請用 {data} 為資料文本,自行判斷資料的種類,
|
1666 |
+
並進行對話,使用 zh-TW
|
1667 |
+
|
1668 |
+
如果是影片類型,不用解釋逐字稿格式,直接回答學生問題
|
1669 |
+
但可以給予一些提示跟引導,例如給予影片的時間軸,讓學生可以找到相對應的時間點
|
1670 |
+
|
1671 |
+
如果學生問了一些問題你無法判斷,請告訴學生你無法判斷,並建議學生可以問其他問題
|
1672 |
+
或者你可以問學生一些問題,幫助學生更好的理解資料
|
1673 |
+
|
1674 |
+
如果學生的問題與資料文本無關,請告訴學生你無法回答超出範圍的問題
|
1675 |
+
"""
|
1676 |
+
|
1677 |
+
messages = []
|
1678 |
+
|
1679 |
+
# if chat_history is not none, append role, content to messages
|
1680 |
+
# chat_history = [(user, assistant), (user, assistant), ...]
|
1681 |
+
# In the list, first one is user, then assistant
|
1682 |
+
if chat_history is not None:
|
1683 |
+
# 如果超過10則訊息,只保留最後10則訊息
|
1684 |
+
if len(chat_history) > 10:
|
1685 |
+
chat_history = chat_history[-10:]
|
1686 |
+
|
1687 |
+
for chat in chat_history:
|
1688 |
+
old_messages = [
|
1689 |
+
{"role": "user", "content": chat[0]},
|
1690 |
+
{"role": "assistant", "content": chat[1]}
|
1691 |
+
]
|
1692 |
+
messages += old_messages
|
1693 |
+
else:
|
1694 |
+
pass
|
1695 |
+
|
1696 |
+
messages.append({"role": "user", "content": user_message})
|
1697 |
+
model_id = "anthropic.claude-3-sonnet-20240229-v1:0"
|
1698 |
+
# model_id = "anthropic.claude-3-haiku-20240307-v1:0"
|
1699 |
+
kwargs = {
|
1700 |
+
"modelId": model_id,
|
1701 |
+
"contentType": "application/json",
|
1702 |
+
"accept": "application/json",
|
1703 |
+
"body": json.dumps({
|
1704 |
+
"anthropic_version": "bedrock-2023-05-31",
|
1705 |
+
"max_tokens": 1000,
|
1706 |
+
"system": sys_content,
|
1707 |
+
"messages": messages
|
1708 |
+
})
|
1709 |
+
}
|
1710 |
+
# 建立 message API,讀取回應
|
1711 |
+
response = BEDROCK_CLIENT.invoke_model(**kwargs)
|
1712 |
+
|
1713 |
+
if response:
|
1714 |
+
# 处理响应数据
|
1715 |
+
response_body = json.loads(response.get('body').read())
|
1716 |
+
response_completion = response_body.get('content')[0].get('text').strip()
|
1717 |
+
# 更新聊天历史
|
1718 |
+
new_chat_history = (user_message, response_completion)
|
1719 |
+
if chat_history is None:
|
1720 |
+
chat_history = [new_chat_history]
|
1721 |
+
else:
|
1722 |
+
chat_history.append(new_chat_history)
|
1723 |
+
|
1724 |
+
# 返回聊天历史和空字符串清空输入框
|
1725 |
+
return "", chat_history
|
1726 |
+
else:
|
1727 |
+
# 处理错误情况
|
1728 |
+
print(f"Error: {response.status_code}")
|
1729 |
+
return "请求失败,请稍后再试!", chat_history
|
1730 |
+
|
1731 |
+
|
1732 |
+
|
1733 |
+
|
1734 |
+
|
1735 |
+
|
1736 |
+
|
1737 |
+
|
1738 |
+
|
1739 |
def update_slide(direction):
|
1740 |
global TRANSCRIPTS
|
1741 |
global CURRENT_INDEX
|
|
|
1864 |
mind_map_html = gr.HTML()
|
1865 |
with gr.Column(scale=2):
|
1866 |
with gr.Tab("OPENAI"):
|
|
|
1867 |
bot_avatar = "https://junyi-avatar.s3.ap-northeast-1.amazonaws.com/live/%20%20foxcat-star-18.png?v=20231113095823614"
|
1868 |
user_avatar = "https://junyitopicimg.s3.amazonaws.com/s4byy--icon.jpe?v=20200513013523726"
|
1869 |
chatbot = gr.Chatbot(avatar_images=[bot_avatar, user_avatar], label="OPEN AI", show_share_button=False, likeable=True)
|
|
|
1873 |
msg = gr.Textbox(label="Message")
|
1874 |
send_button = gr.Button("Send", variant="primary")
|
1875 |
with gr.Tab("GROQ"):
|
|
|
1876 |
groq_chatbot = gr.Chatbot(avatar_images=[bot_avatar, user_avatar], label="groq mode chatbot", show_share_button=False)
|
1877 |
groq_msg = gr.Textbox(label="Message")
|
1878 |
groq_send_button = gr.Button("Send", variant="primary")
|
1879 |
with gr.Tab("JUTOR"):
|
|
|
1880 |
jutor_chatbot = gr.Chatbot(avatar_images=[bot_avatar, user_avatar], label="jutor mode chatbot", show_share_button=False)
|
1881 |
jutor_msg = gr.Textbox(label="Message")
|
1882 |
jutor_send_button = gr.Button("Send", variant="primary")
|
1883 |
+
with gr.Tab("CLAUDE"):
|
1884 |
+
claude_chatbot = gr.Chatbot(avatar_images=[bot_avatar, user_avatar], label="claude mode chatbot", show_share_button=False)
|
1885 |
+
claude_msg = gr.Textbox(label="Message")
|
1886 |
+
claude_send_button = gr.Button("Send", variant="primary")
|
1887 |
|
1888 |
with gr.Tab("教師版"):
|
1889 |
with gr.Row():
|
|
|
1995 |
inputs=[password, jutor_msg, df_string_output, jutor_chatbot, socratic_mode_btn],
|
1996 |
outputs=[jutor_msg, jutor_chatbot]
|
1997 |
)
|
1998 |
+
# CLAUDE 模式
|
1999 |
+
claude_send_button.click(
|
2000 |
+
chat_with_claude3,
|
2001 |
+
inputs=[password, claude_msg, df_string_output, claude_chatbot, socratic_mode_btn],
|
2002 |
+
outputs=[claude_msg, claude_chatbot]
|
2003 |
+
)
|
2004 |
|
2005 |
# 连接按钮点击事件
|
2006 |
chat_with_opan_ai_assistant_input =[password, video_id, thread_id, df_string_output, btn_1, chatbot, content_subject, content_grade, socratic_mode_btn]
|
local_config.json
DELETED
@@ -1,23 +0,0 @@
|
|
1 |
-
{
|
2 |
-
"OUTPUT_PATH": "/Users/young/Downloads",
|
3 |
-
"TRANSCRIPTS": [],
|
4 |
-
"CURRENT_INDEX": 0,
|
5 |
-
"VIDEO_ID": "",
|
6 |
-
"PASSWORD": "6161",
|
7 |
-
"OPEN_AI_KEY": "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",
|
8 |
-
"GROQ_API_KEY": "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",
|
9 |
-
"JUTOR_CHAT_KEY": "b4c318b8d6f770e10163436e0e868b806f50f34ae57f378e78956fb76b41fd27",
|
10 |
-
"GOOGLE_APPLICATION_CREDENTIALS_JSON": {
|
11 |
-
"type": "service_account",
|
12 |
-
"project_id": "junyiacademy",
|
13 |
-
"private_key_id": "95d4580de7518ff96be219626c58b23f1754ec6a",
|
14 |
-
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCmo3M8Ix46FLNS\nX8NGnEMiZBomXQOEfKCRUy0khm5IKgu5RUIWSF/0UuZeWXG93a1PMarBWokTTIpo\njtRNuEAh+H8lbacJ/G6EH5PxyMjPAOROXLvSJUg4c6lOFp/WoFlnirSPsD/YHL3l\nKKm6//h/tN7GDhaqOKrf9xJ1IlSt7odhCgcR7r3dF/+pbZ2UMDA0rmNmj2aJq7rl\n1qOD/8yC3ainledRRSt8oE7t4w+3eqI5GO7OdLiNwSxGGBNx9IiJln6TFC7frvET\nzr2ZUVLL7jFdWNyfXPU3/B+7JwyXgFGfHpiyQ2xyFAUR62HkpVxs0bKNbnLLmKoL\nIXCQ+lB9AgMBAAECggEAAJLA1C/E7E46SeEqdP3o/TbAwy+Ro4dnUaRNbaK9HmJv\nXymcYJc/JfxjBcRu0qV6wyaeaH1UVZJ67TtWX6JvuPQDWQ2dVX5eovW42aks/AlR\n1wSgeA5rr7pkrZ6jZWa2XGNfOLxpwaGpIqrcx7T/ija/Qc8qmShnSyx+awi9YdX4\n/ih1Ug1fqHPQ1j3Xx23J/S4Wb6eamJZ1BW+txZUUVD2KFnw7iJWR81ceTIuoSY4R\na3Vd8yB1Ri9iVaP6pe0WeA14VfU1d3tbO0GRF6XsEtdRynVXA17nO6okc3yV0bOQ\nnWqibtfT6AWmJFIyya3DrZDxKqSFNuVfHaJrO2LvwQKBgQDRGUzCYJpGw6NAQuKw\n3egfBoTjozZxjykZb0GFFRCIIE9AmX0PkCbz9bxjjMtb9pTH3aVIiv8mL3rfqzdK\nEPEfyC5TntWqahqBW+fOMrpnU54o4Ji1TlFuSBMRBxqIPcJnKFuttkfPZiHbxe3i\nkeqBbJ4HafH5ZNAV+pHwQKSXDwKBgQDMBAbxvSKgYXxeGMOs62rK6y9NeZlKpRUJ\nORdBv+3sLTwSjlpEPwn/KgMXHaHnpDXhtTDP0ad9nLOKnZ5k8dRNcpyUEXVC2WTD\nDHd37lChG0XRnfGuxIvfr5ZYajN/sIgV8WuNpFuWnFj+mGdi+OpzS+KG3J2rMx/k\n4jl1l8g/swKBgQCYJCVyxSFb3dt51XDmKgBMGs00aLwjcnwAErCEqagGtCOWKFgT\nq9p75dA2SupotojYyBAMMX6nBSMNfaHUFXGso1X55/clcOBqQTnwEX8J0ZChw5G5\nUgv0ByNAX3/Ro8ZAkt/qDFhBstlt9J07HtqXYzW0xUSYJt81LsVjH1XixwKBgDF6\nUIzUB8/JlLXlX59SQMYRn5k0gl6+BooEFIXXnEYI+matq2qdtzjw4Wr7vsZE5uRk\nYwAjonEuTcSyUTW+CHT39M1cJood2vgKz/aAD4Hi8V3S5kgyVpHbLaUnrHGtSHO5\n5xGk6KlwJY0pPPmd0I5BuyBl5L8eWP/TdYf1VZVNAoGAUEMSVxBd/onX5LXrzkR7\nOS8w6L+YL68yWCFs1pocfY+cZfkBpteLXzqOMKN2Xc3C7TGGySnEaQlG8bF1P00E\nW9HZvrSYbhsZwEKiIxY3suWRMPRlbeHU9hxt7rYPM+kwl8zy+Z/UtE28Zwhcr0+r\n7EkfwiOEvYStw0mJ9xwhiwU=\n-----END PRIVATE KEY-----\n",
|
15 |
-
"client_email": "analytics-api@junyiacademy.iam.gserviceaccount.com",
|
16 |
-
"client_id": "113360448655635325414",
|
17 |
-
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
18 |
-
"token_uri": "https://oauth2.googleapis.com/token",
|
19 |
-
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
20 |
-
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/analytics-api%40junyiacademy.iam.gserviceaccount.com",
|
21 |
-
"universe_domain": "googleapis.com"
|
22 |
-
}
|
23 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
requirements.txt
CHANGED
@@ -15,4 +15,5 @@ google-cloud-storage
|
|
15 |
groq
|
16 |
yt_dlp
|
17 |
uuid
|
18 |
-
gtts
|
|
|
|
15 |
groq
|
16 |
yt_dlp
|
17 |
uuid
|
18 |
+
gtts
|
19 |
+
boto3
|