Spaces:
Running
Running
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,
|