rick commited on
Commit
964514c
·
unverified ·
1 Parent(s): 61bfe55

... not done...

Browse files
Files changed (4) hide show
  1. core/__init__.py +0 -0
  2. core/files.py +53 -0
  3. core/text_to_speech.py +116 -0
  4. pages/main.py +16 -103
core/__init__.py ADDED
File without changes
core/files.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ from typing import Any
3
+ from typing import Dict
4
+ from typing import IO
5
+ from typing import List
6
+ from typing import Optional
7
+ from typing import Tuple
8
+ from typing import Union
9
+
10
+ def load_ui_language(file_path: Optional[str] = "ui_lang_support.json") -> Dict[str, Any]:
11
+ """
12
+ Charge les traductions de l'interface utilisateur à partir d'un fichier JSON.
13
+
14
+ Args:
15
+ file_path (Optional[str]): Chemin vers le fichier JSON contenant les traductions.
16
+
17
+ Returns:
18
+ Dict[str, Any]: Un dictionnaire contenant les traductions de l'interface utilisateur.
19
+ """
20
+ try:
21
+ with open(file_path, 'r', encoding='utf-8') as file:
22
+ return json.load(file)
23
+ except FileNotFoundError:
24
+ print(f"File Not Found: {file_path}")
25
+ return None
26
+ except json.JSONDecodeError:
27
+ print(f"JSON decoding error : {file_path}")
28
+ return None
29
+ except IOError as e:
30
+ print(f"I/O Error : {e}")
31
+ return None
32
+
33
+
34
+ # usage e.g.: read a plaintext prompt file
35
+ def read_file(file_name: str) -> str:
36
+ """
37
+ Lit et retourne le contenu des fichiers texte.
38
+
39
+ Args:
40
+ file_name (str): Le nom du fichier à lire.
41
+
42
+ Returns:
43
+ str: Le contenu du fichier ou un message d'erreur.
44
+ """
45
+ try:
46
+ with open(file_name, 'r', encoding='utf-8') as file:
47
+ content = file.read()
48
+ return content
49
+ except FileNotFoundError:
50
+ return f"File Not Found : {file_name}"
51
+ except IOError as e:
52
+ return f"I/O Error : {str(e)}"
53
+
core/text_to_speech.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #coding: utf-8
2
+
3
+ import os
4
+ import tempfile
5
+
6
+
7
+ #from typing import Any
8
+ #from typing import Dict
9
+ #from typing import IO
10
+ #from typing import List
11
+ from typing import Optional
12
+ from typing import Tuple
13
+ #from typing import Union
14
+ from base64 import b64encode
15
+
16
+ from openai import OpenAI
17
+ from pydub import AudioSegment
18
+
19
+
20
+ class openai_tts(object):
21
+ def __init__(self,
22
+ tts_voice: Optional[str] = "nova",
23
+ tts_model: Optional[str] = "tts-1",
24
+ response_format: Optional[str] = "mp3",
25
+ speed: Optional[float] = 1.0
26
+ ):
27
+ self.client = None
28
+ self.init_supported_formats__()
29
+ self.init_api_client()
30
+
31
+ if response_format:
32
+ self.set_response_format(response_format)
33
+ if tts_voice:
34
+ self.set_tts_voice(tts_voice)
35
+ if tts_model:
36
+ self.set_tts_model(tts_model)
37
+ if speed:
38
+ self.set_tts_speed(speed)
39
+
40
+ def set_tts_speed(self, speed):
41
+ if not (0.25 <= speed <= 4.0):
42
+ raise ValueError(f"La vitesse doit être comprise entre 0.25 et 4.0. Valeur fournie : {speed}")
43
+ else:
44
+ self.speed = speed
45
+ return self
46
+
47
+ def set_tts_voice(self, voice):
48
+ voix_valides = ["alloy", "echo", "fable", "onyx", "nova", "shimmer"]
49
+ if voice not in voix_valides:
50
+ raise ValueError(f"Invalid TTS voice: {voice}. Valid voices are: {', '.join(voix_valides)}.")
51
+ else:
52
+ self.tts_voice = voice
53
+ return self
54
+
55
+ def set_tts_model(self, model):
56
+ if model not in ["tts-1", "tts-1-hd"]:
57
+ raise ValueError(f"Invalid TTS model: {model}. Valid models are 'tts-1' and 'tts-1-hd'.")
58
+ else:
59
+ self.tts_model = model
60
+ return self
61
+
62
+ def init_supported_formats__(self):
63
+ self.supported_formats = [ 'mp3', 'opus', 'aac', 'flac', 'wav', 'pcm' ]
64
+ return self
65
+
66
+ def set_response_format(self, format: str):
67
+ if format not in self.supported_formats:
68
+ raise ValueError(f"Unsupported format: {format}. Supported formats are: {', '.join(self.supported_formats)}")
69
+ else:
70
+ self.response_format = format
71
+ return self
72
+
73
+ def init_api_client(self):
74
+ if not (self.client):
75
+ # OpenAI client configuration with API key
76
+ self.client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
77
+ return self
78
+
79
+ def text_to_speech(self,
80
+ input_text: str) -> Tuple[Optional[bytes], float]:
81
+ """
82
+ Convertit du texte en parole en utilisant l'API OpenAI.
83
+
84
+ Args:
85
+ input_text (str): Le texte à convertir en parole.
86
+
87
+ Returns:
88
+ Tuple[Optional[bytes], float]: Un tuple contenant les octets audio et la durée de l'audio en secondes.
89
+ """
90
+ response = self.client.audio.speech.create(
91
+ model=self.tts_model,
92
+ voice=self.tts_voice ,#st.session_state.tts_voice,
93
+ input=input_text,
94
+ response_format=self.response_format,
95
+ speed=self.speed
96
+ )
97
+ data_output = response.read()
98
+
99
+ tmp_file = tempfile.TemporaryFile()
100
+ tmp_file.write(data_output)
101
+ tmp_file.seek(0)
102
+ audio = AudioSegment.from_file(tmp_file, format=self.response_format)
103
+ duration = len(audio) / 1000
104
+ tmp_file.close()
105
+
106
+ return {
107
+ "audio_duration": duration,
108
+ "data_bytes": b64encode(data_output).decode()
109
+ }
110
+
111
+ """
112
+ if __name__ == "__main__":
113
+
114
+ openai_tts().text_to_speech("Hello, I am an AI assistant. How can I help you?")
115
+
116
+ """
pages/main.py CHANGED
@@ -26,6 +26,9 @@ import warnings
26
  warnings.filterwarnings("ignore", category=DeprecationWarning)
27
 
28
  from var_app import __version__
 
 
 
29
 
30
  # Au début du fichier, après les imports
31
  st.set_page_config(
@@ -35,30 +38,6 @@ st.set_page_config(
35
  initial_sidebar_state="collapsed"
36
  )
37
 
38
- def load_ui_language(file_path: Optional[str] = "ui_lang_support.json") -> Dict[str, Any]:
39
- """
40
- Charge les traductions de l'interface utilisateur à partir d'un fichier JSON.
41
-
42
- Args:
43
- file_path (Optional[str]): Chemin vers le fichier JSON contenant les traductions.
44
-
45
- Returns:
46
- Dict[str, Any]: Un dictionnaire contenant les traductions de l'interface utilisateur.
47
- """
48
- try:
49
- with open(file_path, 'r', encoding='utf-8') as file:
50
- return json.load(file)
51
- except FileNotFoundError:
52
- print(f"{get_translation('erreur_fichier_non_trouve')} {file_path}")
53
- return {}
54
- except json.JSONDecodeError:
55
- print(f"{get_translation('erreur_lecture_fichier')} JSON decoding error")
56
- return {}
57
- except IOError as e:
58
- print(f"{get_translation('erreur_lecture_fichier')} {e}")
59
- return {}
60
-
61
-
62
 
63
  def get_translation(key: str) -> str:
64
  """
@@ -70,27 +49,22 @@ def get_translation(key: str) -> str:
70
  # Dictionary to store translations
71
  translations = load_ui_language()
72
 
73
- # OpenAI client configuration with API key
74
- client = OpenAI(api_key=getenv("OPENAI_API_KEY"))
75
 
76
- def read_file(file_name: str) -> str:
77
- """
78
- Lit et retourne le contenu des fichiers texte.
 
 
 
 
 
 
 
 
 
 
79
 
80
- Args:
81
- file_name (str): Le nom du fichier à lire.
82
 
83
- Returns:
84
- str: Le contenu du fichier ou un message d'erreur.
85
- """
86
- try:
87
- with open(file_name, 'r', encoding='utf-8') as file:
88
- content = file.read()
89
- return content
90
- except FileNotFoundError:
91
- return f"{get_translation('erreur_fichier_non_trouve')} {file_name}"
92
- except IOError as e:
93
- return f"{get_translation('erreur_lecture_fichier')} {str(e)}"
94
 
95
 
96
 
@@ -244,61 +218,7 @@ def detect_language(input_text: str, temperature: float = 0.01) -> str:
244
  raise ValueError(f"Erreur inattendue lors de la détection de la langue : {str(e)}")
245
 
246
 
247
- def text_to_speech(text: str) -> Tuple[Optional[bytes], float]:
248
- """
249
- Convertit du texte en parole en utilisant l'API OpenAI.
250
 
251
- Args:
252
- text (str): Le texte à convertir en parole.
253
-
254
- Returns:
255
- Tuple[Optional[bytes], float]: Un tuple contenant les octets audio et la durée de l'audio en secondes.
256
- """
257
- try:
258
- response = client.audio.speech.create(
259
- model="tts-1",
260
- voice=st.session_state.tts_voice,
261
- input=text
262
- )
263
-
264
- with tempfile.TemporaryDirectory() as temp_dir:
265
- temp_audio_path = os.path.join(temp_dir, "temp_audio.mp3")
266
- response.stream_to_file(temp_audio_path)
267
-
268
- # Lecture du contenu du fichier audio
269
- with open(temp_audio_path, "rb") as audio_file:
270
- audio_bytes = audio_file.read()
271
-
272
- # Obtention de la durée de l'audio
273
- audio_duration = get_duration_pydub(temp_audio_path)
274
-
275
- return audio_bytes, audio_duration
276
-
277
- except Exception as e:
278
- st.error(f"Erreur lors de la conversion texte-parole : {str(e)}")
279
- return None, 0.0
280
- finally:
281
- if temp_audio_path and os.path.exists(temp_audio_path):
282
- os.remove(temp_audio_path)
283
- if temp_dir and os.path.exists(temp_dir):
284
- os.rmdir(temp_dir)
285
-
286
- def get_duration_pydub(audio_file: str) -> float:
287
- """
288
- Obtient la durée d'un fichier audio en utilisant pydub.
289
-
290
- Args:
291
- audio_file (str): Chemin vers le fichier audio.
292
-
293
- Returns:
294
- float: Durée du fichier audio en secondes.
295
- """
296
- try:
297
- audio = AudioSegment.from_file(audio_file)
298
- return audio.duration_seconds
299
- except Exception as e:
300
- st.error(f"Erreur lors de la lecture du fichier audio : {str(e)}")
301
- return 0.0
302
 
303
  def concatenate_audio_files(audio_list: List[Tuple[bytes, float]]) -> Optional[bytes]:
304
  """
@@ -382,13 +302,6 @@ def process_message(
382
  st.error(f"Une erreur s'est produite lors de la génération de la réponse : {e}")
383
  return ""
384
 
385
- def process_tts_message(text_response: str) -> Tuple[Optional[bytes], Optional[float]]:
386
- try:
387
- tts_audio_, tts_duration_ = text_to_speech(text_response)
388
- return tts_audio_, tts_duration_
389
- except Exception as e:
390
- st.error(f"Une erreur s'est produite lors de la conversion texte-parole : {e}")
391
- return None, None
392
 
393
  class GlobalSystemPrompts:
394
  """Class to store global system prompts."""
 
26
  warnings.filterwarnings("ignore", category=DeprecationWarning)
27
 
28
  from var_app import __version__
29
+ from core.files import load_ui_language
30
+ from core.files import read_file
31
+ from core.files import openai_tts
32
 
33
  # Au début du fichier, après les imports
34
  st.set_page_config(
 
38
  initial_sidebar_state="collapsed"
39
  )
40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
  def get_translation(key: str) -> str:
43
  """
 
49
  # Dictionary to store translations
50
  translations = load_ui_language()
51
 
 
 
52
 
53
+ def process_tts_message(text_response: str) -> Tuple[Optional[bytes], Optional[float]]:
54
+ try:
55
+ tts_output_ = openai_tts(
56
+ tts_voice=st.session_state.tts_voice,
57
+ tts_model="tts-1",
58
+ response_format="mp3",
59
+ speed=1.0
60
+ ).text_to_speech(text_response)
61
+
62
+ return tts_output_["data_bytes"], tts_output_["audio_duration"]
63
+ except Exception as e:
64
+ st.error(f"Une erreur s'est produite lors de la conversion texte-parole : {e}")
65
+ return None, None
66
 
 
 
67
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
 
70
 
 
218
  raise ValueError(f"Erreur inattendue lors de la détection de la langue : {str(e)}")
219
 
220
 
 
 
 
221
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
 
223
  def concatenate_audio_files(audio_list: List[Tuple[bytes, float]]) -> Optional[bytes]:
224
  """
 
302
  st.error(f"Une erreur s'est produite lors de la génération de la réponse : {e}")
303
  return ""
304
 
 
 
 
 
 
 
 
305
 
306
  class GlobalSystemPrompts:
307
  """Class to store global system prompts."""