tracetts/noteify
0
1import edge_tts2import gradio as gr3import google.generativeai as genai4import re5 6VOICE = "en-GB-SoniaNeural"7OUTPUT_FILE = "test.mp3"8MAX_QUESTIONS = 59 10try:11 genai.configure(api_key="AIzaSyCMWN0X8FZODaGPCR1_dLuo2iBGtRmrUvY")12 model = genai.GenerativeModel("gemini-2.0-flash")13 chat = model.start_chat()14 feynman_model = genai.GenerativeModel("gemini-2.0-flash")15except Exception as e:16 print(f"Error configuring Generative AI: {e}")17 model = None18 chat = None19 feynman_model = None20 21def generate_audio(text):22 if not text:23 return None24 communicate = edge_tts.Communicate(text, VOICE)25 try:26 communicate.save_sync(OUTPUT_FILE)27 return OUTPUT_FILE28 except Exception as e:29 print(f"Error generating audio: {e}")30 return None31 32def clear_text():33 return ""34 35def start_feynman(original_text):36 default_error_state = {37 feynman_question_box: gr.Textbox(value="Error occurred. Please check text and AI config.", interactive=False),38 feynman_answer_box: gr.Textbox(visible=False),39 feynman_submit_button: gr.Button(visible=False),40 feynman_feedback_box: gr.Textbox(value="", visible=False),41 feynman_state: {"questions": [], "current_index": 0, "original_text": ""},42 tabs_component: gr.Tabs(selected=1)43 }44 45 if not feynman_model or not original_text:46 error_state = default_error_state.copy()47 error_state[feynman_question_box] = gr.Textbox(value="Please enter text above and ensure the AI model is configured.", interactive=False)48 return error_state49 50 prompt = f"""Analyze the following text and generate up to {MAX_QUESTIONS} questions based on its key concepts, suitable for the Feynman learning technique. Each question should test understanding of a specific part of the text. Present each question clearly on a new line, starting with 'Q: '.51 52Text:53---54{original_text}55---56 57Questions:"""58 try:59 response = feynman_model.generate_content(prompt)60 response.resolve()61 questions = re.findall(r"^Q:\s*(.*)", response.text, re.MULTILINE)62 63 if not questions:64 no_question_state = default_error_state.copy()65 no_question_state[feynman_question_box] = gr.Textbox(value="Could not generate questions from the text.", interactive=False)66 return no_question_state67 68 initial_state = {"questions": questions[:MAX_QUESTIONS], "current_index": 0, "original_text": original_text}69 return {70 feynman_question_box: gr.Textbox(value=questions[0], interactive=False, visible=True),71 feynman_answer_box: gr.Textbox(value="", label="Your Answer", interactive=True, visible=True),72 feynman_submit_button: gr.Button(visible=True),73 feynman_feedback_box: gr.Textbox(value="", visible=True, interactive=False),74 feynman_state: initial_state,75 tabs_component: gr.Tabs(selected=1)76 }77 except Exception as e:78 print(f"Error generating Feynman questions: {e}")79 exception_state = default_error_state.copy()80 exception_state[feynman_question_box] = gr.Textbox(value=f"Error generating questions: {e}", interactive=False)81 return exception_state82 83 84def process_answer(user_answer, current_state):85 if not feynman_model or not current_state or not current_state.get("questions"):86 return {87 feynman_question_box: gr.Textbox(value="Error: Q&A session not properly initialized.", interactive=False),88 feynman_answer_box: gr.Textbox(visible=False),89 feynman_submit_button: gr.Button(visible=False),90 feynman_feedback_box: gr.Textbox(value="", visible=False),91 feynman_state: current_state92 }93 94 questions = current_state["questions"]95 index = current_state["current_index"]96 original_text = current_state["original_text"]97 current_question = questions[index]98 99 prompt = f"""Based *only* on the provided text below, evaluate the user's answer to the question.100 101Original Text:102---103{original_text}104---105 106Question: {current_question}107User's Answer: {user_answer}108 109Evaluation: Is the user's answer correct according to the text? Explain briefly why or why not. If incorrect, provide the correct answer based *strictly* on the text. Start your response with "Correct." or "Incorrect.".110"""111 try:112 response = feynman_model.generate_content(prompt)113 response.resolve()114 feedback = response.text115 116 next_index = index + 1117 current_state["current_index"] = next_index118 119 if next_index < len(questions):120 return {121 feynman_question_box: gr.Textbox(value=questions[next_index], interactive=False),122 feynman_answer_box: gr.Textbox(value="", interactive=True),123 feynman_submit_button: gr.Button(visible=True),124 feynman_feedback_box: gr.Textbox(value=feedback, interactive=False),125 feynman_state: current_state126 }127 else:128 return {129 feynman_question_box: gr.Textbox(value="Q&A session complete!", interactive=False),130 feynman_answer_box: gr.Textbox(visible=False),131 feynman_submit_button: gr.Button(visible=False),132 feynman_feedback_box: gr.Textbox(value=feedback + "\n\nEnd of questions.", interactive=False),133 feynman_state: current_state134 }135 except Exception as e:136 print(f"Error evaluating answer: {e}")137 return {138 feynman_question_box: gr.Textbox(value=current_question, interactive=False),139 feynman_answer_box: gr.Textbox(value=user_answer, interactive=True),140 feynman_submit_button: gr.Button(visible=True),141 feynman_feedback_box: gr.Textbox(value=f"Error evaluating answer: {e}", interactive=False),142 feynman_state: current_state143 }144 145 146def gemini_response(message, history):147 if not chat:148 return "Chatbot is not configured."149 try:150 response = chat.send_message(message)151 response.resolve()152 return response.text153 except Exception as e:154 print(f"Error in chatbot response: {e}")155 return f"Sorry, I encountered an error: {e}"156 157with gr.Blocks(theme=gr.themes.Soft(primary_hue=gr.themes.colors.red)) as demo:158 with gr.Row():159 gr.Markdown("<h1>Noteify - Study More Efficiently</h1>")160 gr.Markdown("<center>Use TTS for focused listening, or try the Q&A feature to test your understanding.</center>")161 162 feynman_state = gr.State({"questions": [], "current_index": 0, "original_text": ""})163 164 with gr.Tabs() as tabs_component:165 with gr.TabItem("Text-to-Speech", id=0):166 with gr.Row():167 text_input = gr.Textbox(168 value="In a sunny meadow nestled between whispering pines lived Luna, a fluffy white bunny with ears that twitched at every sound. One day, she spotted a rainbow arching over Sparklewood Forest. “I must find its end!” she declared. Hopping past babbling brooks and chirping crickets, Luna met a wise old owl. “Rainbows hide secrets,” he hooted. “Look closer!” Following his advice, Luna noticed tiny dewdrops glittering on clover leaves—each held a rainbow shard! She giggled, realizing the rainbow wasn’t far away… it was everywhere. From then on, Luna cherished little wonders, knowing magic sparkled in the smallest things",169 label="Enter Text for TTS or Q&A",170 lines=8171 )172 audio_output = gr.Audio(label="Generated Audio", type="filepath")173 174 with gr.Row():175 generate_button = gr.Button("Generate Audio", variant="primary")176 clear_button = gr.Button("Clear Text", variant="secondary")177 start_feynman_button = gr.Button("Start Q&A", variant="primary")178 179 generate_button.click(generate_audio, inputs=text_input, outputs=audio_output)180 clear_button.click(lambda: "", outputs=text_input)181 182 with gr.TabItem("Q&A", id=1):183 gr.Markdown("Click 'Start Q&A' on the Text-to-Speech tab with your text entered.")184 with gr.Column():185 feynman_question_box = gr.Textbox(label="AI Question", interactive=False, visible=True, value="Waiting to start...")186 feynman_answer_box = gr.Textbox(label="Your Answer", interactive=True, visible=False)187 feynman_submit_button = gr.Button("Submit Answer", visible=False, variant="primary")188 feynman_feedback_box = gr.Textbox(label="Feedback", interactive=False, visible=True, value="")189 190 with gr.TabItem("AI Chatbot", id=2):191 gr.ChatInterface(gemini_response, type="messages", chatbot=gr.Chatbot(height=400), title="AI Chatbot - Ask general questions")192 193 start_feynman_outputs = [194 feynman_question_box,195 feynman_answer_box,196 feynman_submit_button,197 feynman_feedback_box,198 feynman_state,199 tabs_component200 ]201 process_answer_outputs = [202 feynman_question_box,203 feynman_answer_box,204 feynman_submit_button,205 feynman_feedback_box,206 feynman_state207 ]208 209 start_feynman_button.click(210 fn=start_feynman,211 inputs=[text_input],212 outputs=start_feynman_outputs213 )214 215 feynman_submit_button.click(216 fn=process_answer,217 inputs=[feynman_answer_box, feynman_state],218 outputs=process_answer_outputs219 )220 221if __name__ == "__main__":222 demo.launch()223 