rick commited on
Commit
39be0d8
·
unverified ·
1 Parent(s): f4e8ff5

align to PEP8

Browse files
Files changed (1) hide show
  1. app.py +217 -108
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # Bibliothèques standard
2
  import base64
3
  import io
4
  import json
@@ -9,51 +9,85 @@ import time
9
  from os import getenv
10
  from typing import Any, Optional, Union
11
 
12
- # Bibliothèques tierces
13
  import streamlit as st
14
  from audiorecorder import audiorecorder
15
  from openai import OpenAI
16
  from pydub import AudioSegment
17
 
18
- def charger_ui_langue(chemin_fichier: Optional[str] = "ui_lang_support.json") -> dict:
 
 
 
 
 
 
 
 
 
19
  try:
20
- with open(chemin_fichier, 'r', encoding='utf-8') as fichier:
21
- return json.load(fichier)
22
  except FileNotFoundError:
23
- print(_("erreur_fichier_non_trouve").format(chemin_fichier))
24
  return {}
25
  except json.JSONDecodeError:
26
- print(_("erreur_lecture_fichier").format(
27
- "Erreur de décodage JSON"
28
  ))
29
  return {}
30
  except Exception as e:
31
- print(_("erreur_lecture_fichier").format(str(e)))
32
  return {}
33
 
34
- # Dictionnaire pour stocker les traductions
35
- traductions = charger_ui_langue()
 
 
 
 
36
 
37
- # Fonction pour obtenir les traductions en fonction de la langue sélectionnée
38
- def _(key):
39
- return traductions[st.session_state.interface_language][key]
40
 
41
- # Configuration du client OpenAI avec la clé API
 
 
 
 
 
42
  client = OpenAI(api_key=getenv("OPENAI_API_KEY"))
43
 
44
- # Fonction pour lire et retourner le contenu de fichiers textes
45
  def read_file(file_name):
 
 
 
 
 
 
 
 
 
46
  try:
47
  with open(file_name, 'r', encoding='utf-8') as file:
48
  content = file.read()
49
  return content
50
  except FileNotFoundError:
51
- return _("erreur_fichier_non_trouve").format(file_name)
52
  except Exception as e:
53
- return _("erreur_lecture_fichier").format(str(e))
54
 
55
- # Fonction pour diviser un fichier audio en segments de 25 Mo ou moins
56
  def split_audio(audio_file, max_size_mb=25):
 
 
 
 
 
 
 
 
 
 
57
  audio = AudioSegment.from_wav(audio_file)
58
  duration_ms = len(audio)
59
  segment_duration_ms = int(
@@ -73,6 +107,16 @@ def split_audio(audio_file, max_size_mb=25):
73
 
74
  # Fonction modifiée pour transcrire l'audio en texte
75
  def transcribe_audio(audio_file, language=None):
 
 
 
 
 
 
 
 
 
 
76
  max_size_mb = 25
77
  file_size_mb = os.path.getsize(audio_file.name) / (1024 * 1024)
78
 
@@ -87,7 +131,7 @@ def transcribe_audio(audio_file, language=None):
87
  language=language
88
  )
89
  full_transcript += transcript.text + " "
90
- os.unlink(segment) # Supprimer le fichier temporaire
91
  return full_transcript.strip()
92
  else:
93
  with open(audio_file.name, "rb") as audio_file:
@@ -99,16 +143,24 @@ def transcribe_audio(audio_file, language=None):
99
  return transcript.text
100
 
101
  # Fonction pour détecter la langue d'un texte donné
102
- def language_detection(input_text, temperature=0.01):
 
 
 
 
 
 
 
 
 
 
103
  system_prompt = "".join([
104
- "Je souhaite que vous agissiez en tant que fonction linguistique.",
105
- "Je m'exprimerai dans n'importe quelle langue, et vous en détecterez ",
106
- "la langue.",
107
- "Vous fournirez le résultat de votre détection au format ISO-639-1.",
108
- "Votre réponse doit représenter l'argument `language` et contenir ",
109
- "seulement sa valeur de type chaîne de caractères.",
110
- "La langue de l'audio d'entrée. Fournir la langue d'entrée au format ",
111
- "ISO-639-1 améliorera la précision et la latence."
112
  ])
113
  response = client.chat.completions.create(
114
  model="gpt-4o-mini",
@@ -127,35 +179,61 @@ def language_detection(input_text, temperature=0.01):
127
  return response.choices[0].message.content
128
 
129
  def get_duration_pydub(audio_file):
 
 
 
 
 
 
 
 
 
130
  audio = AudioSegment.from_file(audio_file)
131
  return audio.duration_seconds
132
 
133
- # Fonction pour convertir du texte en parole
134
  def text_to_speech(text):
 
 
 
 
 
 
 
 
 
135
  response = client.audio.speech.create(
136
  model="tts-1",
137
  voice=st.session_state.tts_voice,
138
  input=text
139
  )
140
 
141
- # Sauvegarder l'audio dans un fichier temporaire
142
  with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_audio:
143
  response.stream_to_file(temp_audio.name)
144
 
145
- # Lire le contenu du fichier audio
146
  with open(temp_audio.name, "rb") as audio_file:
147
  audio_bytes = audio_file.read()
148
 
149
- # Lire la durée de l'audio en secondes
150
  audio_duration = get_duration_pydub(temp_audio.name)
151
 
152
  return audio_bytes, audio_duration
153
 
154
  def concatenate_audio_files(audio_list):
155
- # Créer un segment audio vide
 
 
 
 
 
 
 
 
 
156
  final_audio = AudioSegment.empty()
157
 
158
- # Charger les effets sonores
159
  begin_sound = AudioSegment.from_mp3(
160
  "sound-effects/voice-message-play-begin/voice-message-play-begin-1.mp3"
161
  )
@@ -163,23 +241,33 @@ def concatenate_audio_files(audio_list):
163
  "sound-effects/voice-message-play-ending/voice-message-play-ending-1.mp3"
164
  )
165
 
166
- # Silence de 5 secondes
167
- silence = AudioSegment.silent(duration=5000) # 5000 ms = 5 secondes
168
 
169
  for audio_bytes, _ in audio_list:
170
- # Convertir les bytes en un segment audio
171
  segment = AudioSegment.from_mp3(io.BytesIO(audio_bytes))
172
 
173
- # Ajouter le son de début, le segment TTS, le son de fin, et le silence
174
  final_audio += begin_sound + segment + end_sound + silence
175
 
176
- # Convertir le segment audio final en bytes
177
  buffer = io.BytesIO()
178
  final_audio.export(buffer, format="mp3")
179
  return buffer.getvalue()
180
 
181
- # Fonction pour traiter les messages de l'utilisateur et générer une réponse
182
  def process_message(message, operation_prompt="", tts_enabled=False):
 
 
 
 
 
 
 
 
 
 
 
183
  payload_content = f'{operation_prompt} :\n"""\n{message}\n"""'
184
 
185
  st.session_state.messages.append({"role": "user", "content": payload_content})
@@ -196,8 +284,7 @@ def process_message(message, operation_prompt="", tts_enabled=False):
196
  temperature=0.1):
197
  full_response += (response.choices[0].delta.content or "")
198
  message_placeholder.markdown(full_response + "▌")
199
- # Utiliser un regex pour retirer les trois premières et dernières
200
- # doubles quotes
201
  full_response = re.sub(r'^"{3}|"{3}$', '', full_response.strip())
202
  message_placeholder.markdown(full_response)
203
 
@@ -210,28 +297,41 @@ def process_message(message, operation_prompt="", tts_enabled=False):
210
  return tts_audio, tts_duration
211
  return None, None
212
 
213
- # Classe pour stocker les prompts système globaux
214
  class GlobalSystemPrompts:
215
- # Méthode pour récupérer le prompt système pour la fonctionnalité Linguascribe
 
 
216
  def linguascribe():
 
 
 
 
 
 
217
  system_prompt = f"{read_file('linguascribe.prompt')}"
218
  return system_prompt
219
 
220
 
221
- # Variables globales pour les prompts
222
  system_prompt = ""
223
- op_prompt = ""
224
 
 
 
 
 
225
 
226
- # Fonction pour configurer le mode de traduction
227
- def set_mode_translation(from_lang, dest_lang):
 
 
228
  global system_prompt
229
- global op_prompt
230
  system_prompt = GlobalSystemPrompts.linguascribe()
231
- op_prompt = f"Translate({from_lang} to {dest_lang})"
232
 
233
 
234
- # Liste des langues supportées par l'application
235
  SUPPORTED_LANGUAGES = [
236
  "Afrikaans", "Arabic", "Armenian", "Azerbaijani", "Belarusian", "Bosnian",
237
  "Bulgarian", "Catalan", "Chinese", "Croatian", "Czech", "Danish", "Dutch",
@@ -244,9 +344,17 @@ SUPPORTED_LANGUAGES = [
244
  "Turkish", "Ukrainian", "Urdu", "Vietnamese", "Welsh"
245
  ]
246
 
247
- # Fonction pour convertir le nom d'une langue en code ISO 639-1
248
  def convert_language_name_to_iso6391(language_data):
249
- # Dictionnaire de correspondance entre les noms de langues et les codes ISO 639-1
 
 
 
 
 
 
 
 
 
250
  language_to_iso = {
251
  "Afrikaans": "af", "Arabic": "ar", "Armenian": "hy", "Azerbaijani": "az",
252
  "Belarusian": "be", "Bosnian": "bs", "Bulgarian": "bg", "Catalan": "ca",
@@ -265,20 +373,21 @@ def convert_language_name_to_iso6391(language_data):
265
  "Welsh": "cy"
266
  }
267
 
268
- # Vérifier si language_data est un dictionnaire
269
  if isinstance(language_data, dict):
270
  language_name = language_data.get('language')
271
  else:
272
  language_name = language_data
273
 
274
- # Retourne le code ISO 639-1 correspondant au nom de la langue
275
- return language_to_iso.get(language_name, "en") # Par défaut, retourne 'en' si la langue n'est pas trouvée
276
 
277
- # Fonction principale de l'application
278
  def main():
 
279
  st.title("------- DEMORRHA -------")
280
 
281
- # Initialisation des variables d'état de la session
282
  if "language_detected" not in st.session_state:
283
  st.session_state["language_detected"] = None
284
 
@@ -300,31 +409,31 @@ def main():
300
  st.session_state["enable_tts_for_input_from_audio_record"] = True
301
 
302
  if "interface_language" not in st.session_state:
303
- st.session_state.interface_language = "French" # Langue par défaut
304
 
305
  def init_process_mode():
306
- # Configuration du mode de traduction si nécessaire
307
  if "translation" == st.session_state["process_mode"]:
308
- set_mode_translation(
309
  from_lang=st.session_state.language_detected,
310
  dest_lang=st.session_state.target_language
311
  )
312
 
313
  init_process_mode()
314
 
315
- # Initialisation de l'historique des messages avec le prompt système
316
  if "messages" not in st.session_state:
317
  st.session_state.messages = []
318
 
319
- # Vérifier si un message système existe déjà dans st.session_state.messages
320
  if not any(message["role"] == "system" for message in st.session_state.messages):
321
  st.session_state.messages.insert(0, {"role": "system", "content": system_prompt})
322
 
323
- # Interface utilisateur pour le chat textuel
324
- if user_input := st.chat_input(_("entrez_message")):
325
- # Traitement du message textuel de l'utilisateur
326
- if None == st.session_state.language_detected:
327
- st.session_state.language_detected = language_detection(
328
  input_text=user_input, temperature=0.01
329
  )
330
 
@@ -332,13 +441,13 @@ def main():
332
  for cursor_selected_lang in st.session_state.selected_languages:
333
  st.session_state.target_language = cursor_selected_lang["iso-639-1"]
334
 
335
- # Initialisation du mode de traitement pour la langue cible actuelle
336
  init_process_mode()
337
 
338
- # Traitement du message de l'utilisateur pour la langue cible actuelle
339
  tts_audio, tts_duration = process_message(
340
  user_input,
341
- operation_prompt=f"{op_prompt}",
342
  tts_enabled=st.session_state.enable_tts_for_input_from_text_field
343
  )
344
  if tts_audio is not None:
@@ -349,41 +458,41 @@ def main():
349
  st.audio(final_audio, format="audio/mp3", autoplay=True)
350
 
351
  with st.container(border=True):
352
- # Interface utilisateur pour l'enregistrement audio
353
- st.write(_("enregistrez_message"))
354
  audio = audiorecorder(
355
- start_prompt=_("cliquez_enregistrer"),
356
- stop_prompt=_("cliquez_arreter"),
357
- pause_prompt=_("cliquez_pause"),
358
  show_visualizer=True,
359
  key="vocal_chat_input"
360
  )
361
 
362
- # Traitement de l'entrée audio de l'utilisateur
363
  if len(audio) > 0:
364
  with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as temp_audio:
365
  audio.export(temp_audio.name, format="wav")
366
  transcription = transcribe_audio(temp_audio, language=st.session_state.language_detected)
367
- os.unlink(temp_audio.name) # Supprimer le fichier temporaire
368
- if None == st.session_state.language_detected:
369
- st.session_state.language_detected = language_detection(
370
  input_text=transcription, temperature=0.01
371
  )
372
- st.write(_("langue_detectee").format(st.session_state.language_detected))
373
 
374
- st.write(_("transcription").format(transcription))
375
 
376
  audio_list = []
377
  for cursor_selected_lang in st.session_state.selected_languages:
378
  st.session_state.target_language = cursor_selected_lang["iso-639-1"]
379
 
380
- # Initialisation du mode de traitement pour la langue cible actuelle
381
  init_process_mode()
382
 
383
- # Traitement du message de l'utilisateur pour la langue cible actuelle
384
  tts_audio, tts_duration = process_message(
385
  transcription,
386
- operation_prompt=f"{op_prompt}",
387
  tts_enabled=st.session_state.enable_tts_for_input_from_audio_record
388
  )
389
  if tts_audio is not None:
@@ -392,14 +501,14 @@ def main():
392
  final_audio = concatenate_audio_files(audio_list)
393
  st.audio(final_audio, format="audio/mp3", autoplay=True)
394
 
395
- # Configuration de la barre latérale
396
  with st.sidebar:
397
- st.header(_("sidebar_titre"))
398
- st.markdown("## " + _("a_propos"))
399
- st.info(_("info_app"))
400
 
401
- # Fonction de rappel pour le changement de(s) langue(s) de destination selectionnée(s)
402
  def on_languages_change():
 
403
  selected_language_names = st.session_state.language_selector
404
  st.session_state.selected_languages = [
405
  {"language": lang, "iso-639-1": convert_language_name_to_iso6391(lang)}
@@ -407,27 +516,27 @@ def main():
407
  ]
408
 
409
  with st.container(border=True):
410
- st.subheader(_("langue_interface"))
411
- # Sélection de la langue de l'interface
412
  st.selectbox(
413
- label=_("choix_langue_interface"),
414
- options=list(traductions.keys()),
415
  key="interface_language",
416
  index=(
417
- list(traductions.keys()).index("French")
418
  if "interface_language" not in st.session_state
419
- else list(traductions.keys()).index(st.session_state.interface_language)
420
  )
421
  )
422
 
423
  with st.container(border=True):
424
- # Conteneur pour la sélection de la langue
425
- st.subheader(_("selection_langue"))
426
 
427
- # Sélection multiple des langues de destination
428
  st.multiselect(
429
- label=_("langues_destination"),
430
- placeholder=_("placeholder_langues"),
431
  options=SUPPORTED_LANGUAGES,
432
  default=["English"],
433
  key="language_selector",
@@ -436,22 +545,22 @@ def main():
436
  )
437
 
438
  with st.container(border=True):
439
- st.subheader(_("parametres_tts"))
440
  st.selectbox(
441
- _("choix_voix_tts"),
442
  options=["alloy", "echo", "fable", "onyx", "nova", "shimmer"],
443
- index=3, # "onyx" est à l'index 3
444
  key="tts_voice"
445
  )
446
  st.checkbox(
447
- _("activer_tts_texte"),
448
  key="enable_tts_for_input_from_text_field"
449
  )
450
  st.checkbox(
451
- _("activer_tts_audio"),
452
  key="enable_tts_for_input_from_audio_record"
453
  )
454
 
455
- # Point d'entrée de l'application
456
  if __name__ == "__main__":
457
  main()
 
1
+ # Standard libraries
2
  import base64
3
  import io
4
  import json
 
9
  from os import getenv
10
  from typing import Any, Optional, Union
11
 
12
+ # Third-party libraries
13
  import streamlit as st
14
  from audiorecorder import audiorecorder
15
  from openai import OpenAI
16
  from pydub import AudioSegment
17
 
18
+ def load_ui_language(file_path: Optional[str] = "ui_lang_support.json") -> dict:
19
+ """
20
+ Load UI language translations from a JSON file.
21
+
22
+ Args:
23
+ file_path (Optional[str]): Path to the JSON file containing translations.
24
+
25
+ Returns:
26
+ dict: A dictionary containing UI language translations.
27
+ """
28
  try:
29
+ with open(file_path, 'r', encoding='utf-8') as file:
30
+ return json.load(file)
31
  except FileNotFoundError:
32
+ print(get_translation("erreur_fichier_non_trouve").format(file_path))
33
  return {}
34
  except json.JSONDecodeError:
35
+ print(get_translation("erreur_lecture_fichier").format(
36
+ "JSON decoding error"
37
  ))
38
  return {}
39
  except Exception as e:
40
+ print(get_translation("erreur_lecture_fichier").format(str(e)))
41
  return {}
42
 
43
+ # Dictionary to store translations
44
+ translations = load_ui_language()
45
+
46
+ def get_translation(key):
47
+ """
48
+ Get translation for a given key based on the selected interface language.
49
 
50
+ Args:
51
+ key (str): The translation key.
 
52
 
53
+ Returns:
54
+ str: The translated text.
55
+ """
56
+ return translations[st.session_state.interface_language][key]
57
+
58
+ # OpenAI client configuration with API key
59
  client = OpenAI(api_key=getenv("OPENAI_API_KEY"))
60
 
 
61
  def read_file(file_name):
62
+ """
63
+ Read and return the content of text files.
64
+
65
+ Args:
66
+ file_name (str): The name of the file to read.
67
+
68
+ Returns:
69
+ str: The content of the file or an error message.
70
+ """
71
  try:
72
  with open(file_name, 'r', encoding='utf-8') as file:
73
  content = file.read()
74
  return content
75
  except FileNotFoundError:
76
+ return get_translation("erreur_fichier_non_trouve").format(file_name)
77
  except Exception as e:
78
+ return get_translation("erreur_lecture_fichier").format(str(e))
79
 
 
80
  def split_audio(audio_file, max_size_mb=25):
81
+ """
82
+ Split an audio file into segments of 25 MB or less.
83
+
84
+ Args:
85
+ audio_file (str): Path to the audio file.
86
+ max_size_mb (int): Maximum size of each segment in MB.
87
+
88
+ Returns:
89
+ list: List of paths to the split audio segments.
90
+ """
91
  audio = AudioSegment.from_wav(audio_file)
92
  duration_ms = len(audio)
93
  segment_duration_ms = int(
 
107
 
108
  # Fonction modifiée pour transcrire l'audio en texte
109
  def transcribe_audio(audio_file, language=None):
110
+ """
111
+ Transcribe audio file to text.
112
+
113
+ Args:
114
+ audio_file (file): The audio file to transcribe.
115
+ language (str, optional): The language of the audio. Defaults to None.
116
+
117
+ Returns:
118
+ str: The transcribed text.
119
+ """
120
  max_size_mb = 25
121
  file_size_mb = os.path.getsize(audio_file.name) / (1024 * 1024)
122
 
 
131
  language=language
132
  )
133
  full_transcript += transcript.text + " "
134
+ os.unlink(segment) # Delete temporary file
135
  return full_transcript.strip()
136
  else:
137
  with open(audio_file.name, "rb") as audio_file:
 
143
  return transcript.text
144
 
145
  # Fonction pour détecter la langue d'un texte donné
146
+ def detect_language(input_text, temperature=0.01):
147
+ """
148
+ Detect the language of a given text.
149
+
150
+ Args:
151
+ input_text (str): The text to detect the language from.
152
+ temperature (float, optional): The temperature for the language model. Defaults to 0.01.
153
+
154
+ Returns:
155
+ str: The detected language in ISO-639-1 format.
156
+ """
157
  system_prompt = "".join([
158
+ "Act as a language detection function. ",
159
+ "I will provide text in any language, and you will detect its language. ",
160
+ "Provide the result of your detection in ISO-639-1 format. ",
161
+ "Your response should represent the `language` argument and contain ",
162
+ "only its string value. ",
163
+ "Providing the input language in ISO-639-1 format will improve accuracy and latency."
 
 
164
  ])
165
  response = client.chat.completions.create(
166
  model="gpt-4o-mini",
 
179
  return response.choices[0].message.content
180
 
181
  def get_duration_pydub(audio_file):
182
+ """
183
+ Get the duration of an audio file using pydub.
184
+
185
+ Args:
186
+ audio_file (str): Path to the audio file.
187
+
188
+ Returns:
189
+ float: Duration of the audio file in seconds.
190
+ """
191
  audio = AudioSegment.from_file(audio_file)
192
  return audio.duration_seconds
193
 
 
194
  def text_to_speech(text):
195
+ """
196
+ Convert text to speech using the OpenAI API.
197
+
198
+ Args:
199
+ text (str): The text to convert to speech.
200
+
201
+ Returns:
202
+ tuple: A tuple containing the audio bytes and the duration of the audio in seconds.
203
+ """
204
  response = client.audio.speech.create(
205
  model="tts-1",
206
  voice=st.session_state.tts_voice,
207
  input=text
208
  )
209
 
210
+ # Save the audio to a temporary file
211
  with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_audio:
212
  response.stream_to_file(temp_audio.name)
213
 
214
+ # Read the content of the audio file
215
  with open(temp_audio.name, "rb") as audio_file:
216
  audio_bytes = audio_file.read()
217
 
218
+ # Get the duration of the audio in seconds
219
  audio_duration = get_duration_pydub(temp_audio.name)
220
 
221
  return audio_bytes, audio_duration
222
 
223
  def concatenate_audio_files(audio_list):
224
+ """
225
+ Concatenate multiple audio files with sound effects.
226
+
227
+ Args:
228
+ audio_list (list): A list of tuples, each containing audio bytes and duration.
229
+
230
+ Returns:
231
+ bytes: The concatenated audio as bytes.
232
+ """
233
+ # Create an empty audio segment
234
  final_audio = AudioSegment.empty()
235
 
236
+ # Load sound effects
237
  begin_sound = AudioSegment.from_mp3(
238
  "sound-effects/voice-message-play-begin/voice-message-play-begin-1.mp3"
239
  )
 
241
  "sound-effects/voice-message-play-ending/voice-message-play-ending-1.mp3"
242
  )
243
 
244
+ # 5 seconds of silence
245
+ silence = AudioSegment.silent(duration=5000) # 5000 ms = 5 seconds
246
 
247
  for audio_bytes, _ in audio_list:
248
+ # Convert bytes to an audio segment
249
  segment = AudioSegment.from_mp3(io.BytesIO(audio_bytes))
250
 
251
+ # Add the start sound, TTS segment, end sound, and silence
252
  final_audio += begin_sound + segment + end_sound + silence
253
 
254
+ # Convert the final audio segment to bytes
255
  buffer = io.BytesIO()
256
  final_audio.export(buffer, format="mp3")
257
  return buffer.getvalue()
258
 
 
259
  def process_message(message, operation_prompt="", tts_enabled=False):
260
+ """
261
+ Process user messages and generate a response.
262
+
263
+ Args:
264
+ message (str): The user's input message.
265
+ operation_prompt (str, optional): Additional prompt for operation. Defaults to "".
266
+ tts_enabled (bool, optional): Whether text-to-speech is enabled. Defaults to False.
267
+
268
+ Returns:
269
+ tuple: A tuple containing the TTS audio and its duration, or (None, None) if TTS is disabled.
270
+ """
271
  payload_content = f'{operation_prompt} :\n"""\n{message}\n"""'
272
 
273
  st.session_state.messages.append({"role": "user", "content": payload_content})
 
284
  temperature=0.1):
285
  full_response += (response.choices[0].delta.content or "")
286
  message_placeholder.markdown(full_response + "▌")
287
+ # Use regex to remove the first and last three double quotes
 
288
  full_response = re.sub(r'^"{3}|"{3}$', '', full_response.strip())
289
  message_placeholder.markdown(full_response)
290
 
 
297
  return tts_audio, tts_duration
298
  return None, None
299
 
 
300
  class GlobalSystemPrompts:
301
+ """Class to store global system prompts."""
302
+
303
+ @staticmethod
304
  def linguascribe():
305
+ """
306
+ Retrieve the system prompt for the Linguascribe feature.
307
+
308
+ Returns:
309
+ str: The system prompt for Linguascribe.
310
+ """
311
  system_prompt = f"{read_file('linguascribe.prompt')}"
312
  return system_prompt
313
 
314
 
315
+ # Global variables for prompts
316
  system_prompt = ""
317
+ operation_prompt = ""
318
 
319
+ # Function to configure the translation mode
320
+ def set_translation_mode(from_lang, dest_lang):
321
+ """
322
+ Set the global prompts for translation mode.
323
 
324
+ Args:
325
+ from_lang (str): The source language.
326
+ dest_lang (str): The destination language.
327
+ """
328
  global system_prompt
329
+ global operation_prompt
330
  system_prompt = GlobalSystemPrompts.linguascribe()
331
+ operation_prompt = f"Translate({from_lang} to {dest_lang})"
332
 
333
 
334
+ # List of languages supported by the application
335
  SUPPORTED_LANGUAGES = [
336
  "Afrikaans", "Arabic", "Armenian", "Azerbaijani", "Belarusian", "Bosnian",
337
  "Bulgarian", "Catalan", "Chinese", "Croatian", "Czech", "Danish", "Dutch",
 
344
  "Turkish", "Ukrainian", "Urdu", "Vietnamese", "Welsh"
345
  ]
346
 
 
347
  def convert_language_name_to_iso6391(language_data):
348
+ """
349
+ Convert a language name to its ISO 639-1 code.
350
+
351
+ Args:
352
+ language_data (Union[str, dict]): The language name or a dictionary containing the language name.
353
+
354
+ Returns:
355
+ str: The ISO 639-1 code for the given language, or 'en' if not found.
356
+ """
357
+ # Dictionary mapping language names to ISO 639-1 codes
358
  language_to_iso = {
359
  "Afrikaans": "af", "Arabic": "ar", "Armenian": "hy", "Azerbaijani": "az",
360
  "Belarusian": "be", "Bosnian": "bs", "Bulgarian": "bg", "Catalan": "ca",
 
373
  "Welsh": "cy"
374
  }
375
 
376
+ # Check if language_data is a dictionary
377
  if isinstance(language_data, dict):
378
  language_name = language_data.get('language')
379
  else:
380
  language_name = language_data
381
 
382
+ # Return the ISO 639-1 code corresponding to the language name
383
+ return language_to_iso.get(language_name, "en") # Default to 'en' if the language is not found
384
 
385
+ # Main function of the application
386
  def main():
387
+ """Main function that sets up and runs the Streamlit application."""
388
  st.title("------- DEMORRHA -------")
389
 
390
+ # Initialize session state variables
391
  if "language_detected" not in st.session_state:
392
  st.session_state["language_detected"] = None
393
 
 
409
  st.session_state["enable_tts_for_input_from_audio_record"] = True
410
 
411
  if "interface_language" not in st.session_state:
412
+ st.session_state.interface_language = "French" # Default language
413
 
414
  def init_process_mode():
415
+ """Initialize the process mode for translation if necessary."""
416
  if "translation" == st.session_state["process_mode"]:
417
+ set_translation_mode(
418
  from_lang=st.session_state.language_detected,
419
  dest_lang=st.session_state.target_language
420
  )
421
 
422
  init_process_mode()
423
 
424
+ # Initialize message history with system prompt
425
  if "messages" not in st.session_state:
426
  st.session_state.messages = []
427
 
428
+ # Check if a system message already exists in st.session_state.messages
429
  if not any(message["role"] == "system" for message in st.session_state.messages):
430
  st.session_state.messages.insert(0, {"role": "system", "content": system_prompt})
431
 
432
+ # User interface for text chat
433
+ if user_input := st.chat_input(get_translation("entrez_message")):
434
+ # Process user's text message
435
+ if st.session_state.language_detected is None:
436
+ st.session_state.language_detected = detect_language(
437
  input_text=user_input, temperature=0.01
438
  )
439
 
 
441
  for cursor_selected_lang in st.session_state.selected_languages:
442
  st.session_state.target_language = cursor_selected_lang["iso-639-1"]
443
 
444
+ # Initialize processing mode for current target language
445
  init_process_mode()
446
 
447
+ # Process user message for current target language
448
  tts_audio, tts_duration = process_message(
449
  user_input,
450
+ operation_prompt=f"{operation_prompt}",
451
  tts_enabled=st.session_state.enable_tts_for_input_from_text_field
452
  )
453
  if tts_audio is not None:
 
458
  st.audio(final_audio, format="audio/mp3", autoplay=True)
459
 
460
  with st.container(border=True):
461
+ # User interface for audio recording
462
+ st.write(get_translation("enregistrez_message"))
463
  audio = audiorecorder(
464
+ start_prompt=get_translation("cliquez_enregistrer"),
465
+ stop_prompt=get_translation("cliquez_arreter"),
466
+ pause_prompt=get_translation("cliquez_pause"),
467
  show_visualizer=True,
468
  key="vocal_chat_input"
469
  )
470
 
471
+ # Process user's audio input
472
  if len(audio) > 0:
473
  with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as temp_audio:
474
  audio.export(temp_audio.name, format="wav")
475
  transcription = transcribe_audio(temp_audio, language=st.session_state.language_detected)
476
+ os.unlink(temp_audio.name) # Delete temporary file
477
+ if st.session_state.language_detected is None:
478
+ st.session_state.language_detected = detect_language(
479
  input_text=transcription, temperature=0.01
480
  )
481
+ st.write(get_translation("langue_detectee").format(st.session_state.language_detected))
482
 
483
+ st.write(get_translation("transcription").format(transcription))
484
 
485
  audio_list = []
486
  for cursor_selected_lang in st.session_state.selected_languages:
487
  st.session_state.target_language = cursor_selected_lang["iso-639-1"]
488
 
489
+ # Initialize processing mode for current target language
490
  init_process_mode()
491
 
492
+ # Process user message for current target language
493
  tts_audio, tts_duration = process_message(
494
  transcription,
495
+ operation_prompt=f"{operation_prompt}",
496
  tts_enabled=st.session_state.enable_tts_for_input_from_audio_record
497
  )
498
  if tts_audio is not None:
 
501
  final_audio = concatenate_audio_files(audio_list)
502
  st.audio(final_audio, format="audio/mp3", autoplay=True)
503
 
504
+ # Sidebar configuration
505
  with st.sidebar:
506
+ st.header(get_translation("sidebar_titre"))
507
+ st.markdown("## " + get_translation("a_propos"))
508
+ st.info(get_translation("info_app"))
509
 
 
510
  def on_languages_change():
511
+ """Callback function for destination language(s) change."""
512
  selected_language_names = st.session_state.language_selector
513
  st.session_state.selected_languages = [
514
  {"language": lang, "iso-639-1": convert_language_name_to_iso6391(lang)}
 
516
  ]
517
 
518
  with st.container(border=True):
519
+ st.subheader(get_translation("langue_interface"))
520
+ # Interface language selection
521
  st.selectbox(
522
+ label=get_translation("choix_langue_interface"),
523
+ options=list(translations.keys()),
524
  key="interface_language",
525
  index=(
526
+ list(translations.keys()).index("French")
527
  if "interface_language" not in st.session_state
528
+ else list(translations.keys()).index(st.session_state.interface_language)
529
  )
530
  )
531
 
532
  with st.container(border=True):
533
+ # Container for language selection
534
+ st.subheader(get_translation("selection_langue"))
535
 
536
+ # Multiple selection of destination languages
537
  st.multiselect(
538
+ label=get_translation("langues_destination"),
539
+ placeholder=get_translation("placeholder_langues"),
540
  options=SUPPORTED_LANGUAGES,
541
  default=["English"],
542
  key="language_selector",
 
545
  )
546
 
547
  with st.container(border=True):
548
+ st.subheader(get_translation("parametres_tts"))
549
  st.selectbox(
550
+ get_translation("choix_voix_tts"),
551
  options=["alloy", "echo", "fable", "onyx", "nova", "shimmer"],
552
+ index=3, # "onyx" is at index 3
553
  key="tts_voice"
554
  )
555
  st.checkbox(
556
+ get_translation("activer_tts_texte"),
557
  key="enable_tts_for_input_from_text_field"
558
  )
559
  st.checkbox(
560
+ get_translation("activer_tts_audio"),
561
  key="enable_tts_for_input_from_audio_record"
562
  )
563
 
564
+ # Application entry point
565
  if __name__ == "__main__":
566
  main()