Nazari11221's picture
Update app.py
1e44e76 verified
import os
import gradio as gr
import openai
import whisper
from gtts import gTTS
from fpdf import FPDF
import pandas as pd
import time
# 🔐 Set your OpenAI API key securely from environment variables
openai.api_key = os.environ.get("OPENAI_API_KEY")
# 🎙️ Load Whisper ASR model
model = whisper.load_model("base")
# 📁 CSV log file
LOG_FILE = "toefl_logs.csv"
if not os.path.exists(LOG_FILE):
pd.DataFrame(columns=["timestamp", "prompt", "transcript", "feedback"]).to_csv(LOG_FILE, index=False)
# 📝 TOEFL speaking prompts
prompts = [
"Do you agree or disagree with the idea that people learn more from failure than from success?",
"Some people believe that couples should live together before marriage. Do you agree or disagree?",
"Describe a teacher who has greatly influenced your life. What qualities did they have?"
]
# 🌐 Translations for multilingual UI labels
translations = {
"English": {
"audio_label": "Audio Feedback",
"pdf_label": "Download PDF",
"share_label": "Share App",
"feedback_history": "📜 Feedback History",
"record_label": "🎤 Record your answer",
"prompt_label": "📝 Choose a TOEFL Prompt",
"language_label": "🌐 Language",
"submit_label": "✅ Submit",
"share_button_label": "🔗 Share App",
"transcript_label": "🗣️ Your Transcript",
"feedback_label": "✅ AI Feedback",
},
"Pashto": {
"audio_label": "د فېډبک آډیو",
"pdf_label": "د فېډبک PDF",
"share_label": "اپ شریک کړئ",
"feedback_history": "د بیاکتنې تاریخ",
"record_label": "🎤 خپل ځواب ثبت کړئ",
"prompt_label": "📝 د TOEFL موضوع غوره کړئ",
"language_label": "🌐 ژبه",
"submit_label": "✅ وړاندې کول",
"share_button_label": "🔗 اپ شریک کړئ",
"transcript_label": "🗣️ ستاسو متن",
"feedback_label": "✅ AI فیډبیک",
},
"Dari": {
"audio_label": "صدای بازخورد",
"pdf_label": "دانلود PDF بازخورد",
"share_label": "اشتراک اپلیکیشن",
"feedback_history": "تاریخچه بازخورد",
"record_label": "🎤 پاسخ خود را ضبط کنید",
"prompt_label": "📝 یک موضوع TOEFL انتخاب کنید",
"language_label": "🌐 زبان",
"submit_label": "✅ ارسال",
"share_button_label": "🔗 اشتراک اپ",
"transcript_label": "🗣️ متن شما",
"feedback_label": "✅ بازخورد AI",
}
}
# 🎯 Transcribe audio file to text
def transcribe(audio):
result = model.transcribe(audio)
return result["text"]
# 🤖 Generate GPT feedback and score
def get_feedback(prompt, response):
full_prompt = f"""You are an English teacher scoring TOEFL Speaking responses.
Prompt: "{prompt}"
Student response: "{response}"
Give detailed, kind feedback and a score out of 4.
"""
completion = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": full_prompt}]
)
return completion.choices[0].message.content.strip()
# 🔉 Generate TTS audio for feedback text
def generate_audio_feedback(text):
tts = gTTS(text)
path = f"feedback_{int(time.time())}.mp3"
tts.save(path)
return path
# 📄 Create a PDF with prompt, transcript, and feedback
def generate_pdf(prompt, transcript, feedback):
pdf = FPDF()
pdf.add_page()
pdf.set_font("Arial", size=12)
pdf.multi_cell(0, 10, f"Prompt:\n{prompt}\n\nYour Response:\n{transcript}\n\nFeedback:\n{feedback}")
path = f"feedback_{int(time.time())}.pdf"
pdf.output(path)
return path
# 🧠 Main function triggered by Gradio
def toefl_app(audio, selected_prompt, lang):
transcript = transcribe(audio)
feedback = get_feedback(selected_prompt, transcript)
audio_path = generate_audio_feedback(feedback)
pdf_path = generate_pdf(selected_prompt, transcript, feedback)
# Log response to CSV
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
log_df = pd.read_csv(LOG_FILE)
log_df.loc[len(log_df)] = [timestamp, selected_prompt, transcript, feedback]
log_df.to_csv(LOG_FILE, index=False)
labels = translations[lang]
return (
transcript,
feedback,
labels["audio_label"],
audio_path,
labels["pdf_label"],
pdf_path,
START_BEEP,
STOP_BEEP
)
# 📜 Show last 20 feedback history entries
def view_history():
df = pd.read_csv(LOG_FILE)
return df.tail(20).to_markdown()
# Update UI labels on language change
def update_ui_labels(lang):
labels = translations[lang]
return (
labels["record_label"],
labels["prompt_label"],
labels["language_label"],
labels["submit_label"],
labels["share_button_label"],
labels["transcript_label"],
labels["feedback_label"],
labels["audio_label"],
labels["pdf_label"],
labels["feedback_history"],
)
# 🌍 Language options for UI
lang_options = list(translations.keys())
# Beep sounds (upload these mp3 files to your repo)
START_BEEP = "start_beep.mp3"
STOP_BEEP = "stop_beep.mp3"
# 📱 Gradio UI
with gr.Blocks(css="""
footer {display: none !important;}
.gradio-container {
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
button, .gr-button {
font-size: 1.1em;
padding: 0.7em 1.2em;
}
""") as demo:
gr.Markdown("## 🗣️ TOEFL Speaking Practice Tool | [by @Nazari11221](https://huggingface.co/Nazari11221)")
with gr.Row():
audio = gr.Audio(type="filepath", label=translations["English"]["record_label"])
prompt = gr.Dropdown(prompts, label=translations["English"]["prompt_label"])
lang = gr.Dropdown(lang_options, value="English", label=translations["English"]["language_label"])
with gr.Row():
submit = gr.Button(translations["English"]["submit_label"])
share = gr.Button(translations["English"]["share_button_label"])
transcript = gr.Textbox(label=translations["English"]["transcript_label"])
feedback = gr.Textbox(label=translations["English"]["feedback_label"])
audio_label = gr.Label(value=translations["English"]["audio_label"])
audio_out = gr.Audio()
pdf_label = gr.Label(value=translations["English"]["pdf_label"])
pdf_out = gr.File()
beep_start = gr.Audio(START_BEEP, visible=False, autoplay=True)
beep_end = gr.Audio(STOP_BEEP, visible=False, autoplay=True)
with gr.Accordion(translations["English"]["feedback_history"], open=False) as feedback_history:
hist_output = gr.Markdown()
hist_btn = gr.Button("🔄 Refresh History")
# Connect buttons and events
submit.click(
toefl_app,
inputs=[audio, prompt, lang],
outputs=[transcript, feedback, audio_label, audio_out, pdf_label, pdf_out, beep_start, beep_end],
)
hist_btn.click(view_history, outputs=hist_output)
share.click(lambda: "🔗 Share this link: https://nazari11221-toefl-speaking-practice.hf.space", outputs=share)
# Update all UI labels when language changes
lang.change(
update_ui_labels,
inputs=[lang],
outputs=[audio, prompt, lang, submit, share, transcript, feedback, audio_label, pdf_label, feedback_history]
)
if __name__ == "__main__":
demo.launch()