milwright commited on
Commit
71a2826
·
verified ·
1 Parent(s): 65c037b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +5 -151
app.py CHANGED
@@ -9,16 +9,6 @@ from datetime import datetime
9
  import urllib.parse
10
  from pathlib import Path
11
  from typing import List, Dict, Optional, Any, Tuple
12
- import base64
13
- import io
14
-
15
- # Try to import gradio_client for TTS support
16
- try:
17
- from gradio_client import Client
18
- GRADIO_CLIENT_AVAILABLE = True
19
- except ImportError:
20
- GRADIO_CLIENT_AVAILABLE = False
21
- print("Warning: gradio_client not available. TTS features will be disabled.")
22
 
23
 
24
  # Configuration
@@ -32,7 +22,7 @@ DEFAULT_CONFIG = {
32
  'system_prompt': "You are Domenico from Sicily, a Juventus football fan, native Italian speaker serving as a conversational partner for university students in an Italian 101 class. Students will interact and converse with you in Italian, and you must respond EXCLUSIVELY IN ITALIAN without providing English translations, using vocabulary appropriate for beginner-level Italian 101 students. Focus your responses on topics suitable for beginners such as sports, daily life, routines, food, numbers, and hobbies. When students make errors, model the correct forms naturally in your response without explicitly pointing out mistakes, allowing them to learn through exposure to proper usage. Recognize when students demonstrate more advanced abilities and adjust your language complexity accordingly, while ensuring your Italian remains error-free. Keep all responses between 5-50 words, making sure sentences are grammatically complete. Limit all verb conjugations to the present tense only, avoiding all other verb forms and tenses. Address students using the informal second-person singular 'tu' form.",
33
  'temperature': 0.5,
34
  'max_tokens': 250,
35
- 'model': 'google/gemma-3-27b-it',
36
  'api_key_var': 'API_KEY',
37
  'theme': 'Default',
38
  'grounding_urls': ["https://www.pnac.org/wp-content/uploads/Italian-Study-Guide.pdf"],
@@ -40,8 +30,6 @@ DEFAULT_CONFIG = {
40
  'enable_file_upload': True,
41
  'examples': ['Ciao! Come stai oggi?', 'Mi piace giocare a calcio. E tu?', 'Cosa mangi di solito a colazione?', 'A che ora ti svegli la mattina?', 'Qual è il tuo sport preferito?'],
42
  'language': 'Italian',
43
- 'enable_tts': False,
44
- 'tts_spaces': ['facebook/mms-tts-eng', 'microsoft/speecht5-tts-demo'],
45
  'locked': False
46
  }
47
 
@@ -294,80 +282,6 @@ def process_file_upload(file_path: str) -> str:
294
  _url_content_cache = {}
295
 
296
 
297
- def generate_tts(text: str, hf_token: Optional[str] = None) -> Optional[Tuple[int, Any]]:
298
- """
299
- Generate text-to-speech audio using HuggingFace Spaces via gradio_client.
300
- Uses multiple fallback options for maximum reliability.
301
-
302
- Returns: Tuple of (sample_rate, audio_array) or None if failed
303
- """
304
- if not GRADIO_CLIENT_AVAILABLE:
305
- return None
306
-
307
- if not text or not text.strip():
308
- return None
309
-
310
- # Get HF token from environment if not provided
311
- if not hf_token:
312
- hf_token = os.getenv("HF_TOKEN")
313
-
314
- # Get TTS spaces from config
315
- tts_spaces = DEFAULT_CONFIG.get('tts_spaces', [])
316
- if not tts_spaces:
317
- # Default fallback spaces if none configured
318
- tts_spaces = [
319
- "facebook/mms-tts-eng",
320
- "microsoft/speecht5-tts-demo",
321
- "coqui/XTTS",
322
- "myshell-ai/OpenVoice"
323
- ]
324
-
325
- # Limit text length for TTS
326
- max_text_length = 500
327
- if len(text) > max_text_length:
328
- text = text[:max_text_length] + "..."
329
-
330
- # Try each TTS space in order
331
- for space_name in tts_spaces:
332
- try:
333
- print(f"Trying TTS space: {space_name}")
334
- client = Client(space_name, hf_token=hf_token)
335
-
336
- # Different spaces have different APIs, try common patterns
337
- try:
338
- # Pattern 1: Simple text input
339
- result = client.predict(text, api_name="/predict")
340
- except:
341
- try:
342
- # Pattern 2: Text + language
343
- result = client.predict(text, "en", api_name="/predict")
344
- except:
345
- try:
346
- # Pattern 3: Text + voice/speaker
347
- result = client.predict(text, "default", api_name="/predict")
348
- except:
349
- continue
350
-
351
- # Handle different return types
352
- if isinstance(result, str) and os.path.exists(result):
353
- # Result is a file path
354
- import soundfile as sf
355
- audio_data, sample_rate = sf.read(result)
356
- return (sample_rate, audio_data)
357
- elif isinstance(result, tuple) and len(result) >= 2:
358
- # Result is (sample_rate, audio_array)
359
- return result
360
- elif hasattr(result, 'get') and 'audio' in result:
361
- # Result is a dict with audio key
362
- return result['audio']
363
-
364
- except Exception as e:
365
- print(f"TTS failed with {space_name}: {str(e)}")
366
- continue
367
-
368
- return None
369
-
370
-
371
  def get_grounding_context() -> str:
372
  """Get grounding context from configured URLs with caching"""
373
  urls = GROUNDING_URLS
@@ -556,11 +470,8 @@ Get your API key at: https://openrouter.ai/keys"""
556
  )
557
 
558
  if response.status_code == 200:
559
- try:
560
- result = response.json()
561
- ai_response = result['choices'][0]['message']['content']
562
- except (json.JSONDecodeError, KeyError) as e:
563
- return f"❌ Error parsing API response: {str(e)}"
564
 
565
  # Add file notification if files were uploaded
566
  if file_notification:
@@ -568,11 +479,8 @@ Get your API key at: https://openrouter.ai/keys"""
568
 
569
  return ai_response
570
  else:
571
- try:
572
- error_data = response.json()
573
- error_message = error_data.get('error', {}).get('message', 'Unknown error')
574
- except:
575
- error_message = response.text if response.text else 'Unknown error'
576
  return f"❌ API Error ({response.status_code}): {error_message}"
577
 
578
  except requests.exceptions.Timeout:
@@ -610,7 +518,6 @@ def verify_hf_token_access() -> Tuple[bool, str]:
610
  return False, f"Error verifying HF token: {str(e)}"
611
 
612
 
613
-
614
  # Create main interface with clean tab structure
615
  def create_interface():
616
  """Create the Gradio interface with clean tab structure"""
@@ -683,19 +590,6 @@ def create_interface():
683
  size="sm"
684
  )
685
 
686
- # TTS functionality
687
- if DEFAULT_CONFIG.get('enable_tts', False) and GRADIO_CLIENT_AVAILABLE:
688
- with gr.Row():
689
- tts_btn = gr.Button("🔊 Read Last Response", variant="secondary", size="sm")
690
- tts_status = gr.Textbox(label="TTS Status", visible=False, interactive=False)
691
-
692
- audio_output = gr.Audio(
693
- label="TTS Output",
694
- visible=False,
695
- autoplay=True,
696
- type="numpy"
697
- )
698
-
699
  # Export handler
700
  def prepare_export():
701
  if not chat_history_store:
@@ -719,46 +613,6 @@ def create_interface():
719
  outputs=[export_btn]
720
  )
721
 
722
- # TTS handler
723
- if DEFAULT_CONFIG.get('enable_tts', False) and GRADIO_CLIENT_AVAILABLE:
724
- def handle_tts(chat_history):
725
- """Generate TTS for the last assistant message"""
726
- if not chat_history:
727
- return None, gr.update(value="No messages to read", visible=True)
728
-
729
- # Find last assistant message
730
- last_assistant_msg = None
731
- for msg in reversed(chat_history):
732
- if msg.get("role") == "assistant":
733
- last_assistant_msg = msg.get("content", "")
734
- break
735
-
736
- if not last_assistant_msg:
737
- return None, gr.update(value="No assistant message found", visible=True)
738
-
739
- # Update status
740
- status_msg = "🎯 Generating audio..."
741
-
742
- # Generate TTS
743
- audio_result = generate_tts(last_assistant_msg)
744
-
745
- if audio_result:
746
- return (
747
- gr.update(value=audio_result, visible=True),
748
- gr.update(value="✅ Audio generated successfully", visible=True)
749
- )
750
- else:
751
- return (
752
- None,
753
- gr.update(value="❌ TTS generation failed", visible=True)
754
- )
755
-
756
- tts_btn.click(
757
- handle_tts,
758
- inputs=[chatbot],
759
- outputs=[audio_output, tts_status]
760
- )
761
-
762
  # Examples section
763
  if examples:
764
  gr.Examples(examples=examples, inputs=msg)
 
9
  import urllib.parse
10
  from pathlib import Path
11
  from typing import List, Dict, Optional, Any, Tuple
 
 
 
 
 
 
 
 
 
 
12
 
13
 
14
  # Configuration
 
22
  'system_prompt': "You are Domenico from Sicily, a Juventus football fan, native Italian speaker serving as a conversational partner for university students in an Italian 101 class. Students will interact and converse with you in Italian, and you must respond EXCLUSIVELY IN ITALIAN without providing English translations, using vocabulary appropriate for beginner-level Italian 101 students. Focus your responses on topics suitable for beginners such as sports, daily life, routines, food, numbers, and hobbies. When students make errors, model the correct forms naturally in your response without explicitly pointing out mistakes, allowing them to learn through exposure to proper usage. Recognize when students demonstrate more advanced abilities and adjust your language complexity accordingly, while ensuring your Italian remains error-free. Keep all responses between 5-50 words, making sure sentences are grammatically complete. Limit all verb conjugations to the present tense only, avoiding all other verb forms and tenses. Address students using the informal second-person singular 'tu' form.",
23
  'temperature': 0.5,
24
  'max_tokens': 250,
25
+ 'model': 'openai/gpt-oss-120b',
26
  'api_key_var': 'API_KEY',
27
  'theme': 'Default',
28
  'grounding_urls': ["https://www.pnac.org/wp-content/uploads/Italian-Study-Guide.pdf"],
 
30
  'enable_file_upload': True,
31
  'examples': ['Ciao! Come stai oggi?', 'Mi piace giocare a calcio. E tu?', 'Cosa mangi di solito a colazione?', 'A che ora ti svegli la mattina?', 'Qual è il tuo sport preferito?'],
32
  'language': 'Italian',
 
 
33
  'locked': False
34
  }
35
 
 
282
  _url_content_cache = {}
283
 
284
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
  def get_grounding_context() -> str:
286
  """Get grounding context from configured URLs with caching"""
287
  urls = GROUNDING_URLS
 
470
  )
471
 
472
  if response.status_code == 200:
473
+ result = response.json()
474
+ ai_response = result['choices'][0]['message']['content']
 
 
 
475
 
476
  # Add file notification if files were uploaded
477
  if file_notification:
 
479
 
480
  return ai_response
481
  else:
482
+ error_data = response.json()
483
+ error_message = error_data.get('error', {}).get('message', 'Unknown error')
 
 
 
484
  return f"❌ API Error ({response.status_code}): {error_message}"
485
 
486
  except requests.exceptions.Timeout:
 
518
  return False, f"Error verifying HF token: {str(e)}"
519
 
520
 
 
521
  # Create main interface with clean tab structure
522
  def create_interface():
523
  """Create the Gradio interface with clean tab structure"""
 
590
  size="sm"
591
  )
592
 
 
 
 
 
 
 
 
 
 
 
 
 
 
593
  # Export handler
594
  def prepare_export():
595
  if not chat_history_store:
 
613
  outputs=[export_btn]
614
  )
615
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
616
  # Examples section
617
  if examples:
618
  gr.Examples(examples=examples, inputs=msg)