Download spoken_module.py from ankban/CommTutor: direct link, hf CLI and curl.
- Browser
- Download file 8.89 kB
-
https://huggingface.co/spaces/ankban/CommTutor/resolve/main/spoken_module.py
- Command line
-
hf download hf://spaces/ankban/CommTutor/spoken_module.py
-
curl -L -o spoken_module.py https://huggingface.co/spaces/ankban/CommTutor/resolve/main/spoken_module.py
8.89 kB
| import gradio as gr | |
| import uuid | |
| import os | |
| import matplotlib.pyplot as plt | |
| from gtts import gTTS | |
| from openai import OpenAI | |
| from app_utils import ( | |
| LANG_CODES, save_to_db, fetch_user_sessions, | |
| convert_to_wav, transcribe_audio, | |
| parse_scores_from_feedback, generate_progress_summary, | |
| build_score_comparison_data, render_score_chart, | |
| build_trend_data, render_trend_chart | |
| ) | |
| client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) | |
| def generate_feedback(transcript, language, goal="general improvement", focus_areas=None, previous_transcript=None): | |
| focus_str = ", ".join(focus_areas) if focus_areas else "Clarity, Structure, Fluency, Content Relevance, and Tone" | |
| history_section = f"\n\nFor reference, their previous transcript was:\n{previous_transcript}" if previous_transcript else "" | |
| prompt = f""" | |
| You are a supportive communication coach helping a learner whose goal is: **{goal}**. | |
| First, return a JSON object of scores (0β10) for these areas: | |
| {focus_str} | |
| Then provide a clear and friendly evaluation: | |
| For each area: | |
| - Repeat the score (0β10) | |
| - Explain why the user got that score | |
| Then provide: | |
| - A detailed summary of strengths and improvement areas. | |
| - One motivational line to end with. Do not specifically add motivational keyword, just add the line. | |
| Transcript: | |
| {history_section} | |
| """.strip() | |
| response = client.chat.completions.create( | |
| model="gpt-4", | |
| messages=[ | |
| {"role": "system", "content": f"You are a warm and constructive communication coach responding in {language}."}, | |
| {"role": "user", "content": prompt} | |
| ], | |
| temperature=0.7 | |
| ) | |
| feedback = response.choices[0].message.content | |
| try: | |
| split_idx = feedback.index('}') + 1 | |
| feedback_clean = feedback[split_idx:].strip() | |
| except: | |
| feedback_clean = feedback | |
| return feedback, feedback_clean | |
| def generate_example_response(transcript, language): | |
| prompt = f"""Rewrite this speech to make it more polished, fluent, and confident. | |
| Keep the meaning and tone the same, but improve clarity and structure. | |
| Transcript: | |
| {transcript} | |
| """ | |
| response = client.chat.completions.create( | |
| model="gpt-4", | |
| messages=[ | |
| {"role": "system", "content": f"Reply in {language}. Provide only the improved version of the speech."}, | |
| {"role": "user", "content": prompt} | |
| ] | |
| ) | |
| return response.choices[0].message.content | |
| def render_empty_chart(title): | |
| fig, ax = plt.subplots() | |
| ax.set_title(title) | |
| ax.text(0.5, 0.5, "No scores yet.\nSpeak again to generate progress!", ha='center', va='center', fontsize=12) | |
| ax.axis('off') | |
| return fig | |
| def spoken_dashboard(nickname_input): | |
| with gr.Column() as spoken_panel: | |
| gr.Markdown(""" | |
| <div id="header" style="text-align: center;"> | |
| <h2>π¦ Meet <strong>Chatter the Owl</strong></h2> | |
| <p>Speak in your chosen language and get personalized feedback and progress tracking.</p> | |
| </div> | |
| """) | |
| with gr.Row(): | |
| language_dropdown = gr.Dropdown(label="π Language", choices=list(LANG_CODES.keys()), value="English") | |
| goal_dropdown = gr.Dropdown(label="π― Goal", choices=["Interview preparation", "Public speaking", "Class presentation", "General improvement"], value="General improvement") | |
| focus_checkboxes = gr.CheckboxGroup(label="π§ Focus Areas", choices=["Clarity", "Structure", "Fluency", "Tone", "Content Relevance"], value=["Clarity", "Structure", "Fluency", "Tone", "Content Relevance"]) | |
| with gr.Row(): | |
| audio_input = gr.Audio(type="filepath", label="π Speak or Upload Audio") | |
| audio_output = gr.Audio(label="π Chatter's Response", type="filepath") | |
| transcript_box = gr.Textbox(label="π Transcript", interactive=False) | |
| feedback_box = gr.Textbox(label="π‘ Feedback", interactive=False) | |
| hidden_transcript = gr.Textbox(visible=False) | |
| with gr.Row(): | |
| try_again = gr.Button("π Try Again") | |
| show_example = gr.Button("π― Show Me an Example") | |
| example_box = gr.Textbox(label="π£ Suggested Improvement", visible=True) | |
| history_table = gr.Dataframe(headers=["π Timestamp", "π Language", "π Transcript", "π¬ Feedback"]) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| gr.Dropdown( | |
| choices=[""], | |
| label="π Score Comparison", | |
| interactive=False, | |
| show_label=True | |
| ) | |
| score_chart = gr.Plot() | |
| with gr.Column(scale=1): | |
| trend_category_dropdown = gr.Dropdown( | |
| label="π Track Progress In", | |
| choices=["Clarity", "Structure", "Fluency", "Tone", "Content Relevance"], | |
| value="Tone" | |
| ) | |
| trend_chart = gr.Plot(label="Progress Over Time") | |
| milestone_box = gr.Markdown(visible=False) | |
| def tutor_feedback(audio_file, language, goal, focus_areas, trend_category, nickname): | |
| if not audio_file: | |
| return "", "No audio received.", None, "", [], render_empty_chart("π Score Comparison"), render_empty_chart("π Progress Over Time"), gr.update(visible=False) | |
| if hasattr(nickname, "value"): | |
| nickname = nickname.value | |
| wav_path = convert_to_wav(audio_file) | |
| transcript = transcribe_audio(wav_path) | |
| previous_sessions = fetch_user_sessions(nickname) | |
| previous_transcript = previous_sessions[-1].transcript if previous_sessions else None | |
| previous_feedback = previous_sessions[-1].feedback if previous_sessions else None | |
| full_feedback, feedback_clean = generate_feedback(transcript, language, goal, focus_areas, previous_transcript) | |
| if previous_feedback: | |
| feedback_clean += generate_progress_summary(full_feedback, previous_feedback) | |
| milestone = "" | |
| session_count = len(previous_sessions) + 1 | |
| if session_count in [3, 5, 10]: | |
| milestone = f"π Congrats on completing **{session_count} sessions**!" | |
| feedback_clean += f"\n\n{milestone}" | |
| lang_code = LANG_CODES.get(language, "en") | |
| tts = gTTS(feedback_clean, lang=lang_code) | |
| mp3_path = f"/tmp/{uuid.uuid4()}.mp3" | |
| tts.save(mp3_path) | |
| save_to_db(nickname, transcript, full_feedback, language) | |
| sessions = fetch_user_sessions(nickname) | |
| session_table = [[s.timestamp, s.language, s.transcript[:40], s.feedback[:40]] for s in sessions] | |
| score_plot = render_score_chart(build_score_comparison_data(full_feedback, previous_feedback)) if previous_feedback else render_empty_chart("π Score Comparison") | |
| dates, trend_scores = build_trend_data(sessions, trend_category) | |
| trend_plot = render_trend_chart(dates, trend_scores, trend_category) if trend_scores else render_empty_chart(f"π {trend_category} Progress") | |
| return transcript, feedback_clean, mp3_path, transcript, session_table, score_plot, trend_plot, gr.update(visible=bool(milestone), value=milestone) | |
| audio_input.change( | |
| fn=tutor_feedback, | |
| inputs=[audio_input, language_dropdown, goal_dropdown, focus_checkboxes, trend_category_dropdown, nickname_input], | |
| outputs=[transcript_box, feedback_box, audio_output, hidden_transcript, history_table, score_chart, trend_chart, milestone_box], | |
| show_progress="minimal" | |
| ) | |
| try_again.click(fn=lambda: ("", "", None, "", "", render_empty_chart("π Score Comparison"), render_empty_chart("π Progress Over Time"), gr.update(visible=False)), | |
| inputs=None, | |
| outputs=[transcript_box, feedback_box, audio_output, hidden_transcript, example_box, score_chart, trend_chart, milestone_box]) | |
| show_example.click(fn=generate_example_response, | |
| inputs=[hidden_transcript, language_dropdown], | |
| outputs=example_box) | |
| def update_trend_chart(trend_category, nickname): | |
| if hasattr(nickname, "value"): | |
| nickname = nickname.value | |
| sessions = fetch_user_sessions(nickname) | |
| dates, trend_scores = build_trend_data(sessions, trend_category) | |
| if trend_scores: | |
| return render_trend_chart(dates, trend_scores, trend_category) | |
| return render_empty_chart(f"π {trend_category} Progress") | |
| trend_category_dropdown.change( | |
| fn=update_trend_chart, | |
| inputs=[trend_category_dropdown, nickname_input], | |
| outputs=[trend_chart] | |
| ) | |
| return spoken_panel | |