youngtsai commited on
Commit
c683e79
1 Parent(s): 3bdba8e
Files changed (3) hide show
  1. app.py +236 -75
  2. chatbot.py +2 -2
  3. requirements.txt +2 -2
app.py CHANGED
@@ -489,6 +489,7 @@ def process_transcript_and_screenshots_on_gcs(video_id):
489
  transcript_file_name = f'{video_id}_transcript.json'
490
  transcript_blob_name = f"{video_id}/{transcript_file_name}"
491
  # 检查逐字稿是否存在
 
492
  is_transcript_exists = GCS_SERVICE.check_file_exists(bucket_name, transcript_blob_name)
493
  if not is_transcript_exists:
494
  # 从YouTube获取逐字稿并上传
@@ -507,6 +508,7 @@ def process_transcript_and_screenshots_on_gcs(video_id):
507
 
508
  transcript_text = json.dumps(transcript, ensure_ascii=False, indent=2)
509
  upload_file_to_gcs_with_json_string(gcs_client, bucket_name, transcript_blob_name, transcript_text)
 
510
  else:
511
  # 逐字稿已存在,下载逐字稿内容
512
  print("逐字稿已存在于GCS中")
@@ -542,15 +544,20 @@ def process_transcript_and_screenshots_on_gcs(video_id):
542
  img_file_id = upload_img_and_get_public_url(gcs_client, bucket_name, screenshot_blob_name, screenshot_path)
543
  entry['img_file_id'] = img_file_id
544
  print(f"截图已上传到GCS: {img_file_id}")
545
-
546
- # 更新逐字稿文件
547
- print("===更新逐字稿文件===")
548
- print(transcript)
549
- print("===更新逐字稿文件===")
550
- updated_transcript_text = json.dumps(transcript, ensure_ascii=False, indent=2)
551
- upload_file_to_gcs_with_json_string(gcs_client, bucket_name, transcript_blob_name, updated_transcript_text)
552
- print("逐字稿已更新,包括截图链接")
553
- updated_transcript_json = json.loads(updated_transcript_text)
 
 
 
 
 
554
 
555
  return updated_transcript_json
556
 
@@ -691,11 +698,11 @@ def screenshot_youtube_video(youtube_id, snapshot_sec):
691
 
692
 
693
  # ---- Web ----
694
- def process_web_link(link):
695
- # 抓取和解析网页内容
696
- response = requests.get(link)
697
- soup = BeautifulSoup(response.content, 'html.parser')
698
- return soup.get_text()
699
 
700
 
701
  # ---- LLM Generator ----
@@ -1766,6 +1773,104 @@ def poll_run_status(run_id, thread_id, timeout=600, poll_interval=5):
1766
 
1767
  return run.status
1768
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1769
  # --- Slide mode ---
1770
  def update_slide(direction):
1771
  global TRANSCRIPTS
@@ -1794,6 +1899,8 @@ def prev_slide():
1794
  def next_slide():
1795
  return update_slide(1)
1796
 
 
 
1797
  def init_params(text, request: gr.Request):
1798
  if request:
1799
  print("Request headers dictionary:", request.headers)
@@ -1826,6 +1933,21 @@ def init_params(text, request: gr.Request):
1826
 
1827
  return admin, reading_passage_admin, summary_admin, see_detail, password_text, youtube_link
1828
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1829
  HEAD = """
1830
  <meta charset="UTF-8">
1831
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -1893,15 +2015,20 @@ HEAD = """
1893
  with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, secondary_hue=gr.themes.colors.amber, text_size = gr.themes.sizes.text_lg), head=HEAD) as demo:
1894
  with gr.Row() as admin:
1895
  password = gr.Textbox(label="Password", type="password", elem_id="password_input", visible=True)
1896
- file_upload = gr.File(label="Upload your CSV or Word file", visible=False)
1897
  youtube_link = gr.Textbox(label="Enter YouTube Link", elem_id="youtube_link_input", visible=True)
1898
  video_id = gr.Textbox(label="video_id", visible=False)
1899
- web_link = gr.Textbox(label="Enter Web Page Link", visible=False)
 
1900
  user_data = gr.Textbox(label="User Data", elem_id="user_data_input", visible=True)
1901
  youtube_link_btn = gr.Button("Submit_YouTube_Link", elem_id="youtube_link_btn", visible=True)
 
 
 
 
 
1902
  with gr.Tab("AI小精靈"):
1903
  with gr.Row():
1904
- with gr.Tab("飛特"):
1905
  bot_avatar = "https://junyi-avatar.s3.ap-northeast-1.amazonaws.com/live/%20%20foxcat-star-18.png?v=20231113095823614"
1906
  user_avatar = "https://junyitopicimg.s3.amazonaws.com/s4byy--icon.jpe?v=20200513013523726"
1907
  latex_delimiters = [{"left": "$", "right": "$", "display": False}]
@@ -1917,28 +2044,33 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, seconda
1917
  btn_create_question = gr.Button("生成其他問題", variant="primary")
1918
  openai_chatbot_audio_input = gr.Audio(sources=["microphone"], type="filepath")
1919
  with gr.Row():
1920
- msg = gr.Textbox(label="訊息",scale=3)
1921
- send_button = gr.Button("送出", variant="primary", scale=1)
1922
- # with gr.Tab("GROQ"):
1923
- # groq_ai_name = gr.Textbox(label="AI 助理名稱", value="groq", visible=False)
1924
- # groq_chatbot = gr.Chatbot(avatar_images=[bot_avatar, user_avatar], label="groq mode chatbot", show_share_button=False, likeable=True)
1925
- # groq_msg = gr.Textbox(label="Message")
1926
- # groq_send_button = gr.Button("Send", variant="primary")
1927
- # with gr.Tab("JUTOR"):
1928
- # jutor_ai_name = gr.Textbox(label="AI 助理名稱", value="jutor", visible=False)
1929
- # jutor_chatbot = gr.Chatbot(avatar_images=[bot_avatar, user_avatar], label="jutor mode chatbot", show_share_button=False, likeable=True)
1930
- # jutor_msg = gr.Textbox(label="Message")
1931
- # jutor_send_button = gr.Button("Send", variant="primary")
1932
- # with gr.Tab("CLAUDE"):
1933
- # claude_ai_name = gr.Textbox(label="AI 助理名稱", value="claude3", visible=False)
1934
- # claude_chatbot = gr.Chatbot(avatar_images=[bot_avatar, user_avatar], label="claude mode chatbot", show_share_button=False, likeable=True)
1935
- # claude_msg = gr.Textbox(label="Message")
1936
- # claude_send_button = gr.Button("Send", variant="primary")
1937
  with gr.Tab("其他精靈"):
1938
  ai_name = gr.Dropdown(label="選擇 AI 助理", choices=["jutor", "claude3", "groq"], value="jutor")
1939
- ai_chatbot = gr.Chatbot(avatar_images=[bot_avatar, user_avatar], label="ai_chatbot", show_share_button=False, likeable=True, show_label=False)
1940
- ai_msg = gr.Textbox(label="Message")
1941
- ai_send_button = gr.Button("Send", variant="primary")
 
 
 
 
 
 
 
 
 
1942
  with gr.Tab("文章模式"):
1943
  with gr.Row() as reading_passage_admin:
1944
  reading_passage_kind = gr.Textbox(value="reading_passage", show_label=False)
@@ -1962,6 +2094,7 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, seconda
1962
  with gr.Tab("關鍵時刻"):
1963
  with gr.Row():
1964
  key_moments_html = gr.HTML(value="")
 
1965
  with gr.Tab("教學備課"):
1966
  with gr.Row():
1967
  content_subject = gr.Dropdown(label="選擇主題", choices=["數學", "自然", "國文", "英文", "社會","物理", "化學", "生物", "地理", "歷史", "公民"], value="", visible=False)
@@ -2070,7 +2203,7 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, seconda
2070
  mind_map_html = gr.HTML()
2071
 
2072
  # --- Event ---
2073
- # OPENAI 模式
2074
  send_button.click(
2075
  chat_with_opan_ai_assistant,
2076
  inputs=[password, video_id, thread_id, df_string_output, msg, chatbot, content_subject, content_grade, socratic_mode_btn],
@@ -2081,35 +2214,10 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, seconda
2081
  inputs=[password, openai_chatbot_audio_input],
2082
  outputs=[msg]
2083
  )
2084
- # # GROQ 模式
2085
- # groq_send_button.click(
2086
- # chat_with_ai,
2087
- # inputs=[groq_ai_name, password, video_id, df_string_output, groq_msg, groq_chatbot, content_subject, content_grade, socratic_mode_btn],
2088
- # outputs=[groq_msg, groq_chatbot]
2089
- # )
2090
- # # JUTOR API 模式
2091
- # jutor_send_button.click(
2092
- # chat_with_ai,
2093
- # inputs=[jutor_ai_name, password, video_id, df_string_output, jutor_msg, jutor_chatbot, content_subject, content_grade, socratic_mode_btn],
2094
- # outputs=[jutor_msg, jutor_chatbot]
2095
- # )
2096
- # # CLAUDE 模式
2097
- # claude_send_button.click(
2098
- # chat_with_ai,
2099
- # inputs=[claude_ai_name, password, video_id, df_string_output, claude_msg, claude_chatbot, content_subject, content_grade, socratic_mode_btn],
2100
- # outputs=[claude_msg, claude_chatbot]
2101
- # )
2102
- # ai_chatbot 模式
2103
- ai_send_button.click(
2104
- chat_with_ai,
2105
- inputs=[ai_name, password, video_id, df_string_output, ai_msg, ai_chatbot, content_subject, content_grade, socratic_mode_btn],
2106
- outputs=[ai_msg, ai_chatbot]
2107
- )
2108
-
2109
- # 连接按钮点击事件
2110
- btn_1_chat_with_opan_ai_assistant_input =[password, video_id, thread_id, df_string_output, btn_1, chatbot, content_subject, content_grade, socratic_mode_btn]
2111
- btn_2_chat_with_opan_ai_assistant_input =[password, video_id, thread_id, df_string_output, btn_2, chatbot, content_subject, content_grade, socratic_mode_btn]
2112
- btn_3_chat_with_opan_ai_assistant_input =[password, video_id, thread_id, df_string_output, btn_3, chatbot, content_subject, content_grade, socratic_mode_btn]
2113
  btn_1.click(
2114
  chat_with_opan_ai_assistant,
2115
  inputs=btn_1_chat_with_opan_ai_assistant_input,
@@ -2125,18 +2233,44 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, seconda
2125
  inputs=btn_3_chat_with_opan_ai_assistant_input,
2126
  outputs=[msg, chatbot, thread_id]
2127
  )
2128
-
2129
  btn_create_question.click(
2130
  change_questions,
2131
  inputs = [password, df_string_output],
2132
  outputs = [btn_1, btn_2, btn_3]
2133
  )
2134
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2135
  # file_upload.change(process_file, inputs=file_upload, outputs=df_string_output)
2136
- file_upload.change(process_file, inputs=file_upload, outputs=[btn_1, btn_2, btn_3, df_summarise, df_string_output])
2137
 
2138
  # 当输入 YouTube 链接时触发
2139
- process_youtube_link_output = [
 
2140
  video_id,
2141
  btn_1,
2142
  btn_2,
@@ -2154,17 +2288,44 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, seconda
2154
  content_subject,
2155
  content_grade,
2156
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2157
  youtube_link.change(
2158
  process_youtube_link,
2159
- inputs=[password,youtube_link],
2160
- outputs=process_youtube_link_output
 
 
 
 
2161
  )
2162
-
2163
  youtube_link_btn.click(
2164
  process_youtube_link,
2165
- inputs=[password, youtube_link],
2166
- outputs=process_youtube_link_output
 
 
 
 
2167
  )
 
2168
 
2169
  # 当输入网页链接时触发
2170
  # web_link.change(process_web_link, inputs=web_link, outputs=[btn_1, btn_2, btn_3, df_summarise, df_string_output])
 
489
  transcript_file_name = f'{video_id}_transcript.json'
490
  transcript_blob_name = f"{video_id}/{transcript_file_name}"
491
  # 检查逐字稿是否存在
492
+ is_new_transcript = False
493
  is_transcript_exists = GCS_SERVICE.check_file_exists(bucket_name, transcript_blob_name)
494
  if not is_transcript_exists:
495
  # 从YouTube获取逐字稿并上传
 
508
 
509
  transcript_text = json.dumps(transcript, ensure_ascii=False, indent=2)
510
  upload_file_to_gcs_with_json_string(gcs_client, bucket_name, transcript_blob_name, transcript_text)
511
+ is_new_transcript = True
512
  else:
513
  # 逐字稿已存在,下载逐字稿内容
514
  print("逐字稿已存在于GCS中")
 
544
  img_file_id = upload_img_and_get_public_url(gcs_client, bucket_name, screenshot_blob_name, screenshot_path)
545
  entry['img_file_id'] = img_file_id
546
  print(f"截图已上传到GCS: {img_file_id}")
547
+ is_new_transcript = True
548
+
549
+ # 確認是否更新逐字稿文件
550
+ if is_new_transcript:
551
+ # 更新逐字稿文件
552
+ print("===更新逐字稿文件===")
553
+ print(transcript)
554
+ print("===更新逐字稿文件===")
555
+ updated_transcript_text = json.dumps(transcript, ensure_ascii=False, indent=2)
556
+ upload_file_to_gcs_with_json_string(gcs_client, bucket_name, transcript_blob_name, updated_transcript_text)
557
+ print("逐字稿已更新,包括截图链接")
558
+ updated_transcript_json = json.loads(updated_transcript_text)
559
+ else:
560
+ updated_transcript_json = transcript
561
 
562
  return updated_transcript_json
563
 
 
698
 
699
 
700
  # ---- Web ----
701
+ # def process_web_link(link):
702
+ # # 抓取和解析网页内容
703
+ # response = requests.get(link)
704
+ # soup = BeautifulSoup(response.content, 'html.parser')
705
+ # return soup.get_text()
706
 
707
 
708
  # ---- LLM Generator ----
 
1773
 
1774
  return run.status
1775
 
1776
+ def streaming_chat_with_open_ai(user_message, chat_history, password, thread_id, trascript, content_subject, content_grade):
1777
+ verify_password(password)
1778
+
1779
+ print("===streaming_chat_with_open_ai===")
1780
+ print(thread_id)
1781
+
1782
+ # 先計算 user_message 是否超過 500 個字
1783
+ if len(user_message) > 1500:
1784
+ error_msg = "你的訊息太長了,請縮短訊息長度至五百字以內"
1785
+ raise gr.Error(error_msg)
1786
+
1787
+ # 如果 chat_history 超過 10 則訊息,直接 return "對話超過上限"
1788
+ if chat_history is not None and len(chat_history) > 10:
1789
+ error_msg = "此次對話超過上限"
1790
+ raise gr.Error(error_msg)
1791
+
1792
+ # fake data
1793
+ socratic_mode = True
1794
+
1795
+ try:
1796
+ assistant_id = "asst_kmvZLNkDUYaNkMNtZEAYxyPq"
1797
+ client = OPEN_AI_CLIENT
1798
+ # 直接安排逐字稿資料 in instructions
1799
+ trascript_json = json.loads(trascript)
1800
+ # 移除 embed_url, screenshot_path
1801
+ for entry in trascript_json:
1802
+ entry.pop('embed_url', None)
1803
+ entry.pop('screenshot_path', None)
1804
+ trascript_text = json.dumps(trascript_json, ensure_ascii=False, indent=2)
1805
+ # trascript_text 移除 \n, 空白
1806
+ trascript_text = trascript_text.replace("\n", "").replace(" ", "")
1807
+
1808
+ instructions = f"""
1809
+ 科目:{content_subject}
1810
+ 年級:{content_grade}
1811
+ 逐字稿資料:{trascript_text}
1812
+ -------------------------------------
1813
+ 你是一個專業的{content_subject}老師, user 為{content_grade}的學生
1814
+ socratic_mode = {socratic_mode}
1815
+ if socratic_mode is True,
1816
+ - 請用蘇格拉底式的提問方式,引導學生思考,並且給予學生一些提示
1817
+ - 一次只問一個問題,字數在100字以內
1818
+ - 不要直接給予答案,讓學生自己思考
1819
+ - 但可以給予一些提示跟引導,例如給予影片的時間軸,讓學生自己去找答案
1820
+
1821
+ if socratic_mode is False,
1822
+ - 直接回答學生問題,字數在100字以內
1823
+
1824
+ rule:
1825
+ - 請一定要用繁體中文回答 zh-TW,並用台灣人的口語表達,回答時不用特別說明這是台灣人的語氣,也不用說這是「台語的說法」
1826
+ - 不用提到「逐字稿」這個詞,用「內容」代替
1827
+ - 如果學生問了一些問題你無法判斷,請告訴學生你無法判斷,並建議學生可以問其他問題
1828
+ - 或者你可以反問學生一些問題,幫助學生更好的理解資料,字數在100字以內
1829
+ - 如果學生的問題與資料文本無關,請告訴學生你「無法回答超出影片範圍的問題」,並告訴他可以怎麼問什麼樣的問題(一個就好)
1830
+ - 只要是參考逐字稿資料,請在回答的最後標註【參考資料:(分):(秒)】
1831
+ - 回答範圍一定要在逐字稿資料內,不要引用其他資料,請嚴格執行
1832
+ - 並在重複問句後給予學生鼓勵,讓學生有學習的動力
1833
+ - 請用 {content_grade} 的學生能懂的方式回答
1834
+ """
1835
+
1836
+ # 创建线程
1837
+ if not thread_id:
1838
+ thread = client.beta.threads.create()
1839
+ thread_id = thread.id
1840
+ print(f"new thread_id: {thread_id}")
1841
+ else:
1842
+ thread = client.beta.threads.retrieve(thread_id)
1843
+ print(f"old thread_id: {thread_id}")
1844
+
1845
+ # 向线程添加用户的消息
1846
+ client.beta.threads.messages.create(
1847
+ thread_id=thread.id,
1848
+ role="user",
1849
+ content=user_message + "/n (請一定要用繁體中文回答 zh-TW,並用台灣人的禮貌口語表達,回答時不要特別說明這是台灣人的語氣,不用提到「逐字稿」這個詞,用「內容」代替)),請在回答的最後標註【參考資料:(時):(分):(秒)】,(如果是反問學生,就只問一個問題,請幫助學生更好的理解資料,字數在100字以內)"
1850
+ )
1851
+
1852
+ with client.beta.threads.runs.stream(
1853
+ thread_id=thread.id,
1854
+ assistant_id=assistant_id,
1855
+ instructions=instructions,
1856
+ ) as stream:
1857
+ partial_messages = ""
1858
+ for event in stream:
1859
+ if event.data and event.data.object == "thread.message.delta":
1860
+ message = event.data.delta.content[0].text.value
1861
+ partial_messages += message
1862
+ yield partial_messages
1863
+
1864
+ except Exception as e:
1865
+ print(f"Error: {e}")
1866
+ raise gr.Error(f"Error: {e}")
1867
+
1868
+ def create_thread_id():
1869
+ thread = OPEN_AI_CLIENT.beta.threads.create()
1870
+ thread_id = thread.id
1871
+ print(f"create new thread_id: {thread_id}")
1872
+ return thread_id
1873
+
1874
  # --- Slide mode ---
1875
  def update_slide(direction):
1876
  global TRANSCRIPTS
 
1899
  def next_slide():
1900
  return update_slide(1)
1901
 
1902
+
1903
+ # --- Init params ---
1904
  def init_params(text, request: gr.Request):
1905
  if request:
1906
  print("Request headers dictionary:", request.headers)
 
1933
 
1934
  return admin, reading_passage_admin, summary_admin, see_detail, password_text, youtube_link
1935
 
1936
+ def update_state(content_subject, content_grade, trascript, question_1, question_2, question_3):
1937
+ # inputs=[content_subject, content_grade, df_string_output],
1938
+ # outputs=[content_subject_state, content_grade_state, trascript_state]
1939
+ content_subject_state = content_subject
1940
+ content_grade_state = content_grade
1941
+ trascript_state = trascript
1942
+ streaming_chat_thread_id_state = create_thread_id()
1943
+ ai_chatbot_question_1 = question_1
1944
+ ai_chatbot_question_2 = question_2
1945
+ ai_chatbot_question_3 = question_3
1946
+
1947
+ return content_subject_state, content_grade_state, trascript_state, streaming_chat_thread_id_state, \
1948
+ ai_chatbot_question_1, ai_chatbot_question_2, ai_chatbot_question_3
1949
+
1950
+
1951
  HEAD = """
1952
  <meta charset="UTF-8">
1953
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
 
2015
  with gr.Blocks(theme=gr.themes.Base(primary_hue=gr.themes.colors.orange, secondary_hue=gr.themes.colors.amber, text_size = gr.themes.sizes.text_lg), head=HEAD) as demo:
2016
  with gr.Row() as admin:
2017
  password = gr.Textbox(label="Password", type="password", elem_id="password_input", visible=True)
 
2018
  youtube_link = gr.Textbox(label="Enter YouTube Link", elem_id="youtube_link_input", visible=True)
2019
  video_id = gr.Textbox(label="video_id", visible=False)
2020
+ # file_upload = gr.File(label="Upload your CSV or Word file", visible=False)
2021
+ # web_link = gr.Textbox(label="Enter Web Page Link", visible=False)
2022
  user_data = gr.Textbox(label="User Data", elem_id="user_data_input", visible=True)
2023
  youtube_link_btn = gr.Button("Submit_YouTube_Link", elem_id="youtube_link_btn", visible=True)
2024
+ with gr.Row() as data_state:
2025
+ content_subject_state = gr.State() # 使用 gr.State 存储 content_subject
2026
+ content_grade_state = gr.State() # 使用 gr.State 存储 content_grade
2027
+ trascript_state = gr.State() # 使用 gr.State 存储 trascript
2028
+ streaming_chat_thread_id_state = gr.State() # 使用 gr.State 存储 streaming_chat_thread_id
2029
  with gr.Tab("AI小精靈"):
2030
  with gr.Row():
2031
+ with gr.Tab("飛特精靈"):
2032
  bot_avatar = "https://junyi-avatar.s3.ap-northeast-1.amazonaws.com/live/%20%20foxcat-star-18.png?v=20231113095823614"
2033
  user_avatar = "https://junyitopicimg.s3.amazonaws.com/s4byy--icon.jpe?v=20200513013523726"
2034
  latex_delimiters = [{"left": "$", "right": "$", "display": False}]
 
2044
  btn_create_question = gr.Button("生成其他問題", variant="primary")
2045
  openai_chatbot_audio_input = gr.Audio(sources=["microphone"], type="filepath")
2046
  with gr.Row():
2047
+ msg = gr.Textbox(label="訊息",scale=3)
2048
+ send_button = gr.Button("送出", variant="primary", scale=1)
2049
+ with gr.Tab("飛特音速"):
2050
+ additional_inputs = [password, streaming_chat_thread_id_state, trascript_state, content_subject_state, content_grade_state]
2051
+ streaming_chat = gr.ChatInterface(
2052
+ fn=streaming_chat_with_open_ai,
2053
+ additional_inputs=additional_inputs,
2054
+ submit_btn="送出",
2055
+ retry_btn=None,
2056
+ undo_btn=" 上一步",
2057
+ clear_btn="🗑️ 清除全部",
2058
+ stop_btn="🛑 停止",
2059
+ )
 
 
 
 
2060
  with gr.Tab("其他精靈"):
2061
  ai_name = gr.Dropdown(label="選擇 AI 助理", choices=["jutor", "claude3", "groq"], value="jutor")
2062
+ ai_chatbot = gr.Chatbot(avatar_images=[bot_avatar, user_avatar], label="ai_chatbot", show_share_button=False, likeable=True, show_label=False, latex_delimiters=latex_delimiters)
2063
+ ai_chatbot_socratic_mode_btn = gr.Checkbox(label="蘇格拉底家教助理模式", value=True, visible=False)
2064
+ with gr.Row():
2065
+ with gr.Accordion("你也有類似的問題想問嗎?", open=False) as ask_questions_accordion_2:
2066
+ ai_chatbot_question_1 = gr.Button("問題一")
2067
+ ai_chatbot_question_2 = gr.Button("問題一")
2068
+ ai_chatbot_question_3 = gr.Button("問題一")
2069
+ ai_chatbot_audio_input = gr.Audio(sources=["microphone"], type="filepath")
2070
+ with gr.Row():
2071
+ ai_msg = gr.Textbox(label="Message",scale=3)
2072
+ ai_send_button = gr.Button("Send", variant="primary",scale=1)
2073
+
2074
  with gr.Tab("文章模式"):
2075
  with gr.Row() as reading_passage_admin:
2076
  reading_passage_kind = gr.Textbox(value="reading_passage", show_label=False)
 
2094
  with gr.Tab("關鍵時刻"):
2095
  with gr.Row():
2096
  key_moments_html = gr.HTML(value="")
2097
+
2098
  with gr.Tab("教學備課"):
2099
  with gr.Row():
2100
  content_subject = gr.Dropdown(label="選擇主題", choices=["數學", "自然", "國文", "英文", "社會","物理", "化學", "生物", "地理", "歷史", "公民"], value="", visible=False)
 
2203
  mind_map_html = gr.HTML()
2204
 
2205
  # --- Event ---
2206
+ # OPENAI ASSISTANT CHATBOT 模式
2207
  send_button.click(
2208
  chat_with_opan_ai_assistant,
2209
  inputs=[password, video_id, thread_id, df_string_output, msg, chatbot, content_subject, content_grade, socratic_mode_btn],
 
2214
  inputs=[password, openai_chatbot_audio_input],
2215
  outputs=[msg]
2216
  )
2217
+ # OPENAI ASSISTANT CHATBOT 連接按鈕點擊事件
2218
+ btn_1_chat_with_opan_ai_assistant_input =[password, video_id, thread_id, df_string_output, btn_1, chatbot, content_subject, content_grade, ai_chatbot_socratic_mode_btn]
2219
+ btn_2_chat_with_opan_ai_assistant_input =[password, video_id, thread_id, df_string_output, btn_2, chatbot, content_subject, content_grade, ai_chatbot_socratic_mode_btn]
2220
+ btn_3_chat_with_opan_ai_assistant_input =[password, video_id, thread_id, df_string_output, btn_3, chatbot, content_subject, content_grade, ai_chatbot_socratic_mode_btn]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2221
  btn_1.click(
2222
  chat_with_opan_ai_assistant,
2223
  inputs=btn_1_chat_with_opan_ai_assistant_input,
 
2233
  inputs=btn_3_chat_with_opan_ai_assistant_input,
2234
  outputs=[msg, chatbot, thread_id]
2235
  )
 
2236
  btn_create_question.click(
2237
  change_questions,
2238
  inputs = [password, df_string_output],
2239
  outputs = [btn_1, btn_2, btn_3]
2240
  )
2241
 
2242
+ # ai_chatbot 模式
2243
+ ai_send_button.click(
2244
+ chat_with_ai,
2245
+ inputs=[ai_name, password, video_id, df_string_output, ai_msg, ai_chatbot, content_subject, content_grade, ai_chatbot_socratic_mode_btn],
2246
+ outputs=[ai_msg, ai_chatbot]
2247
+ )
2248
+ # ai_chatbot 连接按钮点击事件
2249
+ ai_chatbot_question_1_chat_with_ai_input =[ai_name, password, video_id, df_string_output, ai_chatbot_question_1, ai_chatbot, content_subject, content_grade, ai_chatbot_socratic_mode_btn]
2250
+ ai_chatbot_question_2_chat_with_ai_input =[ai_name, password, video_id, df_string_output, ai_chatbot_question_2, ai_chatbot, content_subject, content_grade, ai_chatbot_socratic_mode_btn]
2251
+ ai_chatbot_question_3_chat_with_ai_input =[ai_name, password, video_id, df_string_output, ai_chatbot_question_3, ai_chatbot, content_subject, content_grade, ai_chatbot_socratic_mode_btn]
2252
+ ai_chatbot_question_1.click(
2253
+ chat_with_ai,
2254
+ inputs=ai_chatbot_question_1_chat_with_ai_input,
2255
+ outputs=[ai_msg, ai_chatbot]
2256
+ )
2257
+ ai_chatbot_question_2.click(
2258
+ chat_with_ai,
2259
+ inputs=ai_chatbot_question_2_chat_with_ai_input,
2260
+ outputs=[ai_msg, ai_chatbot]
2261
+ )
2262
+ ai_chatbot_question_3.click(
2263
+ chat_with_ai,
2264
+ inputs=ai_chatbot_question_3_chat_with_ai_input,
2265
+ outputs=[ai_msg, ai_chatbot]
2266
+ )
2267
+
2268
  # file_upload.change(process_file, inputs=file_upload, outputs=df_string_output)
2269
+ # file_upload.change(process_file, inputs=file_upload, outputs=[btn_1, btn_2, btn_3, df_summarise, df_string_output])
2270
 
2271
  # 当输入 YouTube 链接时触发
2272
+ process_youtube_link_inputs = [password, youtube_link]
2273
+ process_youtube_link_outputs = [
2274
  video_id,
2275
  btn_1,
2276
  btn_2,
 
2288
  content_subject,
2289
  content_grade,
2290
  ]
2291
+ update_state_inputs = [
2292
+ content_subject,
2293
+ content_grade,
2294
+ df_string_output,
2295
+ btn_1,
2296
+ btn_2,
2297
+ btn_3
2298
+ ]
2299
+ update_state_outputs = [
2300
+ content_subject_state,
2301
+ content_grade_state,
2302
+ trascript_state,
2303
+ streaming_chat_thread_id_state,
2304
+ ai_chatbot_question_1,
2305
+ ai_chatbot_question_2,
2306
+ ai_chatbot_question_3
2307
+ ]
2308
+
2309
  youtube_link.change(
2310
  process_youtube_link,
2311
+ inputs=process_youtube_link_inputs,
2312
+ outputs=process_youtube_link_outputs
2313
+ ).then(
2314
+ update_state,
2315
+ inputs=update_state_inputs,
2316
+ outputs=update_state_outputs
2317
  )
2318
+
2319
  youtube_link_btn.click(
2320
  process_youtube_link,
2321
+ inputs=process_youtube_link_inputs,
2322
+ outputs=process_youtube_link_outputs
2323
+ ).then(
2324
+ update_state,
2325
+ inputs=update_state_inputs,
2326
+ outputs=update_state_outputs
2327
  )
2328
+
2329
 
2330
  # 当输入网页链接时触发
2331
  # web_link.change(process_web_link, inputs=web_link, outputs=[btn_1, btn_2, btn_3, df_summarise, df_string_output])
chatbot.py CHANGED
@@ -122,7 +122,7 @@ class Chatbot:
122
  request_payload = {
123
  "model": "mixtral-8x7b-32768",
124
  "messages": messages,
125
- "max_tokens": 1000 # 設定一個較大的值,可根據需要調整
126
  }
127
  groq_client = self.ai_client
128
  response = groq_client.chat.completions.create(**request_payload)
@@ -141,7 +141,7 @@ class Chatbot:
141
  "accept": "application/json",
142
  "body": json.dumps({
143
  "anthropic_version": "bedrock-2023-05-31",
144
- "max_tokens": 1000,
145
  "system": system_prompt,
146
  "messages": messages
147
  })
 
122
  request_payload = {
123
  "model": "mixtral-8x7b-32768",
124
  "messages": messages,
125
+ "max_tokens": 500 # 設定一個較大的值,可根據需要調整
126
  }
127
  groq_client = self.ai_client
128
  response = groq_client.chat.completions.create(**request_payload)
 
141
  "accept": "application/json",
142
  "body": json.dumps({
143
  "anthropic_version": "bedrock-2023-05-31",
144
+ "max_tokens": 500,
145
  "system": system_prompt,
146
  "messages": messages
147
  })
requirements.txt CHANGED
@@ -1,6 +1,6 @@
1
- gradio>=4.24.0
2
  pandas
3
- openai>=1.0.0
4
  requests
5
  beautifulsoup4
6
  python-docx
 
1
+ gradio==4.8.0
2
  pandas
3
+ openai>=1.16.2
4
  requests
5
  beautifulsoup4
6
  python-docx