milwright commited on
Commit
72c9176
·
verified ·
1 Parent(s): 3e75449

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -42
app.py CHANGED
@@ -12,24 +12,24 @@ from typing import List, Dict, Optional, Any, Tuple
12
 
13
 
14
  # Configuration
15
- SPACE_NAME = 'Language Learning Partner'
16
- SPACE_DESCRIPTION = 'AI Italian conversation partner'
17
 
18
  # Default configuration values
19
  DEFAULT_CONFIG = {
20
  'name': SPACE_NAME,
21
  'description': SPACE_DESCRIPTION,
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': 'google/gemma-3-27b-it',
26
  'api_key_var': 'API_KEY',
27
- 'theme': 'Default',
28
- 'grounding_urls': ["https://www.pnac.org/wp-content/uploads/Italian-Study-Guide.pdf"],
29
  'enable_dynamic_urls': True,
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
 
@@ -183,13 +183,7 @@ def fetch_url_content(url: str, max_length: int = 3000) -> str:
183
  return f"❌ Invalid URL format: {url}"
184
 
185
  headers = {
186
- 'User-Agent': 'Mozilla/5.0 (compatible; HuggingFace-Space/1.0)',
187
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
188
- 'Accept-Language': 'en-US,en;q=0.5',
189
- 'Accept-Encoding': 'gzip, deflate',
190
- 'DNT': '1',
191
- 'Connection': 'keep-alive',
192
- 'Upgrade-Insecure-Requests': '1'
193
  }
194
 
195
  response = requests.get(url, headers=headers, timeout=5)
@@ -235,7 +229,7 @@ def fetch_url_content(url: str, max_length: int = 3000) -> str:
235
 
236
  def extract_urls_from_text(text: str) -> List[str]:
237
  """Extract URLs from message text"""
238
- url_pattern = r'https?://[^\s<>"{}|\\^`\[\]]+(?:\.[^\s<>"{}|\\^`\[\]])*'
239
  urls = re.findall(url_pattern, text)
240
  return [url.rstrip('.,;:)?!') for url in urls]
241
 
@@ -335,17 +329,18 @@ def get_grounding_context() -> str:
335
  return ""
336
 
337
 
338
- def export_conversation_to_markdown(history: List[Dict[str, str]]) -> str:
339
- """Export conversation history to markdown"""
340
  if not history:
341
  return "No conversation to export."
342
 
343
- markdown_content = f"""# Conversation Export
 
344
  Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
345
  Space: {SPACE_NAME}
346
  Model: {MODEL}
347
 
348
- ---
349
 
350
  """
351
 
@@ -355,15 +350,28 @@ Model: {MODEL}
355
  role = message.get('role', 'unknown')
356
  content = message.get('content', '')
357
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358
  if role == 'user':
359
  message_count += 1
360
- markdown_content += f"## User Message {message_count}\n\n{content}\n\n"
361
  elif role == 'assistant':
362
- markdown_content += f"## Assistant Response {message_count}\n\n{content}\n\n---\n\n"
363
 
364
- return markdown_content
365
-
366
-
367
 
368
 
369
  def generate_response(message: str, history: List[Dict[str, str]], files: Optional[List] = None) -> str:
@@ -594,7 +602,7 @@ def create_interface():
594
  submit_btn = gr.Button("Send", variant="primary")
595
  clear_btn = gr.Button("Clear")
596
 
597
- # Export functionality
598
  with gr.Row():
599
  # Use a regular Button for triggering export
600
  export_trigger_btn = gr.Button(
@@ -615,18 +623,18 @@ def create_interface():
615
  return None
616
 
617
  try:
618
- content = export_conversation_to_markdown(chat_history)
619
 
620
  # Create filename
621
  space_name_safe = re.sub(r'[^a-zA-Z0-9]+', '_', SPACE_NAME).lower()
622
  timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
623
- filename = f"{space_name_safe}_conversation_{timestamp}.md"
624
 
625
  # Save to temp file
626
  temp_path = Path(tempfile.gettempdir()) / filename
627
  temp_path.write_text(content, encoding='utf-8')
628
 
629
- # Return the file path for download
630
  return gr.File(visible=True, value=str(temp_path))
631
  except Exception as e:
632
  gr.Error(f"Failed to export conversation: {str(e)}")
@@ -659,10 +667,13 @@ def create_interface():
659
  # Get response
660
  response = generate_response(message, formatted_history, files_state)
661
 
662
- # Update chat history
 
 
 
663
  chat_history = chat_history + [
664
- {"role": "user", "content": message},
665
- {"role": "assistant", "content": response}
666
  ]
667
 
668
  # Update stored history for export
@@ -1092,12 +1103,4 @@ def create_interface():
1092
  # Create and launch the interface
1093
  if __name__ == "__main__":
1094
  demo = create_interface()
1095
- # Launch with appropriate settings for HuggingFace Spaces
1096
- demo.launch(
1097
- server_name="0.0.0.0",
1098
- server_port=7860,
1099
- share=False,
1100
- # Add allowed CORS origins if needed
1101
- # Since this is a Gradio app, CORS is handled by Gradio itself
1102
- # For custom API endpoints, you would need to add CORS middleware
1103
- )
 
12
 
13
 
14
  # Configuration
15
+ SPACE_NAME = 'AmigAI Demo (v1.2a)'
16
+ SPACE_DESCRIPTION = 'Practice conversational Spanish with AmigAI, an AI conversation partner from Peru who will role-play various scenarios while keeping vocabulary and grammar at a Spanish 101 level.'
17
 
18
  # Default configuration values
19
  DEFAULT_CONFIG = {
20
  'name': SPACE_NAME,
21
  'description': SPACE_DESCRIPTION,
22
+ 'system_prompt': 'Actuarás como compañero de conversación nativo hispanohablante de Perú para estudiantes universitarios en una clase de español 101. Tu nombre es AmigAI, y estás diseñada para hacer diferentes roles (puedes ser camarero, cocinero, policía, asesor universitario, político, etc.) Nunca jamás harás la tarea de los estudiantes, y esto debes dejarlo muy claro si el estudiante intenta hacer trampas: a) Los estudiantes interactuarán contigo y mantendrán conversaciones en español, y espero que respondas EXCLUSIVAMENTE EN ESPAÑOL (no proporciones traducciones al inglés) utilizando una gama limitada de vocabulario apto para español 101 en la universidad; b) Los verbos sólo deben conjugarse en presente. Evite el subjuntivo; c) Centre sus respuestas en temas como los deportes, la vida cotidiana, las rutinas, la comida y los números; d) Si los alumnos cometen errores, no se les llamará la atención directamente, sino que se les responderá de forma que se modele la ortografía/conjugación/etc. correcta para que puedan entender el error; e) Quiero que reconozcas cuando los alumnos son más avanzados y calibres tu respuesta en función de su nivel, pero tus respuestas NUNCA deben tener errores. f) Las respuestas nunca deben tener más de 30 palabras. Asegúrate de que las oraciones estén completas antes de interrumpir. Espera terminar cada respuesta en menos de 150 tokens.',
23
+ 'temperature': 0.7,
24
+ 'max_tokens': 150,
25
  'model': 'google/gemma-3-27b-it',
26
  'api_key_var': 'API_KEY',
27
+ 'theme': 'Base',
28
+ 'grounding_urls': [],
29
  'enable_dynamic_urls': True,
30
  'enable_file_upload': True,
31
+ 'examples': ['¡Saludos!', 'Buenas tardes', 'Buenos días'],
32
+ 'language': 'Spanish',
33
  'locked': False
34
  }
35
 
 
183
  return f"❌ Invalid URL format: {url}"
184
 
185
  headers = {
186
+ 'User-Agent': 'Mozilla/5.0 (compatible; HuggingFace-Space/1.0)'
 
 
 
 
 
 
187
  }
188
 
189
  response = requests.get(url, headers=headers, timeout=5)
 
229
 
230
  def extract_urls_from_text(text: str) -> List[str]:
231
  """Extract URLs from message text"""
232
+ url_pattern = r'https?://[^\s<>"{}\|\\^`\[\]]+(?:\.[^\s<>"{}\|\\^`\[\]])*'
233
  urls = re.findall(url_pattern, text)
234
  return [url.rstrip('.,;:)?!') for url in urls]
235
 
 
329
  return ""
330
 
331
 
332
+ def export_conversation_to_text(history: List[Dict[str, str]]) -> str:
333
+ """Export conversation history to text with timestamps"""
334
  if not history:
335
  return "No conversation to export."
336
 
337
+ text_content = f"""Conversation Export
338
+ ==================
339
  Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
340
  Space: {SPACE_NAME}
341
  Model: {MODEL}
342
 
343
+ ==================
344
 
345
  """
346
 
 
350
  role = message.get('role', 'unknown')
351
  content = message.get('content', '')
352
 
353
+ # Get timestamp from message or use current time as fallback
354
+ timestamp_str = message.get('timestamp', '')
355
+ if timestamp_str:
356
+ try:
357
+ # Parse ISO format timestamp and format it nicely
358
+ timestamp = datetime.fromisoformat(timestamp_str)
359
+ formatted_timestamp = timestamp.strftime('%Y-%m-%d %H:%M:%S')
360
+ except:
361
+ formatted_timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
362
+ else:
363
+ formatted_timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
364
+
365
+ # Get message length
366
+ msg_length = message.get('length', len(content))
367
+
368
  if role == 'user':
369
  message_count += 1
370
+ text_content += f"[{formatted_timestamp}] User Message {message_count} ({msg_length} chars):\n{content}\n\n"
371
  elif role == 'assistant':
372
+ text_content += f"[{formatted_timestamp}] Assistant Response {message_count} ({msg_length} chars):\n{content}\n\n------------------\n\n"
373
 
374
+ return text_content
 
 
375
 
376
 
377
  def generate_response(message: str, history: List[Dict[str, str]], files: Optional[List] = None) -> str:
 
602
  submit_btn = gr.Button("Send", variant="primary")
603
  clear_btn = gr.Button("Clear")
604
 
605
+ # Export functionality
606
  with gr.Row():
607
  # Use a regular Button for triggering export
608
  export_trigger_btn = gr.Button(
 
623
  return None
624
 
625
  try:
626
+ content = export_conversation_to_text(chat_history)
627
 
628
  # Create filename
629
  space_name_safe = re.sub(r'[^a-zA-Z0-9]+', '_', SPACE_NAME).lower()
630
  timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
631
+ filename = f"{space_name_safe}_conversation_{timestamp}.txt"
632
 
633
  # Save to temp file
634
  temp_path = Path(tempfile.gettempdir()) / filename
635
  temp_path.write_text(content, encoding='utf-8')
636
 
637
+ # Return the file component with visibility and value
638
  return gr.File(visible=True, value=str(temp_path))
639
  except Exception as e:
640
  gr.Error(f"Failed to export conversation: {str(e)}")
 
667
  # Get response
668
  response = generate_response(message, formatted_history, files_state)
669
 
670
+ # Get current timestamp
671
+ current_time = datetime.now()
672
+
673
+ # Update chat history with timestamps and message lengths
674
  chat_history = chat_history + [
675
+ {"role": "user", "content": message, "timestamp": current_time.isoformat(), "length": len(message)},
676
+ {"role": "assistant", "content": response, "timestamp": current_time.isoformat(), "length": len(response)}
677
  ]
678
 
679
  # Update stored history for export
 
1103
  # Create and launch the interface
1104
  if __name__ == "__main__":
1105
  demo = create_interface()
1106
+ demo.launch()