jonmatthis commited on
Commit
d20eb01
Β·
1 Parent(s): 29e2270

getting there

Browse files
app.py CHANGED
@@ -2,586 +2,31 @@ import io
2
  import os
3
  import ssl
4
  from contextlib import closing
5
- from typing import Optional, Tuple
6
- import datetime
7
 
8
  import boto3
9
  import gradio as gr
10
  import requests
11
-
12
- # UNCOMMENT TO USE WHISPER
13
- import warnings
14
- import whisper
15
-
16
- from langchain import ConversationChain, LLMChain
17
-
18
- from langchain.agents import load_tools, initialize_agent
19
- from langchain.chains.conversation.memory import ConversationBufferMemory
20
- from langchain.llms import OpenAI, OpenAIChat
21
- from threading import Lock
22
-
23
- # Console to variable
24
- from io import StringIO
25
- import sys
26
- import re
27
-
28
- from openai.error import AuthenticationError, InvalidRequestError, RateLimitError
29
-
30
  # Pertains to Express-inator functionality
31
  from langchain.prompts import PromptTemplate
32
 
33
- from polly_utils import PollyVoiceData, NEURAL_ENGINE
34
- from azure_utils import AzureVoiceData
35
-
36
- # Pertains to question answering functionality
37
- from langchain.embeddings.openai import OpenAIEmbeddings
38
- from langchain.text_splitter import CharacterTextSplitter
39
- from langchain.vectorstores.faiss import FAISS
40
- from langchain.docstore.document import Document
41
- from langchain.chains.question_answering import load_qa_chain
42
-
43
- news_api_key = os.environ["NEWS_API_KEY"]
44
- tmdb_bearer_token = os.environ["TMDB_BEARER_TOKEN"]
45
-
46
- TOOLS_LIST = ['serpapi', 'wolfram-alpha', 'pal-math',
47
- 'pal-colored-objects'] # 'google-search','news-api','tmdb-api','open-meteo-api'
48
- TOOLS_DEFAULT_LIST = ['serpapi']
49
- BUG_FOUND_MSG = "Congratulations, you've found a bug in this application!"
50
- # AUTH_ERR_MSG = "Please paste your OpenAI key from openai.com to use this application. It is not necessary to hit a button or key after pasting it."
51
- AUTH_ERR_MSG = "Please paste your OpenAI key from openai.com to use this application. "
52
- MAX_TOKENS = 512
53
-
54
- LOOPING_TALKING_HEAD = "videos/Masahiro.mp4"
55
- TALKING_HEAD_WIDTH = "192"
56
- MAX_TALKING_HEAD_TEXT_LENGTH = 155
57
-
58
- # Pertains to Express-inator functionality
59
- NUM_WORDS_DEFAULT = 0
60
- MAX_WORDS = 400
61
- FORMALITY_DEFAULT = "N/A"
62
- TEMPERATURE_DEFAULT = 0.5
63
- EMOTION_DEFAULT = "N/A"
64
- LANG_LEVEL_DEFAULT = "N/A"
65
- TRANSLATE_TO_DEFAULT = "N/A"
66
- LITERARY_STYLE_DEFAULT = "N/A"
67
- PROMPT_TEMPLATE = PromptTemplate(
68
- input_variables=["original_words", "num_words", "formality", "emotions", "lang_level", "translate_to",
69
- "literary_style"],
70
- template="Restate {num_words}{formality}{emotions}{lang_level}{translate_to}{literary_style}the following: \n{original_words}\n",
71
- )
72
-
73
- FORCE_TRANSLATE_DEFAULT = True
74
- USE_GPT4_DEFAULT = False
75
-
76
- POLLY_VOICE_DATA = PollyVoiceData()
77
- AZURE_VOICE_DATA = AzureVoiceData()
78
-
79
- # Pertains to WHISPER functionality
80
- WHISPER_DETECT_LANG = "Detect language"
81
-
82
- # UNCOMMENT TO USE WHISPER
83
- warnings.filterwarnings("ignore")
84
- WHISPER_MODEL = whisper.load_model("tiny")
85
- print("WHISPER_MODEL", WHISPER_MODEL)
86
-
87
-
88
- # UNCOMMENT TO USE WHISPER
89
- def transcribe(aud_inp, whisper_lang):
90
- if aud_inp is None:
91
- return ""
92
- aud = whisper.load_audio(aud_inp)
93
- aud = whisper.pad_or_trim(aud)
94
- mel = whisper.log_mel_spectrogram(aud).to(WHISPER_MODEL.device)
95
- _, probs = WHISPER_MODEL.detect_language(mel)
96
- options = whisper.DecodingOptions()
97
- if whisper_lang != WHISPER_DETECT_LANG:
98
- whisper_lang_code = POLLY_VOICE_DATA.get_whisper_lang_code(whisper_lang)
99
- options = whisper.DecodingOptions(language=whisper_lang_code)
100
- result = whisper.decode(WHISPER_MODEL, mel, options)
101
- print("result.text", result.text)
102
- result_text = ""
103
- if result and result.text:
104
- result_text = result.text
105
- return result_text
106
-
107
 
108
  # Temporarily address Wolfram Alpha SSL certificate issue
109
  ssl._create_default_https_context = ssl._create_unverified_context
110
 
111
 
112
- # TEMPORARY FOR TESTING
113
- def transcribe_dummy(aud_inp_tb, whisper_lang):
114
- if aud_inp_tb is None:
115
- return ""
116
- # aud = whisper.load_audio(aud_inp)
117
- # aud = whisper.pad_or_trim(aud)
118
- # mel = whisper.log_mel_spectrogram(aud).to(WHISPER_MODEL.device)
119
- # _, probs = WHISPER_MODEL.detect_language(mel)
120
- # options = whisper.DecodingOptions()
121
- # options = whisper.DecodingOptions(language="ja")
122
- # result = whisper.decode(WHISPER_MODEL, mel, options)
123
- result_text = "Whisper will detect language"
124
- if whisper_lang != WHISPER_DETECT_LANG:
125
- whisper_lang_code = POLLY_VOICE_DATA.get_whisper_lang_code(whisper_lang)
126
- result_text = f"Whisper will use lang code: {whisper_lang_code}"
127
- print("result_text", result_text)
128
- return aud_inp_tb
129
-
130
-
131
- # Pertains to Express-inator functionality
132
- def transform_text(desc, express_chain, num_words, formality,
133
- anticipation_level, joy_level, trust_level,
134
- fear_level, surprise_level, sadness_level, disgust_level, anger_level,
135
- lang_level, translate_to, literary_style, force_translate):
136
- num_words_prompt = ""
137
- if num_words and int(num_words) != 0:
138
- num_words_prompt = "using up to " + str(num_words) + " words, "
139
-
140
- # Change some arguments to lower case
141
- formality = formality.lower()
142
- anticipation_level = anticipation_level.lower()
143
- joy_level = joy_level.lower()
144
- trust_level = trust_level.lower()
145
- fear_level = fear_level.lower()
146
- surprise_level = surprise_level.lower()
147
- sadness_level = sadness_level.lower()
148
- disgust_level = disgust_level.lower()
149
- anger_level = anger_level.lower()
150
-
151
- formality_str = ""
152
- if formality != "n/a":
153
- formality_str = "in a " + formality + " manner, "
154
-
155
- # put all emotions into a list
156
- emotions = []
157
- if anticipation_level != "n/a":
158
- emotions.append(anticipation_level)
159
- if joy_level != "n/a":
160
- emotions.append(joy_level)
161
- if trust_level != "n/a":
162
- emotions.append(trust_level)
163
- if fear_level != "n/a":
164
- emotions.append(fear_level)
165
- if surprise_level != "n/a":
166
- emotions.append(surprise_level)
167
- if sadness_level != "n/a":
168
- emotions.append(sadness_level)
169
- if disgust_level != "n/a":
170
- emotions.append(disgust_level)
171
- if anger_level != "n/a":
172
- emotions.append(anger_level)
173
-
174
- emotions_str = ""
175
- if len(emotions) > 0:
176
- if len(emotions) == 1:
177
- emotions_str = "with emotion of " + emotions[0] + ", "
178
- else:
179
- emotions_str = "with emotions of " + ", ".join(emotions[:-1]) + " and " + emotions[-1] + ", "
180
-
181
- lang_level_str = ""
182
- if lang_level != LANG_LEVEL_DEFAULT:
183
- lang_level_str = "at a level that a person in " + lang_level + " can easily comprehend, " if translate_to == TRANSLATE_TO_DEFAULT else ""
184
-
185
- translate_to_str = ""
186
- if translate_to != TRANSLATE_TO_DEFAULT and (force_translate or lang_level != LANG_LEVEL_DEFAULT):
187
- translate_to_str = "translated to " + translate_to + (
188
- "" if lang_level == LANG_LEVEL_DEFAULT else " at a level that a person in " + lang_level + " can easily comprehend") + ", "
189
-
190
- literary_style_str = ""
191
- if literary_style != LITERARY_STYLE_DEFAULT:
192
- if literary_style == "Prose":
193
- literary_style_str = "as prose, "
194
- if literary_style == "Story":
195
- literary_style_str = "as a story, "
196
- elif literary_style == "Summary":
197
- literary_style_str = "as a summary, "
198
- elif literary_style == "Outline":
199
- literary_style_str = "as an outline numbers and lower case letters, "
200
- elif literary_style == "Bullets":
201
- literary_style_str = "as bullet points using bullets, "
202
- elif literary_style == "Poetry":
203
- literary_style_str = "as a poem, "
204
- elif literary_style == "Haiku":
205
- literary_style_str = "as a haiku, "
206
- elif literary_style == "Limerick":
207
- literary_style_str = "as a limerick, "
208
- elif literary_style == "Rap":
209
- literary_style_str = "as a rap, "
210
- elif literary_style == "Joke":
211
- literary_style_str = "as a very funny joke with a setup and punchline, "
212
- elif literary_style == "Knock-knock":
213
- literary_style_str = "as a very funny knock-knock joke, "
214
- elif literary_style == "FAQ":
215
- literary_style_str = "as a FAQ with several questions and answers, "
216
-
217
- formatted_prompt = PROMPT_TEMPLATE.format(
218
- original_words=desc,
219
- num_words=num_words_prompt,
220
- formality=formality_str,
221
- emotions=emotions_str,
222
- lang_level=lang_level_str,
223
- translate_to=translate_to_str,
224
- literary_style=literary_style_str
225
- )
226
-
227
- trans_instr = num_words_prompt + formality_str + emotions_str + lang_level_str + translate_to_str + literary_style_str
228
- if express_chain and len(trans_instr.strip()) > 0:
229
- generated_text = express_chain.run(
230
- {'original_words': desc, 'num_words': num_words_prompt, 'formality': formality_str,
231
- 'emotions': emotions_str, 'lang_level': lang_level_str, 'translate_to': translate_to_str,
232
- 'literary_style': literary_style_str}).strip()
233
- else:
234
- print("Not transforming text")
235
- generated_text = desc
236
-
237
- # replace all newlines with <br> in generated_text
238
- generated_text = generated_text.replace("\n", "\n\n")
239
-
240
- prompt_plus_generated = "GPT prompt: " + formatted_prompt + "\n\n" + generated_text
241
-
242
- print("\n==== date/time: " + str(datetime.datetime.now() - datetime.timedelta(hours=5)) + " ====")
243
- print("prompt_plus_generated: " + prompt_plus_generated)
244
-
245
- return generated_text
246
-
247
-
248
- def load_chain(tools_list, llm):
249
- chain = None
250
- express_chain = None
251
- memory = None
252
- if llm:
253
- print("\ntools_list", tools_list)
254
- tool_names = tools_list
255
- tools = load_tools(tool_names, llm=llm, news_api_key=news_api_key, tmdb_bearer_token=tmdb_bearer_token)
256
-
257
- memory = ConversationBufferMemory(memory_key="chat_history")
258
-
259
- chain = initialize_agent(tools, llm, agent="conversational-react-description", verbose=True, memory=memory)
260
- express_chain = LLMChain(llm=llm, prompt=PROMPT_TEMPLATE, verbose=True)
261
- return chain, express_chain, memory
262
-
263
-
264
- def set_openai_api_key(api_key, use_gpt4):
265
- """Set the api key and return chain.
266
- If no api_key, then None is returned.
267
- """
268
- if api_key and api_key.startswith("sk-") and len(api_key) > 50:
269
- os.environ["OPENAI_API_KEY"] = api_key
270
- print("\n\n ++++++++++++++ Setting OpenAI API key ++++++++++++++ \n\n")
271
- print(str(datetime.datetime.now()) + ": Before OpenAI, OPENAI_API_KEY length: " + str(
272
- len(os.environ["OPENAI_API_KEY"])))
273
-
274
- if use_gpt4:
275
- llm = OpenAIChat(temperature=0, max_tokens=MAX_TOKENS, model_name="gpt-4")
276
- print("Trying to use llm OpenAIChat with gpt-4")
277
- else:
278
- print("Trying to use llm OpenAI with text-davinci-003")
279
- llm = OpenAI(temperature=0, max_tokens=MAX_TOKENS, model_name="text-davinci-003")
280
-
281
- print(str(datetime.datetime.now()) + ": After OpenAI, OPENAI_API_KEY length: " + str(
282
- len(os.environ["OPENAI_API_KEY"])))
283
- chain, express_chain, memory = load_chain(TOOLS_DEFAULT_LIST, llm)
284
-
285
- # Pertains to question answering functionality
286
- embeddings = OpenAIEmbeddings()
287
-
288
- if use_gpt4:
289
- qa_chain = load_qa_chain(OpenAIChat(temperature=0, model_name="gpt-4"), chain_type="stuff")
290
- print("Trying to use qa_chain OpenAIChat with gpt-4")
291
- else:
292
- print("Trying to use qa_chain OpenAI with text-davinci-003")
293
- qa_chain = OpenAI(temperature=0, max_tokens=MAX_TOKENS, model_name="text-davinci-003")
294
-
295
- print(str(datetime.datetime.now()) + ": After load_chain, OPENAI_API_KEY length: " + str(
296
- len(os.environ["OPENAI_API_KEY"])))
297
- os.environ["OPENAI_API_KEY"] = ""
298
- return chain, express_chain, llm, embeddings, qa_chain, memory, use_gpt4
299
- return None, None, None, None, None, None, None
300
-
301
-
302
- def run_chain(chain, inp, capture_hidden_text):
303
- output = ""
304
- hidden_text = None
305
- if capture_hidden_text:
306
- error_msg = None
307
- tmp = sys.stdout
308
- hidden_text_io = StringIO()
309
- sys.stdout = hidden_text_io
310
-
311
- try:
312
- output = chain.run(input=inp)
313
- except AuthenticationError as ae:
314
- error_msg = AUTH_ERR_MSG + str(datetime.datetime.now()) + ". " + str(ae)
315
- print("error_msg", error_msg)
316
- except RateLimitError as rle:
317
- error_msg = "\n\nRateLimitError: " + str(rle)
318
- except ValueError as ve:
319
- error_msg = "\n\nValueError: " + str(ve)
320
- except InvalidRequestError as ire:
321
- error_msg = "\n\nInvalidRequestError: " + str(ire)
322
- except Exception as e:
323
- error_msg = "\n\n" + BUG_FOUND_MSG + ":\n\n" + str(e)
324
-
325
- sys.stdout = tmp
326
- hidden_text = hidden_text_io.getvalue()
327
-
328
- # remove escape characters from hidden_text
329
- hidden_text = re.sub(r'\x1b[^m]*m', '', hidden_text)
330
-
331
- # remove "Entering new AgentExecutor chain..." from hidden_text
332
- hidden_text = re.sub(r"Entering new AgentExecutor chain...\n", "", hidden_text)
333
-
334
- # remove "Finished chain." from hidden_text
335
- hidden_text = re.sub(r"Finished chain.", "", hidden_text)
336
-
337
- # Add newline after "Thought:" "Action:" "Observation:" "Input:" and "AI:"
338
- hidden_text = re.sub(r"Thought:", "\n\nThought:", hidden_text)
339
- hidden_text = re.sub(r"Action:", "\n\nAction:", hidden_text)
340
- hidden_text = re.sub(r"Observation:", "\n\nObservation:", hidden_text)
341
- hidden_text = re.sub(r"Input:", "\n\nInput:", hidden_text)
342
- hidden_text = re.sub(r"AI:", "\n\nAI:", hidden_text)
343
-
344
- if error_msg:
345
- hidden_text += error_msg
346
-
347
- print("hidden_text: ", hidden_text)
348
- else:
349
- try:
350
- output = chain.run(input=inp)
351
- except AuthenticationError as ae:
352
- output = AUTH_ERR_MSG + str(datetime.datetime.now()) + ". " + str(ae)
353
- print("output", output)
354
- except RateLimitError as rle:
355
- output = "\n\nRateLimitError: " + str(rle)
356
- except ValueError as ve:
357
- output = "\n\nValueError: " + str(ve)
358
- except InvalidRequestError as ire:
359
- output = "\n\nInvalidRequestError: " + str(ire)
360
- except Exception as e:
361
- output = "\n\n" + BUG_FOUND_MSG + ":\n\n" + str(e)
362
-
363
- return output, hidden_text
364
-
365
-
366
- def reset_memory(history, memory):
367
- memory.clear()
368
- history = []
369
- return history, history, memory
370
-
371
-
372
- class ChatWrapper:
373
-
374
- def __init__(self):
375
- self.lock = Lock()
376
-
377
- def __call__(
378
- self, api_key: str, inp: str, history: Optional[Tuple[str, str]], chain: Optional[ConversationChain],
379
- trace_chain: bool, speak_text: bool, talking_head: bool, monologue: bool, express_chain: Optional[LLMChain],
380
- num_words, formality, anticipation_level, joy_level, trust_level,
381
- fear_level, surprise_level, sadness_level, disgust_level, anger_level,
382
- lang_level, translate_to, literary_style, qa_chain, docsearch, use_embeddings, force_translate
383
- ):
384
- """Execute the chat functionality."""
385
- self.lock.acquire()
386
- try:
387
- print("\n==== date/time: " + str(datetime.datetime.now()) + " ====")
388
- print("inp: " + inp)
389
- print("trace_chain: ", trace_chain)
390
- print("speak_text: ", speak_text)
391
- print("talking_head: ", talking_head)
392
- print("monologue: ", monologue)
393
- history = history or []
394
- # If chain is None, that is because no API key was provided.
395
- output = "Please paste your OpenAI key from openai.com to use this app. " + str(datetime.datetime.now())
396
- hidden_text = output
397
-
398
- if chain:
399
- # Set OpenAI key
400
- import openai
401
- openai.api_key = api_key
402
- if not monologue:
403
- if use_embeddings:
404
- if inp and inp.strip() != "":
405
- if docsearch:
406
- docs = docsearch.similarity_search(inp)
407
- output = str(qa_chain.run(input_documents=docs, question=inp))
408
- else:
409
- output, hidden_text = "Please supply some text in the the Embeddings tab.", None
410
- else:
411
- output, hidden_text = "What's on your mind?", None
412
- else:
413
- output, hidden_text = run_chain(chain, inp, capture_hidden_text=trace_chain)
414
- else:
415
- output, hidden_text = inp, None
416
-
417
- output = transform_text(output, express_chain, num_words, formality, anticipation_level, joy_level,
418
- trust_level,
419
- fear_level, surprise_level, sadness_level, disgust_level, anger_level,
420
- lang_level, translate_to, literary_style, force_translate)
421
-
422
- text_to_display = output
423
- if trace_chain:
424
- text_to_display = hidden_text + "\n\n" + output
425
- history.append((inp, text_to_display))
426
-
427
- html_video, temp_file, html_audio, temp_aud_file = None, None, None, None
428
- if speak_text:
429
- if talking_head:
430
- if len(output) <= MAX_TALKING_HEAD_TEXT_LENGTH:
431
- html_video, temp_file = do_html_video_speak(output, translate_to)
432
- else:
433
- temp_file = LOOPING_TALKING_HEAD
434
- html_video = create_html_video(temp_file, TALKING_HEAD_WIDTH)
435
- html_audio, temp_aud_file = do_html_audio_speak(output, translate_to)
436
- else:
437
- html_audio, temp_aud_file = do_html_audio_speak(output, translate_to)
438
- else:
439
- if talking_head:
440
- temp_file = LOOPING_TALKING_HEAD
441
- html_video = create_html_video(temp_file, TALKING_HEAD_WIDTH)
442
- else:
443
- # html_audio, temp_aud_file = do_html_audio_speak(output, translate_to)
444
- # html_video = create_html_video(temp_file, "128")
445
- pass
446
-
447
- except Exception as e:
448
- raise e
449
- finally:
450
- self.lock.release()
451
- return history, history, html_video, temp_file, html_audio, temp_aud_file, ""
452
- # return history, history, html_audio, temp_aud_file, ""
453
-
454
 
455
  chat = ChatWrapper()
456
 
457
-
458
- def do_html_audio_speak(words_to_speak, polly_language):
459
- polly_client = boto3.Session(
460
- aws_access_key_id=os.environ["AWS_ACCESS_KEY_ID"],
461
- aws_secret_access_key=os.environ["AWS_SECRET_ACCESS_KEY"],
462
- region_name=os.environ["AWS_DEFAULT_REGION"]
463
- ).client('polly')
464
-
465
- # voice_id, language_code, engine = POLLY_VOICE_DATA.get_voice(polly_language, "Female")
466
- voice_id, language_code, engine = POLLY_VOICE_DATA.get_voice(polly_language, "Male")
467
- if not voice_id:
468
- # voice_id = "Joanna"
469
- voice_id = "Matthew"
470
- language_code = "en-US"
471
- engine = NEURAL_ENGINE
472
- response = polly_client.synthesize_speech(
473
- Text=words_to_speak,
474
- OutputFormat='mp3',
475
- VoiceId=voice_id,
476
- LanguageCode=language_code,
477
- Engine=engine
478
- )
479
-
480
- html_audio = '<pre>no audio</pre>'
481
-
482
- # Save the audio stream returned by Amazon Polly on Lambda's temp directory
483
- if "AudioStream" in response:
484
- with closing(response["AudioStream"]) as stream:
485
- # output = os.path.join("/tmp/", "speech.mp3")
486
-
487
- try:
488
- with open('audios/tempfile.mp3', 'wb') as f:
489
- f.write(stream.read())
490
- temp_aud_file = gr.File("audios/tempfile.mp3")
491
- temp_aud_file_url = "/file=" + temp_aud_file.value['name']
492
- html_audio = f'<audio autoplay><source src={temp_aud_file_url} type="audio/mp3"></audio>'
493
- except IOError as error:
494
- # Could not write to file, exit gracefully
495
- print(error)
496
- return None, None
497
- else:
498
- # The response didn't contain audio data, exit gracefully
499
- print("Could not stream audio")
500
- return None, None
501
-
502
- return html_audio, "audios/tempfile.mp3"
503
-
504
-
505
- def create_html_video(file_name, width):
506
- temp_file_url = "/file=" + tmp_file.value['name']
507
- html_video = f'<video width={width} height={width} autoplay muted loop><source src={temp_file_url} type="video/mp4" poster="Masahiro.png"></video>'
508
- return html_video
509
-
510
-
511
- def do_html_video_speak(words_to_speak, azure_language):
512
- azure_voice = AZURE_VOICE_DATA.get_voice(azure_language, "Male")
513
- if not azure_voice:
514
- azure_voice = "en-US-ChristopherNeural"
515
-
516
- headers = {"Authorization": f"Bearer {os.environ['EXHUMAN_API_KEY']}"}
517
- body = {
518
- 'bot_name': 'Masahiro',
519
- 'bot_response': words_to_speak,
520
- 'azure_voice': azure_voice,
521
- 'azure_style': 'friendly',
522
- 'animation_pipeline': 'high_speed',
523
- }
524
- api_endpoint = "https://api.exh.ai/animations/v1/generate_lipsync"
525
- res = requests.post(api_endpoint, json=body, headers=headers)
526
- print("res.status_code: ", res.status_code)
527
-
528
- html_video = '<pre>no video</pre>'
529
- if isinstance(res.content, bytes):
530
- response_stream = io.BytesIO(res.content)
531
- print("len(res.content)): ", len(res.content))
532
-
533
- with open('videos/tempfile.mp4', 'wb') as f:
534
- f.write(response_stream.read())
535
- temp_file = gr.File("videos/tempfile.mp4")
536
- temp_file_url = "/file=" + temp_file.value['name']
537
- html_video = f'<video width={TALKING_HEAD_WIDTH} height={TALKING_HEAD_WIDTH} autoplay><source src={temp_file_url} type="video/mp4" poster="Masahiro.png"></video>'
538
- else:
539
- print('video url unknown')
540
- return html_video, "videos/tempfile.mp4"
541
-
542
-
543
- def update_selected_tools(widget, state, llm):
544
- if widget:
545
- state = widget
546
- chain, express_chain, memory = load_chain(state, llm)
547
- return state, llm, chain, express_chain
548
-
549
-
550
- def update_talking_head(widget, state):
551
- if widget:
552
- state = widget
553
-
554
- video_html_talking_head = create_html_video(LOOPING_TALKING_HEAD, TALKING_HEAD_WIDTH)
555
- return state, video_html_talking_head
556
- else:
557
- # return state, create_html_video(LOOPING_TALKING_HEAD, "32")
558
- return None, "<pre></pre>"
559
-
560
-
561
- def update_foo(widget, state):
562
- if widget:
563
- state = widget
564
- return state
565
-
566
-
567
- # Pertains to question answering functionality
568
- def update_embeddings(embeddings_text, embeddings, qa_chain):
569
- if embeddings_text:
570
- text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
571
- texts = text_splitter.split_text(embeddings_text)
572
-
573
- docsearch = FAISS.from_texts(texts, embeddings)
574
- print("Embeddings updated")
575
- return docsearch
576
-
577
-
578
- # Pertains to question answering functionality
579
- def update_use_embeddings(widget, state):
580
- if widget:
581
- state = widget
582
- return state
583
-
584
-
585
  with gr.Blocks(css=".gradio-container {background-color: lightgray}") as block:
586
  llm_state = gr.State()
587
  history_state = gr.State()
@@ -639,10 +84,10 @@ with gr.Blocks(css=".gradio-container {background-color: lightgray}") as block:
639
  outputs=[speak_text_state])
640
 
641
  my_file = gr.File(label="Upload a file", type="file", visible=False)
642
- tmp_file = gr.File(LOOPING_TALKING_HEAD, visible=False)
643
  # tmp_file_url = "/file=" + tmp_file.value['name']
644
- htm_video = create_html_video(LOOPING_TALKING_HEAD, TALKING_HEAD_WIDTH)
645
- video_html = gr.HTML(htm_video)
646
 
647
  # my_aud_file = gr.File(label="Audio file", type="file", visible=True)
648
  tmp_aud_file = gr.File("audios/tempfile.mp3", visible=False)
@@ -683,20 +128,20 @@ with gr.Blocks(css=".gradio-container {background-color: lightgray}") as block:
683
  )
684
 
685
  with gr.Tab("Settings"):
686
- tools_cb_group = gr.CheckboxGroup(label="Tools:", choices=TOOLS_LIST,
687
- value=TOOLS_DEFAULT_LIST)
688
- tools_cb_group.change(update_selected_tools,
689
- inputs=[tools_cb_group, tools_list_state, llm_state],
690
- outputs=[tools_list_state, llm_state, chain_state, express_chain_state])
691
-
692
- trace_chain_cb = gr.Checkbox(label="Show reasoning chain in chat bubble", value=False)
693
- trace_chain_cb.change(update_foo, inputs=[trace_chain_cb, trace_chain_state],
694
- outputs=[trace_chain_state])
695
-
696
- force_translate_cb = gr.Checkbox(label="Force translation to selected Output Language",
697
- value=FORCE_TRANSLATE_DEFAULT)
698
- force_translate_cb.change(update_foo, inputs=[force_translate_cb, force_translate_state],
699
- outputs=[force_translate_state])
700
 
701
  # speak_text_cb = gr.Checkbox(label="Speak text from agent", value=False)
702
  # speak_text_cb.change(update_foo, inputs=[speak_text_cb, speak_text_state],
 
2
  import os
3
  import ssl
4
  from contextlib import closing
 
 
5
 
6
  import boto3
7
  import gradio as gr
8
  import requests
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  # Pertains to Express-inator functionality
10
  from langchain.prompts import PromptTemplate
11
 
12
+ from config.config import TALKING_HEAD_WIDTH, TOOLS_DEFAULT_LIST, NUM_WORDS_DEFAULT, FORMALITY_DEFAULT, EMOTION_DEFAULT, \
13
+ LANG_LEVEL_DEFAULT, TRANSLATE_TO_DEFAULT, LITERARY_STYLE_DEFAULT, LOOPING_TALKING_HEAD, TOOLS_LIST, MAX_WORDS
14
+ from utilities.audio import FORCE_TRANSLATE_DEFAULT, USE_GPT4_DEFAULT, transcribe, WHISPER_DETECT_LANG
15
+ from utilities.audio import POLLY_VOICE_DATA, AZURE_VOICE_DATA
16
+ from utilities.html_stuff import create_html_video, update_talking_head
17
+ from utilities.polly_utils import NEURAL_ENGINE
18
+ from utilities.reset_memory import ChatWrapper, reset_memory
19
+ from utilities.set_openai_api_key import set_openai_api_key
20
+ from utilities.update_things import update_foo, update_selected_tools, update_use_embeddings, \
21
+ update_embeddings
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
  # Temporarily address Wolfram Alpha SSL certificate issue
24
  ssl._create_default_https_context = ssl._create_unverified_context
25
 
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
  chat = ChatWrapper()
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  with gr.Blocks(css=".gradio-container {background-color: lightgray}") as block:
31
  llm_state = gr.State()
32
  history_state = gr.State()
 
84
  outputs=[speak_text_state])
85
 
86
  my_file = gr.File(label="Upload a file", type="file", visible=False)
87
+
88
  # tmp_file_url = "/file=" + tmp_file.value['name']
89
+ html_video = create_html_video(LOOPING_TALKING_HEAD, TALKING_HEAD_WIDTH)
90
+ video_html = gr.HTML(html_video)
91
 
92
  # my_aud_file = gr.File(label="Audio file", type="file", visible=True)
93
  tmp_aud_file = gr.File("audios/tempfile.mp3", visible=False)
 
128
  )
129
 
130
  with gr.Tab("Settings"):
131
+ tools_checkbox_group = gr.CheckboxGroup(label="Tools:", choices=TOOLS_LIST,
132
+ value=TOOLS_DEFAULT_LIST)
133
+ tools_checkbox_group.change(update_selected_tools,
134
+ inputs=[tools_checkbox_group, tools_list_state, llm_state],
135
+ outputs=[tools_list_state, llm_state, chain_state, express_chain_state])
136
+
137
+ trace_chain_checkbox = gr.Checkbox(label="Show reasoning chain in chat bubble", value=False)
138
+ trace_chain_checkbox.change(update_foo, inputs=[trace_chain_checkbox, trace_chain_state],
139
+ outputs=[trace_chain_state])
140
+
141
+ force_translate_checkbox = gr.Checkbox(label="Force translation to selected Output Language",
142
+ value=FORCE_TRANSLATE_DEFAULT)
143
+ force_translate_checkbox.change(update_foo, inputs=[force_translate_checkbox, force_translate_state],
144
+ outputs=[force_translate_state])
145
 
146
  # speak_text_cb = gr.Checkbox(label="Speak text from agent", value=False)
147
  # speak_text_cb.change(update_foo, inputs=[speak_text_cb, speak_text_state],
config/config.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ from langchain import PromptTemplate
4
+
5
+ TALKING_HEAD_WIDTH = 192
6
+
7
+ # Console to variable
8
+ # Pertains to question answering functionality
9
+
10
+ TOOLS_LIST = ['serpapi', 'wolfram-alpha', 'pal-math',
11
+ 'pal-colored-objects','google-search','news-api','tmdb-api','open-meteo-api']
12
+ TOOLS_DEFAULT_LIST = ['serpapi']
13
+ BUG_FOUND_MSG = "Congratulations, you've found a bug in this application!"
14
+ # AUTH_ERR_MSG = "Please paste your OpenAI key from openai.com to use this application. It is not necessary to hit a button or key after pasting it."
15
+ AUTH_ERR_MSG = "Please paste your OpenAI key from openai.com to use this application. "
16
+ MAX_TOKENS = 512
17
+
18
+ LOOPING_TALKING_HEAD = "videos/Masahiro.mp4"
19
+
20
+ MAX_TALKING_HEAD_TEXT_LENGTH = 155
21
+
22
+ # Pertains to Express-inator functionality
23
+ NUM_WORDS_DEFAULT = 0
24
+ MAX_WORDS = 4000
25
+ FORMALITY_DEFAULT = "N/A"
26
+ TEMPERATURE_DEFAULT = 0
27
+ EMOTION_DEFAULT = "N/A"
28
+ LANG_LEVEL_DEFAULT = "N/A"
29
+ TRANSLATE_TO_DEFAULT = "N/A"
30
+ LITERARY_STYLE_DEFAULT = "N/A"
31
+ PROMPT_TEMPLATE = PromptTemplate(
32
+ input_variables=["original_words", "num_words", "formality", "emotions", "lang_level", "translate_to",
33
+ "literary_style"],
34
+ template="Restate {num_words}{formality}{emotions}{lang_level}{translate_to}{literary_style}the following: \n{original_words}\n",
35
+ )
36
+
utilities/audio.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import warnings
2
+
3
+ import whisper
4
+
5
+ from utilities.azure_utils import AzureVoiceData
6
+ from utilities.polly_utils import PollyVoiceData
7
+
8
+ FORCE_TRANSLATE_DEFAULT = True
9
+ USE_GPT4_DEFAULT = True
10
+
11
+ POLLY_VOICE_DATA = PollyVoiceData()
12
+ AZURE_VOICE_DATA = AzureVoiceData()
13
+
14
+ # Pertains to WHISPER functionality
15
+ WHISPER_DETECT_LANG = "Detect language"
16
+
17
+ # UNCOMMENT TO USE WHISPER
18
+ warnings.filterwarnings("ignore")
19
+ WHISPER_MODEL = whisper.load_model("large")
20
+ print("WHISPER_MODEL", WHISPER_MODEL)
21
+
22
+
23
+ # UNCOMMENT TO USE WHISPER
24
+ def transcribe(aud_inp, whisper_lang):
25
+ if aud_inp is None:
26
+ return ""
27
+ aud = whisper.load_audio(aud_inp)
28
+ aud = whisper.pad_or_trim(aud)
29
+ mel = whisper.log_mel_spectrogram(aud).to(WHISPER_MODEL.device)
30
+ _, probs = WHISPER_MODEL.detect_language(mel)
31
+ options = whisper.DecodingOptions()
32
+ if whisper_lang != WHISPER_DETECT_LANG:
33
+ whisper_lang_code = POLLY_VOICE_DATA.get_whisper_lang_code(whisper_lang)
34
+ options = whisper.DecodingOptions(language=whisper_lang_code)
35
+ result = whisper.decode(WHISPER_MODEL, mel, options)
36
+ print("result.text", result.text)
37
+ result_text = ""
38
+ if result and result.text:
39
+ result_text = result.text
40
+ return result_text
41
+
42
+
43
+ # TEMPORARY FOR TESTING
44
+ def transcribe_dummy(aud_inp_tb, whisper_lang):
45
+ if aud_inp_tb is None:
46
+ return ""
47
+ # aud = whisper.load_audio(aud_inp)
48
+ # aud = whisper.pad_or_trim(aud)
49
+ # mel = whisper.log_mel_spectrogram(aud).to(WHISPER_MODEL.device)
50
+ # _, probs = WHISPER_MODEL.detect_language(mel)
51
+ # options = whisper.DecodingOptions()
52
+ # options = whisper.DecodingOptions(language="ja")
53
+ # result = whisper.decode(WHISPER_MODEL, mel, options)
54
+ result_text = "Whisper will detect language"
55
+ if whisper_lang != WHISPER_DETECT_LANG:
56
+ whisper_lang_code = POLLY_VOICE_DATA.get_whisper_lang_code(whisper_lang)
57
+ result_text = f"Whisper will use lang code: {whisper_lang_code}"
58
+ print("result_text", result_text)
59
+ return aud_inp_tb
60
+
azure_utils.py β†’ utilities/azure_utils.py RENAMED
File without changes
utilities/html_stuff.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import io
2
+ import os
3
+ from contextlib import closing
4
+
5
+ import boto3
6
+ import gradio as gr
7
+
8
+ import requests
9
+
10
+ from config.config import TALKING_HEAD_WIDTH, LOOPING_TALKING_HEAD
11
+ from utilities.audio import AZURE_VOICE_DATA, POLLY_VOICE_DATA
12
+ from utilities.polly_utils import NEURAL_ENGINE
13
+
14
+
15
+ def create_html_video(file_name, width):
16
+ tmp_file = gr.File(LOOPING_TALKING_HEAD, visible=False)
17
+ temp_file_url = "/file=" + tmp_file.value['name']
18
+ html_video = f'<video width={width} height={width} autoplay muted loop><source src={temp_file_url} type="video/mp4" poster="Masahiro.png"></video>'
19
+ return html_video
20
+
21
+ def update_talking_head(widget, state):
22
+ if widget:
23
+ state = widget
24
+
25
+ video_html_talking_head = create_html_video(LOOPING_TALKING_HEAD, TALKING_HEAD_WIDTH)
26
+ return state, video_html_talking_head
27
+ else:
28
+ # return state, create_html_video(LOOPING_TALKING_HEAD, "32")
29
+ return None, "<pre></pre>"
30
+
31
+
32
+
33
+ def do_html_audio_speak(words_to_speak, polly_language):
34
+ polly_client = boto3.Session(
35
+ aws_access_key_id=os.environ["AWS_ACCESS_KEY_ID"],
36
+ aws_secret_access_key=os.environ["AWS_SECRET_ACCESS_KEY"],
37
+ region_name=os.environ["AWS_DEFAULT_REGION"]
38
+ ).client('polly')
39
+
40
+ # voice_id, language_code, engine = POLLY_VOICE_DATA.get_voice(polly_language, "Female")
41
+ voice_id, language_code, engine = POLLY_VOICE_DATA.get_voice(polly_language, "Male")
42
+ if not voice_id:
43
+ # voice_id = "Joanna"
44
+ voice_id = "Matthew"
45
+ language_code = "en-US"
46
+ engine = NEURAL_ENGINE
47
+ response = polly_client.synthesize_speech(
48
+ Text=words_to_speak,
49
+ OutputFormat='mp3',
50
+ VoiceId=voice_id,
51
+ LanguageCode=language_code,
52
+ Engine=engine
53
+ )
54
+
55
+ html_audio = '<pre>no audio</pre>'
56
+
57
+ # Save the audio stream returned by Amazon Polly on Lambda's temp directory
58
+ if "AudioStream" in response:
59
+ with closing(response["AudioStream"]) as stream:
60
+ # output = os.path.join("/tmp/", "speech.mp3")
61
+
62
+ try:
63
+ with open('audios/tempfile.mp3', 'wb') as f:
64
+ f.write(stream.read())
65
+ temp_aud_file = gr.File("audios/tempfile.mp3")
66
+ temp_aud_file_url = "/file=" + temp_aud_file.value['name']
67
+ html_audio = f'<audio autoplay><source src={temp_aud_file_url} type="audio/mp3"></audio>'
68
+ except IOError as error:
69
+ # Could not write to file, exit gracefully
70
+ print(error)
71
+ return None, None
72
+ else:
73
+ # The response didn't contain audio data, exit gracefully
74
+ print("Could not stream audio")
75
+ return None, None
76
+
77
+ return html_audio, "audios/tempfile.mp3"
78
+
79
+
80
+
81
+
82
+ def do_html_video_speak(words_to_speak, azure_language):
83
+ azure_voice = AZURE_VOICE_DATA.get_voice(azure_language, "Male")
84
+ if not azure_voice:
85
+ azure_voice = "en-US-ChristopherNeural"
86
+
87
+ headers = {"Authorization": f"Bearer {os.environ['EXHUMAN_API_KEY']}"}
88
+ body = {
89
+ 'bot_name': 'Masahiro',
90
+ 'bot_response': words_to_speak,
91
+ 'azure_voice': azure_voice,
92
+ 'azure_style': 'friendly',
93
+ 'animation_pipeline': 'high_speed',
94
+ }
95
+ api_endpoint = "https://api.exh.ai/animations/v1/generate_lipsync"
96
+ res = requests.post(api_endpoint, json=body, headers=headers)
97
+ print("res.status_code: ", res.status_code)
98
+
99
+ html_video = '<pre>no video</pre>'
100
+ if isinstance(res.content, bytes):
101
+ response_stream = io.BytesIO(res.content)
102
+ print("len(res.content)): ", len(res.content))
103
+
104
+ with open('videos/tempfile.mp4', 'wb') as f:
105
+ f.write(response_stream.read())
106
+ temp_file = gr.File("videos/tempfile.mp4")
107
+ temp_file_url = "/file=" + temp_file.value['name']
108
+ html_video = f'<video width={TALKING_HEAD_WIDTH} height={TALKING_HEAD_WIDTH} autoplay><source src={temp_file_url} type="video/mp4" poster="Masahiro.png"></video>'
109
+ else:
110
+ print('video url unknown')
111
+ return html_video, "videos/tempfile.mp4"
utilities/load_chain.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ from langchain import LLMChain
4
+ from langchain.agents import load_tools, initialize_agent
5
+ from langchain.memory import ConversationBufferMemory
6
+
7
+ from config.config import PROMPT_TEMPLATE
8
+
9
+
10
+ def load_chain(tools_list, llm):
11
+ chain = None
12
+ express_chain = None
13
+ memory = None
14
+ if llm:
15
+ print("\ntools_list", tools_list)
16
+ tool_names = tools_list
17
+
18
+ news_api_key = os.environ["NEWS_API_KEY"]
19
+ tmdb_bearer_token = os.environ["TMDB_BEARER_TOKEN"]
20
+ tools = load_tools(tool_names,
21
+ llm=llm,
22
+ news_api_key=news_api_key,
23
+ tmdb_bearer_token=tmdb_bearer_token)
24
+
25
+ memory = ConversationBufferMemory(memory_key="chat_history")
26
+
27
+ chain = initialize_agent(tools, llm, agent="conversational-react-description", verbose=True, memory=memory)
28
+ express_chain = LLMChain(llm=llm, prompt=PROMPT_TEMPLATE, verbose=True)
29
+ return chain, express_chain, memory
polly_utils.py β†’ utilities/polly_utils.py RENAMED
File without changes
utilities/reset_memory.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import datetime
2
+ from threading import Lock
3
+ from typing import Tuple, Optional
4
+
5
+ from langchain import ConversationChain, LLMChain
6
+
7
+ from config.config import MAX_TALKING_HEAD_TEXT_LENGTH, LOOPING_TALKING_HEAD, TALKING_HEAD_WIDTH
8
+ from utilities.html_stuff import do_html_video_speak, create_html_video, do_html_audio_speak
9
+ from utilities.transform_text import transform_text
10
+
11
+
12
+ def reset_memory(history, memory):
13
+ memory.clear()
14
+ history = []
15
+ return history, history, memory
16
+
17
+
18
+ class ChatWrapper:
19
+
20
+ def __init__(self):
21
+ self.lock = Lock()
22
+
23
+ def __call__(
24
+ self, api_key: str, inp: str, history: Optional[Tuple[str, str]], chain: Optional[ConversationChain],
25
+ trace_chain: bool, speak_text: bool, talking_head: bool, monologue: bool, express_chain: Optional[LLMChain],
26
+ num_words, formality, anticipation_level, joy_level, trust_level,
27
+ fear_level, surprise_level, sadness_level, disgust_level, anger_level,
28
+ lang_level, translate_to, literary_style, qa_chain, docsearch, use_embeddings, force_translate
29
+ ):
30
+ """Execute the chat functionality."""
31
+ self.lock.acquire()
32
+ try:
33
+ print("\n==== date/time: " + str(datetime.datetime.now()) + " ====")
34
+ print("inp: " + inp)
35
+ print("trace_chain: ", trace_chain)
36
+ print("speak_text: ", speak_text)
37
+ print("talking_head: ", talking_head)
38
+ print("monologue: ", monologue)
39
+ history = history or []
40
+ # If chain is None, that is because no API key was provided.
41
+ output = "Please paste your OpenAI key from openai.com to use this app. " + str(datetime.datetime.now())
42
+ hidden_text = output
43
+
44
+ if chain:
45
+ # Set OpenAI key
46
+ import openai
47
+ openai.api_key = api_key
48
+ if not monologue:
49
+ if use_embeddings:
50
+ if inp and inp.strip() != "":
51
+ if docsearch:
52
+ docs = docsearch.similarity_search(inp)
53
+ output = str(qa_chain.run(input_documents=docs, question=inp))
54
+ else:
55
+ output, hidden_text = "Please supply some text in the the Embeddings tab.", None
56
+ else:
57
+ output, hidden_text = "What's on your mind?", None
58
+ else:
59
+ output, hidden_text = run_chain(chain, inp, capture_hidden_text=trace_chain)
60
+ else:
61
+ output, hidden_text = inp, None
62
+
63
+ output = transform_text(output, express_chain, num_words, formality, anticipation_level, joy_level,
64
+ trust_level,
65
+ fear_level, surprise_level, sadness_level, disgust_level, anger_level,
66
+ lang_level, translate_to, literary_style, force_translate)
67
+
68
+ text_to_display = output
69
+ if trace_chain:
70
+ text_to_display = hidden_text + "\n\n" + output
71
+ history.append((inp, text_to_display))
72
+
73
+ html_video, temp_file, html_audio, temp_aud_file = None, None, None, None
74
+ if speak_text:
75
+ if talking_head:
76
+ if len(output) <= MAX_TALKING_HEAD_TEXT_LENGTH:
77
+ html_video, temp_file = do_html_video_speak(output, translate_to)
78
+ else:
79
+ temp_file = LOOPING_TALKING_HEAD
80
+ html_video = create_html_video(temp_file, TALKING_HEAD_WIDTH)
81
+ html_audio, temp_aud_file = do_html_audio_speak(output, translate_to)
82
+ else:
83
+ html_audio, temp_aud_file = do_html_audio_speak(output, translate_to)
84
+ else:
85
+ if talking_head:
86
+ temp_file = LOOPING_TALKING_HEAD
87
+ html_video = create_html_video(temp_file, TALKING_HEAD_WIDTH)
88
+ else:
89
+ # html_audio, temp_aud_file = do_html_audio_speak(output, translate_to)
90
+ # html_video = create_html_video(temp_file, "128")
91
+ pass
92
+
93
+ except Exception as e:
94
+ raise e
95
+ finally:
96
+ self.lock.release()
97
+ return history, history, html_video, temp_file, html_audio, temp_aud_file, ""
98
+ # return history, history, html_audio, temp_aud_file, ""
99
+
utilities/run_chain.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import datetime
2
+ import re
3
+ import sys
4
+ from io import StringIO
5
+
6
+ from openai import InvalidRequestError
7
+ from openai.error import RateLimitError, AuthenticationError
8
+
9
+ from config.config import BUG_FOUND_MSG, AUTH_ERR_MSG
10
+
11
+
12
+ def run_chain(chain, inp, capture_hidden_text):
13
+ output = ""
14
+ hidden_text = None
15
+ if capture_hidden_text:
16
+ error_msg = None
17
+ tmp = sys.stdout
18
+ hidden_text_io = StringIO()
19
+ sys.stdout = hidden_text_io
20
+
21
+ try:
22
+ output = chain.run(input=inp)
23
+ except AuthenticationError as ae:
24
+ error_msg = AUTH_ERR_MSG + str(datetime.datetime.now()) + ". " + str(ae)
25
+ print("error_msg", error_msg)
26
+ except RateLimitError as rle:
27
+ error_msg = "\n\nRateLimitError: " + str(rle)
28
+ except ValueError as ve:
29
+ error_msg = "\n\nValueError: " + str(ve)
30
+ except InvalidRequestError as ire:
31
+ error_msg = "\n\nInvalidRequestError: " + str(ire)
32
+ except Exception as e:
33
+ error_msg = "\n\n" + BUG_FOUND_MSG + ":\n\n" + str(e)
34
+
35
+ sys.stdout = tmp
36
+ hidden_text = hidden_text_io.getvalue()
37
+
38
+ # remove escape characters from hidden_text
39
+ hidden_text = re.sub(r'\x1b[^m]*m', '', hidden_text)
40
+
41
+ # remove "Entering new AgentExecutor chain..." from hidden_text
42
+ hidden_text = re.sub(r"Entering new AgentExecutor chain...\n", "", hidden_text)
43
+
44
+ # remove "Finished chain." from hidden_text
45
+ hidden_text = re.sub(r"Finished chain.", "", hidden_text)
46
+
47
+ # Add newline after "Thought:" "Action:" "Observation:" "Input:" and "AI:"
48
+ hidden_text = re.sub(r"Thought:", "\n\nThought:", hidden_text)
49
+ hidden_text = re.sub(r"Action:", "\n\nAction:", hidden_text)
50
+ hidden_text = re.sub(r"Observation:", "\n\nObservation:", hidden_text)
51
+ hidden_text = re.sub(r"Input:", "\n\nInput:", hidden_text)
52
+ hidden_text = re.sub(r"AI:", "\n\nAI:", hidden_text)
53
+
54
+ if error_msg:
55
+ hidden_text += error_msg
56
+
57
+ print("hidden_text: ", hidden_text)
58
+ else:
59
+ try:
60
+ output = chain.run(input=inp)
61
+ except AuthenticationError as ae:
62
+ output = AUTH_ERR_MSG + str(datetime.datetime.now()) + ". " + str(ae)
63
+ print("output", output)
64
+ except RateLimitError as rle:
65
+ output = "\n\nRateLimitError: " + str(rle)
66
+ except ValueError as ve:
67
+ output = "\n\nValueError: " + str(ve)
68
+ except InvalidRequestError as ire:
69
+ output = "\n\nInvalidRequestError: " + str(ire)
70
+ except Exception as e:
71
+ output = "\n\n" + BUG_FOUND_MSG + ":\n\n" + str(e)
72
+
73
+ return output, hidden_text
utilities/set_openai_api_key.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from datetime import datetime
3
+
4
+ from langchain import OpenAI
5
+ from langchain.chains import load_chain
6
+ from langchain.chains.question_answering import load_qa_chain
7
+ from langchain.embeddings import OpenAIEmbeddings
8
+ from langchain.llms import OpenAIChat
9
+
10
+ from config.config import MAX_TOKENS, TOOLS_DEFAULT_LIST
11
+
12
+
13
+ def set_openai_api_key(api_key, use_gpt4):
14
+ """Set the api key and return chain.
15
+ If no api_key, then None is returned.
16
+ """
17
+ if api_key and api_key.startswith("sk-") and len(api_key) > 50:
18
+ os.environ["OPENAI_API_KEY"] = api_key
19
+ print("\n\n ++++++++++++++ Setting OpenAI API key ++++++++++++++ \n\n")
20
+ print(str(datetime.now()) + ": Before OpenAI, OPENAI_API_KEY length: " + str(
21
+ len(os.environ["OPENAI_API_KEY"])))
22
+
23
+ if use_gpt4:
24
+ llm = OpenAIChat(temperature=0, max_tokens=MAX_TOKENS, model_name="gpt-4")
25
+ print("Trying to use llm OpenAIChat with gpt-4")
26
+ else:
27
+ print("Trying to use llm OpenAI with text-davinci-003")
28
+ llm = OpenAI(temperature=0, max_tokens=MAX_TOKENS, model_name="text-davinci-003")
29
+
30
+ print(str(datetime.now()) + ": After OpenAI, OPENAI_API_KEY length: " + str(
31
+ len(os.environ["OPENAI_API_KEY"])))
32
+ chain, express_chain, memory = load_chain(TOOLS_DEFAULT_LIST, llm)
33
+
34
+ # Pertains to question answering functionality
35
+ embeddings = OpenAIEmbeddings()
36
+
37
+ if use_gpt4:
38
+ qa_chain = load_qa_chain(OpenAIChat(temperature=0, model_name="gpt-4"), chain_type="stuff")
39
+ print("Trying to use qa_chain OpenAIChat with gpt-4")
40
+ else:
41
+ print("Trying to use qa_chain OpenAI with text-davinci-003")
42
+ qa_chain = OpenAI(temperature=0, max_tokens=MAX_TOKENS, model_name="text-davinci-003")
43
+
44
+ print(str(datetime.now()) + ": After load_chain, OPENAI_API_KEY length: " + str(
45
+ len(os.environ["OPENAI_API_KEY"])))
46
+ os.environ["OPENAI_API_KEY"] = ""
47
+ return chain, express_chain, llm, embeddings, qa_chain, memory, use_gpt4
48
+ return None, None, None, None, None, None, None
utilities/transform_text.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Pertains to Express-inator functionality
2
+ import datetime
3
+
4
+ from config.config import PROMPT_TEMPLATE, TRANSLATE_TO_DEFAULT, LANG_LEVEL_DEFAULT, LITERARY_STYLE_DEFAULT
5
+
6
+
7
+ def transform_text(desc, express_chain, num_words, formality,
8
+ anticipation_level, joy_level, trust_level,
9
+ fear_level, surprise_level, sadness_level, disgust_level, anger_level,
10
+ lang_level, translate_to, literary_style, force_translate):
11
+ num_words_prompt = ""
12
+ if num_words and int(num_words) != 0:
13
+ num_words_prompt = "using up to " + str(num_words) + " words, "
14
+
15
+ # Change some arguments to lower case
16
+ formality = formality.lower()
17
+ anticipation_level = anticipation_level.lower()
18
+ joy_level = joy_level.lower()
19
+ trust_level = trust_level.lower()
20
+ fear_level = fear_level.lower()
21
+ surprise_level = surprise_level.lower()
22
+ sadness_level = sadness_level.lower()
23
+ disgust_level = disgust_level.lower()
24
+ anger_level = anger_level.lower()
25
+
26
+ formality_str = ""
27
+ if formality != "n/a":
28
+ formality_str = "in a " + formality + " manner, "
29
+
30
+ # put all emotions into a list
31
+ emotions = []
32
+ if anticipation_level != "n/a":
33
+ emotions.append(anticipation_level)
34
+ if joy_level != "n/a":
35
+ emotions.append(joy_level)
36
+ if trust_level != "n/a":
37
+ emotions.append(trust_level)
38
+ if fear_level != "n/a":
39
+ emotions.append(fear_level)
40
+ if surprise_level != "n/a":
41
+ emotions.append(surprise_level)
42
+ if sadness_level != "n/a":
43
+ emotions.append(sadness_level)
44
+ if disgust_level != "n/a":
45
+ emotions.append(disgust_level)
46
+ if anger_level != "n/a":
47
+ emotions.append(anger_level)
48
+
49
+ emotions_str = ""
50
+ if len(emotions) > 0:
51
+ if len(emotions) == 1:
52
+ emotions_str = "with emotion of " + emotions[0] + ", "
53
+ else:
54
+ emotions_str = "with emotions of " + ", ".join(emotions[:-1]) + " and " + emotions[-1] + ", "
55
+
56
+ lang_level_str = ""
57
+ if lang_level != LANG_LEVEL_DEFAULT:
58
+ lang_level_str = "at a level that a person in " + lang_level + " can easily comprehend, " if translate_to == TRANSLATE_TO_DEFAULT else ""
59
+
60
+ translate_to_str = ""
61
+ if translate_to != TRANSLATE_TO_DEFAULT and (force_translate or lang_level != LANG_LEVEL_DEFAULT):
62
+ translate_to_str = "translated to " + translate_to + (
63
+ "" if lang_level == LANG_LEVEL_DEFAULT else " at a level that a person in " + lang_level + " can easily comprehend") + ", "
64
+
65
+ literary_style_str = ""
66
+ if literary_style != LITERARY_STYLE_DEFAULT:
67
+ if literary_style == "Prose":
68
+ literary_style_str = "as prose, "
69
+ if literary_style == "Story":
70
+ literary_style_str = "as a story, "
71
+ elif literary_style == "Summary":
72
+ literary_style_str = "as a summary, "
73
+ elif literary_style == "Outline":
74
+ literary_style_str = "as an outline numbers and lower case letters, "
75
+ elif literary_style == "Bullets":
76
+ literary_style_str = "as bullet points using bullets, "
77
+ elif literary_style == "Poetry":
78
+ literary_style_str = "as a poem, "
79
+ elif literary_style == "Haiku":
80
+ literary_style_str = "as a haiku, "
81
+ elif literary_style == "Limerick":
82
+ literary_style_str = "as a limerick, "
83
+ elif literary_style == "Rap":
84
+ literary_style_str = "as a rap, "
85
+ elif literary_style == "Joke":
86
+ literary_style_str = "as a very funny joke with a setup and punchline, "
87
+ elif literary_style == "Knock-knock":
88
+ literary_style_str = "as a very funny knock-knock joke, "
89
+ elif literary_style == "FAQ":
90
+ literary_style_str = "as a FAQ with several questions and answers, "
91
+
92
+ formatted_prompt = PROMPT_TEMPLATE.format(
93
+ original_words=desc,
94
+ num_words=num_words_prompt,
95
+ formality=formality_str,
96
+ emotions=emotions_str,
97
+ lang_level=lang_level_str,
98
+ translate_to=translate_to_str,
99
+ literary_style=literary_style_str
100
+ )
101
+
102
+ trans_instr = num_words_prompt + formality_str + emotions_str + lang_level_str + translate_to_str + literary_style_str
103
+ if express_chain and len(trans_instr.strip()) > 0:
104
+ generated_text = express_chain.run(
105
+ {'original_words': desc, 'num_words': num_words_prompt, 'formality': formality_str,
106
+ 'emotions': emotions_str, 'lang_level': lang_level_str, 'translate_to': translate_to_str,
107
+ 'literary_style': literary_style_str}).strip()
108
+ else:
109
+ print("Not transforming text")
110
+ generated_text = desc
111
+
112
+ # replace all newlines with <br> in generated_text
113
+ generated_text = generated_text.replace("\n", "\n\n")
114
+
115
+ prompt_plus_generated = "GPT prompt: " + formatted_prompt + "\n\n" + generated_text
116
+
117
+ print("\n==== date/time: " + str(datetime.datetime.now() - datetime.timedelta(hours=5)) + " ====")
118
+ print("prompt_plus_generated: " + prompt_plus_generated)
119
+
120
+ return generated_text
utilities/update_things.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain import FAISS
2
+ from langchain.text_splitter import CharacterTextSplitter
3
+
4
+
5
+ from utilities.load_chain import load_chain
6
+
7
+
8
+ def update_selected_tools(widget, state, llm):
9
+ if widget:
10
+ state = widget
11
+ chain, express_chain, memory = load_chain(state, llm)
12
+ return state, llm, chain, express_chain
13
+
14
+
15
+
16
+
17
+ def update_foo(widget, state):
18
+ if widget:
19
+ state = widget
20
+ return state
21
+
22
+
23
+ # Pertains to question answering functionality
24
+ def update_embeddings(embeddings_text, embeddings, qa_chain):
25
+ if embeddings_text:
26
+ text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
27
+ texts = text_splitter.split_text(embeddings_text)
28
+
29
+ docsearch = FAISS.from_texts(texts, embeddings)
30
+ print("Embeddings updated")
31
+ return docsearch
32
+
33
+
34
+ # Pertains to question answering functionality
35
+ def update_use_embeddings(widget, state):
36
+ if widget:
37
+ state = widget
38
+ return state
39
+