mramirez2001 commited on
Commit
9abaf57
verified
1 Parent(s): 13542aa

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +61 -20
app.py CHANGED
@@ -108,43 +108,81 @@ def chat_interaction(audio_input, history_state):
108
  except (json.JSONDecodeError, KeyError) as e:
109
  print(f"Error parsing final report: {e}"); return chat_display, history_state, gr.Markdown(value="Error generating report.", visible=True), gr.Markdown(visible=False)
110
 
 
111
  def run_sentence_evaluation(audio_input, reference_transcript):
112
  if not api_key_found: raise gr.Error("OpenAI API key not found.")
113
  if audio_input is None or not reference_transcript:
114
- return 0, "N/A", "Please provide both an audio file and the reference text.", None
115
- sr, y = audio_input; temp_audio_path = "temp_audio_sentence.wav"; sf.write(temp_audio_path, y, sr)
 
 
 
 
116
  word_features = extract_word_level_features(temp_audio_path)
117
  if not word_features:
118
  return 0, "N/A", "Could not process the audio.", None
 
119
  prompt_data = {"reference_transcript": reference_transcript, "spoken_words": word_features}
 
120
  print("Sending detailed data to GPT-4o for sentence analysis...")
121
- response = client.chat.completions.create(model="gpt-4o", response_format={"type": "json_object"}, messages=[{"role": "system", "content": SENTENCE_EVALUATION_SYSTEM_PROMPT}, {"role": "user", "content": json.dumps(prompt_data)}])
 
 
 
 
 
122
  try:
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):
@@ -172,11 +210,14 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
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.")
182
  else: demo.launch(debug=True)
 
108
  except (json.JSONDecodeError, KeyError) as e:
109
  print(f"Error parsing final report: {e}"); return chat_display, history_state, gr.Markdown(value="Error generating report.", visible=True), gr.Markdown(visible=False)
110
 
111
+ # --- CAMBIO: La funci贸n de evaluaci贸n ahora devuelve Markdown ---
112
  def run_sentence_evaluation(audio_input, reference_transcript):
113
  if not api_key_found: raise gr.Error("OpenAI API key not found.")
114
  if audio_input is None or not reference_transcript:
115
+ return 0, "N/A", "Please provide both an audio file and the reference text.", ""
116
+
117
+ sr, y = audio_input
118
+ temp_audio_path = "temp_audio_sentence.wav"
119
+ sf.write(temp_audio_path, y, sr)
120
+
121
  word_features = extract_word_level_features(temp_audio_path)
122
  if not word_features:
123
  return 0, "N/A", "Could not process the audio.", None
124
+
125
  prompt_data = {"reference_transcript": reference_transcript, "spoken_words": word_features}
126
+
127
  print("Sending detailed data to GPT-4o for sentence analysis...")
128
+ response = client.chat.completions.create(
129
+ model="gpt-4o",
130
+ response_format={"type": "json_object"},
131
+ messages=[{"role": "system", "content": SENTENCE_EVALUATION_SYSTEM_PROMPT}, {"role": "user", "content": json.dumps(prompt_data)}]
132
+ )
133
+
134
  try:
135
  result = json.loads(response.choices[0].message.content)
136
  holistic_feedback_md = f"### Strengths\n{result['holistic_feedback']['strengths']}\n\n### Areas for Improvement\n{result['holistic_feedback']['areas_for_improvement']}"
137
+ word_analysis_list = result['word_by_word_analysis']
138
+
139
+ # --- NUEVO: Construir una tabla en Markdown ---
140
+ md_table = "| Reference Word | Spoken Word | Score | Feedback (EN) | Feedback (ES) | Reference Audio |\n"
141
+ md_table += "| :--- | :--- | :---: | :--- | :--- | :---: |\n"
142
+
143
  os.makedirs("reference_audio", exist_ok=True)
144
+
145
+ for index, item in enumerate(word_analysis_list):
146
+ word_to_speak = item['reference_word']
147
+ safe_filename = re.sub(r'\W+', '', word_to_speak.lower())
148
+ audio_path = f"reference_audio/{index}_{safe_filename}.mp3"
149
+
150
  try:
151
+ tts = gTTS(text=word_to_speak, lang='en')
152
+ tts.save(audio_path)
153
+ # Embed the audio using an HTML5 tag within the Markdown table
154
+ audio_player = f'<audio src="file/{audio_path}" controls></audio>'
155
  except Exception as e:
156
+ print(f"Error al generar TTS para '{word_to_speak}': {e}")
157
+ audio_player = "Error"
158
+
159
+ # Add a row to the Markdown table
160
+ md_table += (f"| **{item['reference_word']}** "
161
+ f"| {item['spoken_word']} "
162
+ f"| {item['word_score_100']} "
163
+ f"| {item['feedback_en']} "
164
+ f"| {item['feedback_es']} "
165
+ f"| {audio_player} |\n")
166
+
167
+ return (
168
+ result.get("overall_score_100", 0),
169
+ result.get("cefr_level", "N/A"),
170
+ holistic_feedback_md,
171
+ md_table # Return the Markdown string instead of a DataFrame
172
+ )
173
  except (json.JSONDecodeError, KeyError) as e:
174
+ print(f"Error processing API response: {e}")
175
+ error_msg = "The API response was not in the expected format."
176
+ return 0, "Error", error_msg, ""
177
 
178
 
179
+
180
+ # --- 3. INTERFAZ DE GRADIO CON PESTA脩AS (Con salida Markdown) ---
181
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
182
  gr.Markdown("# 馃嚞馃嚙 AI English Speaking Practice & Assessment")
183
+
184
  with gr.Tabs():
185
+ # --- PESTA脩A 1: CHAT AI (sin cambios) ---
186
  with gr.TabItem("Pr谩ctica Conversacional (Chat AI)"):
187
  with gr.Row():
188
  with gr.Column(scale=2):
 
210
  level_out_sentence = gr.Textbox(label="Estimated CEFR Level", interactive=False)
211
  holistic_feedback_out_sentence = gr.Markdown(label="Examiner's Feedback")
212
  gr.Markdown("--- \n ### Detailed Word-by-Word Analysis")
213
+ word_analysis_out_sentence = gr.Markdown(label="Phonetic Breakdown")
214
  def update_text(choice): return gr.Textbox(value=choice)
215
  tongue_twister_selector.change(fn=update_text, inputs=tongue_twister_selector, outputs=text_in_sentence)
216
+ submit_btn_sentence.click(
217
+ fn=run_sentence_evaluation,
218
+ inputs=[audio_in_sentence, text_in_sentence],
219
+ outputs=[score_out_sentence, level_out_sentence, holistic_feedback_out_sentence, word_analysis_out_sentence]
220
+ )
221
  if __name__ == "__main__":
222
  if not api_key_found: print("\nFATAL: OpenAI API key not found.")
223
  else: demo.launch(debug=True)