CommTutor / spoken_module.py
ankban's picture
Update spoken_module.py
6191204 verified
Raw
History Blame Contribute Delete
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