wdeback commited on
Commit
20f080f
·
1 Parent(s): 9b3e5e0

Upload folder using huggingface_hub

Browse files
app/__pycache__/app.cpython-310.pyc ADDED
Binary file (4.77 kB). View file
 
app/__pycache__/app.cpython-39.pyc ADDED
Binary file (4.63 kB). View file
 
app/__pycache__/llm.cpython-310.pyc ADDED
Binary file (5.69 kB). View file
 
app/__pycache__/speech.cpython-310.pyc ADDED
Binary file (1.23 kB). View file
 
app/app.py CHANGED
@@ -9,182 +9,18 @@ load_dotenv()
9
  from retry import retry
10
  from typing import List, Dict, Optional
11
  from tqdm import tqdm
 
 
12
 
13
- countries = {"nl": {"language":"Dutch", "country":"the Netherlands"},
14
- "de": {"language":"German", "country":"Germany"},
15
- "se": {"language":"Swedish", "country":"Sweden"},
16
- "en": {"language":"English", "country":"England"},
17
- "fr": {"language":"French", "country":"France"},
18
- "it": {"language":"Italian", "country":"Italy"},
19
- "es": {"language":"Spanish", "country":"Spain"},
20
- "pl": {"language":"Polish", "country":"Poland"},
21
- "hu": {"language":"Hungarian", "country":"Hungary"},
22
- }
23
-
24
- moods = ["hilarious", "funny", "serious", "poetic"]
25
-
26
- levels = {"easy": [4, 8],
27
- "medium": [7, 16],
28
- "complicated": [12, 25],
29
- "very complicated": [20, 40]}
30
-
31
- def get_languages():
32
- return list(countries.keys())
33
-
34
- def get_level_names():
35
- return list(levels.keys())
36
 
37
  languages = get_languages()
38
  #languages_flags = [ emoji.emojize(f":flag-{countries[language]['country'].lower().replace(' ', '-')}:") for language in languages]
39
  level_names = get_level_names()
40
 
41
- #
42
- # -- llm.py --
43
- #
44
-
45
- class LLM():
46
-
47
- def __init__(self):
48
-
49
- load_dotenv()
50
- openai.api_key = os.getenv("OPENAI_API_KEY")
51
- self.min_length = 10
52
-
53
- def parse_response(self, response:str) -> List[Dict[str, str]]:
54
-
55
- logger.info(f"{response = }")
56
-
57
- logger.info(f"Parsing response from OpenAI API.")
58
-
59
- text = response
60
- tokens = text.split("Sentence ")
61
-
62
- logger.debug(f"Number of tokens: {len(tokens)}")
63
- logger.debug(f"{tokens = }")
64
-
65
-
66
- qas = []
67
- for token in tokens:
68
- if len(token) == 0:
69
- continue
70
- lines = token.split("\n")
71
- #print(f"{lines = }")
72
- original = lines[0][3:]
73
-
74
- true_trans = ""
75
- for line in lines:
76
- if line.startswith("True: "):
77
- true_trans = line[6:]
78
-
79
- # get line starting with "False: "
80
- false_trans = ""
81
- for line in lines:
82
- if line.startswith("False: "):
83
- false_trans = line[7:]
84
-
85
- # get line starting with "Funny: "
86
- funny_trans = ""
87
- for line in lines:
88
- if line.startswith("Funny: "):
89
- funny_trans = line[7:]
90
-
91
- qa = {"original": original, "true": true_trans, "false": false_trans, "funny": funny_trans}
92
-
93
- logger.debug(f"------------------------")
94
- logger.debug(f"{qa = }")
95
- logger.debug(f"------------------------")
96
-
97
- if len(qa["original"]) > self.min_length and \
98
- len(qa["true"]) > self.min_length and \
99
- len(qa["false"]) > self.min_length and \
100
- len(qa["funny"]) > self.min_length:
101
- qas.append(qa)
102
-
103
- logger.info(f"Returning {len(qas)} valid QA pairs.")
104
-
105
- return qas
106
-
107
- @retry(delay=0, backoff=2, max_delay=20, tries=10, logger=logger)
108
- def generate(self, n:int,
109
- input_country:str,
110
- target_country:str,
111
- level:str,
112
- temperature:float=0.80,
113
- streaming:bool=False) -> Dict[str, str]:
114
- input_length = levels[level]
115
-
116
- language = countries[input_country]['language']
117
- country = countries[input_country]['country']
118
- target_language = countries[target_country]['language']
119
- mood = random.choice(moods)
120
-
121
- logger.info(f"Generating {str(n)} QA pairs for {language} to {target_language} with level: {level}.")
122
-
123
-
124
- assert temperature >= 0.0 and temperature <= 1.0, "temperature must be between 0 and 1"
125
- response = openai.ChatCompletion.create(
126
- model="gpt-3.5-turbo",
127
- messages=[
128
- {"role": "system", "content":
129
- f"You are a helpful assistant at creating a translation game. \
130
- You create sentences in {language} with a length that is exactly between {str(input_length[0])} to {str(input_length[1])} words. \
131
- You create translations in {target_language}. Do not include a translation in the original sentence. \
132
- Ensure that each translation is quite different from the other ones and reduce repetition. \
133
- Formulate your answer in exactly this format: Sentence N: [X],\True: [A],\nFalse: [B],\nFunny: [C]."},
134
- {"role": "assistant", "content":
135
- f"Sometimes, create original sentences with words, locations, concepts and phrases are typical for {country}. Otherwise, create sentences that are unlreated to the country."},
136
- {"role": "user", "content":
137
- f"Generate {str(n)} {level} and {mood} sentences in {language} and 3 corresponding translations in {target_language}. \
138
- You create 1 correct translation, 1 incorrect translations, and 1 which very wrong and funny. \
139
- "},
140
- ],
141
- temperature=temperature,
142
- stream=streaming
143
- )
144
-
145
- if streaming:
146
- import time
147
- start_time = time.time()
148
- collected_chunks = []
149
- collected_messages = []
150
- for chunk in tqdm(response, total=250):
151
- chunk_time = time.time() - start_time # calculate the time delay of the chunk
152
- collected_chunks.append(chunk) # save the event response
153
- chunk_message = chunk['choices'][0]['delta'] # extract the message
154
- collected_messages.append(chunk_message) # save the message
155
- #print(f"Message received {chunk_time:.2f} seconds after request: {chunk_message}") # print the delay and text
156
-
157
- full_reply_content = ''.join([m.get('content', '') for m in collected_messages])
158
- return full_reply_content
159
- else:
160
- return response.choices[0].message.content
161
-
162
- def get_QAs(self, n:int, input_countries:List[str], target_country:str, level:str, debug:bool=False):
163
-
164
- logger.info(f"Generating new sentences...")
165
- # gr.Info(f"Generating new Q&A in {input_countries} with level: {level}.")
166
-
167
-
168
- if debug:
169
- return [ {"original": "The Netherlands is a country in Europe.",
170
- "true": "Nederland is een land in Europa.",
171
- "false": "Nederland is een land in Azië.",
172
- "funny": "Nederland is een aap in Europa."},
173
- {"original": "Aap, noot, mies.",
174
- "true": "Aap.",
175
- "false": "Noot.",
176
- "funny": "Mies."} ]
177
- else:
178
- return self.parse_response(
179
- self.generate(n=n,
180
- input_country=random.choice(input_countries),
181
- target_country=target_country,
182
- level=level))
183
-
184
- # n = 10
185
- # input_country = "nl"
186
- # target_country = "de"
187
- # input_length = "easy"
188
 
189
  class Game:
190
 
@@ -195,6 +31,7 @@ class Game:
195
  debug:bool=False):
196
 
197
  self.llm = LLM()
 
198
  self.n = n
199
  self.input_countries = input_countries
200
  self.target_country = target_country
@@ -206,11 +43,19 @@ class Game:
206
  self.score_relative = {'correct': 0., 'incorrect': 0.}
207
  self.total = 0
208
 
209
- self.qas = self.llm.get_QAs(n=self.n,
210
- input_countries=self.input_countries,
211
- target_country=self.target_country,
212
- level=self.level,
213
- debug=self.debug)
 
 
 
 
 
 
 
 
214
 
215
 
216
  def get_qa(self):
@@ -232,28 +77,31 @@ class Game:
232
  true = qa["true"]
233
  random.shuffle(options)
234
  options_md = f"""### A: {options[0]}\n\n### B: {options[1]}\n\n### C: {options[2]}"""
 
235
  # get correct answer
236
  self.correct_answer = [letter for letter, option in zip(["A", "B", "C"], options) if option == true][0]
237
 
238
- logger.info(f"get_qa()")
239
- logger.info(f"Question: {question_md}")
240
- logger.info(f"Options: {options}")
241
- logger.info(f"Correct answer: {self.correct_answer}")
 
242
  return question_md, options_md
243
 
244
- def update(self, answer):
245
 
246
  # check answer
247
  logger.info(f"Checking answer \"{answer}\" against \"{self.correct_answer}\"")
248
  result = answer == self.correct_answer
 
249
  # display output
250
  gr.Info(emoji.emojize(":thumbs_up:")+" Correct!") if result else gr.Info(emoji.emojize(":thumbs_down:"+f" Wrong! Correct answer was: {self.correct_answer}"))
251
  #output = emoji.emojize("# :thumbs_up:") if result else emoji.emojize("# :thumbs_down:")
252
 
253
- self.score["correct"] += 1 if result else 0
254
- self.score["incorrect"] += 0 if result else 1
255
- self.total += 1
256
- score_relative = {'correct': self.score['correct']/self.total, 'incorrect': self.score['incorrect']/self.total}
257
 
258
 
259
  # get new question and answer
@@ -263,7 +111,7 @@ class Game:
263
  logger.info(f"Question: {question}")
264
  logger.info(f"Options: {options}")
265
 
266
- return question, options, score_relative
267
 
268
  def update_settings(self, new_input_countries, new_target_country, new_level):
269
 
@@ -290,7 +138,7 @@ class Game:
290
 
291
  if changed:
292
  logger.info(f"Setting changed, generating new QAs...")
293
- gr.Info("Setting changed, generating new QAs...")
294
  self.qas = self.llm.get_QAs(n=1,
295
  input_countries=self.input_countries,
296
  target_country=self.target_country,
@@ -311,6 +159,10 @@ class Game:
311
  # show question
312
  question_md = gr.Markdown(question)
313
 
 
 
 
 
314
  # show answers
315
  answers_md = gr.Markdown(options)
316
 
@@ -323,13 +175,13 @@ class Game:
323
  # # show output box
324
  # output = gr.Markdown()
325
 
326
- # show scores
327
- if score_relative is None:
328
- score_relative = {'correct': 0., 'incorrect': 0.}
329
- scores = gr.Label(score_relative, label="Scores", show_label=False) #, visible=True if self.total > 0 else False)
330
 
331
  # event listener
332
- button.click(fn=self.update, inputs=radio, outputs=[question_md, answers_md, scores], scroll_to_output=True)
333
 
334
  with gr.Tab("Settings"):
335
  # Settings
@@ -344,6 +196,6 @@ class Game:
344
 
345
 
346
  if __name__ == "__main__":
347
- game = Game(n=1, input_countries=["nl", "en", "se"], target_country="de", level="medium", debug=False)
348
  question, options = game.get_qa()
349
  game.run(question, options, share=False)
 
9
  from retry import retry
10
  from typing import List, Dict, Optional
11
  from tqdm import tqdm
12
+ from .llm import LLM, get_languages, get_level_names
13
+ from .speech import Speech
14
 
15
+ # n = 10
16
+ # input_country = "nl"
17
+ # target_country = "de"
18
+ # input_length = "easy"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  languages = get_languages()
21
  #languages_flags = [ emoji.emojize(f":flag-{countries[language]['country'].lower().replace(' ', '-')}:") for language in languages]
22
  level_names = get_level_names()
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  class Game:
26
 
 
31
  debug:bool=False):
32
 
33
  self.llm = LLM()
34
+ # self.speech = Speech()
35
  self.n = n
36
  self.input_countries = input_countries
37
  self.target_country = target_country
 
43
  self.score_relative = {'correct': 0., 'incorrect': 0.}
44
  self.total = 0
45
 
46
+
47
+ # self.qas = self.llm.get_QAs(n=self.n,
48
+ # input_countries=self.input_countries,
49
+ # target_country=self.target_country,
50
+ # level=self.level,
51
+ # debug=self.debug)
52
+
53
+ self.qas = [{
54
+ "original": "So you think you can translate?",
55
+ "true": "Ja",
56
+ "false": "Sure",
57
+ "funny": "Igen"
58
+ }]
59
 
60
 
61
  def get_qa(self):
 
77
  true = qa["true"]
78
  random.shuffle(options)
79
  options_md = f"""### A: {options[0]}\n\n### B: {options[1]}\n\n### C: {options[2]}"""
80
+
81
  # get correct answer
82
  self.correct_answer = [letter for letter, option in zip(["A", "B", "C"], options) if option == true][0]
83
 
84
+ logger.debug(f"get_qa()")
85
+ logger.debug(f"Question: {question_md}")
86
+ logger.debug(f"Options: {options}")
87
+ logger.debug(f"Correct answer: {self.correct_answer}")
88
+
89
  return question_md, options_md
90
 
91
+ def check_answer(self, answer):
92
 
93
  # check answer
94
  logger.info(f"Checking answer \"{answer}\" against \"{self.correct_answer}\"")
95
  result = answer == self.correct_answer
96
+
97
  # display output
98
  gr.Info(emoji.emojize(":thumbs_up:")+" Correct!") if result else gr.Info(emoji.emojize(":thumbs_down:"+f" Wrong! Correct answer was: {self.correct_answer}"))
99
  #output = emoji.emojize("# :thumbs_up:") if result else emoji.emojize("# :thumbs_down:")
100
 
101
+ # self.score["correct"] += 1 if result else 0
102
+ # self.score["incorrect"] += 0 if result else 1
103
+ # self.total += 1
104
+ # score_relative = {'correct': self.score['correct']/self.total, 'incorrect': self.score['incorrect']/self.total}
105
 
106
 
107
  # get new question and answer
 
111
  logger.info(f"Question: {question}")
112
  logger.info(f"Options: {options}")
113
 
114
+ return question, options
115
 
116
  def update_settings(self, new_input_countries, new_target_country, new_level):
117
 
 
138
 
139
  if changed:
140
  logger.info(f"Setting changed, generating new QAs...")
141
+ gr.Info("Setting changed, generating new sentences...")
142
  self.qas = self.llm.get_QAs(n=1,
143
  input_countries=self.input_countries,
144
  target_country=self.target_country,
 
159
  # show question
160
  question_md = gr.Markdown(question)
161
 
162
+ # # add audio
163
+ # self.speech.text_to_speech(question, self.input_countries[0])
164
+ # speech = gr.Audio("output.wav", interactive=False)
165
+
166
  # show answers
167
  answers_md = gr.Markdown(options)
168
 
 
175
  # # show output box
176
  # output = gr.Markdown()
177
 
178
+ # # show scores
179
+ # if score_relative is None:
180
+ # score_relative = {'correct': 0., 'incorrect': 0.}
181
+ # scores = gr.Label(score_relative, label="Scores", show_label=False) #, visible=True if self.total > 0 else False)
182
 
183
  # event listener
184
+ button.click(fn=self.check_answer, inputs=radio, outputs=[question_md, answers_md], scroll_to_output=True)
185
 
186
  with gr.Tab("Settings"):
187
  # Settings
 
196
 
197
 
198
  if __name__ == "__main__":
199
+ game = Game(n=1, input_countries=["en"], target_country="de", level="complicated", debug=False)
200
  question, options = game.get_qa()
201
  game.run(question, options, share=False)
app/llm.py ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import openai
3
+ import random
4
+ from loguru import logger
5
+ from dotenv import load_dotenv
6
+ load_dotenv()
7
+ from retry import retry
8
+ from typing import List, Dict, Optional
9
+ from tqdm import tqdm
10
+
11
+
12
+ # speech ISO codes from: https://dl.fbaipublicfiles.com/mms/tts/all-tts-languages.html
13
+ countries = {"nl": {"language":"Dutch", "country":"the Netherlands", "flag": "🇳🇱", "iso": "nld"},
14
+ "de": {"language":"German", "country":"Germany", "flag": "🇩🇪", "iso": "deu"},
15
+ "se": {"language":"Swedish", "country":"Sweden", "flag": "🇸🇪", "iso": "swe"},
16
+ "en": {"language":"English", "country":"England", "flag": "🇬🇧", "iso": "eng"},
17
+ "fr": {"language":"French", "country":"France", "flag": "🇫🇷", "iso": "fra"},
18
+ "it": {"language":"Italian", "country":"Italy", "flag": "🇮🇹", "iso": None},
19
+ "es": {"language":"Spanish", "country":"Spain", "flag": "🇪🇸", "iso": "spa"},
20
+ "pl": {"language":"Polish", "country":"Poland", "flag": "🇵🇱", "iso": "pol"},
21
+ "hu": {"language":"Hungarian", "country":"Hungary", "flag": "🇭🇺", "iso": "hun"},
22
+ "fi": {"language":"Finnish", "country":"Finland", "flag": "🇫🇮", "iso": "fin"},
23
+ }
24
+
25
+ moods = ["hilarious", "funny", "serious", "poetic"]
26
+
27
+ levels = {"easy": [4, 8],
28
+ "medium": [7, 16],
29
+ "complicated": [12, 25],
30
+ "very complicated": [20, 40]}
31
+
32
+ def get_languages():
33
+ return list(countries.keys())
34
+
35
+ def get_level_names():
36
+ return list(levels.keys())
37
+
38
+ class LLM():
39
+
40
+ def __init__(self):
41
+
42
+ load_dotenv()
43
+ openai.api_key = os.getenv("OPENAI_API_KEY")
44
+ self.min_length = 10
45
+
46
+ def parse_response(self, response:str) -> List[Dict[str, str]]:
47
+
48
+ logger.info(f"{response = }")
49
+
50
+ logger.info(f"Parsing response from OpenAI API.")
51
+
52
+ text = response
53
+ tokens = text.split("Sentence ")
54
+
55
+ logger.debug(f"Number of tokens: {len(tokens)}")
56
+ logger.debug(f"{tokens = }")
57
+
58
+
59
+ qas = []
60
+ for token in tokens:
61
+ if len(token) == 0:
62
+ continue
63
+ lines = token.split("\n")
64
+ #print(f"{lines = }")
65
+ original = lines[0][3:]
66
+
67
+ true_trans = ""
68
+ for line in lines:
69
+ if line.startswith("True: "):
70
+ true_trans = line[6:]
71
+
72
+ # get line starting with "False: "
73
+ false_trans = ""
74
+ for line in lines:
75
+ if line.startswith("False: "):
76
+ false_trans = line[7:]
77
+
78
+ # get line starting with "Funny: "
79
+ funny_trans = ""
80
+ for line in lines:
81
+ if line.startswith("Funny: "):
82
+ funny_trans = line[7:]
83
+
84
+ qa = {"original": original, "true": true_trans, "false": false_trans, "funny": funny_trans}
85
+
86
+ logger.debug(f"------------------------")
87
+ logger.debug(f"{qa = }")
88
+ logger.debug(f"------------------------")
89
+
90
+ if len(qa["original"]) > self.min_length and \
91
+ len(qa["true"]) > self.min_length and \
92
+ len(qa["false"]) > self.min_length and \
93
+ len(qa["funny"]) > self.min_length:
94
+ qas.append(qa)
95
+
96
+ logger.info(f"Returning {len(qas)} valid QA pairs.")
97
+
98
+ return qas
99
+
100
+ @retry(delay=0, backoff=2, max_delay=20, tries=10, logger=logger)
101
+ def generate(self, n:int,
102
+ input_country:str,
103
+ target_country:str,
104
+ level:str,
105
+ temperature:float=0.80,
106
+ streaming:bool=False) -> Dict[str, str]:
107
+ input_length = levels[level]
108
+
109
+ language = countries[input_country]['language']
110
+ country = countries[input_country]['country']
111
+ target_language = countries[target_country]['language']
112
+ mood = random.choice(moods)
113
+
114
+ logger.info(f"Generating {str(n)} QA pairs for {language} to {target_language} with level: {level}.")
115
+
116
+
117
+ assert temperature >= 0.0 and temperature <= 1.0, "temperature must be between 0 and 1"
118
+ response = openai.ChatCompletion.create(
119
+ model="gpt-3.5-turbo",
120
+ messages=[
121
+ {"role": "system", "content":
122
+ f"You are a helpful assistant at creating a translation game. \
123
+ You create sentences in {language} with a length that is exactly between {str(input_length[0])} to {str(input_length[1])} words. \
124
+ You create translations in {target_language}. Do not include a translation in the original sentence. \
125
+ Ensure that each translation is quite different from the other ones and reduce repetition. \
126
+ Formulate your answer in exactly this format: Sentence N: [X],\True: [A],\nFalse: [B],\nFunny: [C]."},
127
+ {"role": "assistant", "content":
128
+ f"Sometimes, create original sentences with words, locations, concepts and phrases are typical for {country}. Otherwise, create sentences that are unlreated to the country."},
129
+ {"role": "user", "content":
130
+ f"Generate {str(n)} {level} and {mood} sentences in {language} and 3 corresponding translations in {target_language}. \
131
+ You create 1 correct translation, 1 incorrect translations, and 1 which very wrong and funny. \
132
+ "},
133
+ ],
134
+ temperature=temperature,
135
+ stream=streaming
136
+ )
137
+
138
+ if streaming:
139
+ import time
140
+ start_time = time.time()
141
+ collected_chunks = []
142
+ collected_messages = []
143
+ for chunk in tqdm(response, total=250):
144
+ chunk_time = time.time() - start_time # calculate the time delay of the chunk
145
+ collected_chunks.append(chunk) # save the event response
146
+ chunk_message = chunk['choices'][0]['delta'] # extract the message
147
+ collected_messages.append(chunk_message) # save the message
148
+ #print(f"Message received {chunk_time:.2f} seconds after request: {chunk_message}") # print the delay and text
149
+
150
+ full_reply_content = ''.join([m.get('content', '') for m in collected_messages])
151
+ return full_reply_content
152
+ else:
153
+ return response.choices[0].message.content
154
+
155
+ def get_QAs(self, n:int, input_countries:List[str], target_country:str, level:str, debug:bool=False):
156
+
157
+ logger.info(f"Generating new sentences...")
158
+ # gr.Info(f"Generating new Q&A in {input_countries} with level: {level}.")
159
+
160
+
161
+ if debug:
162
+ return [ {"original": "The Netherlands is a country in Europe.",
163
+ "true": "Nederland is een land in Europa.",
164
+ "false": "Nederland is een land in Azië.",
165
+ "funny": "Nederland is een aap in Europa."},
166
+ {"original": "Aap, noot, mies.",
167
+ "true": "Aap.",
168
+ "false": "Noot.",
169
+ "funny": "Mies."} ]
170
+ else:
171
+ return self.parse_response(
172
+ self.generate(n=n,
173
+ input_country=random.choice(input_countries),
174
+ target_country=target_country,
175
+ level=level))
app/speech.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from TTS.api import TTS
3
+ from loguru import logger
4
+
5
+ class Speech():
6
+
7
+ def __init__(self) -> None:
8
+
9
+ # List available 🐸TTS models
10
+ # print(TTS().list_models())
11
+
12
+ # Get device
13
+ device = "cuda" if torch.cuda.is_available() else "cpu"
14
+
15
+ # Init TTS (and download model if necessary)
16
+ self.tts = TTS("tts_models/multilingual/multi-dataset/xtts_v1").to(device)
17
+
18
+ logger.info(f"Initialized TTS: {self.tts}")
19
+
20
+ def text_to_speech(self, text:str, language:str):
21
+
22
+ logger.info(f"Text to speech: {text} to {language}")
23
+
24
+ # remove ## from text
25
+ text = text.replace("##", "")
26
+
27
+ # language = en, de, es, fr, it, pt, pl.
28
+ valid_languages = ["en", "de", "es", "fr", "it", "pt", "pl"]
29
+ if language not in valid_languages:
30
+ raise ValueError(f"Language '{language}' is not one of the supported languages: {valid_languages}")
31
+ return None
32
+ else:
33
+ # Run TTS
34
+ # ❗ Since this model is multi-lingual voice cloning model, we must set the target speaker_wav and language
35
+ # Text to speech list of amplitude values as output
36
+ # wav = self.tts.tts(text=text, language=language)
37
+ # # Text to speech to a file
38
+ self.tts.tts_to_file(text=text, language=language, file_path="output.wav")
39
+
40
+ logger.info(f"Converted text to speech")
41
+ return "output.wav"
app/speech_google.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Synthesizes speech from the input string of text or ssml.
2
+ Make sure to be working in a virtual environment.
3
+
4
+ Note: ssml must be well-formed according to:
5
+ https://www.w3.org/TR/speech-synthesis/
6
+ """
7
+ from google.cloud import texttospeech
8
+ from loguru import logger
9
+
10
+ class Speech:
11
+
12
+ def __init__(self) -> None:
13
+
14
+ # Instantiates a client
15
+ self.client = texttospeech.TextToSpeechClient()
16
+
17
+ # Select the type of audio file you want returned
18
+ self.audio_config = texttospeech.AudioConfig(
19
+ audio_encoding=texttospeech.AudioEncoding.MP3
20
+ )
21
+
22
+ logger.info(f"Initialized Speech()")
23
+
24
+ def text_to_speech(self, text:str, language:str):
25
+
26
+ logger.info(f"Converting text to speech.")
27
+
28
+ # Set the text input to be synthesized
29
+ synthesis_input = texttospeech.SynthesisInput(text=text)
30
+
31
+ # Build the voice request, select the language code ("en-US") and the ssml
32
+ # voice gender ("neutral")
33
+ voice = texttospeech.VoiceSelectionParams(
34
+ language_code="en-US",
35
+ ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL
36
+ )
37
+
38
+ # Perform the text-to-speech request on the text input with the selected
39
+ # voice parameters and audio file type
40
+ response = self.client.synthesize_speech(
41
+ input=synthesis_input, voice=voice, audio_config=self.audio_config
42
+ )
43
+
44
+ # The response's audio_content is binary.
45
+ with open("output.mp3", "wb") as out:
46
+ # Write the response to the output file.
47
+ out.write(response.audio_content)
48
+ logger.info('Audio content written to file "output.mp3"')
requirements.txt CHANGED
@@ -1,6 +1,7 @@
1
- emoji
2
- gradio
3
- python-dotenv
4
- openai
5
- loguru
6
- retry
 
 
1
+ openai # openai api for chatGPT: https://platform.openai.com/docs/introduction
2
+ gradio # UI: https://gradio.app/
3
+ python-dotenv # dotenv: https://github.com/theskumar/python-dotenv
4
+ emoji # convert emoji to text: https://github.com/carpedm20/emoji/
5
+ loguru # logging: https://loguru.readthedocs.io/en/stable/index.html
6
+ retry # retry decorator: https://github.com/invl/retry
7
+ TTS # text to speech: https://github.com/coqui-ai/TTS