import gradio as gr import random import torch from transformers import AutoConfig, AutoTokenizer, AutoModelWithLMHead from transformers import GPT2Tokenizer, GPT2LMHeadModel from itertools import chain import os import librosa import tempfile from typing import Optional import numpy as np import wave from huggingface_hub import hf_hub_download from stt import Model #### STT ########### ########### STT English ############## state = gr.Variable() REPO_ID = "mbarnig/lb-de-fr-en-pt-coqui-stt-models" my_title = "STT-ChatGPT-TTS with Coqui" my_description = "TODO add description and reference: STT base from mbarnig/lb-de-fr-en-pt-coqui-stt-models - 🐸 [Coqui.ai](https://coqui.ai/)." STT_LANGUAGES = [ "English", ] EXAMPLES = [ ["examples/english.wav", "English", True, "Linda", "every window and roof which could command a view of the horrible performance was occupied"], ] def stt_record(audio_record_buffer): #using english model, it is here to reduce memory usage, will trigger download first run #unfortunately will be slow as it is shared cpu/memory need to free memory after run acoustic_model = Model(hf_hub_download(repo_id = REPO_ID, filename = "english/model.tflite")) scorer_path = hf_hub_download(repo_id = REPO_ID, filename = "english/huge-vocabulary.scorer") if type(audio_record_buffer)!=tuple: y, sr = librosa.load(audio_record_buffer) else: sr, y = audio_record_buffer y = librosa.resample(y, orig_sr=sr, target_sr=16000) #normalize to int16 y = ( np.iinfo("int16").max *(y - np.min(y))/np.ptp(y)).astype("int16") scorer = True # use scorer if scorer: acoustic_model.enableExternalScorer(scorer_path) result = acoustic_model.stt(y) else: acoustic_model.disableExternalScorer() result = acoustic_model.stt(y) print("STT:",result) return result #emotion_tokenizer = AutoTokenizer.from_pretrained("mrm8488/t5-base-finetuned-emotion") #emotion_model = AutoModelWithLMHead.from_pretrained("mrm8488/t5-base-finetuned-emotion") def get_emotion(text): input_ids = tokenizer.encode(text + '', return_tensors='pt') output = model.generate(input_ids=input_ids,max_length=2) dec = [tokenizer.decode(ids) for ids in output] label = dec[0] return label.split()[1] config = AutoConfig.from_pretrained('gorkemgoknar/gpt2chatbotenglish') model = GPT2LMHeadModel.from_pretrained('gorkemgoknar/gpt2chatbotenglish', config=config) tokenizer = GPT2Tokenizer.from_pretrained('gorkemgoknar/gpt2chatbotenglish') tokenizer.model_max_length = 1024 #Dynamic Temperature #See experiment https://www.linkedin.com/pulse/ai-goes-job-interview-g%25C3%25B6rkem-g%25C3%25B6knar base_temperature = 1.2 dynamic_temperature_range = 0.15 rand_range = random.uniform(-1 * dynamic_temperature_range , dynamic_temperature_range ) temperature = base_temperature + rand_range SPECIAL_TOKENS = ["", "", "", "", ""] #See document for experiment https://www.linkedin.com/pulse/ai-goes-job-interview-g%C3%B6rkem-g%C3%B6knar/ def get_chat_response(name,history=[], input_txt = "Hello , what is your name?"): ai_history = history.copy() #ai_history.append(input_txt) ai_history_e = [tokenizer.encode(e) for e in ai_history] personality = "My name is " + name bos, eos, speaker1, speaker2 = tokenizer.convert_tokens_to_ids(SPECIAL_TOKENS[:-1]) #persona first, history next, input text must be at the end #[[bos, persona] , [history] , [input]] sequence = [[bos] + tokenizer.encode(personality)] + ai_history_e + [tokenizer.encode(input_txt)] ##[[bos, persona] , [speaker1 .., speakser2 .., speaker1 ... speaker2 ... , [input]] sequence = [sequence[0]] + [[speaker2 if (len(sequence)-i) % 2 else speaker1] + s for i, s in enumerate(sequence[1:])] sequence = list(chain(*sequence)) #bot_input_ids = tokenizer.encode(personality + tokenizer.eos_token + input_txt + tokenizer.eos_token , return_tensors='pt') sequence_len = len(sequence) #optimum response and speed chat_history_ids = model.generate( torch.tensor(sequence).unsqueeze(0), max_length=50, pad_token_id=tokenizer.eos_token_id, no_repeat_ngram_size=3, do_sample=True, top_k=60, top_p=0.8, temperature = 1.3 ) out_str = tokenizer.decode(chat_history_ids[0][sequence_len:], skip_special_tokens=True) #out_str = tokenizer.decode(chat_history_ids[:, sequence.shape[-1]:][0], skip_special_tokens=False) return out_str ##you can use anyone from below ''' | Macleod | Moran | Brenda | Ramirez | Peter Parker | Quentin Beck | Andy | Red | Norton | Willard | Chief | Chef | Kilgore | Kurtz | Westley | Buttercup | Vizzini | Fezzik | Inigo | Man In Black | Taylor | Zira | Zaius | Cornelius | Bud | Lindsey | Hippy | Erin | Ed | George | Donna | Trinity | Agent Smith | Morpheus | Neo | Tank | Meryl | Truman | Marlon | Christof | Stromboli | Bumstead | Schreber | Walker | Korben | Cornelius | Loc Rhod | Anakin | Obi-Wan | Palpatine | Padme | Superman | Luthor | Dude | Walter | Donny | Maude | General | Starkiller | Indiana | Willie | Short Round | John | Sarah | Terminator | Miller | Sarge | Reiben | Jackson | Upham | Chuckie | Will | Lambeau | Sean | Skylar | Saavik | Spock | Kirk | Bones | Khan | Kirk | Spock | Sybok | Scotty | Bourne | Pamela | Abbott | Nicky | Marshall | Korshunov | Troy | Vig | Archie Gates | Doc | Interrogator | Ellie | Ted | Peter | Drumlin | Joss | Macready | Childs | Nicholas | Conrad | Feingold | Christine | Adam | Barbara | Delia | Lydia | Cathy | Charles | Otho | Schaefer | Han | Luke | Leia | Threepio | Vader | Yoda | Lando | Elaine | Striker | Dr. Rumack | Kramer | David | Saavik | Kirk | Kruge | Holden | Deckard | Rachael | Batty | Sebastian | Sam | Frodo | Pippin | Gandalf | Kay | Edwards | Laurel | Edgar | Zed | Jay | Malloy | Plissken | Steve Rogers | Tony Stark | Scott Lang | Bruce Banner | Bruce | Edward | Two-Face | Batman | Chase | Alfred | Dick | Riddler | Din Djarin | Greef Karga | Kuiil | Ig-11 | Cara Dune | Peli Motto | Toro Calican | Ripley | Meredith | Dickie | Marge | Peter | Lambert | Kane | Dallas | Ripley | Ash | Parker | Threepio | Luke | Leia | Ben | Han | Common Bob | Common Alice | Jack | Tyler | Marla | Dana | Stantz | Venkman | Spengler | Louis | Fry | Johns | Riddick | Kirk | Decker | Spock | "Ilia | Indy | Belloq | Marion | Brother | Allnut | Rose | Qui-Gon | Jar Jar ''' MODEL_NAME= "tts_models/multilingual/multi-dataset/your_tts" def greet(character,your_voice,message,history): #gradios set_state/get_state had problems on embedded html! history = history or {"character": character, "message_history" : [] } #gradios set_state/get_state does not persist session for now using global #global history if history["character"] != character: #switching character history = {"character": character, "message_history" : [] } response = get_chat_response(character,history=history["message_history"],input_txt=message) os.system('tts --text "'+response+'" --model_name tts_models/multilingual/multi-dataset/your_tts --speaker_wav '+your_voice+' --language_idx "en"') history["message_history"].append((message, response)) #emotion = get_emotion(response) html = "
" for user_msg, resp_msg in history["message_history"]: html += f"
You: {user_msg}
" html += f"
{character}: {resp_msg}
" html += "
" return html,history,"tts_output.wav" def greet_stt_to_tts(character,your_voice,chat_audio,history,use_your_voice_as_output): #gradios set_state/get_state had problems on embedded html! history = history or {"character": character, "message_history" : [] } #gradios set_state/get_state does not persist session for now using global #global history if history["character"] != character: #switching character history = {"character": character, "message_history" : [] } # speech -> text (Whisper) message = stt_record(your_voice) response = get_chat_response(character,history=history["message_history"],input_txt=message) print("Response:",response) if type(response) == tuple: # only get first response = response[0] print("Response only first:",response) if use_your_voice_as_output: os.system('tts --text "'+response+'" --model_name tts_models/multilingual/multi-dataset/your_tts --speaker_wav '+your_voice+' --language_idx "en"') else: os.system('tts --text "'+response+'" --model_name tts_models/multilingual/multi-dataset/your_tts --speaker_wav '+chat_audio+' --language_idx "en"') history["message_history"].append((message, response)) #emotion = get_emotion(response) html = "
" for user_msg, resp_msg in history["message_history"]: html += f"
You: {user_msg}
" html += f"
{character}: {resp_msg}
" html += "
" return html,history,"tts_output.wav" def greet_textonly(character,message,history): #gradios set_state/get_state had problems on embedded html! history = history or {"character": character, "message_history" : [] } #gradios set_state/get_state does not persist session for now using global #global history if history["character"] != character: #switching character history = {"character": character, "message_history" : [] } response = get_chat_response(character,history=history["message_history"],input_txt=message) history["message_history"].append((message, response)) #emotion = get_emotion(response) html = "
" for user_msg, resp_msg in history["message_history"]: html += f"
You: {user_msg}
" html += f"
{character}: {resp_msg}
" html += "
" return html,history personality_choices = ["Gandalf", "Riddick", "Macleod", "Morpheus", "Neo","Spock","Vader","Indy"] examples= ["Gandalf", "What is your name?"] css=""" .chatbox {display:flex;flex-direction:column} .user_msg, .resp_msg {padding:4px;margin-bottom:4px;border-radius:4px;width:80%} .user_msg {background-color:cornflowerblue;color:white;align-self:start} .resp_msg {background-color:lightgray;align-self:self-end} """ #some selected ones are in for demo use personality_choices = ["Gandalf", "Riddick", "Macleod", "Morpheus", "Neo","Spock","Vader","Indy", "Ig-11","Threepio","Tony Stark","Batman","Vizzini"] title = "Movie Chatbot with Coqui YourTTS" article = "STT base model from mbarnig/lb-de-fr-en-pt-coqui-stt-models - 🐸 [Coqui.ai](https://https://coqui.ai/)" #History not implemented in this demo, use metayazar.com/chatbot for a movie and character dropdown chat interface ##interface = gr.Interface(fn=greet, inputs=[gr.inputs.Dropdown(personality_choices) ,"text"], title=title, description=description, outputs="text") examples=[['Gandalf','dragon.wav','Who are you sir?',{}]] history = {"character": "None", "message_history" : [] } description = "Speak with your your voice, get chat output with your voice. If you want you can upload an audio file (with your favourite character) and get chat response with that voice.\n See Coqui Space for more TTS models https://huggingface.co/spaces/coqui/CoquiTTS" interface_full = gr.Interface(fn=greet_stt_to_tts, inputs=[gr.Dropdown(personality_choices), gr.Audio(source="microphone", type="filepath", label="Record Audio for STT") , gr.Audio(type="filepath", label="Character Audio Voice Reference"), "state", gr.Checkbox(label="Use Your Microphone for character Voice?", value=True)], outputs=["html","state",gr.Audio(type="filepath")], css=css, title="Chat with Your Voice", description=description,article=article , live=False) description = "Record your voice, get chat output with your voice." interface_mic = gr.Interface(fn=greet, inputs=[gr.Dropdown(personality_choices), gr.Audio(source="microphone", type="filepath") , "text", "state"], outputs=["html","state",gr.Audio(type="filepath")], css=css, title="TTS with Your Voice (YourTTS)", description=description,article=article ) interface_text = gr.Interface(fn=greet_textonly, inputs=[gr.Dropdown(personality_choices), "text", "state"], outputs=["html","state"], css=css, title="Chat Text Only", description=description,article=article) description = "Upload an audio file, get chat output as that voice." interface_file= gr.Interface(fn=greet, inputs=[gr.Dropdown(personality_choices), gr.Audio(type="filepath") , "text", "state"], outputs=["html","state",gr.Audio(type="filepath")], css=css, title="TTS with Your Voice (YourTTS) - upload file", description=description,article=article ) appinterface = gr.TabbedInterface([interface_full,interface_mic,interface_file], ["Chat Speech -> Speech","Chat with Mic Record", "Chat with Audio Upload" , "Chat Text only"]) appinterface.launch()