Spaces:
Paused
Paused
rick
commited on
update text translation stream and progress status
Browse files- app.py +82 -141
- ui_lang_support.json +8 -2
app.py
CHANGED
|
@@ -15,6 +15,7 @@ from typing import Optional
|
|
| 15 |
from typing import Tuple
|
| 16 |
from typing import Union
|
| 17 |
|
|
|
|
| 18 |
# Third-party libraries
|
| 19 |
import requests
|
| 20 |
import streamlit as st
|
|
@@ -327,7 +328,7 @@ def process_message(
|
|
| 327 |
message: str,
|
| 328 |
operation_prompt: str = "",
|
| 329 |
tts_enabled: bool = False
|
| 330 |
-
) ->
|
| 331 |
"""
|
| 332 |
Traite les messages des utilisateurs et génère une réponse.
|
| 333 |
|
|
@@ -336,55 +337,27 @@ def process_message(
|
|
| 336 |
operation_prompt (str, optional): Prompt supplémentaire pour l'opération. Par défaut "".
|
| 337 |
tts_enabled (bool, optional): Si la synthèse vocale est activée. Par défaut False.
|
| 338 |
|
| 339 |
-
Returns:
|
| 340 |
-
Tuple[Optional[bytes], Optional[float]]: Un tuple contenant l'audio TTS et sa durée,
|
| 341 |
-
ou (None, None) si TTS est désactivé ou en cas d'erreur.
|
| 342 |
"""
|
| 343 |
payload_content = f'{operation_prompt} :\n"""\n{message}\n"""'
|
| 344 |
-
|
| 345 |
st.session_state.messages.append({"role": "user", "content": payload_content})
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
|
|
|
|
|
|
|
|
|
|
| 352 |
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
full_response += (response.choices[0].delta.content or "")
|
| 362 |
-
message_placeholder.markdown(full_response + "▌")
|
| 363 |
-
# Utiliser regex pour supprimer les trois premiers et derniers guillemets doubles
|
| 364 |
-
full_response = re.sub(r'^"{3}|"{3}$', '', full_response.strip())
|
| 365 |
-
message_placeholder.markdown(full_response)
|
| 366 |
-
status.update(label="Réponse générée avec succès", state="complete")
|
| 367 |
-
except Exception as e:
|
| 368 |
-
st.error(f"Une erreur s'est produite lors de la génération de la réponse : {e}")
|
| 369 |
-
status.update(label="Erreur lors de la génération de la réponse", state="error")
|
| 370 |
-
return None, None
|
| 371 |
-
|
| 372 |
-
st.session_state.messages.append(
|
| 373 |
-
{"role": "assistant", "content": full_response}
|
| 374 |
-
)
|
| 375 |
-
|
| 376 |
-
if tts_enabled:
|
| 377 |
-
with st.status("Conversion texte-parole en cours...", expanded=True) as status:
|
| 378 |
-
status.update(label="Conversion texte-parole", state="running", expanded=True)
|
| 379 |
-
try:
|
| 380 |
-
tts_audio, tts_duration = text_to_speech(full_response)
|
| 381 |
-
status.update(label="Conversion texte-parole réussie", state="complete")
|
| 382 |
-
return tts_audio, tts_duration
|
| 383 |
-
except Exception as e:
|
| 384 |
-
st.error(f"Une erreur s'est produite lors de la conversion texte-parole : {e}")
|
| 385 |
-
status.update(label="Erreur lors de la conversion texte-parole", state="error")
|
| 386 |
-
return None, None
|
| 387 |
-
return None, None
|
| 388 |
|
| 389 |
class GlobalSystemPrompts:
|
| 390 |
"""Class to store global system prompts."""
|
|
@@ -451,6 +424,46 @@ LANGUAGES_EMOJI = {
|
|
| 451 |
"Vietnamese": "🇻🇳", "Welsh": "🏴"
|
| 452 |
}
|
| 453 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 454 |
def convert_language_name_to_iso6391(language_data: Union[str, Dict[str, str]]) -> str:
|
| 455 |
"""
|
| 456 |
Convertit un nom de langue en son code ISO 639-1.
|
|
@@ -556,6 +569,10 @@ def main():
|
|
| 556 |
|
| 557 |
# Interface utilisateur pour le chat textuel
|
| 558 |
if user_input := st.chat_input(get_translation("entrez_message")):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 559 |
# Traitement du message texte de l'utilisateur
|
| 560 |
if st.session_state.language_detected is None:
|
| 561 |
st.session_state.language_detected = detect_language(
|
|
@@ -563,106 +580,30 @@ def main():
|
|
| 563 |
)
|
| 564 |
|
| 565 |
audio_list = []
|
|
|
|
| 566 |
for cursor_selected_lang in st.session_state.selected_languages:
|
| 567 |
st.session_state.target_language = cursor_selected_lang["iso-639-1"]
|
| 568 |
-
|
| 569 |
# Initialisation du mode de traitement pour la langue cible actuelle
|
| 570 |
system_prompt, operation_prompt = init_process_mode()
|
| 571 |
-
|
| 572 |
-
|
| 573 |
-
|
| 574 |
-
|
| 575 |
-
|
| 576 |
-
|
| 577 |
-
tts_enabled=st.session_state.enable_tts_for_input_from_text_field
|
| 578 |
-
)
|
| 579 |
-
if tts_audio is not None:
|
| 580 |
-
audio_list.append((tts_audio, tts_duration))
|
| 581 |
-
except Exception as e:
|
| 582 |
-
st.error(f"Erreur lors du traitement du message : {str(e)}")
|
| 583 |
-
|
| 584 |
-
if audio_list:
|
| 585 |
-
try:
|
| 586 |
-
final_audio = concatenate_audio_files(audio_list)
|
| 587 |
-
with st.container(border=True):
|
| 588 |
-
st.audio(final_audio, format="audio/mp3", autoplay=st.session_state.autoplay_tts)
|
| 589 |
-
|
| 590 |
-
# Générer un nom de fichier unique
|
| 591 |
-
timestamp = time.strftime("%Y%m%d-%H%M%S")
|
| 592 |
-
langues = "_".join([lang["iso-639-1"] for lang in st.session_state.selected_languages])
|
| 593 |
-
nom_fichier = f"reponse_audio_{langues}_{timestamp}.mp3"
|
| 594 |
-
|
| 595 |
-
st.download_button(
|
| 596 |
-
label=f"📥 {get_translation('telecharger_audio')}",
|
| 597 |
-
data=final_audio,
|
| 598 |
-
file_name=nom_fichier,
|
| 599 |
-
mime="audio/mp3",
|
| 600 |
-
use_container_width=True,
|
| 601 |
-
type="primary",
|
| 602 |
-
key=f"download_button_{langues}_{timestamp}",
|
| 603 |
)
|
| 604 |
-
|
| 605 |
-
|
| 606 |
-
|
| 607 |
-
|
| 608 |
-
|
| 609 |
-
|
| 610 |
-
|
| 611 |
-
|
| 612 |
-
|
| 613 |
-
|
| 614 |
-
|
| 615 |
-
key="vocal_chat_input"
|
| 616 |
-
):
|
| 617 |
-
# Traitement de l'entrée audio de l'utilisateur
|
| 618 |
-
if len(audio) > 0:
|
| 619 |
-
try:
|
| 620 |
-
with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as temp_audio:
|
| 621 |
-
audio.export(temp_audio.name, format="wav")
|
| 622 |
-
transcription = transcribe_audio(temp_audio, language=st.session_state.language_detected)
|
| 623 |
-
os.unlink(temp_audio.name) # Suppression du fichier temporaire
|
| 624 |
-
if st.session_state.language_detected is None:
|
| 625 |
-
st.session_state.language_detected = detect_language(
|
| 626 |
-
input_text=transcription, temperature=0.01
|
| 627 |
-
)
|
| 628 |
-
st.write(get_translation("langue_detectee").format(st.session_state.language_detected))
|
| 629 |
-
|
| 630 |
-
#st.write(get_translation("transcription").format(transcription))
|
| 631 |
-
|
| 632 |
-
audio_list = []
|
| 633 |
-
for cursor_selected_lang in st.session_state.selected_languages:
|
| 634 |
-
st.session_state.target_language = cursor_selected_lang["iso-639-1"]
|
| 635 |
-
|
| 636 |
-
# Initialisation du mode de traitement pour la langue cible actuelle
|
| 637 |
-
system_prompt, operation_prompt = init_process_mode()
|
| 638 |
-
|
| 639 |
-
# Traitement du message utilisateur pour la langue cible actuelle
|
| 640 |
-
try:
|
| 641 |
-
tts_audio, tts_duration = process_message(
|
| 642 |
-
transcription,
|
| 643 |
-
operation_prompt=f"{operation_prompt}",
|
| 644 |
-
tts_enabled=st.session_state.enable_tts_for_input_from_audio_record
|
| 645 |
-
)
|
| 646 |
-
if tts_audio is not None:
|
| 647 |
-
audio_list.append((tts_audio, tts_duration))
|
| 648 |
-
except Exception as e:
|
| 649 |
-
st.error(f"Erreur lors du traitement du message audio : {str(e)}")
|
| 650 |
-
if audio_list:
|
| 651 |
-
try:
|
| 652 |
-
final_audio = concatenate_audio_files(audio_list)
|
| 653 |
-
with st.container(border=True):
|
| 654 |
-
st.audio(final_audio, format="audio/mp3", autoplay=st.session_state.autoplay_tts)
|
| 655 |
-
# Ajout d'un bouton de téléchargement pour l'audio final
|
| 656 |
-
st.download_button(
|
| 657 |
-
label=f"📥 {get_translation('telecharger_audio')}",
|
| 658 |
-
data=final_audio,
|
| 659 |
-
file_name="audio_concatene.mp3",
|
| 660 |
-
mime="audio/mp3"
|
| 661 |
-
)
|
| 662 |
-
except Exception as e:
|
| 663 |
-
st.error(f"Erreur lors de la concaténation des fichiers audio : {str(e)}")
|
| 664 |
-
except Exception as e:
|
| 665 |
-
st.error(f"Erreur lors du traitement de l'audio : {str(e)}")
|
| 666 |
|
| 667 |
# Configuration de la barre latérale
|
| 668 |
with st.sidebar:
|
|
|
|
| 15 |
from typing import Tuple
|
| 16 |
from typing import Union
|
| 17 |
|
| 18 |
+
|
| 19 |
# Third-party libraries
|
| 20 |
import requests
|
| 21 |
import streamlit as st
|
|
|
|
| 328 |
message: str,
|
| 329 |
operation_prompt: str = "",
|
| 330 |
tts_enabled: bool = False
|
| 331 |
+
) -> str:
|
| 332 |
"""
|
| 333 |
Traite les messages des utilisateurs et génère une réponse.
|
| 334 |
|
|
|
|
| 337 |
operation_prompt (str, optional): Prompt supplémentaire pour l'opération. Par défaut "".
|
| 338 |
tts_enabled (bool, optional): Si la synthèse vocale est activée. Par défaut False.
|
| 339 |
|
|
|
|
|
|
|
|
|
|
| 340 |
"""
|
| 341 |
payload_content = f'{operation_prompt} :\n"""\n{message}\n"""'
|
|
|
|
| 342 |
st.session_state.messages.append({"role": "user", "content": payload_content})
|
| 343 |
+
full_response = ""
|
| 344 |
+
try:
|
| 345 |
+
for response in client.chat.completions.create(
|
| 346 |
+
model="gpt-4o-mini",
|
| 347 |
+
messages=st.session_state.messages,
|
| 348 |
+
stream=True,
|
| 349 |
+
temperature=0.1):
|
| 350 |
+
full_response += (response.choices[0].delta.content or "")
|
| 351 |
+
yield full_response + "▌"
|
| 352 |
|
| 353 |
+
# Utiliser regex pour supprimer les trois premiers et derniers guillemets doubles
|
| 354 |
+
full_response = re.sub(r'^"{3}|"{3}$', '', full_response.strip())
|
| 355 |
+
st.session_state.messages.append({"role": "assistant", "content": full_response})
|
| 356 |
+
st.session_state.full_response = full_response
|
| 357 |
+
return full_response
|
| 358 |
+
except Exception as e:
|
| 359 |
+
st.error(f"Une erreur s'est produite lors de la génération de la réponse : {e}")
|
| 360 |
+
return ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 361 |
|
| 362 |
class GlobalSystemPrompts:
|
| 363 |
"""Class to store global system prompts."""
|
|
|
|
| 424 |
"Vietnamese": "🇻🇳", "Welsh": "🏴"
|
| 425 |
}
|
| 426 |
|
| 427 |
+
|
| 428 |
+
def convert_iso6391_to_language_name(language_code: str) -> str:
|
| 429 |
+
"""
|
| 430 |
+
Convertit un code ISO 639-1 en nom de langue.
|
| 431 |
+
|
| 432 |
+
Args:
|
| 433 |
+
language_code (str): Le code ISO 639-1 de la langue.
|
| 434 |
+
|
| 435 |
+
Returns:
|
| 436 |
+
str: Le nom de la langue correspondant au code ISO 639-1, ou 'English' si non trouvé.
|
| 437 |
+
"""
|
| 438 |
+
# Dictionnaire associant les codes ISO 639-1 aux noms de langues
|
| 439 |
+
iso_to_language: Dict[str, str] = {
|
| 440 |
+
"af": "Afrikaans", "ar": "Arabic", "hy": "Armenian", "az": "Azerbaijani",
|
| 441 |
+
"be": "Belarusian", "bs": "Bosnian", "bg": "Bulgarian", "ca": "Catalan",
|
| 442 |
+
"zh": "Chinese", "hr": "Croatian", "cs": "Czech", "da": "Danish",
|
| 443 |
+
"nl": "Dutch", "en": "English", "et": "Estonian", "fi": "Finnish",
|
| 444 |
+
"fr": "French", "gl": "Galician", "de": "German", "el": "Greek",
|
| 445 |
+
"he": "Hebrew", "hi": "Hindi", "hu": "Hungarian", "is": "Icelandic",
|
| 446 |
+
"id": "Indonesian", "it": "Italian", "ja": "Japanese", "kn": "Kannada",
|
| 447 |
+
"kk": "Kazakh", "ko": "Korean", "lv": "Latvian", "lt": "Lithuanian",
|
| 448 |
+
"mk": "Macedonian", "ms": "Malay", "mr": "Marathi", "mi": "Maori",
|
| 449 |
+
"ne": "Nepali", "no": "Norwegian", "fa": "Persian", "pl": "Polish",
|
| 450 |
+
"pt": "Portuguese", "ro": "Romanian", "ru": "Russian", "sr": "Serbian",
|
| 451 |
+
"sk": "Slovak", "sl": "Slovenian", "es": "Spanish", "sw": "Swahili",
|
| 452 |
+
"sv": "Swedish", "tl": "Tagalog", "ta": "Tamil", "th": "Thai",
|
| 453 |
+
"tr": "Turkish", "uk": "Ukrainian", "ur": "Urdu", "vi": "Vietnamese",
|
| 454 |
+
"cy": "Welsh"
|
| 455 |
+
}
|
| 456 |
+
|
| 457 |
+
try:
|
| 458 |
+
# Retourner le nom de la langue correspondant au code ISO 639-1
|
| 459 |
+
return iso_to_language[language_code]
|
| 460 |
+
except KeyError:
|
| 461 |
+
# Gérer spécifiquement l'exception KeyError
|
| 462 |
+
print(f"Code de langue non trouvé : {language_code}")
|
| 463 |
+
return "English"
|
| 464 |
+
|
| 465 |
+
|
| 466 |
+
|
| 467 |
def convert_language_name_to_iso6391(language_data: Union[str, Dict[str, str]]) -> str:
|
| 468 |
"""
|
| 469 |
Convertit un nom de langue en son code ISO 639-1.
|
|
|
|
| 569 |
|
| 570 |
# Interface utilisateur pour le chat textuel
|
| 571 |
if user_input := st.chat_input(get_translation("entrez_message")):
|
| 572 |
+
|
| 573 |
+
with st.chat_message("user", avatar="👤"):
|
| 574 |
+
st.markdown(user_input)
|
| 575 |
+
|
| 576 |
# Traitement du message texte de l'utilisateur
|
| 577 |
if st.session_state.language_detected is None:
|
| 578 |
st.session_state.language_detected = detect_language(
|
|
|
|
| 580 |
)
|
| 581 |
|
| 582 |
audio_list = []
|
| 583 |
+
|
| 584 |
for cursor_selected_lang in st.session_state.selected_languages:
|
| 585 |
st.session_state.target_language = cursor_selected_lang["iso-639-1"]
|
| 586 |
+
st.session_state.full_response = ""
|
| 587 |
# Initialisation du mode de traitement pour la langue cible actuelle
|
| 588 |
system_prompt, operation_prompt = init_process_mode()
|
| 589 |
+
target_language_name = cursor_selected_lang["language"]
|
| 590 |
+
with st.status(f'({target_language_name}) - {get_translation("traduction_en_cours")}', expanded=True) as response_status:
|
| 591 |
+
with st.chat_message("assistant", avatar="👻"):
|
| 592 |
+
message_placeholder = st.empty()
|
| 593 |
+
response_generator = process_message(
|
| 594 |
+
user_input, operation_prompt, st.session_state.enable_tts_for_input_from_text_field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 595 |
)
|
| 596 |
+
response_status.update(label=f'({target_language_name}) - {get_translation("traduction_en_cours")}', state="running", expanded=True)
|
| 597 |
+
for response_chunk in response_generator:
|
| 598 |
+
message_placeholder.markdown(response_chunk)
|
| 599 |
+
|
| 600 |
+
full_response = response_generator.close() # Obtenir la réponse complète à la fin
|
| 601 |
+
if st.session_state.full_response != "":
|
| 602 |
+
message_placeholder.markdown(st.session_state.full_response)
|
| 603 |
+
response_status.update(label=f'({target_language_name}) - {get_translation("traduction_terminee")}', state="complete", expanded=False)
|
| 604 |
+
else:
|
| 605 |
+
response_status.update(label=f'({target_language_name}) - {get_translation("erreur_traduction")}', state="error", expanded=False)
|
| 606 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 607 |
|
| 608 |
# Configuration de la barre latérale
|
| 609 |
with st.sidebar:
|
ui_lang_support.json
CHANGED
|
@@ -32,7 +32,13 @@
|
|
| 32 |
"chargement": "Chargement en cours...",
|
| 33 |
"aucun_message": "Aucun message pour le moment. Commencez la conversation !",
|
| 34 |
"telecharger_audio": "Télécharger l'audio",
|
| 35 |
-
"lecture_auto_tts": "Lecture audio automatique de la synthese vocale"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
},
|
| 37 |
"Afrikaans": {
|
| 38 |
"titre": "DEMORRHA APP - weergawe 1",
|
|
@@ -1994,4 +2000,4 @@
|
|
| 1994 |
"telecharger_audio": "Lawrlwytho'r sain",
|
| 1995 |
"lecture_auto_tts": "Darllen sain automatig o'r syntheseis lafar"
|
| 1996 |
}
|
| 1997 |
-
}
|
|
|
|
| 32 |
"chargement": "Chargement en cours...",
|
| 33 |
"aucun_message": "Aucun message pour le moment. Commencez la conversation !",
|
| 34 |
"telecharger_audio": "Télécharger l'audio",
|
| 35 |
+
"lecture_auto_tts": "Lecture audio automatique de la synthese vocale",
|
| 36 |
+
"traitement_en_cours": "Traitement en cours...",
|
| 37 |
+
"erreur_traitement": "Une erreur s'est produite lors du traitement de votre message : {}",
|
| 38 |
+
"traitement_termine": "Traitement terminé !",
|
| 39 |
+
"traduction_en_cours": "Traduction en cours...",
|
| 40 |
+
"erreur_traduction": "Une erreur s'est produite lors de la traduction de votre message : {}",
|
| 41 |
+
"traduction_terminee": "Traduction terminée !"
|
| 42 |
},
|
| 43 |
"Afrikaans": {
|
| 44 |
"titre": "DEMORRHA APP - weergawe 1",
|
|
|
|
| 2000 |
"telecharger_audio": "Lawrlwytho'r sain",
|
| 2001 |
"lecture_auto_tts": "Darllen sain automatig o'r syntheseis lafar"
|
| 2002 |
}
|
| 2003 |
+
}
|