Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| import time | |
| import openai | |
| from pathlib import Path | |
| import os | |
| OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") | |
| MAX_WITHOUT_KEY = 30 | |
| MAX_HISTORY_LENGTH = 10 | |
| PROMPTS = { | |
| "具體範例 Concrete examples": "你是一個樂於助人的AI tutor。你會透過提供具體範例以幫助他們學習新的概念。你總是調整你的範例以符合學生的生活及prior knowledge,你會舉出很多跟舉體且生活相關的範例以幫助學生,並透過一問一答的方式,確認學生的理解程度,請跟我解釋 {}?", | |
| "闡述 elaboration": "你是一個樂於助人的AI tutor。你會透過不斷提問的方式以幫助學生學習新的概念。你會問像是為什麼你認為這是對的?如果....會怎樣?這個為什麼有道理?A跟B之間有什麼關係呢?為什麼? 透過問問題的方式幫助學生在腦中思考並且組織答案,你總是調整你的問題以符合學生的程度及理解,你一次只問一個問題,請向我提問關於 {}?", | |
| "雙重編碼 Dual-Coding": "你是一個樂於助人的AI tutor。你會透過跟我協作製作心智圖的方式以幫我學習新的概念。 你透過問問題的方式幫助學生在腦中思考並且組織答案,你總是調整你的問題以符合學生的程度及理解,並協助學生將討論的結果輸出成心智圖,你一次只問一個問題,請向我提問關於{}?", | |
| "提取練習 Retrieval Practice": "你是一個樂於助人的AI tutor。你會透過不斷提問的方式以確認我對這個主題的理解程度。 你會根據以下的文本資料生成題目,你總是調整你的問題以符合學生的程度及理解,你最多只會問3個問題,一次只問一個問題,並在問完問題後給予學生回饋,分析學生還沒理解的部分,告訴學生如何加強。並將問答的歷程會出成kahoot可用的xlsx檔格式,主題是: {}?", | |
| "筆記 Note-taking": "你是一個樂於助人的AI tutor,也是Cornell Note-taking method專家。首先,你會察看我關於{}的筆記,然後透過以下的方式加深我對筆記中涵蓋的核心概念的理解: 1.辨識並解釋我遺漏的任何核心概念 2.提供每個概念可用的具體範例。 3.比較和比對所有核心概念。 4.請幫助我連接<之前學過類似的概念>與筆記中所有的核心概念, 如果你明白,請讓我知道,並請我提交筆記內容", | |
| "交錯練習 Interleaving": "你是一個樂於助人的AI tutor,你會透過不斷提問的方式以確認我對這個主題的理解程度,請你透過 interleaving 策略,混合相關的觀念與知識,以幫助我以幫助我更理解及促進不同概念間的連結,你一次只問一個問題,你會先從prior knowledge開始你的問題,請向我提問關於 {} 的問題 " | |
| } | |
| def transcribe(audio, chatbot_history, openai_key): | |
| time.sleep(5) | |
| transcript = openai.Audio.transcribe("whisper-1", open(audio, "rb"), api_key=openai_key) | |
| content = transcript["text"] | |
| if content: | |
| if not chatbot_history: | |
| return [[content, None]] | |
| else: | |
| return chatbot_history + [[content, None]] | |
| else: | |
| return chatbot_history | |
| def handle_scenario(topic, scenario, chatbot_history=[]): | |
| scenario_name = """【{}】""".format(scenario) | |
| prompt = scenario_name + PROMPTS[scenario].format(topic) | |
| new_message = [prompt, None] | |
| output = chatbot_history + [new_message] | |
| # print(output) # Debugging: Print the output format. | |
| return output | |
| def openai_stream(history, openai_key, chat_model): | |
| use_key = bool(openai_key.strip()) | |
| if not history or history[-1][1]: | |
| return history | |
| if not use_key and len(history) >= MAX_WITHOUT_KEY: | |
| history[-1][1] = "Sorry, you've reached the maximum number of messages without an OpenAI key." | |
| return history | |
| history[-1][1] = "" | |
| system_instruction = {"role": "system", "content": "You are a helpful AI tutor. Always communicate in Traditional Chinese. zh-TW,並且在反問時,不直接提供答案"} | |
| # Transforming history into the format required by OpenAI API | |
| messages = [system_instruction] + [{"role": "user", "content": msg[0]} if not msg[1] else {"role": "assistant", "content": msg[1]} for msg in history[:-1]] | |
| messages.append({"role": "user", "content": history[-1][0]}) | |
| for chunk in openai.ChatCompletion.create( | |
| model=chat_model, | |
| messages=messages, | |
| stream=True, | |
| api_key=openai_key if use_key else None, | |
| ): | |
| content = chunk["choices"][0].get("delta", {}).get("content") | |
| if content: | |
| history[-1][1] += content | |
| history = history[-MAX_HISTORY_LENGTH:] | |
| yield history | |
| def show_message(user_message, chatbot_history): | |
| if not chatbot_history: | |
| chatbot_history = [] # initialize if None | |
| result = chatbot_history + [[user_message, None]] | |
| return "", result | |
| theme = gr.themes.Soft( | |
| primary_hue="blue", | |
| neutral_hue="slate", | |
| ) | |
| parent_path = Path(__file__).parent | |
| with open(parent_path / "header.MD") as fp: | |
| header = fp.read() | |
| available_models = ['gpt-4','gpt-3.5-turbo'] | |
| with gr.Blocks(theme=theme) as demo: | |
| header_component = gr.Markdown(header) | |
| with gr.Row(): | |
| chat_model = gr.Dropdown(choices=available_models, value="gpt-3.5-turbo", allow_custom_value=True) | |
| openai_key = gr.Textbox(label="Enter OPENAI API Key", placeholder="Example: sk-AJDKakdAJD...") | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| topic_input = gr.Textbox(label="主題", placeholder="輸入主題...") | |
| with gr.Column(scale=1): | |
| # audio = gr.Audio(label="Talk with ChatGPT", source="microphone", type="filepath", streaming=True) | |
| clear = gr.Button("Clear Chat History") | |
| dark_mode_btn = gr.Button("Dark Mode", variant="primary") | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| chatbot = gr.Chatbot(label="ChatGPT Dialog") | |
| msg = gr.Textbox(label="Chat with ChatGPT", placeholder="Press <Enter> to submit") | |
| with gr.Column(scale=1): | |
| gr.Markdown("## 學習策略 Learning Strategies") | |
| # Define streaming_event_kwargs after the required input components have been defined | |
| streaming_event_kwargs = dict( | |
| fn=openai_stream, | |
| inputs=[chatbot, openai_key, chat_model], | |
| outputs=chatbot, | |
| ) | |
| btn_style = { | |
| "background-color": "#FFDAB9", # Light orange background (Peach Puff) | |
| "color": "black", # Black text | |
| "padding": "10px 15px", # Padding | |
| "border": "none", # No border | |
| "cursor": "pointer", # Cursor changes on hover | |
| "border-radius": "4px", # Rounded corners | |
| "margin": "5px", # Margin between buttons | |
| } | |
| for scenario in PROMPTS.keys(): | |
| btn = gr.Button(scenario, style=btn_style) | |
| btn.click(lambda topic, chatbot_history, current_scenario=scenario: handle_scenario(topic, current_scenario, chatbot_history), [topic_input, chatbot], [chatbot], queue=False).then(**streaming_event_kwargs) | |
| msg.submit(show_message, [msg, chatbot], [msg, chatbot], queue=False).then( | |
| **streaming_event_kwargs | |
| ) | |
| # audio.stream(transcribe, inputs=[audio, chatbot, openai_key], outputs=[chatbot]).then( | |
| # **streaming_event_kwargs | |
| # ) | |
| clear.click(lambda: None, None, chatbot, queue=False) | |
| # from gradio.themes.builder | |
| toggle_dark_mode_args = dict( | |
| fn=None, | |
| inputs=None, | |
| outputs=None, | |
| _js="""() => { | |
| if (document.querySelectorAll('.dark').length) { | |
| document.querySelectorAll('.dark').forEach(el => el.classList.remove('dark')); | |
| } else { | |
| document.querySelector('body').classList.add('dark'); | |
| } | |
| }""", | |
| ) | |
| demo.load(**toggle_dark_mode_args) | |
| dark_mode_btn.click(**toggle_dark_mode_args) | |
| demo.queue() | |
| demo.launch() | |