mramirez2001 commited on
Commit
13542aa
verified
1 Parent(s): 65dd538

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +13 -29
app.py CHANGED
@@ -10,6 +10,7 @@ import soundfile as sf
10
  import whisper
11
  import pandas as pd
12
  from gtts import gTTS
 
13
 
14
  # --- 0. CONFIGURACI脫N INICIAL ---
15
  try:
@@ -19,12 +20,12 @@ except TypeError:
19
  api_key_found = False
20
 
21
  print("Loading Whisper for transcription...")
 
22
  whisper_model = whisper.load_model("base", device="cpu")
23
  print("Whisper model loaded.")
24
 
25
 
26
  # --- 1. DEFINICI脫N DE PROMPTS PARA LA IA ---
27
- # (Estos son los prompts completos y correctos para cada funci贸n)
28
 
29
  CONVERSATION_SYSTEM_PROMPT = """
30
  You are a friendly and encouraging English language tutor named Alex.
@@ -122,30 +123,29 @@ def run_sentence_evaluation(audio_input, reference_transcript):
122
  result = json.loads(response.choices[0].message.content)
123
  holistic_feedback_md = f"### Strengths\n{result['holistic_feedback']['strengths']}\n\n### Areas for Improvement\n{result['holistic_feedback']['areas_for_improvement']}"
124
  word_analysis_df = pd.DataFrame(result['word_by_word_analysis'])
125
- os.makedirs("reference_audio", exist_ok=True)
126
  reference_audio_paths = []
 
127
  for index, row in word_analysis_df.iterrows():
128
- word_to_speak = row['reference_word']; audio_path = f"reference_audio/{index}_{word_to_speak.lower()}.mp3"
129
  try:
130
  tts = gTTS(text=word_to_speak, lang='en'); tts.save(audio_path); reference_audio_paths.append(audio_path)
131
- except Exception: reference_audio_paths.append(None)
 
132
  word_analysis_df['reference_audio'] = reference_audio_paths
133
  df_for_display = word_analysis_df[['reference_word', 'spoken_word', 'word_score_100', 'feedback_en', 'feedback_es', 'reference_audio']]
134
- return (result.get("overall_score_100", 0), result.get("cefr_level", "N/A"), holistic_feedback_md, gr.DataFrame(value=df_for_display))
135
  except (json.JSONDecodeError, KeyError) as e:
136
  print(f"Error processing API response: {e}"); error_msg = "The API response was not in the expected format."
137
  return 0, "Error", error_msg, None
138
 
139
 
140
- # --- 3. INTERFAZ DE GRADIO CON PESTA脩AS (Con la tabla corregida) ---
141
-
142
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
143
  gr.Markdown("# 馃嚞馃嚙 AI English Speaking Practice & Assessment")
144
-
145
  with gr.Tabs():
146
- # --- PESTA脩A 1: CHAT AI (sin cambios) ---
147
  with gr.TabItem("Pr谩ctica Conversacional (Chat AI)"):
148
- # ... (todo el c贸digo de la interfaz del chatbot se mantiene igual)
149
  with gr.Row():
150
  with gr.Column(scale=2):
151
  chatbot = gr.Chatbot(value=[(None, "Hi there! I'm Alex. How are you doing today?")], label="Conversation with your AI Tutor")
@@ -155,12 +155,11 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
155
  history = gr.State([])
156
  audio_in_chat.stop_recording(fn=chat_interaction, inputs=[audio_in_chat, history], outputs=[chatbot, history, feedback_en_out, feedback_es_out])
157
 
158
- # --- PESTA脩A 2: EVALUACI脫N POR FRASE (Con la tabla corregida) ---
159
  with gr.TabItem("Evaluaci贸n por Frase"):
160
  TONGUE_TWISTERS = ["Peter Piper picked a peck of pickled peppers.", "She sells seashells by the seashore.", "How much wood would a woodchuck chuck if a woodchuck could chuck wood?", "Betty Botter bought some butter but she said the butter鈥檚 bitter.", "A proper copper coffee pot."]
161
  gr.Markdown("Choose a tongue twister or write your own sentence. Record yourself, and our AI examiner will provide a detailed diagnostic report.")
162
  tongue_twister_selector = gr.Dropdown(choices=TONGUE_TWISTERS, label="Or Choose a Tongue Twister to Practice")
163
-
164
  with gr.Row():
165
  with gr.Column(scale=1):
166
  audio_in_sentence = gr.Audio(sources=["microphone"], type="numpy", label="1. Record Your Voice")
@@ -172,26 +171,11 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
172
  score_out_sentence = gr.Number(label="Overall Score (0-100)", interactive=False)
173
  level_out_sentence = gr.Textbox(label="Estimated CEFR Level", interactive=False)
174
  holistic_feedback_out_sentence = gr.Markdown(label="Examiner's Feedback")
175
-
176
  gr.Markdown("--- \n ### Detailed Word-by-Word Analysis")
177
-
178
- # --- AJUSTE CLAVE: Especificamos el tipo de dato para cada columna ---
179
- word_analysis_out_sentence = gr.DataFrame(
180
- headers=["Reference Word", "Spoken Word", "Score (0-100)", "Feedback (English)", "Feedback (Espa帽ol)", "Reference Audio"],
181
- # Le decimos a Gradio que la 煤ltima columna es de tipo 'audio'
182
- datatype=["str", "str", "number", "str", "str", "audio"],
183
- label="Phonetic Breakdown",
184
- wrap=True
185
- )
186
-
187
  def update_text(choice): return gr.Textbox(value=choice)
188
  tongue_twister_selector.change(fn=update_text, inputs=tongue_twister_selector, outputs=text_in_sentence)
189
-
190
- submit_btn_sentence.click(
191
- fn=run_sentence_evaluation,
192
- inputs=[audio_in_sentence, text_in_sentence],
193
- outputs=[score_out_sentence, level_out_sentence, holistic_feedback_out_sentence, word_analysis_out_sentence]
194
- )
195
 
196
  if __name__ == "__main__":
197
  if not api_key_found: print("\nFATAL: OpenAI API key not found.")
 
10
  import whisper
11
  import pandas as pd
12
  from gtts import gTTS
13
+ import re # Necesario para limpiar nombres de archivo
14
 
15
  # --- 0. CONFIGURACI脫N INICIAL ---
16
  try:
 
20
  api_key_found = False
21
 
22
  print("Loading Whisper for transcription...")
23
+ # Usamos el modelo 'base' que es un buen compromiso entre velocidad y precisi贸n
24
  whisper_model = whisper.load_model("base", device="cpu")
25
  print("Whisper model loaded.")
26
 
27
 
28
  # --- 1. DEFINICI脫N DE PROMPTS PARA LA IA ---
 
29
 
30
  CONVERSATION_SYSTEM_PROMPT = """
31
  You are a friendly and encouraging English language tutor named Alex.
 
123
  result = json.loads(response.choices[0].message.content)
124
  holistic_feedback_md = f"### Strengths\n{result['holistic_feedback']['strengths']}\n\n### Areas for Improvement\n{result['holistic_feedback']['areas_for_improvement']}"
125
  word_analysis_df = pd.DataFrame(result['word_by_word_analysis'])
126
+ print("Generando audios de referencia...")
127
  reference_audio_paths = []
128
+ os.makedirs("reference_audio", exist_ok=True)
129
  for index, row in word_analysis_df.iterrows():
130
+ word_to_speak = row['reference_word']; safe_filename = re.sub(r'\W+', '', word_to_speak.lower()); audio_path = f"reference_audio/{index}_{safe_filename}.mp3"
131
  try:
132
  tts = gTTS(text=word_to_speak, lang='en'); tts.save(audio_path); reference_audio_paths.append(audio_path)
133
+ except Exception as e:
134
+ print(f"Error al generar TTS para '{word_to_speak}': {e}"); reference_audio_paths.append(None)
135
  word_analysis_df['reference_audio'] = reference_audio_paths
136
  df_for_display = word_analysis_df[['reference_word', 'spoken_word', 'word_score_100', 'feedback_en', 'feedback_es', 'reference_audio']]
137
+ return (result.get("overall_score_100", 0), result.get("cefr_level", "N/A"), holistic_feedback_md, df_for_display)
138
  except (json.JSONDecodeError, KeyError) as e:
139
  print(f"Error processing API response: {e}"); error_msg = "The API response was not in the expected format."
140
  return 0, "Error", error_msg, None
141
 
142
 
143
+ # --- 3. INTERFAZ DE GRADIO CON PESTA脩AS ---
 
144
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
145
  gr.Markdown("# 馃嚞馃嚙 AI English Speaking Practice & Assessment")
 
146
  with gr.Tabs():
147
+ # --- PESTA脩A 1: CHAT AI ---
148
  with gr.TabItem("Pr谩ctica Conversacional (Chat AI)"):
 
149
  with gr.Row():
150
  with gr.Column(scale=2):
151
  chatbot = gr.Chatbot(value=[(None, "Hi there! I'm Alex. How are you doing today?")], label="Conversation with your AI Tutor")
 
155
  history = gr.State([])
156
  audio_in_chat.stop_recording(fn=chat_interaction, inputs=[audio_in_chat, history], outputs=[chatbot, history, feedback_en_out, feedback_es_out])
157
 
158
+ # --- PESTA脩A 2: EVALUACI脫N POR FRASE ---
159
  with gr.TabItem("Evaluaci贸n por Frase"):
160
  TONGUE_TWISTERS = ["Peter Piper picked a peck of pickled peppers.", "She sells seashells by the seashore.", "How much wood would a woodchuck chuck if a woodchuck could chuck wood?", "Betty Botter bought some butter but she said the butter鈥檚 bitter.", "A proper copper coffee pot."]
161
  gr.Markdown("Choose a tongue twister or write your own sentence. Record yourself, and our AI examiner will provide a detailed diagnostic report.")
162
  tongue_twister_selector = gr.Dropdown(choices=TONGUE_TWISTERS, label="Or Choose a Tongue Twister to Practice")
 
163
  with gr.Row():
164
  with gr.Column(scale=1):
165
  audio_in_sentence = gr.Audio(sources=["microphone"], type="numpy", label="1. Record Your Voice")
 
171
  score_out_sentence = gr.Number(label="Overall Score (0-100)", interactive=False)
172
  level_out_sentence = gr.Textbox(label="Estimated CEFR Level", interactive=False)
173
  holistic_feedback_out_sentence = gr.Markdown(label="Examiner's Feedback")
 
174
  gr.Markdown("--- \n ### Detailed Word-by-Word Analysis")
175
+ word_analysis_out_sentence = gr.DataFrame(headers=["Reference Word", "Spoken Word", "Score (0-100)", "Feedback (English)", "Feedback (Espa帽ol)", "Reference Audio"], datatype=["str", "str", "number", "str", "str", "filepath"], label="Phonetic Breakdown", wrap=True)
 
 
 
 
 
 
 
 
 
176
  def update_text(choice): return gr.Textbox(value=choice)
177
  tongue_twister_selector.change(fn=update_text, inputs=tongue_twister_selector, outputs=text_in_sentence)
178
+ submit_btn_sentence.click(fn=run_sentence_evaluation, inputs=[audio_in_sentence, text_in_sentence], outputs=[score_out_sentence, level_out_sentence, holistic_feedback_out_sentence, word_analysis_out_sentence])
 
 
 
 
 
179
 
180
  if __name__ == "__main__":
181
  if not api_key_found: print("\nFATAL: OpenAI API key not found.")