Spaces:
Sleeping
Sleeping
def chat_with_any_ai(ai_type, password, video_id, user_data, transcript_state, key_moments, user_message, chat_history, content_subject, content_grade, questions_answers_json, socratic_mode=False, thread_id=None, ai_name=None):
Browse files
app.py
CHANGED
|
@@ -1261,7 +1261,6 @@ def change_questions(password, df_string):
|
|
| 1261 |
print("=====get_questions=====")
|
| 1262 |
return q1, q2, q3
|
| 1263 |
|
| 1264 |
-
# 「關鍵時刻」另外獨立成一個 tab,時間戳記和文字的下方附上對應的截圖,重點摘要的「關鍵時刻」加上截圖資訊
|
| 1265 |
def get_key_moments(video_id, formatted_simple_transcript, formatted_transcript, source):
|
| 1266 |
if source == "gcs":
|
| 1267 |
print("===get_key_moments on gcs===")
|
|
@@ -2100,12 +2099,10 @@ def get_instructions(content_subject, content_grade, key_moments, socratic_mode=
|
|
| 2100 |
"""
|
| 2101 |
return instructions
|
| 2102 |
|
| 2103 |
-
def
|
| 2104 |
-
|
| 2105 |
-
|
| 2106 |
-
print("=====user_data=====")
|
| 2107 |
print(f"user_data: {user_data}")
|
| 2108 |
-
|
| 2109 |
verify_message_length(user_message, max_length=1500)
|
| 2110 |
|
| 2111 |
is_questions_answers_exists, question_message, answer_message = check_questions_answers(user_message, questions_answers_json)
|
|
@@ -2113,10 +2110,52 @@ def chat_with_ai(ai_name, password, video_id, user_data, trascript_state, key_mo
|
|
| 2113 |
chat_history = update_chat_history(question_message, answer_message, chat_history)
|
| 2114 |
send_btn_update, send_feedback_btn_update = update_send_and_feedback_buttons(chat_history, CHAT_LIMIT)
|
| 2115 |
time.sleep(3)
|
| 2116 |
-
return "", chat_history, send_btn_update, send_feedback_btn_update
|
| 2117 |
|
|
|
|
|
|
|
| 2118 |
verify_chat_limit(chat_history, CHAT_LIMIT)
|
| 2119 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2120 |
if not ai_name in ["foxcat", "lili", "maimai"]:
|
| 2121 |
ai_name = "foxcat"
|
| 2122 |
|
|
@@ -2140,10 +2179,10 @@ def chat_with_ai(ai_name, password, video_id, user_data, trascript_state, key_mo
|
|
| 2140 |
ai_client = ai_name_clients_model.get(ai_name, "foxcat")["ai_client"]
|
| 2141 |
ai_model_name = ai_name_clients_model.get(ai_name, "foxcat")["ai_model_name"]
|
| 2142 |
|
| 2143 |
-
if isinstance(
|
| 2144 |
-
simple_transcript = json.loads(
|
| 2145 |
else:
|
| 2146 |
-
simple_transcript =
|
| 2147 |
|
| 2148 |
if isinstance(key_moments, str):
|
| 2149 |
key_moments_json = json.loads(key_moments)
|
|
@@ -2170,26 +2209,9 @@ def chat_with_ai(ai_name, password, video_id, user_data, trascript_state, key_mo
|
|
| 2170 |
"instructions": instructions
|
| 2171 |
}
|
| 2172 |
|
| 2173 |
-
|
| 2174 |
-
chatbot = Chatbot(chatbot_config)
|
| 2175 |
-
response_completion = chatbot.chat(user_message, chat_history, socratic_mode, ai_model_name)
|
| 2176 |
-
except Exception as e:
|
| 2177 |
-
print(f"Error: {e}")
|
| 2178 |
-
response_completion = "學習精靈有點累,請稍後再試!"
|
| 2179 |
-
|
| 2180 |
-
try:
|
| 2181 |
-
# 更新聊天历史
|
| 2182 |
-
chat_history = update_chat_history(user_message, response_completion, chat_history)
|
| 2183 |
-
send_btn_update, send_feedback_btn_update = update_send_and_feedback_buttons(chat_history, CHAT_LIMIT)
|
| 2184 |
-
|
| 2185 |
-
# 返回聊天历史和空字符串清空输入框
|
| 2186 |
-
return "", chat_history, send_btn_update, send_feedback_btn_update
|
| 2187 |
-
except Exception as e:
|
| 2188 |
-
# 处理错误情况
|
| 2189 |
-
print(f"Error: {e}")
|
| 2190 |
-
return "请求失败,请稍后再试!", chat_history
|
| 2191 |
|
| 2192 |
-
def feedback_with_ai(chat_history):
|
| 2193 |
# prompt: 請依據以上的對話(chat_history),總結我的「提問力」,並給予我是否有「問對問題」的回饋和建議
|
| 2194 |
system_content = """
|
| 2195 |
你是一個擅長引導問答素養的老師,user 為學生的提問跟回答,請精讀對話過程,針對 user 給予回饋就好,根據以下 Rule:
|
|
@@ -2225,10 +2247,16 @@ def feedback_with_ai(chat_history):
|
|
| 2225 |
提問表現:【🟡】加油,持續練習,你的提問力會越來越好!
|
| 2226 |
"""
|
| 2227 |
|
| 2228 |
-
|
| 2229 |
client = OPEN_AI_CLIENT
|
| 2230 |
-
|
| 2231 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2232 |
chat_history = update_chat_history(feedback_request_message, response_text, chat_history)
|
| 2233 |
feedback_btn_update = gr.update(value="已回饋", interactive=False, variant="secondary")
|
| 2234 |
|
|
@@ -2246,139 +2274,6 @@ def handle_conversation_by_open_ai_chat_completions(client, model_name, user_con
|
|
| 2246 |
response_text = response.choices[0].message.content.strip()
|
| 2247 |
return response_text
|
| 2248 |
|
| 2249 |
-
# open ai assistant
|
| 2250 |
-
def chat_with_opan_ai_assistant(password, youtube_id, user_data, thread_id, trascript_state, key_moments, user_message, chat_history, content_subject, content_grade, questions_answers_json, socratic_mode=False):
|
| 2251 |
-
verify_password(password)
|
| 2252 |
-
|
| 2253 |
-
print("=====user_data=====")
|
| 2254 |
-
print(f"user_data: {user_data}")
|
| 2255 |
-
|
| 2256 |
-
verify_message_length(user_message, max_length=1500)
|
| 2257 |
-
|
| 2258 |
-
is_questions_answers_exists, question_message, answer_message = check_questions_answers(user_message, questions_answers_json)
|
| 2259 |
-
if is_questions_answers_exists:
|
| 2260 |
-
chat_history = update_chat_history(question_message, answer_message, chat_history)
|
| 2261 |
-
send_btn_update, send_feedback_btn_update = update_send_and_feedback_buttons(chat_history, CHAT_LIMIT)
|
| 2262 |
-
time.sleep(3)
|
| 2263 |
-
return "", chat_history, thread_id, send_btn_update, send_feedback_btn_update
|
| 2264 |
-
|
| 2265 |
-
verify_chat_limit(chat_history, CHAT_LIMIT)
|
| 2266 |
-
|
| 2267 |
-
client = OPEN_AI_CLIENT
|
| 2268 |
-
assistant_id = OPEN_AI_ASSISTANT_ID_GPT4 #GPT 4 turbo
|
| 2269 |
-
if isinstance(key_moments, str):
|
| 2270 |
-
key_moments_json = json.loads(key_moments)
|
| 2271 |
-
else:
|
| 2272 |
-
key_moments_json = key_moments
|
| 2273 |
-
# key_moments_json remove images
|
| 2274 |
-
for moment in key_moments_json:
|
| 2275 |
-
moment.pop('images', None)
|
| 2276 |
-
moment.pop('end', None)
|
| 2277 |
-
moment.pop('transcript', None)
|
| 2278 |
-
key_moments_text = json.dumps(key_moments_json, ensure_ascii=False)
|
| 2279 |
-
instructions = get_instructions(content_subject, content_grade, key_moments_text, socratic_mode)
|
| 2280 |
-
print(f"=== instructions:{instructions} ===")
|
| 2281 |
-
metadata={
|
| 2282 |
-
"video_id": youtube_id,
|
| 2283 |
-
"user_data": user_data,
|
| 2284 |
-
"content_subject": content_subject,
|
| 2285 |
-
"content_grade": content_grade,
|
| 2286 |
-
"socratic_mode": str(socratic_mode),
|
| 2287 |
-
"assistant_id": assistant_id,
|
| 2288 |
-
"is_streaming": "false",
|
| 2289 |
-
}
|
| 2290 |
-
user_message_note = "/n 請嚴格遵循instructions,擔任一位蘇格拉底家教,絕對不要重複 user 的問句,請用引導的方式指引方向,請一定要用繁體中文回答 zh-TW,並用台灣人的禮貌口語表達,回答時不要特別說明這是台灣人的語氣,請在回答的最後標註【參考:(時):(分):(秒)】,(如果是反問學生,就只問一個問題,請幫助學生更好的理解資料,字數在100字以內,回答時如果講到數學專有名詞,請用數學符號代替文字(Latex 用 $ 字號 render, ex: $x^2$)"
|
| 2291 |
-
user_content = user_message + user_message_note
|
| 2292 |
-
response_text, thread_id = handle_conversation_by_open_ai_assistant(client, user_content, instructions, assistant_id, thread_id, metadata, fallback=True)
|
| 2293 |
-
|
| 2294 |
-
# 更新聊天历史
|
| 2295 |
-
chat_history = update_chat_history(user_message, response_text, chat_history)
|
| 2296 |
-
send_btn_update, send_feedback_btn_update = update_send_and_feedback_buttons(chat_history, CHAT_LIMIT)
|
| 2297 |
-
|
| 2298 |
-
return "", chat_history, thread_id, send_btn_update, send_feedback_btn_update
|
| 2299 |
-
|
| 2300 |
-
def feedback_with_opan_ai_assistant(thread_id, chat_history):
|
| 2301 |
-
# prompt: 請依據以上的對話(chat_history),總結我的「提問力」,並給予我是否有「問對問題」的回饋和建議
|
| 2302 |
-
system_content = """
|
| 2303 |
-
你是一個擅長引導問答素養的老師,user 為學生的提問跟回答,請精讀對話過程,針對 user 給予回饋就好,根據以下 Rule:
|
| 2304 |
-
- 請使用繁體中文 zh-TW 總結 user 的提問力,並給予是否有問對問題的回饋和建議
|
| 2305 |
-
- 不採計【預設提問】的問題,如果 user 的提問都來自【預設提問】,表達用戶善於使用系統,請給予回饋並鼓勵 user 親自提問更具體的問題
|
| 2306 |
-
- 如果用戶提問都相當簡短,甚至就是一個字或都是一個數字(像是 user: 1, user:2),請給予回饋並建議 user 提問更具體的問題
|
| 2307 |
-
- 如果用戶提問內容只有符號或是亂碼,像是?,!, ..., 3bhwbqhfw2vve2 等,請給予回饋並建議 user 提問更具體的問題
|
| 2308 |
-
- 如果用戶提問內容有色情、暴力、仇恨、不當言論等,請給予嚴厲的回饋並建議 user 提問更具體的問題
|
| 2309 |
-
- 並用第二人稱「你」來代表 user
|
| 2310 |
-
- 請禮貌,並給予鼓勵
|
| 2311 |
-
"""
|
| 2312 |
-
chat_history_conversation = ""
|
| 2313 |
-
# 標註 user and assistant as string
|
| 2314 |
-
# chat_history 第一組不採計
|
| 2315 |
-
for chat in chat_history[1:]:
|
| 2316 |
-
user_message = chat[0]
|
| 2317 |
-
assistant_message = chat[1]
|
| 2318 |
-
chat_history_conversation += f"User: {user_message}\nAssistant: {assistant_message}\n"
|
| 2319 |
-
|
| 2320 |
-
feedback_request_message = "請依據以上的對話,總結我的「提問力」,並給予我是否有「問對問題」的回饋和建議"
|
| 2321 |
-
user_content = f"""conversation: {chat_history_conversation}
|
| 2322 |
-
{feedback_request_message}
|
| 2323 |
-
最後根據提問力表現,給予提問建議、提問表現,並用 emoji 來表示評分:
|
| 2324 |
-
🟢:(表現很好的回饋,給予正向肯定)
|
| 2325 |
-
🟡:(還可以加油的的回饋,給予明確的建議)
|
| 2326 |
-
🔴:(非常不懂提問的回饋,給予鼓勵並給出明確示範)
|
| 2327 |
-
|
| 2328 |
-
example:
|
| 2329 |
-
另一方面,你表達「我不想學了」這個情感,其實也是一種重要的反饋。這顯示你可能感到挫折或疲倦。在這種情況下,表達出你的感受是好的,但如果能具體說明是什麼讓你感到這樣,或是有什麼具體的學習障礙,會更有助於找到解決方案。
|
| 2330 |
-
給予你的建議是,嘗試在提問時更明確一些,這樣不僅能幫助你獲得更好的學習支持,也能提高你的問題解決技巧。
|
| 2331 |
-
......
|
| 2332 |
-
提問建議:在提問時,試著具體並清晰地表達你的需求和疑惑,這樣能更有效地得到幫助。
|
| 2333 |
-
提問表現:【🟡】加油,持續練習,你的提問力會越來越好!
|
| 2334 |
-
"""
|
| 2335 |
-
|
| 2336 |
-
|
| 2337 |
-
client = OPEN_AI_CLIENT
|
| 2338 |
-
assistant_id = OPEN_AI_ASSISTANT_ID_GPT4 #GPT 4 turbo
|
| 2339 |
-
# assistant_id = OPEN_AI_ASSISTANT_ID_GPT3 #GPT 3.5 turbo
|
| 2340 |
-
instructions = system_content
|
| 2341 |
-
response_text, thread_id = handle_conversation_by_open_ai_assistant(client, user_content, instructions, assistant_id, thread_id, metadata=None, fallback=True)
|
| 2342 |
-
chat_history = update_chat_history(feedback_request_message, response_text, chat_history)
|
| 2343 |
-
feedback_btn_update = gr.update(value="已回饋", interactive=False, variant="secondary")
|
| 2344 |
-
|
| 2345 |
-
return chat_history, feedback_btn_update
|
| 2346 |
-
|
| 2347 |
-
def verify_message_length(user_message, max_length=500):
|
| 2348 |
-
# 驗證用戶消息的長度
|
| 2349 |
-
if len(user_message) > max_length:
|
| 2350 |
-
error_msg = "你的訊息太長了,請縮短訊息長度至五百字以內"
|
| 2351 |
-
raise gr.Error(error_msg)
|
| 2352 |
-
|
| 2353 |
-
def check_questions_answers(user_message, questions_answers_json):
|
| 2354 |
-
"""檢查問答是否存在,並處理相關邏輯"""
|
| 2355 |
-
is_questions_answers_exists = False
|
| 2356 |
-
answer = ""
|
| 2357 |
-
# 解析問答數據
|
| 2358 |
-
if isinstance(questions_answers_json, str):
|
| 2359 |
-
qa_data = json.loads(questions_answers_json)
|
| 2360 |
-
else:
|
| 2361 |
-
qa_data = questions_answers_json
|
| 2362 |
-
|
| 2363 |
-
question_message = ""
|
| 2364 |
-
answer_message = ""
|
| 2365 |
-
for qa in qa_data:
|
| 2366 |
-
if user_message == qa["question"] and qa["answer"]:
|
| 2367 |
-
is_questions_answers_exists = True
|
| 2368 |
-
question_message = f"【預設問題】{user_message}"
|
| 2369 |
-
answer_message = qa["answer"]
|
| 2370 |
-
print("=== in questions_answers_json==")
|
| 2371 |
-
print(f"question: {qa['question']}")
|
| 2372 |
-
print(f"answer: {answer_message}")
|
| 2373 |
-
break # 匹配到答案後退出循環
|
| 2374 |
-
|
| 2375 |
-
return is_questions_answers_exists, question_message, answer_message
|
| 2376 |
-
|
| 2377 |
-
def verify_chat_limit(chat_history, chat_limit):
|
| 2378 |
-
if chat_history is not None and len(chat_history) > chat_limit:
|
| 2379 |
-
error_msg = "此次對話超過上限(對話一輪10次)"
|
| 2380 |
-
raise gr.Error(error_msg)
|
| 2381 |
-
|
| 2382 |
def handle_conversation_by_open_ai_assistant(client, user_message, instructions, assistant_id, thread_id=None, metadata=None, fallback=False):
|
| 2383 |
"""
|
| 2384 |
Handles the creation and management of a conversation thread.
|
|
@@ -2433,6 +2328,41 @@ def handle_conversation_by_open_ai_assistant(client, user_message, instructions,
|
|
| 2433 |
|
| 2434 |
return response_text, thread_id
|
| 2435 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2436 |
def update_chat_history(user_message, response, chat_history):
|
| 2437 |
# 更新聊天歷史的邏輯
|
| 2438 |
new_chat_history = (user_message, response)
|
|
@@ -2661,7 +2591,8 @@ def chatbot_select(chatbot_name):
|
|
| 2661 |
chatbot_open_ai_streaming_visible = gr.update(visible=True)
|
| 2662 |
else:
|
| 2663 |
chatbot_jutor_visible = gr.update(visible=True)
|
| 2664 |
-
|
|
|
|
| 2665 |
|
| 2666 |
return chatbot_select_accordion_visible, all_chatbot_select_btn_visible, chatbot_open_ai_visible, chatbot_open_ai_streaming_visible, chatbot_jutor_visible, ai_name_update
|
| 2667 |
|
|
@@ -2833,6 +2764,18 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, seconda
|
|
| 2833 |
with gr.Tab("AI小精靈"):
|
| 2834 |
with gr.Row():
|
| 2835 |
all_chatbot_select_btn = gr.Button("選擇 AI 小精靈 👈", elem_id="all_chatbot_select_btn", visible=False, variant="secondary", size="sm")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2836 |
with gr.Accordion("選擇 AI 小精靈", elem_id="chatbot_select_accordion") as chatbot_select_accordion:
|
| 2837 |
with gr.Row():
|
| 2838 |
user_avatar = "https://em-content.zobj.net/source/google/263/flushed-face_1f633.png"
|
|
@@ -2927,6 +2870,7 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, seconda
|
|
| 2927 |
with gr.Row():
|
| 2928 |
chatbot = gr.Chatbot(avatar_images=[user_avatar, bot_avatar], label="OPEN AI", show_share_button=False, likeable=True, show_label=False, latex_delimiters=latex_delimiters,value=chatbot_greeting)
|
| 2929 |
with gr.Row():
|
|
|
|
| 2930 |
thread_id = gr.Textbox(label="thread_id", visible=False)
|
| 2931 |
socratic_mode_btn = gr.Checkbox(label="蘇格拉底家教助理模式", value=True, visible=False)
|
| 2932 |
with gr.Row():
|
|
@@ -2972,18 +2916,12 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, seconda
|
|
| 2972 |
💤 精靈們體力都有限,每一次學習只能回答十個問題,請讓我休息一下再問問題喔!
|
| 2973 |
""",
|
| 2974 |
]]
|
| 2975 |
-
|
| 2976 |
-
label="
|
| 2977 |
-
|
| 2978 |
-
|
| 2979 |
-
|
| 2980 |
-
|
| 2981 |
-
],
|
| 2982 |
-
value="foxcat",
|
| 2983 |
-
visible=False
|
| 2984 |
-
)
|
| 2985 |
-
ai_chatbot = gr.Chatbot(label="ai_chatbot", show_share_button=False, likeable=True, show_label=False, latex_delimiters=latex_delimiters, value=ai_chatbot_greeting)
|
| 2986 |
-
ai_chatbot_socratic_mode_btn = gr.Checkbox(label="蘇格拉底家教助理模式", value=True, visible=False)
|
| 2987 |
with gr.Row():
|
| 2988 |
with gr.Accordion("你也有類似的問題想問嗎? 請按下 ◀︎", open=False) as ask_questions_accordion_2:
|
| 2989 |
ai_chatbot_question_1 = gr.Button("問題一")
|
|
@@ -3234,14 +3172,14 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, seconda
|
|
| 3234 |
|
| 3235 |
# OPENAI ASSISTANT CHATBOT 模式
|
| 3236 |
send_button.click(
|
| 3237 |
-
|
| 3238 |
-
inputs=[password, video_id, user_data,
|
| 3239 |
-
outputs=[msg, chatbot,
|
| 3240 |
scroll_to_output=True
|
| 3241 |
)
|
| 3242 |
send_feedback_btn.click(
|
| 3243 |
-
|
| 3244 |
-
inputs=[
|
| 3245 |
outputs=[chatbot, send_feedback_btn],
|
| 3246 |
scroll_to_output=True
|
| 3247 |
)
|
|
@@ -3260,9 +3198,9 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, seconda
|
|
| 3260 |
)
|
| 3261 |
question_buttons = [btn_1, btn_2, btn_3]
|
| 3262 |
for question_btn in question_buttons:
|
| 3263 |
-
inputs_list = [password, video_id, user_data,
|
| 3264 |
-
outputs_list = [msg, chatbot,
|
| 3265 |
-
setup_question_button_click(question_btn, inputs_list, outputs_list,
|
| 3266 |
|
| 3267 |
# 為生成問題按鈕設定特殊的點擊事件
|
| 3268 |
btn_create_question.click(
|
|
@@ -3273,23 +3211,23 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, seconda
|
|
| 3273 |
|
| 3274 |
# 其他精靈 ai_chatbot 模式
|
| 3275 |
ai_send_button.click(
|
| 3276 |
-
|
| 3277 |
-
inputs=[
|
| 3278 |
-
outputs=[ai_msg, ai_chatbot, ai_send_button, ai_send_feedback_btn],
|
| 3279 |
scroll_to_output=True
|
| 3280 |
)
|
| 3281 |
ai_send_feedback_btn.click(
|
| 3282 |
feedback_with_ai,
|
| 3283 |
-
inputs=[ai_chatbot],
|
| 3284 |
outputs=[ai_chatbot, ai_send_feedback_btn],
|
| 3285 |
scroll_to_output=True
|
| 3286 |
)
|
| 3287 |
# 其他精靈 ai_chatbot 连接 QA 按钮点击事件
|
| 3288 |
ai_chatbot_question_buttons = [ai_chatbot_question_1, ai_chatbot_question_2, ai_chatbot_question_3]
|
| 3289 |
for question_btn in ai_chatbot_question_buttons:
|
| 3290 |
-
inputs_list = [
|
| 3291 |
-
outputs_list = [ai_msg, ai_chatbot, ai_send_button, ai_send_feedback_btn]
|
| 3292 |
-
setup_question_button_click(question_btn, inputs_list, outputs_list,
|
| 3293 |
|
| 3294 |
ai_chatbot_audio_input.change(
|
| 3295 |
process_open_ai_audio_to_chatbot,
|
|
|
|
| 1261 |
print("=====get_questions=====")
|
| 1262 |
return q1, q2, q3
|
| 1263 |
|
|
|
|
| 1264 |
def get_key_moments(video_id, formatted_simple_transcript, formatted_transcript, source):
|
| 1265 |
if source == "gcs":
|
| 1266 |
print("===get_key_moments on gcs===")
|
|
|
|
| 2099 |
"""
|
| 2100 |
return instructions
|
| 2101 |
|
| 2102 |
+
def chat_with_any_ai(ai_type, password, video_id, user_data, transcript_state, key_moments, user_message, chat_history, content_subject, content_grade, questions_answers_json, socratic_mode=False, thread_id=None, ai_name=None):
|
| 2103 |
+
print(f"ai_type: {ai_type}")
|
|
|
|
|
|
|
| 2104 |
print(f"user_data: {user_data}")
|
| 2105 |
+
verify_password(password)
|
| 2106 |
verify_message_length(user_message, max_length=1500)
|
| 2107 |
|
| 2108 |
is_questions_answers_exists, question_message, answer_message = check_questions_answers(user_message, questions_answers_json)
|
|
|
|
| 2110 |
chat_history = update_chat_history(question_message, answer_message, chat_history)
|
| 2111 |
send_btn_update, send_feedback_btn_update = update_send_and_feedback_buttons(chat_history, CHAT_LIMIT)
|
| 2112 |
time.sleep(3)
|
|
|
|
| 2113 |
|
| 2114 |
+
return "", chat_history, send_btn_update, send_feedback_btn_update, thread_id
|
| 2115 |
+
|
| 2116 |
verify_chat_limit(chat_history, CHAT_LIMIT)
|
| 2117 |
|
| 2118 |
+
if ai_type == "chat_completions":
|
| 2119 |
+
chatbot_config = get_chatbot_config(ai_name, transcript_state, key_moments, content_subject, content_grade, video_id, socratic_mode)
|
| 2120 |
+
chatbot = Chatbot(chatbot_config)
|
| 2121 |
+
response_text = chatbot.chat(user_message, chat_history)
|
| 2122 |
+
thread_id = ""
|
| 2123 |
+
elif ai_type == "assistant":
|
| 2124 |
+
client = OPEN_AI_CLIENT
|
| 2125 |
+
assistant_id = OPEN_AI_ASSISTANT_ID_GPT4 #GPT 4 turbo
|
| 2126 |
+
if isinstance(key_moments, str):
|
| 2127 |
+
key_moments_json = json.loads(key_moments)
|
| 2128 |
+
else:
|
| 2129 |
+
key_moments_json = key_moments
|
| 2130 |
+
# key_moments_json remove images
|
| 2131 |
+
for moment in key_moments_json:
|
| 2132 |
+
moment.pop('images', None)
|
| 2133 |
+
moment.pop('end', None)
|
| 2134 |
+
moment.pop('transcript', None)
|
| 2135 |
+
key_moments_text = json.dumps(key_moments_json, ensure_ascii=False)
|
| 2136 |
+
instructions = get_instructions(content_subject, content_grade, key_moments_text, socratic_mode)
|
| 2137 |
+
print(f"=== instructions:{instructions} ===")
|
| 2138 |
+
metadata={
|
| 2139 |
+
"video_id": video_id,
|
| 2140 |
+
"user_data": user_data,
|
| 2141 |
+
"content_subject": content_subject,
|
| 2142 |
+
"content_grade": content_grade,
|
| 2143 |
+
"socratic_mode": str(socratic_mode),
|
| 2144 |
+
"assistant_id": assistant_id,
|
| 2145 |
+
"is_streaming": "false",
|
| 2146 |
+
}
|
| 2147 |
+
user_message_note = "/n 請嚴格遵循instructions,擔任一位蘇格拉底家教,絕對不要重複 user 的問句,請用引導的方式指引方向,請一定要用繁體中文回答 zh-TW,並用台灣人的禮貌口語表達,回答時不要特別說明這是台灣人的語氣,請在回答的最後標註【參考:(時):(分):(秒)】,(如果是反問學生,就只問一個問題,請幫助學生更好的理解資料,字數在100字以內,回答時如果講到數學專有名詞,請用數學符號代替文字(Latex 用 $ 字號 render, ex: $x^2$)"
|
| 2148 |
+
user_content = user_message + user_message_note
|
| 2149 |
+
response_text, thread_id = handle_conversation_by_open_ai_assistant(client, user_content, instructions, assistant_id, thread_id, metadata, fallback=True)
|
| 2150 |
+
|
| 2151 |
+
# 更新聊天历史
|
| 2152 |
+
chat_history = update_chat_history(user_message, response_text, chat_history)
|
| 2153 |
+
send_btn_update, send_feedback_btn_update = update_send_and_feedback_buttons(chat_history, CHAT_LIMIT)
|
| 2154 |
+
|
| 2155 |
+
# 返回聊天历史和空字符串清空输入框
|
| 2156 |
+
return "", chat_history, send_btn_update, send_feedback_btn_update, thread_id
|
| 2157 |
+
|
| 2158 |
+
def get_chatbot_config(ai_name, transcript_state, key_moments, content_subject, content_grade, video_id, socratic_mode=True):
|
| 2159 |
if not ai_name in ["foxcat", "lili", "maimai"]:
|
| 2160 |
ai_name = "foxcat"
|
| 2161 |
|
|
|
|
| 2179 |
ai_client = ai_name_clients_model.get(ai_name, "foxcat")["ai_client"]
|
| 2180 |
ai_model_name = ai_name_clients_model.get(ai_name, "foxcat")["ai_model_name"]
|
| 2181 |
|
| 2182 |
+
if isinstance(transcript_state, str):
|
| 2183 |
+
simple_transcript = json.loads(transcript_state)
|
| 2184 |
else:
|
| 2185 |
+
simple_transcript = transcript_state
|
| 2186 |
|
| 2187 |
if isinstance(key_moments, str):
|
| 2188 |
key_moments_json = json.loads(key_moments)
|
|
|
|
| 2209 |
"instructions": instructions
|
| 2210 |
}
|
| 2211 |
|
| 2212 |
+
return chatbot_config
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2213 |
|
| 2214 |
+
def feedback_with_ai(ai_type, chat_history, thread_id=None):
|
| 2215 |
# prompt: 請依據以上的對話(chat_history),總結我的「提問力」,並給予我是否有「問對問題」的回饋和建議
|
| 2216 |
system_content = """
|
| 2217 |
你是一個擅長引導問答素養的老師,user 為學生的提問跟回答,請精讀對話過程,針對 user 給予回饋就好,根據以下 Rule:
|
|
|
|
| 2247 |
提問表現:【🟡】加油,持續練習,你的提問力會越來越好!
|
| 2248 |
"""
|
| 2249 |
|
|
|
|
| 2250 |
client = OPEN_AI_CLIENT
|
| 2251 |
+
|
| 2252 |
+
if ai_type == "chat_completions":
|
| 2253 |
+
model_name = "gpt-4-turbo"
|
| 2254 |
+
response_text = handle_conversation_by_open_ai_chat_completions(client, model_name, user_content, system_content)
|
| 2255 |
+
elif ai_type == "assistant":
|
| 2256 |
+
assistant_id = OPEN_AI_ASSISTANT_ID_GPT4 #GPT 4 turbo
|
| 2257 |
+
# assistant_id = OPEN_AI_ASSISTANT_ID_GPT3 #GPT 3.5 turbo
|
| 2258 |
+
response_text, thread_id = handle_conversation_by_open_ai_assistant(client, user_content, system_content, assistant_id, thread_id, metadata=None, fallback=True)
|
| 2259 |
+
|
| 2260 |
chat_history = update_chat_history(feedback_request_message, response_text, chat_history)
|
| 2261 |
feedback_btn_update = gr.update(value="已回饋", interactive=False, variant="secondary")
|
| 2262 |
|
|
|
|
| 2274 |
response_text = response.choices[0].message.content.strip()
|
| 2275 |
return response_text
|
| 2276 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2277 |
def handle_conversation_by_open_ai_assistant(client, user_message, instructions, assistant_id, thread_id=None, metadata=None, fallback=False):
|
| 2278 |
"""
|
| 2279 |
Handles the creation and management of a conversation thread.
|
|
|
|
| 2328 |
|
| 2329 |
return response_text, thread_id
|
| 2330 |
|
| 2331 |
+
def verify_message_length(user_message, max_length=500):
|
| 2332 |
+
# 驗證用戶消息的長度
|
| 2333 |
+
if len(user_message) > max_length:
|
| 2334 |
+
error_msg = "你的訊息太長了,請縮短訊息長度至五百字以內"
|
| 2335 |
+
raise gr.Error(error_msg)
|
| 2336 |
+
|
| 2337 |
+
def check_questions_answers(user_message, questions_answers_json):
|
| 2338 |
+
"""檢查問答是否存在,並處理相關邏輯"""
|
| 2339 |
+
is_questions_answers_exists = False
|
| 2340 |
+
answer = ""
|
| 2341 |
+
# 解析問答數據
|
| 2342 |
+
if isinstance(questions_answers_json, str):
|
| 2343 |
+
qa_data = json.loads(questions_answers_json)
|
| 2344 |
+
else:
|
| 2345 |
+
qa_data = questions_answers_json
|
| 2346 |
+
|
| 2347 |
+
question_message = ""
|
| 2348 |
+
answer_message = ""
|
| 2349 |
+
for qa in qa_data:
|
| 2350 |
+
if user_message == qa["question"] and qa["answer"]:
|
| 2351 |
+
is_questions_answers_exists = True
|
| 2352 |
+
question_message = f"【預設問題】{user_message}"
|
| 2353 |
+
answer_message = qa["answer"]
|
| 2354 |
+
print("=== in questions_answers_json==")
|
| 2355 |
+
print(f"question: {qa['question']}")
|
| 2356 |
+
print(f"answer: {answer_message}")
|
| 2357 |
+
break # 匹配到答案後退出循環
|
| 2358 |
+
|
| 2359 |
+
return is_questions_answers_exists, question_message, answer_message
|
| 2360 |
+
|
| 2361 |
+
def verify_chat_limit(chat_history, chat_limit):
|
| 2362 |
+
if chat_history is not None and len(chat_history) > chat_limit:
|
| 2363 |
+
error_msg = "此次對話超過上限(對話一輪10次)"
|
| 2364 |
+
raise gr.Error(error_msg)
|
| 2365 |
+
|
| 2366 |
def update_chat_history(user_message, response, chat_history):
|
| 2367 |
# 更新聊天歷史的邏輯
|
| 2368 |
new_chat_history = (user_message, response)
|
|
|
|
| 2591 |
chatbot_open_ai_streaming_visible = gr.update(visible=True)
|
| 2592 |
else:
|
| 2593 |
chatbot_jutor_visible = gr.update(visible=True)
|
| 2594 |
+
|
| 2595 |
+
ai_name_update = gr.update(value=chatbot_name)
|
| 2596 |
|
| 2597 |
return chatbot_select_accordion_visible, all_chatbot_select_btn_visible, chatbot_open_ai_visible, chatbot_open_ai_streaming_visible, chatbot_jutor_visible, ai_name_update
|
| 2598 |
|
|
|
|
| 2764 |
with gr.Tab("AI小精靈"):
|
| 2765 |
with gr.Row():
|
| 2766 |
all_chatbot_select_btn = gr.Button("選擇 AI 小精靈 👈", elem_id="all_chatbot_select_btn", visible=False, variant="secondary", size="sm")
|
| 2767 |
+
ai_name = gr.Dropdown(
|
| 2768 |
+
label="選擇 AI 助理",
|
| 2769 |
+
choices=[
|
| 2770 |
+
("飛特精靈","chatbot_open_ai"),
|
| 2771 |
+
("飛特音速","chatbot_open_ai_streaming"),
|
| 2772 |
+
("梨梨","lili"),
|
| 2773 |
+
("麥麥","maimai"),
|
| 2774 |
+
("狐狸貓","foxcat")
|
| 2775 |
+
],
|
| 2776 |
+
value="foxcat",
|
| 2777 |
+
visible=False
|
| 2778 |
+
)
|
| 2779 |
with gr.Accordion("選擇 AI 小精靈", elem_id="chatbot_select_accordion") as chatbot_select_accordion:
|
| 2780 |
with gr.Row():
|
| 2781 |
user_avatar = "https://em-content.zobj.net/source/google/263/flushed-face_1f633.png"
|
|
|
|
| 2870 |
with gr.Row():
|
| 2871 |
chatbot = gr.Chatbot(avatar_images=[user_avatar, bot_avatar], label="OPEN AI", show_share_button=False, likeable=True, show_label=False, latex_delimiters=latex_delimiters,value=chatbot_greeting)
|
| 2872 |
with gr.Row():
|
| 2873 |
+
chatbot_ai_type = gr.Textbox(value="assistant", visible=False)
|
| 2874 |
thread_id = gr.Textbox(label="thread_id", visible=False)
|
| 2875 |
socratic_mode_btn = gr.Checkbox(label="蘇格拉底家教助理模式", value=True, visible=False)
|
| 2876 |
with gr.Row():
|
|
|
|
| 2916 |
💤 精靈們體力都有限,每一次學習只能回答十個問題,請讓我休息一下再問問題喔!
|
| 2917 |
""",
|
| 2918 |
]]
|
| 2919 |
+
with gr.Row():
|
| 2920 |
+
ai_chatbot = gr.Chatbot(label="ai_chatbot", show_share_button=False, likeable=True, show_label=False, latex_delimiters=latex_delimiters, value=ai_chatbot_greeting)
|
| 2921 |
+
with gr.Row():
|
| 2922 |
+
ai_chatbot_ai_type = gr.Textbox(value="chat_completions", visible=False)
|
| 2923 |
+
ai_chatbot_thread_id = gr.Textbox(label="thread_id", visible=False)
|
| 2924 |
+
ai_chatbot_socratic_mode_btn = gr.Checkbox(label="蘇格拉底家教助理模式", value=True, visible=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2925 |
with gr.Row():
|
| 2926 |
with gr.Accordion("你也有類似的問題想問嗎? 請按下 ◀︎", open=False) as ask_questions_accordion_2:
|
| 2927 |
ai_chatbot_question_1 = gr.Button("問題一")
|
|
|
|
| 3172 |
|
| 3173 |
# OPENAI ASSISTANT CHATBOT 模式
|
| 3174 |
send_button.click(
|
| 3175 |
+
chat_with_any_ai,
|
| 3176 |
+
inputs=[chatbot_ai_type, password, video_id, user_data, trascript_state, key_moments, msg, chatbot, content_subject, content_grade, questions_answers_json, socratic_mode_btn, thread_id, ai_name],
|
| 3177 |
+
outputs=[msg, chatbot, send_button, send_feedback_btn, thread_id],
|
| 3178 |
scroll_to_output=True
|
| 3179 |
)
|
| 3180 |
send_feedback_btn.click(
|
| 3181 |
+
feedback_with_ai,
|
| 3182 |
+
inputs=[chatbot_ai_type, chatbot, thread_id],
|
| 3183 |
outputs=[chatbot, send_feedback_btn],
|
| 3184 |
scroll_to_output=True
|
| 3185 |
)
|
|
|
|
| 3198 |
)
|
| 3199 |
question_buttons = [btn_1, btn_2, btn_3]
|
| 3200 |
for question_btn in question_buttons:
|
| 3201 |
+
inputs_list = [chatbot_ai_type, password, video_id, user_data, trascript_state, key_moments, question_btn, chatbot, content_subject, content_grade, questions_answers_json, socratic_mode_btn, thread_id, ai_name]
|
| 3202 |
+
outputs_list = [msg, chatbot, send_button, send_feedback_btn, thread_id]
|
| 3203 |
+
setup_question_button_click(question_btn, inputs_list, outputs_list, chat_with_any_ai)
|
| 3204 |
|
| 3205 |
# 為生成問題按鈕設定特殊的點擊事件
|
| 3206 |
btn_create_question.click(
|
|
|
|
| 3211 |
|
| 3212 |
# 其他精靈 ai_chatbot 模式
|
| 3213 |
ai_send_button.click(
|
| 3214 |
+
chat_with_any_ai,
|
| 3215 |
+
inputs=[ai_chatbot_ai_type, password, video_id, user_data, trascript_state, key_moments, ai_msg, ai_chatbot, content_subject, content_grade, questions_answers_json, ai_chatbot_socratic_mode_btn, ai_chatbot_thread_id, ai_name],
|
| 3216 |
+
outputs=[ai_msg, ai_chatbot, ai_send_button, ai_send_feedback_btn, ai_chatbot_thread_id],
|
| 3217 |
scroll_to_output=True
|
| 3218 |
)
|
| 3219 |
ai_send_feedback_btn.click(
|
| 3220 |
feedback_with_ai,
|
| 3221 |
+
inputs=[ai_chatbot_ai_type, ai_chatbot, ai_chatbot_thread_id],
|
| 3222 |
outputs=[ai_chatbot, ai_send_feedback_btn],
|
| 3223 |
scroll_to_output=True
|
| 3224 |
)
|
| 3225 |
# 其他精靈 ai_chatbot 连接 QA 按钮点击事件
|
| 3226 |
ai_chatbot_question_buttons = [ai_chatbot_question_1, ai_chatbot_question_2, ai_chatbot_question_3]
|
| 3227 |
for question_btn in ai_chatbot_question_buttons:
|
| 3228 |
+
inputs_list = [ai_chatbot_ai_type, password, video_id, user_data, trascript_state, key_moments, question_btn, ai_chatbot, content_subject, content_grade, questions_answers_json, ai_chatbot_socratic_mode_btn, ai_chatbot_thread_id, ai_name]
|
| 3229 |
+
outputs_list = [ai_msg, ai_chatbot, ai_send_button, ai_send_feedback_btn, ai_chatbot_thread_id]
|
| 3230 |
+
setup_question_button_click(question_btn, inputs_list, outputs_list, chat_with_any_ai)
|
| 3231 |
|
| 3232 |
ai_chatbot_audio_input.change(
|
| 3233 |
process_open_ai_audio_to_chatbot,
|