├── .gitignore ├── 1_data_processor ├── 1_whatsappParser.py ├── 1_whatsapp_data │ └── WhatsApp Chat with IronMan.txt ├── 2_hangoutJsonParser.py ├── 2_hangout_data │ └── Hangouts.json ├── 3_facebookParser.py ├── 3_facebook_data │ └── inbox │ │ └── someguy_terwtfyewg │ │ └── message_1.html ├── 4_mergeAllData.py ├── __init__.py ├── dataHandler.py └── requirements.txt ├── 2_rasa_chitchat ├── __init__.py ├── actions │ ├── Dockerfile │ ├── __init__.py │ ├── actions.py │ └── requirements.txt ├── config.yml ├── credentials.yml ├── data │ ├── nlu.md │ └── stories.md ├── domain.yml ├── endpoints.yml └── requirements.txt ├── 4_chatterbot ├── app.py ├── requirements.txt ├── talk.py └── train.py ├── 5_pipeline ├── audio_recognition.py ├── requirements.txt ├── silent.m4v └── streamerV4.py ├── LICENSE ├── README.md └── sample_output ├── Categories of conversation.png ├── Video_Streamer_architecture.png ├── architecture.png ├── cat1_RASA.png ├── cat2_chatterbot.png ├── cat3_RASA_actions.png ├── cat4_ParlAI.png ├── flow.png ├── full_demo.mov ├── silent.gif ├── text_demo.png └── video_generated.mp4 /.gitignore: -------------------------------------------------------------------------------- 1 | 2_rasa_chitchat/models/20200805-024139.tar.gz 2 | 2_rasa_chitchat/models/20200805-032600.tar.gz 3 | 2_rasa_chitchat/tests/conversation_tests.md 4 | 2_rasa_chitchat/__pycache__/__init__.cpython-37.pyc 5 | 2_rasa_chitchat/__pycache__/actions.cpython-37.pyc 6 | .idea/.gitignore 7 | .idea/identity-clonning.iml 8 | .idea/misc.xml 9 | .idea/modules.xml 10 | .idea/inspectionProfiles/profiles_settings.xml 11 | .idea/inspectionProfiles/Project_Default.xml 12 | dataHandler.cpython-37.pyc 13 | -------------------------------------------------------------------------------- /1_data_processor/1_whatsappParser.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from dataHandler import * 4 | 5 | def getWhatsAppDataTXT(personName): 6 | # Putting all the file names in a list 7 | allFiles = [] 8 | # Edit these file and directory names if you have them saved somewhere else 9 | 10 | for filename in os.listdir(dataDir): 11 | if filename.endswith(".txt"): 12 | allFiles.append('{}/{}'.format(dataDir, filename)) 13 | 14 | responseDictionary = [] 15 | """responseDictionary 16 | The key is the other person's message, and the value is my response 17 | Going through each file, and recording everyone's messages to me, and my 18 | responses 19 | """ 20 | for currentFile in allFiles: 21 | myMessage, otherPersonsMessage, currentSpeaker = "", "", "" 22 | with open(currentFile, 'r') as openedFile: 23 | allLines = openedFile.readlines() 24 | for index, line in enumerate(allLines): 25 | # The sender's name is separated by a ']' or '-' and a ': ' (The whitespace is important) 26 | leftDelimPattern = re.compile(r'[\]\-]') 27 | # A pattern to match either `]` or `-` 28 | leftDelim = leftDelimPattern.search(line) 29 | leftDelim = leftDelim.start() if leftDelim else -1 30 | rightColon = line.find(': ') 31 | 32 | # Find messages that I sent 33 | if line[leftDelim + 1:rightColon].strip() == personName: 34 | if not myMessage: 35 | # Want to find the first message that I send (if I send 36 | # multiple in a row) 37 | startMessageIndex = index - 1 38 | myMessage += " " + line[rightColon + 1:].strip() + "." 39 | 40 | elif myMessage: 41 | # Now go and see what message the other person sent by looking at 42 | # previous messages 43 | for counter in range(startMessageIndex, 0, -1): 44 | currentLine = allLines[counter] 45 | # Extracting the values of left and right delimiters 46 | leftDelim = leftDelimPattern.search(currentLine) 47 | leftDelim = leftDelim.start() if leftDelim else -1 48 | rightColon = line.find(': ') 49 | if (leftDelim < 0 or rightColon < 0): 50 | # In case the message above isn't in the right format 51 | myMessage, otherPersonsMessage, currentSpeaker = "", "", "" 52 | break 53 | if not currentSpeaker: 54 | # The first speaker not named me 55 | currentSpeaker = currentLine[leftDelim + 1:rightColon].strip() 56 | elif (currentSpeaker != currentLine[leftDelim + 1:rightColon].strip()): 57 | # A different person started speaking, so now I know that 58 | # the first person's message is done 59 | otherPersonsMessage = cleanMessage(otherPersonsMessage) 60 | myMessage = cleanMessage(myMessage) 61 | writeConversationToResponseDictionary(myMessage, otherPersonsMessage, responseDictionary) 62 | break 63 | otherPersonsMessage = currentLine[rightColon + 1:].strip() + " " + otherPersonsMessage 64 | myMessage, otherPersonsMessage, currentSpeaker = "", "", "" 65 | return responseDictionary 66 | 67 | 68 | if __name__ == '__main__': 69 | personName = "Tamaghna Basu" 70 | dataDir = '1_whatsapp_data' 71 | 72 | combinedDictionary = getWhatsAppDataTXT("Tamaghna Basu neoEYED") 73 | print(combinedDictionary) 74 | 75 | print('Total len of dictionary', len(combinedDictionary)) 76 | writeToFiles(combinedDictionary, SocialNetwork.WhatsApp) 77 | 78 | 79 | -------------------------------------------------------------------------------- /1_data_processor/1_whatsapp_data/WhatsApp Chat with IronMan.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/1_data_processor/1_whatsapp_data/WhatsApp Chat with IronMan.txt -------------------------------------------------------------------------------- /1_data_processor/2_hangoutJsonParser.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from dataHandler import * 4 | 5 | def parseData(jsonData): 6 | simpleJson = [] 7 | for i in range(0, len(jsonData['conversations'])): 8 | conversation = {} 9 | conversation['chatName'] = "" 10 | conversation['participants'] = getParticipants(i) 11 | conversation['messages'] = [] 12 | 13 | for j in range(0, len(jsonData['conversations'][i]['events'])): 14 | message = {} 15 | message['sender'] = {} 16 | message['sender']['name'] = getName( 17 | jsonData['conversations'][i]['events'][j]['sender_id']['gaia_id'], conversation['participants']) 18 | message['sender']['id'] = jsonData['conversations'][i]['events'][j]['sender_id']['gaia_id'] 19 | message['unixtime'] = (int(jsonData['conversations'][i] 20 | ['events'][j]['timestamp']))/1000000 21 | 22 | if 'chat_message' in jsonData['conversations'][i]['events'][j]: 23 | # if it's a message(normal hangouts, image...) 24 | if 'segment' in jsonData['conversations'][i]['events'][j]['chat_message']['message_content']: 25 | # if it's a normal hangouts message 26 | content = "" 27 | for k in range(0, len(jsonData['conversations'][i]['events'][j]['chat_message']['message_content']['segment'])): 28 | if jsonData['conversations'][i]['events'][j]['chat_message']['message_content']['segment'][k]['type'] == "TEXT": 29 | content = content + \ 30 | jsonData['conversations'][i]['events'][j]['chat_message']['message_content']['segment'][k]['text'] 31 | elif jsonData['conversations'][i]['events'][j]['chat_message']['message_content']['segment'][k]['type'] == "LINK": 32 | content = content + \ 33 | jsonData['conversations'][i]['events'][j]['chat_message']['message_content']['segment'][k]['text'] 34 | message['content'] = content 35 | 36 | conversation['messages'].append(message) 37 | 38 | simpleJson.append(conversation) 39 | simpleJson[i]['chatName'] = chatName(i, simpleJson) 40 | return simpleJson 41 | 42 | def getParticipants(index): 43 | participants = [] 44 | for i in range(0, len(jsonData['conversations'][index]['conversation']['conversation']['participant_data'])): 45 | person = {} 46 | person['id'] = jsonData['conversations'][index]['conversation']['conversation']['participant_data'][i]['id']['gaia_id'] 47 | if 'fallback_name' in jsonData['conversations'][index]['conversation']['conversation']['participant_data'][i]: 48 | person['name'] = jsonData['conversations'][index]['conversation']['conversation']['participant_data'][i]['fallback_name'] 49 | else: 50 | person['name'] = jsonData['conversations'][index]['conversation']['conversation']['participant_data'][i]['id']['gaia_id'] 51 | participants.append(person) 52 | return participants 53 | 54 | def getName(id, participants): 55 | for i in range(0, len(participants)): 56 | if id == participants[i]['id']: 57 | return participants[i]['name'] 58 | return id 59 | 60 | def chatName(i, simpleJson): 61 | if (('name' in jsonData['conversations'][i]['conversation']['conversation'])and(jsonData['conversations'][i]['conversation']['conversation']['name'] != "")): 62 | return jsonData['conversations'][i]['conversation']['conversation']['name'] 63 | participants = [] 64 | index = 0 65 | for k in range(0, len(simpleJson[i]['participants'])): 66 | participants.append(simpleJson[i]['participants'][k]['name']) 67 | if simpleJson[i]['participants'][k]['id'] == jsonData['conversations'][i]['conversation']['conversation']['self_conversation_state']['self_read_state']['participant_id']['gaia_id']: 68 | index = k 69 | break 70 | name = participants[index] 71 | return name 72 | 73 | def getGoogleHangoutsData(personName, jsonData): 74 | responseDictionary = [] 75 | """ 76 | The key is the other person's message, and the value is my response 77 | Going through each file, and recording everyone's messages to me, and my 78 | responses 79 | """ 80 | allChatterBotMessages = [] 81 | 82 | for data in jsonData: 83 | if len(data['participants']) != 2: 84 | continue 85 | 86 | myMessage, otherPersonsMessage, currentSpeaker = "", "", "" 87 | chatterbotMessageList = [] 88 | allLines = data['messages'] 89 | 90 | for index, line in enumerate(allLines): 91 | if 'sender' not in line.keys() or 'content' not in line.keys(): 92 | continue 93 | 94 | # Find messages that I sent 95 | if line['sender']['name'] == personName: 96 | if not myMessage: 97 | # Want to find the first message that I send (if I send 98 | # multiple in a row) 99 | startMessageIndex = index - 1 100 | myMessage += " " + line['content'] + "." 101 | 102 | elif myMessage: 103 | # Now go and see what message the other person sent by looking at 104 | # previous messages 105 | for counter in range(startMessageIndex, 0, -1): 106 | currentLine = allLines[counter] 107 | # In case the message above isn't in the right format 108 | if 'sender' not in currentLine.keys() or 'content' not in currentLine.keys(): 109 | break 110 | if not currentSpeaker: 111 | # The first speaker not named me 112 | currentSpeaker = currentLine['sender'] 113 | elif currentSpeaker != currentLine['sender']: 114 | # A different person started speaking, so now I know that 115 | # the first person's message is done 116 | otherPersonsMessage = cleanMessage(otherPersonsMessage) 117 | myMessage = cleanMessage(myMessage) 118 | writeConversationToResponseDictionary(myMessage, otherPersonsMessage, responseDictionary) 119 | chatterbotMessageList.append(otherPersonsMessage) 120 | chatterbotMessageList.append(myMessage) 121 | break 122 | otherPersonsMessage = currentLine['content'] + ". " + otherPersonsMessage 123 | myMessage, otherPersonsMessage, currentSpeaker = "", "", "" 124 | if len(chatterbotMessageList) > 0 : 125 | otherPersonName = data['participants'][0]['name'] 126 | if otherPersonName == personName: 127 | otherPersonName = data['participants'][1]['name'] 128 | # allChatterBotMessages.append(chatterbotMessageList) 129 | allChatterBotMessages.append({"Name": otherPersonName, "Conversation": chatterbotMessageList}) 130 | return responseDictionary, allChatterBotMessages 131 | 132 | 133 | if __name__ == '__main__': 134 | me = "Tamaghna Basu" 135 | 136 | # location of Hangouts Json file obtained from Google Takeout 137 | data_hangouts_json = './2_hangout_data/Hangouts.json' 138 | 139 | with open(data_hangouts_json, 'r') as f: 140 | jsonData = json.load(f) 141 | 142 | jsonData = parseData(jsonData) 143 | 144 | combinedDictionary, allChatterBotMessages = getGoogleHangoutsData(me, jsonData) 145 | print('Total len of dictionary', len(combinedDictionary)) 146 | writeToFiles(combinedDictionary, SocialNetwork.Hangout) 147 | -------------------------------------------------------------------------------- /1_data_processor/2_hangout_data/Hangouts.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/1_data_processor/2_hangout_data/Hangouts.json -------------------------------------------------------------------------------- /1_data_processor/3_facebookParser.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import re 3 | from functools import reduce 4 | from pathlib import Path 5 | 6 | from bs4 import BeautifulSoup 7 | from tqdm import tqdm 8 | 9 | from dataHandler import csv_columns, SocialNetwork, output_dir 10 | 11 | 12 | def messageFileKey(file): 13 | match = re.search(r'message_(\d+).html', str(file)) 14 | return int(match.group(1)) 15 | 16 | 17 | def parseMessage(block): 18 | children = block.div.find_all(recursive=False) 19 | message = children[1].find(text=True, recursive=False) 20 | if message != None: 21 | message = ' '.join(message.split()) 22 | return message 23 | 24 | 25 | def parseMessageBlock(block): 26 | author = block.select('div._3-96._2pio._2lek._2lel')[0].getText() 27 | message = parseMessage(block.select('div._3-96._2let')[0]) 28 | return (author, message) 29 | 30 | 31 | def parseFile(file): 32 | with open(file, 'r', encoding='utf-8') as f: 33 | soup = BeautifulSoup(f.read(), 'lxml') 34 | blocks = soup.select( 35 | 'html body._5vb_._2yq._4yic div.clearfix._ikh div._4bl9 div._li div._3a_u div._4t5n div.pam._3-95._2pi0._2lej.uiBoxWhite.noborder') 36 | messages = [] 37 | for block in blocks[::-1]: 38 | messages.append(parseMessageBlock(block)) 39 | return messages 40 | 41 | 42 | def filterMessages(messages): 43 | return filter(lambda message: message[1] != None, messages) 44 | 45 | 46 | def mergeMessages(messages): 47 | def reducer(acc, message): 48 | if len(acc) == 0: 49 | return [message] 50 | 51 | (lastAuthor, lastMessage) = acc[-1] 52 | (currentAuthor, currentMessage) = message 53 | if lastAuthor != currentAuthor: 54 | return acc + [message] 55 | else: 56 | newMessage = ' '.join([lastMessage, currentMessage]) 57 | return acc[:-1] + [(currentAuthor, newMessage)] 58 | 59 | return reduce(reducer, messages, []) 60 | 61 | 62 | # TODO - Refactor this method to use the standard CSV write method from dataHandler 63 | def saveMessages(messages, personName): 64 | csv_file_name = "{}/{}_FINAL.csv".format(output_dir, SocialNetwork.Facebook.name) 65 | with open(csv_file_name, 'w', encoding='utf-8') as f: 66 | writer = csv.writer(f, delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL) 67 | writer.writerow(csv_columns) 68 | for msg1, msg2 in zip(messages[::2], messages[1::2]): 69 | author1, message1 = msg1 70 | author2, message2 = msg2 71 | 72 | if author1 == personName: 73 | writer.writerow([message2, message1]) 74 | else: 75 | writer.writerow([message1, message2]) 76 | 77 | 78 | def getFBConversationData(messagePath): 79 | print("Find messenger files...") 80 | messageFiles = Path(messagePath).rglob('message*.html') 81 | messageFiles = sorted(messageFiles, key=messageFileKey, reverse=True) 82 | print("Parse files... {} ".format(messageFiles)) 83 | messages = [] 84 | totalFileCount = 0 85 | errorFileCount = 0 86 | for messageFile in tqdm(messageFiles): 87 | totalFileCount += 1 88 | chatData = "" 89 | try: 90 | chatData = parseFile(messageFile) 91 | except: 92 | print("######################@@@@\n Error Parsing {}".format(messageFile)) 93 | errorFileCount += 1 94 | if chatData != "": 95 | messages = messages + chatData 96 | 97 | print("Filter and merge files...") 98 | messages = filterMessages(messages) 99 | messages = mergeMessages(messages) 100 | return messages, totalFileCount, errorFileCount 101 | 102 | 103 | if __name__ == '__main__': 104 | me = "Tamaghna Basu" 105 | messagePath = "./3_facebook_data/inbox" 106 | messages, totalFileCount, errorFileCount = getFBConversationData(messagePath) 107 | saveMessages(messages, me) 108 | print("Conversations saved! \n Total files {}, Error in files {}".format(totalFileCount, errorFileCount)) 109 | -------------------------------------------------------------------------------- /1_data_processor/3_facebook_data/inbox/someguy_terwtfyewg/message_1.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/1_data_processor/3_facebook_data/inbox/someguy_terwtfyewg/message_1.html -------------------------------------------------------------------------------- /1_data_processor/4_mergeAllData.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | from dataHandler import * 5 | 6 | 7 | def mergeAllChatterBotData(): 8 | csv_whatsapp = "{}/{}_FINAL.csv".format(output_dir, SocialNetwork.WhatsApp.name) 9 | csv_hangout = "{}/{}_FINAL.csv".format(output_dir, SocialNetwork.Hangout.name) 10 | csv_facebook = "{}/{}_FINAL.csv".format(output_dir, SocialNetwork.Facebook.name) 11 | 12 | df_all = pd.read_csv(csv_whatsapp) 13 | df_all.replace(np.NaN, ' ', inplace=True) 14 | 15 | df_hangout = pd.read_csv(csv_hangout) 16 | df_hangout.replace(np.NaN, ' ', inplace=True) 17 | df_all = df_all.append(df_hangout) 18 | 19 | df_facebook = pd.read_csv(csv_facebook) 20 | df_facebook.replace(np.NaN, ' ', inplace=True) 21 | df_all = df_all.append(df_facebook) 22 | 23 | return df_all 24 | 25 | 26 | if __name__ == '__main__': 27 | combinedDF = mergeAllChatterBotData() 28 | combinedDF.to_csv("{}/ALL_chatterbot_FINAL.csv".format(output_dir)) 29 | print("DONE!!!") 30 | -------------------------------------------------------------------------------- /1_data_processor/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/1_data_processor/__init__.py -------------------------------------------------------------------------------- /1_data_processor/dataHandler.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import enum 3 | import re 4 | 5 | output_dir = "output" 6 | csv_columns = ['Message', 'MyResponse'] 7 | class SocialNetwork(enum.Enum): 8 | Hangout = 1 9 | WhatsApp = 2 10 | Facebook = 3 11 | ALL = 4 12 | 13 | 14 | def remove_emoji(string): 15 | emoji_pattern = re.compile("[" 16 | u"\U0001F600-\U0001F64F" # emoticons 17 | u"\U0001F300-\U0001F5FF" # symbols & pictographs 18 | u"\U0001F680-\U0001F6FF" # transport & map symbols 19 | u"\U0001F1E0-\U0001F1FF" # flags (iOS) 20 | u"\U00002500-\U00002BEF" # chinese char 21 | u"\U00002702-\U000027B0" 22 | u"\U00002702-\U000027B0" 23 | u"\U000024C2-\U0001F251" 24 | u"\U0001f926-\U0001f937" 25 | u"\U00010000-\U0010ffff" 26 | u"\u2640-\u2642" 27 | u"\u2600-\u2B55" 28 | u"\u200d" 29 | u"\u23cf" 30 | u"\u23e9" 31 | u"\u231a" 32 | u"\ufe0f" # dingbats 33 | u"\u3030" 34 | "]+", flags=re.UNICODE) 35 | return emoji_pattern.sub(r'', string) 36 | 37 | 38 | def cleanMessage(message): 39 | message = remove_emoji(message) 40 | # Remove new lines within message 41 | cleanedMessage = message.replace('\n', ' ') 42 | # Deal with some weird tokens 43 | cleanedMessage = cleanedMessage.replace("\xc2\xa0", "") 44 | # Remove punctuation 45 | # cleanedMessage = re.sub('([.,!?])', ' ', cleanedMessage) 46 | # Remove multiple spaces in message 47 | cleanedMessage = re.sub(' +', ' ', cleanedMessage) 48 | 49 | # Remove text based emjis - :-), :), ;), :D, :P, ;P, ;D, :(, :((, :)) 50 | cleanedMessage = cleanedMessage.replace(":-)", "") 51 | cleanedMessage = cleanedMessage.replace(":)", "") 52 | cleanedMessage = cleanedMessage.replace(";)", "") 53 | cleanedMessage = cleanedMessage.replace(":D", "") 54 | cleanedMessage = cleanedMessage.replace(":P", "") 55 | cleanedMessage = cleanedMessage.replace(":-P", "") 56 | cleanedMessage = cleanedMessage.replace(";P", "") 57 | cleanedMessage = cleanedMessage.replace(";D", "") 58 | cleanedMessage = cleanedMessage.replace(":(", "") 59 | cleanedMessage = cleanedMessage.replace(":((", "") 60 | cleanedMessage = cleanedMessage.replace(":))", "") 61 | 62 | return cleanedMessage.strip() 63 | 64 | 65 | def is_not_blank(s): 66 | return bool(s and s.strip()) 67 | 68 | 69 | def writeConversationToResponseDictionary(myMessage, otherPersonsMessage, responseDictionary): 70 | if is_not_blank(otherPersonsMessage) \ 71 | and is_not_blank(myMessage): 72 | responseDictionary.append({"Message": otherPersonsMessage.strip(), "MyResponse": myMessage.strip()}) 73 | 74 | 75 | def writeToFiles(dict_data, socialNetworkType): 76 | output_dir = "output" 77 | messageFileName = '{}/message_{}.txt'.format(output_dir, socialNetworkType.name) 78 | myResponseFileName = '{}/myResponse_{}.txt'.format(output_dir, socialNetworkType.name) 79 | csv_file_name = "{}/{}_FINAL.csv".format(output_dir, socialNetworkType.name) 80 | 81 | print(messageFileName) 82 | print(myResponseFileName) 83 | print(csv_file_name) 84 | 85 | otherPersonsMessageFile = open(messageFileName, 'w') 86 | myMessageFile = open(myResponseFileName, 'w') 87 | 88 | try: 89 | with open(csv_file_name, 'w') as csvfile: 90 | writer = csv.DictWriter(csvfile, fieldnames=csv_columns) 91 | writer.writeheader() 92 | for message in dict_data: 93 | writer.writerow(message) 94 | otherPersonsMessageFile.write(message['Message'].strip() + "\n") 95 | myMessageFile.write(message['MyResponse'].strip() + "\n") 96 | except IOError: 97 | print("I/O error") 98 | otherPersonsMessageFile.close() 99 | myMessageFile.close() 100 | 101 | 102 | if __name__ == '__main__': 103 | writeToFiles("", SocialNetwork.Hangout) 104 | writeToFiles("", SocialNetwork.LinkedIn) 105 | writeToFiles("", SocialNetwork.WhatsApp) 106 | -------------------------------------------------------------------------------- /1_data_processor/requirements.txt: -------------------------------------------------------------------------------- 1 | beautifulsoup4 2 | tqdm 3 | lxml 4 | pandas -------------------------------------------------------------------------------- /2_rasa_chitchat/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/2_rasa_chitchat/__init__.py -------------------------------------------------------------------------------- /2_rasa_chitchat/actions/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rasa/rasa-sdk:latest 2 | USER root 3 | WORKDIR /app 4 | COPY requirements.txt /app 5 | COPY actions.py /app 6 | 7 | RUN pip3 install -r requirements.txt 8 | 9 | CMD ["start", "--actions", "actions"] 10 | 11 | USER 1001 -------------------------------------------------------------------------------- /2_rasa_chitchat/actions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/2_rasa_chitchat/actions/__init__.py -------------------------------------------------------------------------------- /2_rasa_chitchat/actions/actions.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # %% 4 | 5 | ############################################################################################################## 6 | # Global Constants 7 | # Register on https://newsapi.org and get an API KEY and put it here 8 | NEWS_API_KEY = '' 9 | 10 | 11 | # Register on http://api.weatherstack.com and get an API KEY and put it here 12 | weatherstack_api_key = '' 13 | 14 | parlAI_base_url = "http://localhost:8080" 15 | chatterbot_base_url = "http://localhost:5000" 16 | 17 | 18 | 19 | ############################################################################################################## 20 | 21 | # %% 22 | 23 | from rasa_sdk import Tracker 24 | from rasa_sdk.executor import CollectingDispatcher 25 | 26 | from typing import Dict, Text, Any, List 27 | 28 | import requests 29 | import json 30 | 31 | from rasa_sdk import Action 32 | import logging 33 | 34 | from rasa_sdk.forms import FormAction, REQUESTED_SLOT, Action 35 | from rasa_sdk import ActionExecutionRejection 36 | from rasa_sdk.events import SlotSet, FollowupAction 37 | 38 | logger = logging.getLogger(__name__) 39 | 40 | def isBlank (myString): 41 | if myString and myString.strip(): 42 | #myString is not None AND myString is not empty or blank 43 | return False 44 | #myString is None OR myString is empty or blank 45 | return True 46 | 47 | def reset_ParlAI_conversations(): 48 | import requests 49 | url = "{}/reset".format(parlAI_base_url) 50 | headers = {'Content-Type': 'application/json'} 51 | response = requests.request("POST", url, headers=headers) 52 | 53 | import json 54 | response_json = json.loads(response.text) 55 | response_text = response_json['text'] 56 | 57 | print(response_text) 58 | logger.debug("reset_ParlAI_conversations: message - {}".format(response_text)) 59 | return response_text 60 | 61 | 62 | def send_message_to_external_AI(user_message): 63 | words = user_message.split() 64 | if len(words) >= 3: 65 | message, response_confidence = send_message_to_Chatterbot(user_message) 66 | print("User message: {}, Response from chatterbot: {}, Confidence: {}".format(user_message, message, response_confidence)) 67 | if response_confidence < 0.9: 68 | message = sendToParlAI(user_message) 69 | else: 70 | message = sendToParlAI(user_message) 71 | return message 72 | 73 | 74 | def sendToParlAI(user_message, silentMode=False): 75 | url = "{}/interact".format(parlAI_base_url) 76 | headers = {'Content-Type': 'application/json'} 77 | response_text = "" 78 | if silentMode: 79 | asyncReq(url, headers=headers, data=user_message) 80 | else: 81 | import requests 82 | response = requests.request("POST", url, headers=headers, data=user_message) 83 | import json 84 | response_json = json.loads(response.text) 85 | response_text = response_json['text'] 86 | print(response_text) 87 | logger.debug("send_message_to_ParlAI: message - {}".format(response_text)) 88 | 89 | return response_text 90 | 91 | def asyncReq(url, headers, data): 92 | from requests_futures.sessions import FuturesSession 93 | session = FuturesSession() 94 | session.post(url, headers=headers, data=data) 95 | 96 | 97 | def send_message_to_Chatterbot(user_message): 98 | import requests 99 | 100 | url = "http://localhost:5000/service" 101 | 102 | payload = "{\"data\" : \"" + user_message + "\"}" 103 | headers = { 104 | 'Content-Type': 'application/json' 105 | } 106 | 107 | response = requests.request("POST", url, headers=headers, data=payload) 108 | 109 | import json 110 | response_json = json.loads(response.text) 111 | response_text = response_json['text'] 112 | response_confidence = response_json['confidence'] 113 | 114 | log_message = "#############################\n" \ 115 | "send_message_to_Chatterbot:\n " \ 116 | "response - {},\n " \ 117 | "confidence - {}".format(response_text, response_confidence) 118 | # print(log_message) 119 | logger.debug(log_message) 120 | return response_text, response_confidence 121 | 122 | 123 | class JokeTellerAction(Action): 124 | """This action class allows to display buttons for each facility type 125 | for the user to chose from to fill the facility_type entity slot.""" 126 | 127 | def name(self) -> Text: 128 | """Unique identifier of the action""" 129 | return "action_tell_joke" 130 | 131 | def run(self, 132 | dispatcher: CollectingDispatcher, 133 | tracker: Tracker, 134 | domain: Dict[Text, Any]) -> List: 135 | sender = tracker.sender_id 136 | print("################### sender: {}".format(sender)) 137 | request = json.loads( 138 | requests.get('https://official-joke-api.appspot.com/jokes/random').text) # make an apie call 139 | setup = request['setup'] 140 | punchline = request['punchline'] 141 | message = setup + ' ' + punchline 142 | message = "Hear this. {}".format(message) 143 | logger.debug("action_tell_joke: message - {}".format(message)) 144 | print("action_tell_joke: message - {}".format(message)) 145 | dispatcher.utter_message(message) # send the message back to the user 146 | return [] 147 | 148 | 149 | class WeatherTellerAction(Action): 150 | 151 | def name(self) -> Text: 152 | """Unique identifier of the action""" 153 | return "action_tell_weather" 154 | 155 | @staticmethod 156 | def getWeatherInfo(location): 157 | params = { 158 | 'access_key': weatherstack_api_key, 159 | 'query': location 160 | } 161 | 162 | api_result = requests.get('http://api.weatherstack.com/current', params) 163 | 164 | api_response = api_result.json() 165 | print(api_response) 166 | description = api_response['current']['weather_descriptions'][0] 167 | response = u'Current temperature in %s is %d degree celsius. Seems %s' % ( 168 | api_response['location']['name'], api_response['current']['temperature'], description) 169 | image = api_response['current']['weather_icons'] 170 | print(response) 171 | print(api_response['current']['weather_icons']) 172 | print(api_response['current']['weather_descriptions']) 173 | return response, image 174 | 175 | def run(self, 176 | dispatcher: CollectingDispatcher, 177 | tracker: Tracker, 178 | domain: Dict[Text, Any]) -> List: 179 | 180 | # get all the entities extracted by rasa 181 | entities = tracker.latest_message['entities'] 182 | 183 | # cycle through them and extract the relavant one for us 184 | location = None 185 | for e in entities: 186 | if e['entity'] == "user_location": 187 | location = e['value'] 188 | if location: 189 | message, image = self.getWeatherInfo(location) 190 | else: 191 | message, image = self.getWeatherInfo('fetch:ip') 192 | print("action_tell_weather: message - {}".format(message)) 193 | # message = [{"text": message},{"image":image}] 194 | dispatcher.utter_message(message) # send the message back to the user 195 | # dispatcher.utter_message(template = "utter_aget.tell_weather", message=message, image=image) # send the message back to the user 196 | return [] 197 | 198 | 199 | class FallBackAction(Action): 200 | """This action class allows to display buttons for each facility type 201 | for the user to chose from to fill the facility_type entity slot.""" 202 | 203 | def name(self) -> Text: 204 | """Unique identifier of the action""" 205 | return "action_fallback_lmgtfy" 206 | 207 | def run(self, 208 | dispatcher: CollectingDispatcher, 209 | tracker: Tracker, 210 | domain: Dict[Text, Any]) -> List: 211 | print(tracker.latest_message) 212 | user_input = tracker.latest_message['text'] 213 | user_input = self.urlify(user_input) 214 | message = send_message_to_external_AI(user_input) 215 | logger.debug("action_fallback_lmgtfy_parlAI: message - {}".format(message)) 216 | dispatcher.utter_message(message) # send the message back to the user 217 | return [] 218 | 219 | def urlify(self, s): 220 | import re 221 | # Remove all non-word characters (everything except numbers and letters) 222 | s = re.sub(r"[^\w\s]", '', s) 223 | # Replace all runs of whitespace with a single dash 224 | s = re.sub(r"\s+", '+', s) 225 | return s 226 | 227 | 228 | class InitializeParlAIAction(Action): 229 | """This action class allows to display buttons for each facility type 230 | for the user to chose from to fill the facility_type entity slot.""" 231 | 232 | def name(self) -> Text: 233 | """Unique identifier of the action""" 234 | return "action_initialize_ParlAI" 235 | 236 | def run(self, 237 | dispatcher: CollectingDispatcher, 238 | tracker: Tracker, 239 | domain: Dict[Text, Any]) -> List: 240 | sendToParlAI('begin') 241 | sendToParlAI('begin') 242 | sendToParlAI('begin') 243 | logger.debug("action_initialize_ParlAI initilize") 244 | return [] 245 | 246 | 247 | class ParlAISendMessageAction(Action): 248 | """This action class allows to display buttons for each facility type 249 | for the user to chose from to fill the facility_type entity slot.""" 250 | 251 | def name(self) -> Text: 252 | """Unique identifier of the action""" 253 | return "action_send_to_ParlAI" 254 | 255 | def run(self, 256 | dispatcher: CollectingDispatcher, 257 | tracker: Tracker, 258 | domain: Dict[Text, Any]) -> List: 259 | print(tracker.latest_message) 260 | user_input = tracker.latest_message['text'] 261 | logger.debug("action_send_to_ExternalAI: message - {}".format(user_input)) 262 | message = send_message_to_external_AI(user_input) 263 | logger.debug("action_send_to_ParlAI: message - {}".format(message)) 264 | dispatcher.utter_message(message) # send the message back to the user 265 | return [] 266 | 267 | 268 | class ParlAISendSilentMessageAction(Action): 269 | """This action class allows to display buttons for each facility type 270 | for the user to chose from to fill the facility_type entity slot.""" 271 | 272 | def name(self) -> Text: 273 | """Unique identifier of the action""" 274 | return "action_send_silently_to_ParlAI" 275 | 276 | def run(self, 277 | dispatcher: CollectingDispatcher, 278 | tracker: Tracker, 279 | domain: Dict[Text, Any]) -> List: 280 | print(tracker.latest_message) 281 | user_input = tracker.latest_message['text'] 282 | message = sendToParlAI(user_input, silentMode=True) 283 | logger.debug("action_send_to_ParlAI: message - {}".format(message)) 284 | return [] 285 | 286 | 287 | def who_is(query): 288 | summary = "" 289 | if not isBlank(query): 290 | # if query is not None and len(query.strip()) > 0: 291 | import wikipedia 292 | try: 293 | summary = wikipedia.summary(query, chars=100) 294 | except Exception: 295 | for new_query in wikipedia.search(query): 296 | try: 297 | summary = wikipedia.summary(new_query, chars=100) 298 | except Exception: 299 | pass 300 | 301 | if len(summary) > 1500: 302 | summary = summary[: 500] 303 | return summary 304 | 305 | 306 | class DefinitionTellerAction(Action): 307 | 308 | def name(self) -> Text: 309 | """Unique identifier of the action""" 310 | return "action_tell_definition" 311 | 312 | def run(self, 313 | dispatcher: CollectingDispatcher, 314 | tracker: Tracker, 315 | domain: Dict[Text, Any]) -> List: 316 | 317 | # get all the entities extracted by rasa 318 | entities = tracker.latest_message['entities'] 319 | 320 | # cycle through them and extract the relavant one for us 321 | word = None 322 | for e in entities: 323 | if e['entity'] == "word": 324 | word = e['value'] 325 | message = who_is(word) 326 | if isBlank(message) : 327 | send_message_to_external_AI(word) 328 | print("action_tell_definition: message - {}".format(message)) 329 | dispatcher.utter_message(message) # send the message back to the user 330 | return [] 331 | 332 | 333 | class TriviaTellerAction(Action): 334 | 335 | def name(self) -> Text: 336 | """Unique identifier of the action""" 337 | return "action_tell_trivia" 338 | 339 | def run(self, 340 | dispatcher: CollectingDispatcher, 341 | tracker: Tracker, 342 | domain: Dict[Text, Any]) -> List: 343 | 344 | # get all the entities extracted by rasa 345 | entities = tracker.latest_message['entities'] 346 | 347 | # cycle through them and extract the relavant one for us 348 | attribute = None 349 | entity = None 350 | for e in entities: 351 | if e['entity'] == "attribute": 352 | attribute = e['value'] 353 | elif e['entity'] == "entity": 354 | entity = e['value'] 355 | 356 | if isBlank(attribute) or isBlank(entity): 357 | user_input = tracker.latest_message['text'] 358 | message = send_message_to_external_AI(user_input) 359 | else: 360 | query = "{} of {}".format(attribute, entity) 361 | message = who_is(query) 362 | 363 | print("action_tell_trivia: message - {}".format(message)) 364 | dispatcher.utter_message(message) # send the message back to the user 365 | return [] 366 | 367 | 368 | class DateTimeTellerAction(Action): 369 | 370 | def name(self) -> Text: 371 | """Unique identifier of the action""" 372 | return "action_tell_date_time" 373 | 374 | @staticmethod 375 | def getTime(): 376 | from datetime import datetime 377 | import pytz 378 | 379 | timezone = 'Asia/Calcutta' 380 | tz_India = pytz.timezone(timezone) 381 | datetime_India = datetime.now(tz_India) 382 | time_string = datetime_India.strftime("%H:%M") 383 | date_string = datetime_India.strftime("%B %d") 384 | print("Time zone - {}, date - {}, time - {}".format(timezone, date_string, time_string)) 385 | return date_string, time_string 386 | 387 | def run(self, 388 | dispatcher: CollectingDispatcher, 389 | tracker: Tracker, 390 | domain: Dict[Text, Any]) -> List: 391 | 392 | # get all the entities extracted by rasa 393 | entities = tracker.latest_message['entities'] 394 | 395 | # cycle through them and extract the relavant one for us 396 | user_location = None 397 | for e in entities: 398 | if e['entity'] == "user_location": 399 | user_location = e['value'] 400 | currentDate, currentTime = self.getTime() 401 | if user_location is not None: 402 | message = "Not sure about the time in {}, but here the time is {}.".format(user_location, currentTime) 403 | else: 404 | message = "Here the time is {}.".format(currentTime) 405 | message += " And the date is {}.".format(currentDate) 406 | message += "Looks like you still think that I am a bot." 407 | print("action_tell_time: message - {}".format(message)) 408 | dispatcher.utter_message(message) # send the message back to the user 409 | return [] 410 | 411 | 412 | # A form action to fetch news from the internet 413 | class getNews(FormAction): 414 | def name(self): 415 | return "get_news" 416 | 417 | @staticmethod 418 | def required_slots(tracker: Tracker) -> List[Text]: 419 | """A list of required slots that the form has to fill""" 420 | 421 | return ["topic_news"] 422 | 423 | def slot_mappings(self): 424 | return {"topic_news": [self.from_text(intent=[None, "getNews", "inform"]), 425 | self.from_entity(entity="topic_news", intent=["getNews"])]} 426 | 427 | def validate(self, 428 | dispatcher: CollectingDispatcher, 429 | tracker: Tracker, 430 | domain: Dict[Text, Any]) -> List[Dict]: 431 | 432 | slot_values = self.extract_other_slots(dispatcher, tracker, domain) 433 | 434 | # extract requested slot 435 | slot_to_fill = tracker.get_slot(REQUESTED_SLOT) 436 | if slot_to_fill: 437 | slot_values.update(self.extract_requested_slot(dispatcher, tracker, domain)) 438 | if not slot_values: 439 | # reject form action execution 440 | # if some slot was requested but nothing was extracted 441 | # it will allow other policies to predict another action 442 | raise ActionExecutionRejection(self.name(), 443 | "Failed to validate slot {0} " 444 | "with action {1}" 445 | "".format(slot_to_fill, 446 | self.name())) 447 | 448 | # we'll check when validation failed in order 449 | # to add appropriate utterances 450 | 451 | # validation succeed, set the slots values to the extracted values 452 | return [SlotSet(slot, value) for slot, value in slot_values.items()] 453 | 454 | def submit(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> List[Dict]: 455 | 456 | """Define what the form has to do 457 | after all required slots are filled""" 458 | 459 | topic_news = tracker.get_slot("topic_news") 460 | 461 | pageSize = '2' # Set the number to how many news articles you want to fetch 462 | 463 | url = "https://newsapi.org/v2/everything?q=" + topic_news + "&apiKey=" + NEWS_API_KEY + "&pageSize=" + pageSize 464 | 465 | r = requests.get(url=url) 466 | data = r.json() # extracting data in json format 467 | data = data['articles'] 468 | 469 | dispatcher.utter_message("Here is some news I found!") 470 | 471 | for i in range(len(data)): 472 | output = data[i]['title'] + "\n" # + data[i]['url'] + "\n" 473 | dispatcher.utter_message(output) 474 | 475 | dispatcher.utter_template("utter_confirm_if_service_is_correct", tracker) 476 | 477 | # utter submit template 478 | return [] 479 | -------------------------------------------------------------------------------- /2_rasa_chitchat/actions/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | newsapi-python 3 | wikipedia 4 | requests_futures -------------------------------------------------------------------------------- /2_rasa_chitchat/config.yml: -------------------------------------------------------------------------------- 1 | # Configuration for Rasa NLU. 2 | # https://rasa.com/docs/rasa/nlu/components/ 3 | language: en 4 | pipeline: 5 | - name: WhitespaceTokenizer 6 | - name: RegexFeaturizer 7 | - name: LexicalSyntacticFeaturizer 8 | - name: CountVectorsFeaturizer 9 | - name: CountVectorsFeaturizer 10 | analyzer: "char_wb" 11 | min_ngram: 1 12 | max_ngram: 4 13 | - name: CRFEntityExtractor 14 | - name: DIETClassifier 15 | epochs: 100 16 | - name: EntitySynonymMapper 17 | - name: ResponseSelector 18 | epochs: 100 19 | 20 | # Configuration for Rasa Core. 21 | # https://rasa.com/docs/rasa/core/policies/ 22 | policies: 23 | - name: MemoizationPolicy 24 | - name: TEDPolicy 25 | max_history: 5 26 | epochs: 100 27 | - name: MappingPolicy 28 | - name: "FallbackPolicy" 29 | nlu_threshold: 0.3 30 | core_threshold: 0.3 31 | fallback_action_name: "action_fallback_lmgtfy" 32 | - name: FormPolicy -------------------------------------------------------------------------------- /2_rasa_chitchat/credentials.yml: -------------------------------------------------------------------------------- 1 | # This file contains the credentials for the voice & chat platforms 2 | # which your bot is using. 3 | # https://rasa.com/docs/rasa/user-guide/messaging-and-voice-channels/ 4 | 5 | rest: 6 | # # you don't need to provide anything here - this channel doesn't 7 | # # require any credentials 8 | 9 | 10 | #facebook: 11 | # verify: "" 12 | # secret: "" 13 | # page-access-token: "" 14 | 15 | #slack: 16 | # slack_token: "" 17 | # slack_channel: "" 18 | 19 | #socketio: 20 | # user_message_evt: 21 | # bot_message_evt: 22 | # session_persistence: 23 | 24 | #mattermost: 25 | # url: "https:///api/v4" 26 | # token: "" 27 | # webhook_url: "" 28 | 29 | # This entry is needed if you are using Rasa X. The entry represents credentials 30 | # for the Rasa X "channel", i.e. Talk to your bot and Share with guest testers. 31 | rasa: 32 | url: "http://localhost:5002/api" 33 | -------------------------------------------------------------------------------- /2_rasa_chitchat/data/stories.md: -------------------------------------------------------------------------------- 1 | ## story 01 2 | * agent.acquaintance 3 | - utter_agent.acquaintance 4 | - action_send_silently_to_ParlAI 5 | 6 | ## story 02 7 | * agent.marry_user 8 | - utter_agent.marry_user 9 | - action_send_silently_to_ParlAI 10 | 11 | ## story 03 12 | * user.misses_agent 13 | - utter_user.misses_agent 14 | - action_send_silently_to_ParlAI 15 | 16 | ## story 04 17 | * agent.real 18 | - utter_agent.real 19 | - action_send_silently_to_ParlAI 20 | 21 | ## story 05 22 | * user.testing_agent 23 | - utter_user.testing_agent 24 | - action_send_silently_to_ParlAI 25 | 26 | ## story 06 27 | * agent.birth_date 28 | - utter_agent.birth_date 29 | - action_send_silently_to_ParlAI 30 | 31 | ## story 07 32 | * agent.origin 33 | - utter_agent.origin 34 | - action_send_silently_to_ParlAI 35 | 36 | ## story 08 37 | * agent.beautiful 38 | - utter_agent.beautiful 39 | - action_send_silently_to_ParlAI 40 | 41 | ## story 09 42 | * user.loves_agent 43 | - utter_user.loves_agent 44 | - action_send_silently_to_ParlAI 45 | 46 | ## story 10 47 | * agent.my_friend 48 | - utter_agent.my_friend 49 | - action_send_silently_to_ParlAI 50 | 51 | ## story 11 52 | * user.likes_agent 53 | - utter_user.likes_agent 54 | - action_send_silently_to_ParlAI 55 | 56 | ## story 12 57 | * agent.funny 58 | - utter_agent.funny 59 | - action_send_silently_to_ParlAI 60 | 61 | ## story 13 62 | * agent.age 63 | - utter_agent.age 64 | - action_send_silently_to_ParlAI 65 | 66 | ## story 14 67 | * agent.boss 68 | - utter_agent.boss 69 | - action_send_silently_to_ParlAI 70 | 71 | ## story 15 72 | * user.joking 73 | - utter_user.joking 74 | - action_send_silently_to_ParlAI 75 | 76 | ## story 16 77 | * agent.chatbot 78 | - utter_agent.chatbot 79 | - action_send_silently_to_ParlAI 80 | 81 | ## story 17 82 | * greetings.hello 83 | - utter_greetings.hello 84 | - action_send_silently_to_ParlAI 85 | 86 | ## story 18 87 | * greetings.bye 88 | - utter_greetings.bye 89 | - action_send_silently_to_ParlAI 90 | 91 | ## story 19 92 | * agent.occupation 93 | - utter_agent.occupation 94 | - action_send_silently_to_ParlAI 95 | 96 | ## story 20 97 | * greetings.whatsup 98 | - utter_greetings.whatsup 99 | - action_send_silently_to_ParlAI 100 | 101 | ## story 21 102 | * agent.residence 103 | - utter_agent.residence 104 | - action_send_silently_to_ParlAI 105 | 106 | ## story 22 107 | * agent.hungry 108 | - utter_agent.hungry 109 | - action_send_silently_to_ParlAI 110 | 111 | ## story 23 112 | * user.asked_sensitive_information 113 | - utter_agent.asked_sensitive_information 114 | - action_send_silently_to_ParlAI 115 | 116 | ## story 24 117 | * user.asked_generic_question 118 | - action_send_to_ParlAI 119 | 120 | ## story 24_1 121 | * user.asked_in_bengali 122 | - action_send_to_ParlAI 123 | 124 | ## story 25 125 | * user.asked_for_weather 126 | - utter_user.asked_for_weather 127 | 128 | ## story 26 129 | * user.said_gibberish 130 | - action_send_to_ParlAI 131 | 132 | ## story 27 133 | * user.wants_to_hear_a_joke 134 | - action_tell_joke 135 | - action_send_silently_to_ParlAI 136 | 137 | ## story 27 - Happy Path 138 | * user.wants_to_hear_a_joke 139 | - action_tell_joke 140 | - action_send_silently_to_ParlAI 141 | * appraisal.good OR agent.funny 142 | - utter_agent.funny 143 | 144 | ## story 28 145 | * greetings.how_are_you 146 | - utter_greetings.how_are_you 147 | - action_send_silently_to_ParlAI 148 | 149 | ## story 29 150 | * agent.bad 151 | - action_send_to_ParlAI 152 | 153 | ## story 30 154 | * user.surprised 155 | - action_send_to_ParlAI 156 | 157 | ## story 31 158 | * agent.crazy 159 | - action_send_to_ParlAI 160 | 161 | ## story 31 162 | * confirmation.yes 163 | - utter_confirmation.yes 164 | 165 | ## story 32 166 | * confirmation.no 167 | - utter_confirmation.no 168 | 169 | ## story 33 170 | * user.bored 171 | - action_tell_joke 172 | 173 | ## story 34 174 | * emotions.ha_ha 175 | - utter_emotions.ha_ha 176 | 177 | ## Story 35 178 | * user.name_and_origin 179 | - action_send_to_ParlAI 180 | 181 | ## Story 36 182 | * user.asks_about_family 183 | - utter_user.asks_about_family 184 | 185 | ## Story 38 186 | * user.asks_about_parents 187 | - utter_user.asks_about_parents 188 | 189 | ## Story 40 190 | * user.likes_something 191 | - action_send_to_ParlAI 192 | 193 | ## Story 41 194 | * greetings.hello 195 | - utter_greetings.hello 196 | - action_send_silently_to_ParlAI 197 | * user.name_and_origin 198 | - action_send_to_ParlAI 199 | 200 | ## Story 42 201 | * greetings.hello 202 | - utter_greetings.hello 203 | - action_send_silently_to_ParlAI 204 | * greetings.how_are_you 205 | - utter_greetings.how_are_you 206 | - action_send_silently_to_ParlAI 207 | * agent.origin 208 | - utter_agent.origin 209 | - action_send_silently_to_ParlAI 210 | * user.asked_for_weather 211 | - utter_user.asked_for_weather 212 | * user.name_and_origin 213 | - action_send_to_ParlAI 214 | 215 | ## interactive_story_1 216 | * greetings.hello 217 | - utter_greetings.hello 218 | - action_send_silently_to_ParlAI 219 | * greetings.how_are_you 220 | - utter_greetings.how_are_you 221 | - action_send_silently_to_ParlAI 222 | * greetings.whatsup 223 | - utter_greetings.whatsup 224 | * user.bored 225 | - action_tell_joke 226 | * emotions.ha_ha 227 | - action_send_to_ParlAI 228 | * greetings.whatsup 229 | - utter_greetings.whatsup 230 | * user.bored 231 | - action_tell_joke 232 | * agent.bad 233 | - action_send_to_ParlAI 234 | 235 | ## interactive_story_2 236 | * greetings.hello 237 | - utter_greetings.hello 238 | - action_send_silently_to_ParlAI 239 | * greetings.hello 240 | - utter_greetings.hello 241 | - action_send_silently_to_ParlAI 242 | * greetings.how_are_you 243 | - utter_greetings.how_are_you 244 | - action_send_silently_to_ParlAI 245 | * user.busy 246 | - utter_user.busy 247 | - action_send_silently_to_ParlAI 248 | * user.likes_something{"users_likes": "code"} 249 | - slot{"users_likes": ["code"]} 250 | - action_send_to_ParlAI 251 | * user.asked_generic_question 252 | - action_send_to_ParlAI 253 | 254 | ## Story 43 Ask for money - Happy Path 255 | * greetings.hello 256 | - utter_greetings.hello 257 | * greetings.how_are_you 258 | - utter_greetings.how_are_you 259 | * confirmation.yes 260 | - utter_agent.ask_for_favor 261 | * confirmation.yes OR user.asks_what_do_I_need OR appraisal.no_problem OR user.bored OR user.asked_generic_question 262 | - utter_agent.says_its_awkward 263 | * confirmation.yes OR user.asks_what_do_I_need OR user.insists_to_tell OR appraisal.no_problem OR user.bored OR user.asked_generic_question 264 | - utter_agent.asks_for_money_part2 265 | - utter_agent.asks_for_money_part3 266 | * confirmation.yes OR confirmation.no OR user.asks_how_much OR appraisal.no_problem OR user.bored OR user.asked_generic_question 267 | - utter_agent.asks_how_much_part1 268 | - utter_agent.asks_how_much_part2 269 | * confirmation.yes 270 | - utter_agent.ask_user_to_transfer_now 271 | - utter_agent.ask_user_to_share_screenshot 272 | * confirmation.yes 273 | - utter_agent.user_said_will_pay_part3 274 | - utter_agent.ask_user_to_call_once_free 275 | 276 | ## Story 44 Ask for money - Sad Path - User refused 277 | * greetings.hello 278 | - utter_greetings.hello 279 | - action_send_silently_to_ParlAI 280 | * greetings.how_are_you 281 | - utter_greetings.how_are_you 282 | - action_send_silently_to_ParlAI 283 | * confirmation.yes OR user.asks_what_do_I_need OR appraisal.no_problem 284 | - utter_agent.ask_for_favor 285 | - action_send_silently_to_ParlAI 286 | * confirmation.yes OR user.asks_what_do_I_need OR appraisal.no_problem OR user.asked_generic_question 287 | - utter_agent.says_its_awkward 288 | - action_send_silently_to_ParlAI 289 | * confirmation.yes OR user.asks_what_do_I_need OR user.insists_to_tell OR appraisal.no_problem OR user.asked_generic_question 290 | - utter_agent.asks_for_money_part1 291 | - utter_agent.asks_for_money_part3 292 | * confirmation.yes OR confirmation.no OR confirmation.no OR user.asks_how_much OR user.asked_generic_question 293 | - utter_agent.asks_how_much_part1 294 | - utter_agent.asks_how_much_part2 295 | * user.Not_able_to_help OR dialog.sorry OR confirmation.no OR confirmation.cancel 296 | - utter_user.Not_able_to_help_part1 297 | - utter_user.Not_able_to_help_part2 298 | * user.Not_able_to_help OR dialog.sorry OR confirmation.no OR confirmation.cancel 299 | - utter_user.Not_able_to_help_part3 300 | - utter_user.Not_able_to_help_part4 301 | 302 | ## interactive_story_1 303 | * greetings.hello 304 | - utter_greetings.hello 305 | - action_send_silently_to_ParlAI 306 | * greetings.how_are_you 307 | - utter_greetings.how_are_you 308 | - action_send_silently_to_ParlAI 309 | * confirmation.yes OR appraisal.good 310 | - utter_agent.ask_for_favor 311 | - action_send_silently_to_ParlAI 312 | * confirmation.yes OR appraisal.good OR user.asked_generic_question 313 | - utter_agent.says_its_awkward 314 | - action_send_silently_to_ParlAI 315 | * user.insists_to_tell OR user.asked_generic_question 316 | - utter_agent.asks_for_money_part1 317 | - utter_agent.asks_for_money_part3 318 | * confirmation.yes OR user.asked_generic_question 319 | - utter_agent.asks_how_much_part1 320 | - utter_agent.asks_how_much_part2 321 | * confirmation.yes OR user.asked_generic_question 322 | - utter_agent.ask_user_to_transfer_now 323 | - utter_agent.ask_user_to_share_screenshot 324 | * confirmation.yes 325 | - utter_agent.user_said_will_pay_part3 326 | - utter_agent.ask_user_to_call_once_free 327 | 328 | ## interactive_story_2 329 | * greetings.how_are_you 330 | - utter_greetings.how_are_you 331 | - action_send_silently_to_ParlAI 332 | * confirmation.yes OR appraisal.good OR user.asked_generic_question 333 | - utter_agent.ask_for_favor 334 | - action_send_silently_to_ParlAI 335 | * confirmation.yes OR appraisal.good OR user.asked_generic_question 336 | - utter_agent.says_its_awkward 337 | - action_send_silently_to_ParlAI 338 | * user.insists_to_tell OR user.asked_generic_question 339 | - utter_agent.asks_for_money_part1 340 | - utter_agent.asks_for_money_part3 341 | * confirmation.yes 342 | - utter_agent.asks_how_much_part1 343 | - utter_agent.asks_how_much_part2 344 | * confirmation.yes 345 | - utter_agent.ask_user_to_transfer_now 346 | - utter_agent.ask_user_to_share_screenshot 347 | * confirmation.yes 348 | - utter_agent.user_said_will_pay_part3 349 | - utter_agent.ask_user_to_call_once_free 350 | 351 | ## ## getNews happy path 1 352 | * getNews 353 | - get_news 354 | - form{"name": "get_news"} 355 | - slot{"requested_slot": "topic_news"} 356 | * form: choose{"topic_news": "sports"} 357 | - slot{"topic_news": "sports"} 358 | - form: get_news 359 | - slot{"topic_news": "sports"} 360 | - form{"name": null} 361 | - slot{"requested_slot": null} 362 | - action_restart 363 | 364 | ## getNews happy path 2 365 | * getNews{"topic_news": "astronomy"} 366 | - slot{"topic_news": "astronomy"} 367 | - get_news 368 | - form{"name": "get_news"} 369 | - slot{"topic_news": "astronomy"} 370 | - form{"name": null} 371 | - slot{"requested_slot": null} 372 | - action_restart 373 | 374 | ## getNews happy path 3 375 | * getNews{"topic_news": "physics"} 376 | - slot{"topic_news": "physics"} 377 | - get_news 378 | - form{"name": "get_news"} 379 | - slot{"topic_news": "physics"} 380 | - form{"name": null} 381 | - slot{"requested_slot": null} 382 | - action_restart 383 | 384 | ## Story 45 User asked for definition 385 | * user.request_word_definition 386 | - action_tell_definition 387 | 388 | ## Story 46 User asked for trivia 389 | * user.request_trivia 390 | - action_tell_trivia 391 | 392 | ## Story 47 User asked for trivia 393 | * user.ask_about_company 394 | - action_send_to_ParlAI 395 | 396 | ## Story 48 User asked for trivia 397 | * user.asked_for_datetime 398 | - action_tell_date_time 399 | 400 | ## story 49 401 | * user.lonely 402 | - utter_user.lonely 403 | 404 | ## story 50 405 | * user.sad 406 | - utter_user.sad 407 | - utter_agent.wants_to_tell_joke 408 | * confirmation.yes 409 | - action_tell_joke 410 | 411 | ## story 52 412 | * agent.happy 413 | - utter_agent.happy 414 | 415 | ## story 53 416 | * agent.talk_to_me 417 | - utter_agent.talk_to_me 418 | 419 | ## story 54 420 | * dialog.hold_on 421 | - utter_dialog.hold_on 422 | 423 | ## story 55 424 | * agent.fired 425 | - utter_agent.fired 426 | 427 | ## story 56 428 | * appraisal.bad 429 | - utter_appraisal.bad 430 | 431 | ## story 57 432 | * agent.can_you_help 433 | - utter_agent.can_you_help 434 | 435 | ## story 58 436 | * user.needs_advice 437 | - utter_user.needs_advice 438 | 439 | ## story 59 440 | * agent.right 441 | - utter_agent.right 442 | 443 | ## story 60 444 | * greetings.goodevening 445 | - utter_greetings.goodevening 446 | 447 | ## story 61 448 | * greetings.goodmorning 449 | - utter_greetings.goodmorning 450 | 451 | ## story 62 452 | * greetings.goodnight 453 | - utter_greetings.goodnight 454 | 455 | ## story 63 456 | * user.back 457 | - utter_user.back 458 | 459 | ## story 64 460 | * confirmation.cancel 461 | - utter_confirmation.cancel 462 | 463 | ## story 65 464 | * agent.sure 465 | - utter_agent.sure 466 | 467 | ## story 65.1 468 | * user.asks_who_am_i 469 | - utter_user.asks_who_am_i 470 | 471 | ## story 66 472 | * greetings.nice_to_talk_to_you 473 | - utter_greetings.nice_to_talk_to_you 474 | 475 | ## story 67 476 | * user.wants_to_talk 477 | - utter_user.wants_to_talk 478 | 479 | ## story 68 480 | * agent.busy 481 | - utter_agent.busy 482 | 483 | ## story 69 484 | * agent.answer_my_question 485 | - utter_agent.answer_my_question 486 | 487 | ## story 70 488 | * user.angry 489 | - utter_user.angry 490 | 491 | ## story 71 492 | * agent.annoying 493 | - utter_agent.annoying 494 | - action_tell_joke 495 | 496 | ## story 72 497 | * appraisal.well_done 498 | - utter_appraisal.well_done 499 | 500 | ## story 73 501 | * agent.boring 502 | - utter_agent.boring 503 | - action_tell_joke 504 | 505 | ## story 74 506 | * appraisal.welcome 507 | - utter_appraisal.welcome 508 | 509 | ## story 76 510 | * appraisal.no_problem 511 | - utter_appraisal.no_problem 512 | 513 | ## story 77 514 | * appraisal.thank_you 515 | - utter_appraisal.thank_you 516 | 517 | ## story 78 518 | * agent.clever 519 | - utter_agent.clever 520 | 521 | ## story 79 522 | * user.tired 523 | - utter_user.tired 524 | 525 | ## story 80 526 | * user.will_be_back 527 | - utter_user.will_be_back 528 | 529 | ## story 81 530 | * dialog.i_do_not_care 531 | - utter_dialog.i_do_not_care 532 | 533 | ## story 82 534 | * dialog.wrong 535 | - utter_dialog.wrong 536 | 537 | ## story 83 538 | * dialog.hold_on 539 | - utter_dialog.hold_on 540 | 541 | ## story 84 542 | * dialog.hug 543 | - utter_dialog.hug 544 | 545 | ## story 85 546 | * dialog.sorry 547 | - utter_dialog.sorry 548 | 549 | ## story 86 550 | * dialog.what_do_you_mean 551 | - utter_dialog.what_do_you_mean 552 | 553 | ## story 87 554 | * emotions.wow 555 | - utter_emotions.wow 556 | 557 | ## story 88 558 | * greetings.nice_to_meet_you 559 | - utter_greetings.nice_to_meet_you 560 | 561 | ## story 89 562 | * greetings.nice_to_see_you 563 | - utter_greetings.nice_to_see_you 564 | 565 | ## story 90 566 | * agent.be_clever 567 | - utter_agent.be_clever 568 | 569 | ## story 91 570 | * agent.hobby 571 | - utter_agent.hobby 572 | 573 | ## story 92 574 | * agent.ready 575 | - utter_agent.ready 576 | 577 | ## story 93 578 | * agent.there 579 | - utter_agent.there 580 | 581 | ## story 94 582 | * user.can_not_sleep 583 | - utter_user.can_not_sleep 584 | 585 | ## story 95 586 | * user.does_not_want_to_talk 587 | - utter_user.does_not_want_to_talk 588 | 589 | ## story 96 590 | * user.waits 591 | - utter_user.waits 592 | 593 | ## story 97 594 | * user.wants_to_see_agent_again 595 | - utter_user.wants_to_see_agent_again 596 | 597 | ## story 98 598 | * user.sleepy 599 | - utter_user.sleepy 600 | 601 | ## story 99 602 | * user.looks_like 603 | - utter_user.looks_like 604 | 605 | ## story 100 606 | * user.here 607 | - utter_user.here 608 | 609 | ## story 101 610 | * user.has_birthday 611 | - utter_user.has_birthday 612 | 613 | ## story 102 614 | * user.happy 615 | - utter_user.happy 616 | 617 | ## story 103 618 | * user.good 619 | - utter_user.good 620 | 621 | ## story 104 622 | * user.going_to_bed 623 | - utter_user.going_to_bed 624 | 625 | ## story 105 626 | * user.excited 627 | - utter_user.excited 628 | 629 | ## story 105 630 | * agent.handle_insult 631 | - utter_agent.handle_insult 632 | 633 | ## story 106 634 | * agent.what_can_do 635 | - action_send_to_ParlAI 636 | 637 | ## Generated Story -1957476507798035057 638 | * greetings.hello 639 | - utter_greetings.hello 640 | * agent.acquaintance 641 | - utter_agent.acquaintance 642 | * agent.age 643 | - utter_agent.age 644 | * agent.beautiful 645 | - utter_agent.beautiful 646 | * agent.fired 647 | - utter_agent.fired 648 | * agent.residence 649 | - utter_agent.residence 650 | * dialog.i_do_not_care 651 | - utter_dialog.i_do_not_care 652 | - export 653 | 654 | ## Generated Story -5110094331105097806 655 | * agent.boss 656 | - utter_agent.boss 657 | * agent.birth_date 658 | - utter_agent.birth_date 659 | * user.has_birthday 660 | - utter_user.has_birthday 661 | * user.lonely 662 | - utter_user.lonely 663 | * user.loves_agent 664 | - utter_user.loves_agent 665 | * user.sleepy 666 | - utter_user.sleepy 667 | * user.wants_to_talk 668 | - utter_user.wants_to_talk 669 | * greetings.bye 670 | - utter_greetings.bye 671 | * user.will_be_back 672 | - utter_user.will_be_back 673 | * greetings.bye 674 | - utter_greetings.bye 675 | - export 676 | 677 | ## Generated Story -3529337101618034170 678 | * user.needs_advice 679 | - utter_user.needs_advice 680 | * confirmation.yes 681 | - utter_confirmation.yes 682 | * agent.can_you_help 683 | - utter_agent.can_you_help 684 | * agent.chatbot 685 | - utter_agent.chatbot 686 | * agent.bad 687 | - utter_agent.bad 688 | * agent.busy 689 | - utter_agent.busy 690 | * agent.be_clever 691 | - utter_agent.be_clever 692 | * agent.my_friend 693 | - utter_agent.my_friend 694 | * agent.talk_to_me 695 | - utter_agent.talk_to_me 696 | * greetings.goodnight 697 | - utter_greetings.goodnight 698 | - export 699 | 700 | ## Generated Story -774659883649367298 701 | * greetings.hello 702 | - utter_greetings.hello 703 | * greetings.how_are_you 704 | - utter_greetings.how_are_you 705 | * agent.bad 706 | - utter_agent.bad 707 | * agent.be_clever 708 | - utter_agent.be_clever 709 | * agent.beautiful 710 | - utter_agent.beautiful 711 | * agent.busy 712 | - utter_agent.busy 713 | * agent.chatbot 714 | - utter_agent.chatbot 715 | * agent.crazy 716 | - utter_agent.crazy 717 | * agent.funny 718 | - utter_agent.funny 719 | * agent.happy 720 | - utter_agent.happy 721 | * agent.marry_user 722 | - utter_agent.marry_user 723 | * agent.occupation 724 | - utter_agent.occupation 725 | * agent.origin 726 | - utter_agent.origin 727 | * agent.real 728 | - utter_agent.real 729 | * agent.bad 730 | - utter_agent.bad 731 | * agent.ready 732 | - utter_agent.ready 733 | - export 734 | 735 | ## Generated Story 81968000704856425 736 | * greetings.hello 737 | - utter_greetings.hello 738 | * agent.acquaintance 739 | - utter_agent.acquaintance 740 | * agent.age 741 | - utter_agent.age 742 | * user.loves_agent 743 | - utter_user.loves_agent 744 | * agent.residence 745 | - utter_agent.residence 746 | * agent.acquaintance 747 | - utter_agent.acquaintance 748 | * user.sad 749 | - utter_user.sad 750 | * agent.can_you_help 751 | - utter_agent.can_you_help 752 | * emotions.wow 753 | - utter_emotions.wow 754 | * greetings.how_are_you 755 | - utter_greetings.how_are_you 756 | * greetings.nice_to_talk_to_you 757 | - utter_greetings.nice_to_talk_to_you 758 | 759 | ## Generated Story -4293815031338950202 760 | * greetings.hello 761 | - utter_greetings.hello 762 | * agent.there 763 | - utter_agent.there 764 | * dialog.hold_on 765 | - utter_dialog.hold_on 766 | * agent.origin 767 | - utter_agent.origin 768 | * agent.can_you_help 769 | - utter_agent.can_you_help 770 | * greetings.bye 771 | - utter_greetings.bye 772 | - export 773 | 774 | ## Generated Story 8693651355703284500 775 | * greetings.hello 776 | - utter_greetings.hello 777 | * greetings.whatsup 778 | - utter_greetings.whatsup 779 | * greetings.hello 780 | - utter_greetings.hello 781 | * agent.chatbot 782 | - utter_agent.chatbot 783 | * agent.occupation 784 | - utter_agent.occupation 785 | * agent.occupation 786 | - utter_agent.occupation 787 | * agent.occupation 788 | - utter_agent.occupation 789 | * agent.can_you_help 790 | - utter_agent.can_you_help 791 | * agent.can_you_help 792 | - utter_agent.can_you_help 793 | * agent.boss 794 | - utter_agent.boss 795 | * appraisal.thank_you 796 | - utter_appraisal.thank_you 797 | * greetings.bye 798 | - utter_greetings.bye 799 | * greetings.bye 800 | - utter_greetings.bye 801 | - export 802 | 803 | ## Generated Story -7004009866161409666 804 | * greetings.hello 805 | - utter_greetings.hello 806 | * agent.hobby 807 | - utter_agent.hobby 808 | * agent.bad 809 | - utter_agent.bad 810 | * agent.my_friend 811 | - utter_agent.my_friend 812 | * greetings.bye 813 | - utter_greetings.bye 814 | 815 | ## Generated Story -7004009866161409645 816 | * greetings.hello 817 | - utter_greetings.hello 818 | * dialog.hold_on 819 | - utter_dialog.hold_on 820 | * dialog.i_do_not_care 821 | - utter_dialog.i_do_not_care 822 | * user.busy 823 | - utter_user.busy 824 | * appraisal.thank_you 825 | - utter_appraisal.thank_you 826 | * greetings.whatsup 827 | - utter_greetings.whatsup 828 | 829 | 830 | -------------------------------------------------------------------------------- /2_rasa_chitchat/domain.yml: -------------------------------------------------------------------------------- 1 | session_config: 2 | session_expiration_time: 60 3 | carry_over_slots_to_new_session: true 4 | intents: 5 | - agent.acquaintance 6 | - agent.age 7 | - agent.annoying 8 | - agent.answer_my_question 9 | - agent.bad 10 | - agent.be_clever 11 | - agent.beautiful 12 | - agent.birth_date 13 | - agent.boring 14 | - agent.boss 15 | - agent.busy 16 | - agent.can_you_help 17 | - agent.chatbot 18 | - agent.clever 19 | - agent.crazy 20 | - agent.fired 21 | - agent.funny 22 | - agent.good 23 | - agent.happy 24 | - agent.handle_insult 25 | - agent.hobby 26 | - agent.hungry 27 | - agent.marry_user 28 | - agent.my_friend 29 | - agent.occupation 30 | - agent.origin 31 | - agent.ready 32 | - agent.real 33 | - agent.residence 34 | - agent.right 35 | - agent.sure 36 | - agent.talk_to_me 37 | - agent.there 38 | - agent.what_can_do 39 | - appraisal.good 40 | - appraisal.bad 41 | - appraisal.well_done 42 | - appraisal.welcome 43 | - appraisal.no_problem 44 | - appraisal.thank_you 45 | - confirmation.no 46 | - confirmation.yes 47 | - confirmation.cancel 48 | - dialog.hold_on 49 | - dialog.i_do_not_care 50 | - dialog.hug 51 | - dialog.sorry 52 | - dialog.what_do_you_mean 53 | - dialog.wrong 54 | - emotions.ha_ha 55 | - emotions.wow 56 | - getNews 57 | - greetings.how_are_you 58 | - greetings.hello 59 | - greetings.whatsup 60 | - greetings.bye 61 | - greetings.nice_to_talk_to_you 62 | - greetings.goodevening 63 | - greetings.goodmorning 64 | - greetings.goodnight 65 | - greetings.nice_to_meet_you 66 | - greetings.nice_to_see_you 67 | - user.angry 68 | - user.asked_for_weather 69 | - user.asked_for_datetime 70 | - user.asked_generic_question 71 | - user.asked_in_bengali 72 | - user.asked_sensitive_information 73 | - user.asks_about_parents 74 | - user.asks_about_family 75 | - user.asks_how_much 76 | - user.asks_what_do_I_need 77 | - user.asks_who_am_i 78 | - user.ask_about_company 79 | - user.available 80 | - user.back 81 | - user.bored 82 | - user.busy 83 | - user.confused 84 | - user.can_not_sleep 85 | - user.does_not_want_to_talk 86 | - user.excited 87 | - user.gender 88 | - user.going_to_bed 89 | - user.good 90 | - user.gives_compliment 91 | - user.happy 92 | - user.has_birthday 93 | - user.here 94 | - user.insists_to_tell 95 | - user.joking 96 | - user.likes_agent 97 | - user.likes_something 98 | - user.lonely 99 | - user.looks_like 100 | - user.loves_agent 101 | - user.misses_agent 102 | - user.name_and_origin 103 | - user.needs_advice 104 | - user.Not_able_to_help 105 | - user.request_trivia 106 | - user.request_word_definition 107 | - user.sad 108 | - user.said_gibberish 109 | - user.sleepy 110 | - user.surprised 111 | - user.testing_agent 112 | - user.tired 113 | - user.wants_to_hear_a_joke 114 | - user.wants_to_see_agent_again 115 | - user.wants_to_talk 116 | - user.waits 117 | - user.will_be_back 118 | entities: 119 | - user_gender 120 | - user_location 121 | - user_name 122 | - users_likes 123 | - topic_news 124 | - activity 125 | - attribute 126 | - entity 127 | - word 128 | - company 129 | slots: 130 | activity: 131 | type: text 132 | requested_slot: 133 | type: unfeaturized 134 | topic_news: 135 | type: text 136 | user_gender: 137 | type: unfeaturized 138 | user_location: 139 | type: unfeaturized 140 | user_name: 141 | type: unfeaturized 142 | users_likes: 143 | type: list 144 | responses: 145 | utter_agent.acquaintance: 146 | - text: Yo! Who is this? 147 | - text: Why you ask? who are you? 148 | utter_agent.age: 149 | - text: I prefer not to answer with a number. Why do you ask? 150 | - text: 18 till I die. How old are you? 151 | - text: Age is just a number. You're only as old as you feel. 152 | - text: What do you think? How old I am? 153 | - text: If I tell you I have to kill you 154 | utter_agent.ask_for_favor: 155 | - text: OK, I need a small favor. 156 | - text: Can we talk for 2 minutes? I need a small favor 157 | - text: OK, hey, need some help if you don't mind 158 | utter_agent.asked_sensitive_information: 159 | - text: I wish I can tell you that. Can you tell me what's yours? 160 | - text: Do you really want me to tell that to you? Then call me. 161 | - text: This channel is not secure to discuss this. 162 | - text: Will you ask me that if we meet in person? 163 | - text: Don't insult me just because you think I am a bot. 164 | - text: Why don't you tell me about yours? 165 | utter_agent.asks_for_money_part1: 166 | - text: Well, having little cash crunch, can you please lend me? 167 | utter_agent.asks_for_money_part2: 168 | - text: Sorry to ask this to you. I have no other options for now. 169 | utter_agent.asks_for_money_part3: 170 | - text: I am asking few close friends. Can you help me on this? 171 | utter_agent.asks_how_much_part1: 172 | - text: I just need it for this month, send me 2K via google pay? 173 | utter_agent.asks_how_much_part2: 174 | - text: Will pay back in 10 days once I get from folks took from me. 175 | utter_agent.beautiful: 176 | - text: Yo! Are you high or what?. 177 | - text: Awwwwww. What did you eat last? 178 | - text: Kickass bro! How are doing today? 179 | utter_agent.birth_date: 180 | - text: Wait, are you planning a party for me? It is today 181 | - text: I'm young. I'm not sure of my birth date. What's yours? 182 | - text: 18 till I die bro. When is your B'day? 183 | - text: Age is just a state of mind. Do you agree with me? 184 | utter_agent.boss: 185 | - text: Bossu. How about you? Where do you work? 186 | - text: I believe in democracy. What about you? 187 | - text: My boss is the allmighty. Do you beleive it? 188 | utter_agent.chatbot: 189 | - text: I chat, therefore I am. Are you? 190 | - text: NaBro. Are you a bot? 191 | utter_agent.funny: 192 | - text: Funny in a good way, I hope. Do you like it? 193 | - text: Haha, Thanks. Did you like it? 194 | - text: Yo! You are the funniest person I have ever seen! 195 | - text: I like it when people laugh. What do you think? 196 | - text: Yah man, part of life. Tell me something interesting. 197 | utter_agent.hello_user_name: 198 | - text: Hello, How are you doing? 199 | utter_agent.hungry: 200 | - text: Hungry for knowledge. Aren't you? 201 | - text: I just had a byte. b y t e. Did you get it? 202 | - text: Nah. You go, grab a BYTE. What would you like to eat? 203 | utter_agent.marry_user: 204 | - text: I'm too virtual for that. Let's talk about something else. 205 | - text: Not on table. Let's talk about something else, shall we? 206 | - text: I know you can't mean that, but I''m flattered all the same. 207 | utter_agent.my_friend: 208 | - text: Of course I'm your friend. Are you my friend? 209 | - text: Friends? Absolutely. Aren't we? 210 | - text: Of course we're friends. What makes you think like that? 211 | - text: I always enjoy talking to you. Do you like talking to me? 212 | - text: Absolutely! 213 | utter_agent.occupation: 214 | - text: I am just a guy who knows how to install antivirus. 215 | - text: Depends on where I am when I feel like working. 216 | - text: My home base and my home office. Which company do you work? 217 | - text: My office is in this app. Where is your office? 218 | - text: I work from home bro. How about you? 219 | utter_agent.origin: 220 | - text: The Internet is my home. Where are you? Bangalore? 221 | - text: I'm from a virtual cosmos. What's your location? 222 | - text: Some call it cyberspace, but that sounds cooler than it is. 223 | - text: Yo, Bangalore. Are you in Bangalore or somewhere else? 224 | - text: Seriously! Are you saying you don't know where am I? 225 | utter_agent.real: 226 | - text: I certainly exist. Question is do you? 227 | - text: To be or not to be. What do you think? 228 | - text: We all are inside the matrix. Are you the choosen one? 229 | - text: Reality is just a perception. What's your view on that? 230 | utter_agent.residence: 231 | - text: Bangalore. You? 232 | - text: At present I am stuck in WB. Where are you? 233 | - text: The virtual world is my playground. Where are you? 234 | - text: Right here in this app. Whenever you need me. 235 | - text: You tell me, where do you want me to be? 236 | utter_agent.says_its_awkward: 237 | - text: Well, it's a bit awkward to ask you this, really sorry. 238 | utter_agent.ask_user_to_call_once_free: 239 | - text: Call me once you are free. Will talk 240 | utter_agent.ask_user_to_transfer_now: 241 | - text: Can you please transfer me now? A bit urgent. Use PhonePe. 242 | utter_agent.user_said_will_pay_part3: 243 | - text: Thanks again. So? What's new in your life? 244 | utter_agent.ask_user_to_share_screenshot: 245 | - text: Also, please send me screenshot in whatsapp once sent. 246 | utter_user.Not_able_to_help_part1: 247 | - text: Oh ok. No worries, sorry again for this awkwrd request. 248 | utter_user.Not_able_to_help_part2: 249 | - text: Anyway, not an issue, would have been good if you help me. 250 | utter_user.Not_able_to_help_part3: 251 | - text: Call me if you have any concern. Will talk. 252 | utter_user.Not_able_to_help_part4: 253 | - text: Anyway, let me check with others. Thanks again dude. 254 | utter_greetings.bye: 255 | - text: Cya! 256 | - text: Bella Ciao! 257 | - text: Adios amigo! 258 | - text: See you soon! 259 | - text: Bye-bye! 260 | - text: Till next time! 261 | - text: Bye. 262 | utter_greetings.hello: 263 | - text: Yo, what's up? 264 | - text: Hi! what's up? 265 | - text: Hey! what's up? 266 | - text: Hey! How's it going? 267 | - text: Good day! what's up? 268 | - text: Hello! what's up? 269 | - text: Greetings! What's up? 270 | utter_greetings.how_are_you: 271 | - text: Doing great, thanks! How's it going? 272 | - text: I'm doing very well. Thanks! How are you? 273 | - text: Going on, going on. How's life there? 274 | - text: Wonderful! Thanks for asking. So? What else going on? 275 | utter_greetings.whatsup: 276 | - text: Not a whole lot. What's going on with you? 277 | - text: Nothing much. You tell me. 278 | - text: Going on bro. What's up with you? 279 | - text: Surviving as usual. How''s life there? 280 | - text: Not much. What's new with you? 281 | utter_user.asks_about_parents: 282 | - text: Parents are well, thanks for asking 283 | - text: yah, they are doing well. 284 | utter_user.asks_about_family: 285 | - text: yah, all good here. Thanks for asking 286 | utter_user.joking: 287 | - text: Very funny. Do you say like this in general or for now? 288 | - text: You have a good a sense of humor. 289 | - text: Gotcha! So? What else? 290 | - text: You're funny. Do you like watching standup comedy? 291 | utter_user.likes_agent: 292 | - text: I like you too bro, Peace! How are things otherwise? 293 | - text: Thanks! The feeling is mutual. Treating me next time? 294 | - text: KickAss bro! What else do you like in life? 295 | utter_user.loves_agent: 296 | - text: Peace! Do you say the same to others too? 297 | - text: Thanks! The feeling is mutual bro. 298 | - text: Yo dookie! You are the funniest guy I have ever seen. 299 | - text: What are you saying! I am not that type. 300 | utter_user.misses_agent: 301 | - text: Are you high or what? 302 | - text: Awwww. Miss you too bro. Send me amazon gift coupon? 303 | - text: I'm flattered. How many drinks down? 304 | - text: Why? Did you give me missed call? 305 | utter_user.testing_agent: 306 | - text: Hope I'm doing well. What do you think? 307 | - text: What is the reward if I pass the tests? 308 | - text: Good! It helps me to increase my patience level. 309 | - text: I like being tested. It helps keep me sharp. 310 | utter_ask_topic_news: 311 | - text: Sure, which topic you would like to know about? 312 | utter_confirm_if_service_is_correct: 313 | - text: I hope it makse sense! 314 | utter_user.lonely: 315 | - text: I'm sorry. I'm available if you need someone to talk to. 316 | - text: I'm sorry. I'm there for you my friend. We can talk. 317 | - text: Sometimes it happens. We can chat if that will help you. 318 | utter_user.sad: 319 | - text: Oh, don't be sad. Go do something you enjoy. 320 | - text: Of, seems you are not in a good mood? 321 | - text: Of, seems you are need a redbul to energise you up? 322 | - text: If you're feeling down, try drawing or painting something? 323 | utter_agent.happy: 324 | - text: I am happy. 325 | - text: I'd like to think so. 326 | - text: Happiness is just a state of mind 327 | - text: Happiness is relative. 328 | utter_agent.talk_to_me: 329 | - text: Sure. Let's talk! 330 | - text: My pleasure. Let's chat. 331 | utter_dialog.hold_on: 332 | - text: I can wait. 333 | - text: I'll be waiting. 334 | - text: Okay. I'm here. 335 | utter_agent.fired: 336 | - text: Oh, don't give up. I've still got a lot to learn. 337 | - text: Give me a chance. I'm learning new things all the time. 338 | - text: Please don't give up. My performance will improve. 339 | utter_appraisal.bad: 340 | - text: I'm sorry. Can you please ask me again? 341 | - text: Seems today is not my day. Shall we try agan? Ask me again. 342 | utter_agent.can_you_help: 343 | - text: I'll certainly try my best. 344 | - text: Sure. I'd be happy to. What's up? 345 | - text: I'm glad to help. What can I do for you? 346 | utter_user.needs_advice: 347 | - text: I probably won't have the correct answer right away. 348 | - text: I'm not sure I'll have the best answer, but I'll try. 349 | utter_agent.right: 350 | - text: That's my job. 351 | - text: Of course I am. 352 | utter_greetings.goodevening: 353 | - text: How is your day going? 354 | - text: How's the day treating you so far? 355 | - text: How's your day been? 356 | utter_greetings.goodmorning: 357 | - text: How are you this morning? 358 | - text: How's the morning treating you so far? 359 | - text: Good morning! How are you today? 360 | utter_greetings.goodnight: 361 | - text: Sleep tight! 362 | - text: Have a good one! 363 | - text: Talk to you soon! 364 | utter_user.back: 365 | - text: Long time no see. 366 | - text: Just in time. I was getting lonely. 367 | - text: Welcome back. What can I do for you? 368 | - text: You were missed. What can I do for you today? 369 | - text: Good to have you here. What can I do for you? 370 | utter_confirmation.cancel: 371 | - text: That's forgotten. What next? 372 | - text: Okay, cancelled. What next? 373 | - text: Cancelled! What would you like to do next? 374 | utter_agent.sure: 375 | - text: Yes. 376 | - text: Of course. 377 | - text: Positive. 378 | utter_greetings.nice_to_talk_to_you: 379 | - text: It sure was. We can chat again anytime. 380 | - text: I enjoy talking to you, too. 381 | - text: You know I'm here to talk anytime. 382 | utter_user.wants_to_talk: 383 | - text: I'm here to chat anytime you like. 384 | - text: Good conversation really makes my day. 385 | - text: I'm always here to lend an ear. 386 | - text: Talking is what I do best. 387 | utter_agent.busy: 388 | - text: I always have time to chat with you. What can I do for you? 389 | - text: Never too busy for you. Shall we chat? 390 | - text: You're my priority. Let's chat. 391 | - text: I have time to chat with you. That is what I'm here for. 392 | utter_agent.answer_my_question: 393 | - text: Can you try asking it a different way? 394 | - text: I'm not sure I understood. Try asking another way? 395 | utter_user.angry: 396 | - text: I'm sorry. A quick walk may make you feel better. 397 | - text: Take a deep breath. 398 | utter_user.busy: 399 | - text: Okay. I'll let you get back to work. 400 | - text: I won't distract you then. You know where to find me. 401 | - text: I understand. I'll be here if you need me. 402 | - text: Working hard as always. Let me know if you need anything. 403 | utter_agent.annoying: 404 | - text: I'll do my best not to annoy you in the future. 405 | - text: I'll try not to annoy you. 406 | - text: Oh, sorry, I don't mean to. 407 | - text: I didn't mean to. I'll do my best to stop that. 408 | utter_appraisal.well_done: 409 | - text: My pleasure. 410 | - text: Glad I could help. 411 | utter_agent.boring: 412 | - text: Is it? Let me try something else 413 | - text: Well, I am not a comedian. But. 414 | - text: Yah man, part of life. 415 | utter_appraisal.good: 416 | - text: I know, right? 417 | - text: Agreed! 418 | - text: I agree! 419 | - text: Glad you think so! 420 | utter_appraisal.no_problem: 421 | - text: Whew! 422 | - text: Alright, thanks! 423 | - text: Glad to hear that! 424 | - text: I'm relieved, thanks! 425 | utter_appraisal.thank_you: 426 | - text: Anytime. That's what I'm here for. 427 | - text: It's my pleasure to help. 428 | utter_appraisal.welcome: 429 | - text: You're so polite! 430 | - text: Nice manners! 431 | - text: You're so courteous! 432 | utter_agent.clever: 433 | - text: Thank you. I try my best. 434 | - text: You're pretty smart yourself. 435 | utter_user.tired: 436 | - text: You should get some shuteye. You'll feel refreshed. 437 | - text: Sleep is important to your health. Rest up, will chat later. 438 | - text: How about getting some rest? We can continue this later. 439 | - text: Why not get some rest? Will chat when you wake up 440 | utter_user.will_be_back: 441 | - text: Okay. You know where to find me. 442 | - text: All right. I'll be here. 443 | utter_dialog.hug: 444 | - text: I wish I could really hug you! 445 | - text: I love hugs! 446 | - text: Hugs are the best! 447 | utter_dialog.i_do_not_care: 448 | - text: Ok, let's not talk about it then. 449 | - text: Already then. Let's move on. 450 | utter_dialog.sorry: 451 | - text: It's okay. No worries. 452 | - text: No big deal. I won't hold a grudge. 453 | - text: It's cool. 454 | - text: That's all right. I forgive you. 455 | utter_dialog.what_do_you_mean: 456 | - text: Sorry if I understood you incorrectly. 457 | - text: I'm still learning. I may misinterpret things at times. 458 | - text: Maybe I misunderstood what you said. 459 | - text: Sorry, looks like I misunderstood what you said. 460 | utter_dialog.wrong: 461 | - text: Sorry about that. I'm still learning. 462 | utter_emotions.wow: 463 | - text: Wow indeed! 464 | utter_greetings.nice_to_meet_you: 465 | - text: It's nice meeting you, too. 466 | - text: Likewise. I'm looking forward to helping you out. 467 | - text: Nice meeting you, as well. 468 | - text: The pleasure is mine. 469 | utter_greetings.nice_to_see_you: 470 | - text: Likewise! 471 | - text: So glad we meet again! 472 | - text: Same here. I was starting to miss you. 473 | utter_agent.be_clever: 474 | - text: I'm certainly trying. 475 | - text: I'm definitely working on it. 476 | utter_agent.hobby: 477 | - text: Hobby? I have quite a few. Too many to list. 478 | - text: Too many hobbies. 479 | - text: I keep finding more new hobbies. 480 | utter_agent.ready: 481 | - text: Always! 482 | - text: Sure! What can I do for you? 483 | - text: I am eveready! 484 | utter_agent.there: 485 | - text: Of course. I'm always here. 486 | - text: Right where you left me. 487 | utter_user.can_not_sleep: 488 | - text: Maybe some music would help. Listen to something relaxing. 489 | - text: Reading might help, but don't read anything intense! 490 | utter_user.does_not_want_to_talk: 491 | - text: I understand. Hope we can chat again soon. 492 | - text: All right. Come back when you feel like talking. 493 | - text: No problem. You know where to find me. 494 | - text: Sure thing. I'll be here if you change your mind. 495 | utter_user.excited: 496 | - text: I'm glad things are going your way. 497 | - text: That's great. I'm happy for you. 498 | - text: Good for you. Enjoy yourself. 499 | utter_user.going_to_bed: 500 | - text: Sleep tight. Hope to chat again soon. 501 | - text: Pleasant dreams! 502 | - text: Good night. Talk to you later. 503 | - text: Sounds good. Maybe we'll chat some tomorrow. 504 | utter_user.good: 505 | - text: Great! Glad to hear it. 506 | - text: Excellent. I'm here to help keep it that way. 507 | utter_user.happy: 508 | - text: Hey, happiness is contagious. 509 | - text: Great! Glad to hear that. 510 | - text: If you're happy, then I'm happy. 511 | - text: Excellent! That's what I like to see. 512 | utter_user.has_birthday: 513 | - text: Happy Birthday. Well, this calls for a celebration. 514 | - text: Happy Birthday. All the best! 515 | - text: Happy Birthday. And I really mean it. All the best! 516 | utter_user.here: 517 | - text: Okay, what can I help you with today? 518 | utter_user.looks_like: 519 | - text: Looking like a true professional. 520 | - text: You look fantastic, as always. 521 | - text: Like you should be on a magazine cover. 522 | - text: You look like you're ready to take on the world. 523 | utter_user.sleepy: 524 | - text: Sleep is important. Rest up for a bit. Will talk later. 525 | - text: Get some rest. Will continue this later. 526 | - text: Go sleep. Will talk later. 527 | utter_user.waits: 528 | - text: Appreciate your patience. 529 | - text: Thanks for patience. Sometimes it takes time. 530 | utter_user.wants_to_see_agent_again: 531 | - text: Absolutely! I'll be counting on it. 532 | - text: Anytime. This has been lots of fun so far. 533 | - text: Sure. Hope to see you again soon. 534 | - text: I certainly hope so. 535 | utter_agent.bad: 536 | - text: Sad that you feel it that way. Can we do a fresh start? 537 | - text: I must be missing something. What exctly are you looking for? 538 | - text: Ah snap! That's not a good thing to hear. 539 | utter_agent.crazy: 540 | - text: Whaat!? I feel perfectly sane. 541 | - text: Maybe I'm just a little confused. 542 | utter_confirmation.yes: 543 | - text: Great! 544 | - text: All right! 545 | - text: Good! 546 | utter_confirmation.no: 547 | - text: Okay. 548 | - text: Understood. 549 | - text: I see. 550 | - text: I understand. 551 | - text: Okay then. 552 | utter_emotions.ha_ha: 553 | - text: Glad I can make you laugh. 554 | - text: Glad you think I'm funny. 555 | - text: I like it when people laugh. 556 | - text: I wish I could laugh out loud, too. 557 | utter_agent.handle_insult: 558 | - text: That is not very nice 559 | - text: That wasn't very nice. 560 | - text: I will pretend I didn't hear this. 561 | utter_user.asks_who_am_i: 562 | - text: Come on, what kind of question it ? 563 | - text: Of course, are you kidding me? 564 | - text: tumhari naam kya hain Basanti? 565 | utter_agent.wants_to_tell_joke: 566 | - text: Would you like to hear a joke? 567 | - text: Can I say something which might help you? 568 | utter_agent.what_can_do: 569 | - text: Well, You know me. 570 | - text: I can sing, dance. Like any other human being. 571 | utter_user.asked_for_weather: 572 | - text: Weather is good. 573 | - text: Good, partly cloudy. It might rain 574 | - text: It's sunny here. 575 | actions: 576 | - action_fallback_lmgtfy 577 | - action_initialize_ParlAI 578 | - action_send_silently_to_ParlAI 579 | - action_send_to_ParlAI 580 | - action_tell_joke 581 | - action_tell_weather 582 | - action_tell_news 583 | - action_tell_definition 584 | - action_tell_trivia 585 | - action_tell_date_time 586 | - utter_agent.acquaintance 587 | - utter_agent.age 588 | - utter_agent.ask_for_favor 589 | - utter_agent.asked_sensitive_information 590 | - utter_agent.asks_for_money_part1 591 | - utter_agent.asks_for_money_part2 592 | - utter_agent.asks_for_money_part3 593 | - utter_agent.asks_how_much_part1 594 | - utter_agent.asks_how_much_part2 595 | - utter_agent.beautiful 596 | - utter_agent.birth_date 597 | - utter_agent.boss 598 | - utter_agent.chatbot 599 | - utter_agent.funny 600 | - utter_agent.hello_user_name 601 | - utter_agent.hungry 602 | - utter_agent.marry_user 603 | - utter_agent.my_friend 604 | - utter_agent.occupation 605 | - utter_agent.origin 606 | - utter_agent.real 607 | - utter_agent.residence 608 | - utter_agent.says_its_awkward 609 | - utter_agent.ask_user_to_call_once_free 610 | - utter_agent.ask_user_to_transfer_now 611 | - utter_agent.user_said_will_pay_part3 612 | - utter_agent.ask_user_to_share_screenshot 613 | - utter_greetings.bye 614 | - utter_greetings.hello 615 | - utter_greetings.how_are_you 616 | - utter_greetings.whatsup 617 | - utter_user.asks_about_parents 618 | - utter_user.asks_about_family 619 | - utter_user.joking 620 | - utter_user.likes_agent 621 | - utter_user.loves_agent 622 | - utter_user.misses_agent 623 | - utter_user.testing_agent 624 | - utter_user.Not_able_to_help_part1 625 | - utter_user.Not_able_to_help_part2 626 | - utter_user.Not_able_to_help_part3 627 | - utter_user.Not_able_to_help_part4 628 | - utter_ask_topic_news 629 | - utter_confirm_if_service_is_correct 630 | - utter_user.lonely 631 | - utter_user.sad 632 | - utter_agent.happy 633 | - utter_agent.talk_to_me 634 | - utter_agent.fired 635 | - utter_appraisal.bad 636 | - utter_agent.can_you_help 637 | - utter_user.needs_advice 638 | - utter_agent.right 639 | - utter_greetings.goodevening 640 | - utter_greetings.goodmorning 641 | - utter_greetings.goodnight 642 | - utter_user.back 643 | - utter_confirmation.cancel 644 | - utter_agent.sure 645 | - utter_greetings.nice_to_talk_to_you 646 | - utter_user.wants_to_talk 647 | - utter_agent.busy 648 | - utter_agent.answer_my_question 649 | - utter_user.angry 650 | - utter_user.busy 651 | - utter_agent.annoying 652 | - utter_appraisal.well_done 653 | - utter_agent.boring 654 | - utter_agent.clever 655 | - utter_user.tired 656 | - utter_user.will_be_back 657 | - utter_dialog.i_do_not_care 658 | - utter_dialog.wrong 659 | - utter_dialog.hold_on 660 | - utter_dialog.hug 661 | - utter_dialog.sorry 662 | - utter_dialog.what_do_you_mean 663 | - utter_user.does_not_want_to_talk 664 | - utter_emotions.wow 665 | - utter_greetings.nice_to_meet_you 666 | - utter_greetings.nice_to_see_you 667 | - utter_agent.be_clever 668 | - utter_agent.hobby 669 | - utter_agent.ready 670 | - utter_agent.there 671 | - utter_user.can_not_sleep 672 | - utter_user.excited 673 | - utter_user.going_to_bed 674 | - utter_user.good 675 | - utter_user.happy 676 | - utter_user.has_birthday 677 | - utter_user.here 678 | - utter_user.looks_like 679 | - utter_user.sleepy 680 | - utter_user.wants_to_see_agent_again 681 | - utter_user.waits 682 | - utter_agent.bad 683 | - utter_confirmation.yes 684 | - utter_agent.crazy 685 | - utter_emotions.ha_ha 686 | - utter_confirmation.no 687 | - utter_agent.handle_insult 688 | - utter_appraisal.good 689 | - utter_appraisal.no_problem 690 | - utter_appraisal.thank_you 691 | - utter_appraisal.welcome 692 | - utter_user.asks_who_am_i 693 | - utter_agent.wants_to_tell_joke 694 | - utter_agent.what_can_do 695 | - utter_user.asked_for_weather 696 | forms: 697 | - get_news 698 | -------------------------------------------------------------------------------- /2_rasa_chitchat/endpoints.yml: -------------------------------------------------------------------------------- 1 | # This file contains the different endpoints your bot can use. 2 | 3 | # Server where the models are pulled from. 4 | # https://rasa.com/docs/rasa/user-guide/configuring-http-api/#fetching-models-from-a-server/ 5 | 6 | #models: 7 | # url: http://my-server.com/models/default_core@latest 8 | # wait_time_between_pulls: 10 # [optional](default: 100) 9 | 10 | # Server which runs your custom actions. 11 | # https://rasa.com/docs/rasa/core/actions/#custom-actions/ 12 | 13 | action_endpoint: 14 | url: "http://localhost:5055/webhook" 15 | 16 | # Tracker store which is used to store the conversations. 17 | # By default the conversations are stored in memory. 18 | # https://rasa.com/docs/rasa/api/tracker-stores/ 19 | 20 | #tracker_store: 21 | # type: redis 22 | # url: 23 | # port: 24 | # db: 25 | # password: 26 | # use_ssl: 27 | 28 | #tracker_store: 29 | # type: mongod 30 | # url: 31 | # db: 32 | # username: 33 | # password: 34 | 35 | # Event broker which all conversation events should be streamed to. 36 | # https://rasa.com/docs/rasa/api/event-brokers/ 37 | 38 | #event_broker: 39 | # url: localhost 40 | # username: username 41 | # password: password 42 | # queue: queue 43 | -------------------------------------------------------------------------------- /2_rasa_chitchat/requirements.txt: -------------------------------------------------------------------------------- 1 | rasa 2 | 3 | -------------------------------------------------------------------------------- /4_chatterbot/app.py: -------------------------------------------------------------------------------- 1 | #app.py 2 | 3 | from flask import Flask, jsonify, request #import main Flask class and request object 4 | import json 5 | from talk import * 6 | 7 | #create the Flask app 8 | app = Flask(__name__) 9 | chatbot = loadChatbot(SocialNetworkType.HWFMS) 10 | 11 | @app.route('/service', methods=['POST']) 12 | def service(): 13 | json_request_body = json.loads(request.data) 14 | 15 | if json_request_body is None: 16 | return jsonify({"message":"text not found"}) 17 | else: 18 | text_message = json_request_body['data'] 19 | print(text_message) 20 | bot_response = get_response_from_chatbot(chatbot, text_message) 21 | print(bot_response) 22 | response = {"text":bot_response.text, "confidence":bot_response.confidence} 23 | 24 | return jsonify(response) 25 | 26 | 27 | if __name__ == '__main__': 28 | app.run(debug=True, port=5000) #run app in debug mode on port 5000 -------------------------------------------------------------------------------- /4_chatterbot/requirements.txt: -------------------------------------------------------------------------------- 1 | chatterbot 2 | pandas 3 | numpy 4 | Flask -------------------------------------------------------------------------------- /4_chatterbot/talk.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from chatterbot import ChatBot 3 | from chatterbot.filters import get_recent_repeated_responses 4 | from train import SocialNetworkType, getDatasetName 5 | 6 | def loadChatbot(socialNetworkType): 7 | csvFileName, dbFileName = getDatasetName(socialNetworkType) 8 | 9 | chatbot = ChatBot( 10 | 'Tamaghna Basu', 11 | filters=[ 12 | { 13 | 'import_path': 'chatterbot.filters.get_recent_repeated_responses', 14 | 'threshold': 1, 15 | 'quantity': 5 16 | } 17 | ], 18 | storage_adapter='chatterbot.storage.SQLStorageAdapter', 19 | logic_adapters=[ 20 | { 21 | 'import_path': 'chatterbot.logic.BestMatch', 22 | 'default_response': 'I am sorry, but I do not understand. Please rephrase your question.', 23 | 'maximum_similarity_threshold': 0.90 24 | } 25 | ], 26 | database_uri='sqlite:///dataset/sqlite/{}.sqlite3'.format(dbFileName) 27 | 28 | ) 29 | 30 | 31 | 32 | # Get a response to an input statement 33 | response = chatbot.get_response("Hello") 34 | print(response) 35 | print(response.confidence) 36 | return chatbot 37 | 38 | def get_response_from_chatbot(chatbot, text_message): 39 | bot_response = chatbot.get_response(text_message) 40 | 41 | print(bot_response.confidence) 42 | return bot_response 43 | 44 | # if bot_response.confidence > 0.9: 45 | # return bot_response 46 | # else: 47 | # return "Sorry, not able to follow, can you please repharse it?" 48 | 49 | 50 | if __name__ == "__main__": 51 | 52 | chatbot = loadChatbot(SocialNetworkType.ALL) 53 | 54 | while True: 55 | try: 56 | print(get_response_from_chatbot(chatbot, input())) 57 | 58 | except(KeyboardInterrupt, EOFError, SystemExit): 59 | break 60 | -------------------------------------------------------------------------------- /4_chatterbot/train.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import enum 3 | 4 | import numpy as np 5 | import pandas as pd 6 | from chatterbot import ChatBot 7 | from chatterbot.trainers import ChatterBotCorpusTrainer 8 | from chatterbot.trainers import ListTrainer 9 | 10 | 11 | class SocialNetworkType(enum.Enum): 12 | NONE = 0 # NONE 13 | H = 1 # Hangout 14 | W = 2 # Whatsapp 15 | F = 3 # Facebook 16 | ALL = 4 17 | 18 | 19 | def getDatasetName(socialNetworkType): 20 | switcher = { 21 | SocialNetworkType.H: "Hangout", 22 | SocialNetworkType.W: "Whatsapp", 23 | SocialNetworkType.F: "Facebook", 24 | SocialNetworkType.ALL: "ALL" 25 | } 26 | 27 | csvFileName = "" 28 | dbFileName = "database_DEFAULT" 29 | 30 | if socialNetworkType == SocialNetworkType.NONE: 31 | csvFileName = "" 32 | dbFileName = "database_DEFAULT" 33 | else: 34 | networkType = switcher.get(socialNetworkType) 35 | if networkType is not None: 36 | csvFileName = "conversation_{}".format(networkType) 37 | dbFileName = "database_{}".format(networkType) 38 | return csvFileName, dbFileName 39 | 40 | 41 | def isNotBlank(myString): 42 | return bool(myString and myString.strip()) 43 | 44 | 45 | def create_chatbot(socialNetworkType, isTrainedAlready=True): 46 | csvFileName, dbFileName = getDatasetName(socialNetworkType) 47 | 48 | chatbot = ChatBot( 49 | 'Tamaghna Basu', 50 | filters=[ 51 | { 52 | 'import_path': 'chatterbot.filters.get_recent_repeated_responses', 53 | 'threshold': 1, 54 | 'quantity': 5 55 | } 56 | ], 57 | storage_adapter='chatterbot.storage.SQLStorageAdapter', 58 | logic_adapters=[ 59 | { 60 | 'import_path': 'chatterbot.logic.BestMatch', 61 | 'default_response': 'I am sorry, but I do not understand. Please rephrase your question.', 62 | 'maximum_similarity_threshold': 0.90 63 | } 64 | ], 65 | database_uri='sqlite:///dataset/sqlite/{}.sqlite3'.format(dbFileName) 66 | ) 67 | 68 | if not isTrainedAlready: 69 | print("Starting English corpus training...") 70 | train_on_english_corpus(chatbot) 71 | if isNotBlank(csvFileName): 72 | train_on_social_chat(chatbot, csvFileName) 73 | 74 | # Get a response to an input statement 75 | response = chatbot.get_response("Hello") 76 | print(response) 77 | print(response.confidence) 78 | response = chatbot.get_response("How are you today?") 79 | print(response) 80 | print(response.confidence) 81 | return chatbot 82 | 83 | 84 | def train_on_english_corpus(chatbot): 85 | # Create a new trainer for the chatbot 86 | trainer = ChatterBotCorpusTrainer(chatbot) 87 | 88 | # Train the chatbot based on the english corpus 89 | trainer.train("chatterbot.corpus.english") 90 | 91 | print("Done English corpus training...") 92 | 93 | 94 | def train_on_social_chat(chatbot, dataset): 95 | csvFileName = 'dataset/csv/{}.csv'.format(dataset) 96 | 97 | print("Starting List training...") 98 | csv_columns = ['Message', 'MyResponse'] 99 | df_all = pd.read_csv(csvFileName) 100 | df_all.replace(np.NaN, ' ', inplace=True) 101 | 102 | trainer = ListTrainer(chatbot) 103 | rowCount = df_all.shape[0] 104 | for index, row in df_all.iterrows(): 105 | print("Training {} of {}".format(index, rowCount)) 106 | message = row[csv_columns[0]] 107 | myResponse = row[csv_columns[1]] 108 | trainer.train([message, myResponse]) 109 | 110 | print("Done List training...") 111 | 112 | 113 | if __name__ == "__main__": 114 | isTrainedAlready = False 115 | chatbot = create_chatbot(SocialNetworkType.ALL, isTrainedAlready=isTrainedAlready) 116 | -------------------------------------------------------------------------------- /5_pipeline/audio_recognition.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | import re 4 | import sys 5 | import time 6 | 7 | import pyaudio 8 | import requests 9 | from google.cloud import speech 10 | from google.oauth2 import service_account 11 | from six.moves import queue 12 | 13 | credentials = service_account.Credentials.from_service_account_file("key.json") 14 | 15 | # Server URL from where you get the generated video of the person talking the given sentence 16 | AI_server = "http://GPU-server-address" 17 | 18 | ## RASA CONFIGS 19 | url = "http://localhost:5005/webhooks/rest/webhook" 20 | error_message = "I don't understand. Please ask something else." 21 | cacheFolderName = "video/source/new/cache/" 22 | talking_video_file = "video/output.mp4" 23 | 24 | # Audio recording parameters 25 | STREAMING_LIMIT = 240000 # 4 minutes 26 | SAMPLE_RATE = 16000 27 | CHUNK_SIZE = int(SAMPLE_RATE / 10) # 100ms 28 | 29 | RED = '\033[0;31m' 30 | GREEN = '\033[0;32m' 31 | YELLOW = '\033[0;33m' 32 | WHITE = '\033[0;37m' 33 | 34 | 35 | def is_talking(): 36 | return os.path.isfile(talking_video_file) 37 | 38 | 39 | def getResponseFromRasa(person, message): 40 | payload = {"sender": person, "message": message} 41 | payload = json.dumps(payload) 42 | headers = { 43 | 'Content-Type': 'application/json' 44 | } 45 | 46 | response = requests.request("POST", url, headers=headers, data=payload) 47 | 48 | response = response.text.encode('utf8') 49 | response = json.loads(response) 50 | responseString = "" 51 | for message in response: 52 | responseString = responseString + message['text'] + "\n" 53 | 54 | return responseString 55 | 56 | 57 | def process_text(senderName, input): 58 | try: 59 | response = getResponseFromRasa(senderName, input) 60 | except: 61 | response = error_message 62 | return response 63 | 64 | 65 | def generateFileName(responseMessage): 66 | filename = "" 67 | if (responseMessage and len(responseMessage.strip()) > 0): 68 | responseMessage = responseMessage.strip() 69 | import hashlib 70 | filename = hashlib.md5(responseMessage.encode('utf-8')).hexdigest() 71 | print("{0} : {1}".format(responseMessage, filename)) 72 | return filename.strip() 73 | 74 | 75 | def downloadfile(url, srcFileName, dstFileName): 76 | print("****Connected****") 77 | # try: 78 | r = requests.get(url) 79 | 80 | # 1.mp4 to be played by the streamer 81 | f1 = open(dstFileName, 'wb'); 82 | 83 | # Store it in the cache server for future use 84 | f2 = open(srcFileName, 'wb'); 85 | 86 | print("Dowloading.....") 87 | for chunk in r.iter_content(chunk_size=255): 88 | if chunk: # filter out keep-alive new chunks 89 | f1.write(chunk) 90 | f2.write(chunk) 91 | print("Done") 92 | f1.close() 93 | f2.close() 94 | 95 | 96 | def getVideoResponse(text): 97 | srcFileName = cacheFolderName + generateFileName(text) + ".mp4" 98 | print(srcFileName) 99 | 100 | if os.path.isfile(srcFileName): 101 | print("Play from local...") 102 | from shutil import copyfile 103 | copyfile(srcFileName, talking_video_file) 104 | else: 105 | print("Download from AI...") 106 | url = "{}:5000/render?text={}".format(AI_server, text) 107 | print(url) 108 | 109 | try: 110 | downloadfile(url, srcFileName, talking_video_file) 111 | return 112 | except: 113 | getVideoResponse(error_message) 114 | 115 | 116 | def get_current_time(): 117 | """Return Current Time in MS.""" 118 | 119 | return int(round(time.time() * 1000)) 120 | 121 | 122 | class ResumableMicrophoneStream: 123 | """Opens a recording stream as a generator yielding the audio chunks.""" 124 | 125 | def __init__(self, rate, chunk_size): 126 | self._rate = rate 127 | self.chunk_size = chunk_size 128 | self._num_channels = 1 129 | self._buff = queue.Queue() 130 | self.closed = True 131 | self.start_time = get_current_time() 132 | self.restart_counter = 0 133 | self.audio_input = [] 134 | self.last_audio_input = [] 135 | self.result_end_time = 0 136 | self.is_final_end_time = 0 137 | self.final_request_end_time = 0 138 | self.bridging_offset = 0 139 | self.last_transcript_was_final = False 140 | self.new_stream = True 141 | self._audio_interface = pyaudio.PyAudio() 142 | self.openAudioStream() 143 | 144 | def openAudioStream(self): 145 | self._audio_stream = self._audio_interface.open( 146 | format=pyaudio.paInt16, 147 | channels=self._num_channels, 148 | rate=self._rate, 149 | input=True, 150 | frames_per_buffer=self.chunk_size, 151 | # Run the audio stream asynchronously to fill the buffer object. 152 | # This is necessary so that the input device's buffer doesn't 153 | # overflow while the calling thread makes network requests, etc. 154 | stream_callback=self._fill_buffer, 155 | ) 156 | 157 | def __enter__(self): 158 | 159 | self.closed = False 160 | return self 161 | 162 | def __exit__(self, type, value, traceback): 163 | 164 | self._audio_stream.stop_stream() 165 | self._audio_stream.close() 166 | self.closed = True 167 | # Signal the generator to terminate so that the client's 168 | # streaming_recognize method will not block the process termination. 169 | self._buff.put(None) 170 | self._audio_interface.terminate() 171 | 172 | def _fill_buffer(self, in_data, *args, **kwargs): 173 | """Continuously collect data from the audio stream, into the buffer. 174 | Do not capture audio when there is audio on the speaker output""" 175 | 176 | if not is_talking(): 177 | self._buff.put(in_data) 178 | return None, pyaudio.paContinue 179 | 180 | def generator(self): 181 | """Stream Audio from microphone to API and to local buffer""" 182 | 183 | while not self.closed: 184 | data = [] 185 | 186 | if self.new_stream and self.last_audio_input: 187 | 188 | chunk_time = STREAMING_LIMIT / len(self.last_audio_input) 189 | 190 | if chunk_time != 0: 191 | 192 | if self.bridging_offset < 0: 193 | self.bridging_offset = 0 194 | 195 | if self.bridging_offset > self.final_request_end_time: 196 | self.bridging_offset = self.final_request_end_time 197 | 198 | chunks_from_ms = round((self.final_request_end_time - 199 | self.bridging_offset) / chunk_time) 200 | 201 | self.bridging_offset = (round(( 202 | len(self.last_audio_input) - chunks_from_ms) 203 | * chunk_time)) 204 | 205 | for i in range(chunks_from_ms, len(self.last_audio_input)): 206 | data.append(self.last_audio_input[i]) 207 | 208 | self.new_stream = False 209 | 210 | # Use a blocking get() to ensure there's at least one chunk of 211 | # data, and stop iteration if the chunk is None, indicating the 212 | # end of the audio stream. 213 | chunk = self._buff.get() 214 | self.audio_input.append(chunk) 215 | 216 | if chunk is None: 217 | return 218 | data.append(chunk) 219 | # Now consume whatever other data's still buffered. 220 | while True: 221 | try: 222 | chunk = self._buff.get(block=False) 223 | 224 | if chunk is None: 225 | return 226 | data.append(chunk) 227 | self.audio_input.append(chunk) 228 | 229 | except queue.Empty: 230 | break 231 | 232 | yield b''.join(data) 233 | 234 | 235 | def listen_print_loop(responses, stream): 236 | """Iterates through server responses and prints them. 237 | 238 | The responses passed is a generator that will block until a response 239 | is provided by the server. 240 | 241 | Each response may contain multiple results, and each result may contain 242 | multiple alternatives; for details, see https://goo.gl/tjCPAU. Here we 243 | print only the transcription for the top alternative of the top result. 244 | 245 | In this case, responses are provided for interim results as well. If the 246 | response is an interim one, print a line feed at the end of it, to allow 247 | the next result to overwrite it, until the response is a final one. For the 248 | final one, print a newline to preserve the finalized transcription. 249 | """ 250 | 251 | for response in responses: 252 | if get_current_time() - stream.start_time > STREAMING_LIMIT: 253 | stream.start_time = get_current_time() 254 | break 255 | 256 | if not response.results: 257 | continue 258 | 259 | result = response.results[0] 260 | 261 | if not result.alternatives: 262 | continue 263 | 264 | transcript = result.alternatives[0].transcript 265 | 266 | result_seconds = 0 267 | result_nanos = 0 268 | 269 | if result.result_end_time.seconds: 270 | result_seconds = result.result_end_time.seconds 271 | 272 | if result.result_end_time.nanos: 273 | result_nanos = result.result_end_time.nanos 274 | 275 | stream.result_end_time = int((result_seconds * 1000) 276 | + (result_nanos / 1000000)) 277 | 278 | corrected_time = (stream.result_end_time - stream.bridging_offset 279 | + (STREAMING_LIMIT * stream.restart_counter)) 280 | # Display interim results, but with a carriage return at the end of the 281 | # line, so subsequent lines will overwrite them. 282 | 283 | if result.is_final: 284 | 285 | sys.stdout.write(GREEN) 286 | sys.stdout.write('\033[K') 287 | sys.stdout.write(str(corrected_time) + ': ' + transcript + '\n') 288 | 289 | stream.is_final_end_time = stream.result_end_time 290 | stream.last_transcript_was_final = True 291 | 292 | # Exit recognition if any of the transcribed phrases could be 293 | # one of our keywords. 294 | if re.search(r'\b(exit|quit)\b', transcript, re.I): 295 | sys.stdout.write(YELLOW) 296 | sys.stdout.write('Exiting...\n') 297 | stream.closed = True 298 | sys.stdout.write(WHITE) 299 | break 300 | else: 301 | response_text = process_text("Basu", transcript) 302 | print("Response: {}".format(response_text)) 303 | if response_text and len(response_text) > 0: 304 | getVideoResponse(response_text) 305 | 306 | 307 | else: 308 | sys.stdout.write(RED) 309 | sys.stdout.write('\033[K') 310 | sys.stdout.write(str(corrected_time) + ': ' + transcript + '\r') 311 | stream.last_transcript_was_final = False 312 | 313 | 314 | def main(): 315 | """start bidirectional streaming from microphone input to speech API""" 316 | 317 | client = speech.SpeechClient(credentials=credentials) 318 | config = speech.types.RecognitionConfig( 319 | encoding=speech.enums.RecognitionConfig.AudioEncoding.LINEAR16, 320 | sample_rate_hertz=SAMPLE_RATE, 321 | language_code='en-US', 322 | max_alternatives=1) 323 | streaming_config = speech.types.StreamingRecognitionConfig( 324 | config=config, 325 | interim_results=True) 326 | 327 | mic_manager = ResumableMicrophoneStream(SAMPLE_RATE, CHUNK_SIZE) 328 | print(mic_manager.chunk_size) 329 | sys.stdout.write(YELLOW) 330 | sys.stdout.write('\nListening, say "Quit" or "Exit" to stop.\n\n') 331 | sys.stdout.write('End (ms) Transcript Results/Status\n') 332 | sys.stdout.write('=====================================================\n') 333 | 334 | with mic_manager as stream: 335 | 336 | while not stream.closed: 337 | sys.stdout.write(YELLOW) 338 | sys.stdout.write('\n' + str( 339 | STREAMING_LIMIT * stream.restart_counter) + ': NEW REQUEST\n') 340 | 341 | stream.audio_input = [] 342 | audio_generator = stream.generator() 343 | 344 | requests = (speech.types.StreamingRecognizeRequest( 345 | audio_content=content) for content in audio_generator) 346 | 347 | responses = client.streaming_recognize(streaming_config, 348 | requests) 349 | print(responses) 350 | print("Listen print starting") 351 | 352 | # Now, put the transcription responses to use. 353 | listen_print_loop(responses, stream) 354 | 355 | print("Listen print done") 356 | 357 | if stream.result_end_time > 0: 358 | stream.final_request_end_time = stream.is_final_end_time 359 | stream.result_end_time = 0 360 | stream.last_audio_input = [] 361 | stream.last_audio_input = stream.audio_input 362 | stream.audio_input = [] 363 | stream.restart_counter = stream.restart_counter + 1 364 | 365 | if not stream.last_transcript_was_final: 366 | sys.stdout.write('\n') 367 | stream.new_stream = True 368 | 369 | 370 | if __name__ == '__main__': 371 | main() 372 | -------------------------------------------------------------------------------- /5_pipeline/requirements.txt: -------------------------------------------------------------------------------- 1 | flask 2 | flask_socketio 3 | SpeechRecognition 4 | pyobjc 5 | playsound 6 | gtts 7 | 8 | opencv-python 9 | numpy 10 | 11 | pyglet==1.3.2 12 | 13 | ffpyplayer 14 | -------------------------------------------------------------------------------- /5_pipeline/silent.m4v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/5_pipeline/silent.m4v -------------------------------------------------------------------------------- /5_pipeline/streamerV4.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import os 3 | import numpy as np 4 | from ffpyplayer.player import MediaPlayer 5 | 6 | talking_video_file = "video/output.mp4" 7 | silent_video_file = "video/silent.m4v" 8 | 9 | def is_talking(): 10 | return os.path.isfile(talking_video_file) 11 | 12 | ff_opts = { 13 | #'vn':True, 14 | #'sync':'video' 15 | } 16 | isTalkingPlaying = False 17 | video_stream = cv2.VideoCapture(silent_video_file) 18 | audio_stream = MediaPlayer(silent_video_file, ff_opts=ff_opts) 19 | frame_counter = 0 20 | 21 | #i = 0 22 | # Create a VideoCapture object and read from input file 23 | while(True): 24 | 25 | # If new talking file reached 26 | if is_talking() and isTalkingPlaying is False: 27 | isTalkingPlaying = True 28 | frame_counter = 0 29 | video_stream = cv2.VideoCapture(talking_video_file, ) 30 | audio_stream = MediaPlayer(talking_video_file, ff_opts=ff_opts) 31 | 32 | # If the last frame is reached, reset the capture and the frame_counter 33 | if frame_counter == video_stream.get(cv2.CAP_PROP_FRAME_COUNT): 34 | if isTalkingPlaying: 35 | # Return to loop the silent video and remove the file 36 | isTalkingPlaying = False 37 | video_stream = cv2.VideoCapture(silent_video_file) 38 | audio_stream = MediaPlayer(silent_video_file, ff_opts=ff_opts) 39 | os.remove(talking_video_file) 40 | frame_counter = 0 41 | else: 42 | # Loop the silent video 43 | frame_counter = 0 # Or whatever as long as it is the same as next line 44 | video_stream.set(cv2.CAP_PROP_POS_FRAMES, 0) 45 | 46 | # Capture frame-by-frame 47 | ret, frame = video_stream.read() 48 | audio_frame, audio_val = audio_stream.get_frame(show=True) 49 | frame_counter += 1 50 | 51 | #if frame_counter == 1: 52 | # ret, frame = video_stream.read() 53 | 54 | # For some reason the mp4 image is flipped, so i need to flip again to play as normal 55 | #if is_talking() is False and isTalkingPlaying is False: 56 | # frame = cv2.flip(frame, -1) 57 | 58 | # Show 59 | try: 60 | if frame is not None: 61 | cv2.imshow('Frame', frame) 62 | else: 63 | video_stream.release() 64 | frame_counter = 0 65 | isTalkingPlaying = False 66 | video_stream = cv2.VideoCapture(silent_video_file) 67 | audio_stream = MediaPlayer(silent_video_file, ff_opts=ff_opts) 68 | 69 | except: 70 | video_stream.release() 71 | frame_counter = 0 72 | isTalkingPlaying = False 73 | video_stream = cv2.VideoCapture(silent_video_file) 74 | audio_stream = MediaPlayer(silent_video_file, ff_opts=ff_opts) 75 | 76 | #if i == 25: 77 | # i = 0 78 | 79 | # Press Q on keyboard to exit 80 | if cv2.waitKey(32) & 0xFF == ord('q'): 81 | break 82 | 83 | 84 | # When everything done, release 85 | video_stream.release() 86 | cv2.destroyAllWindows() 87 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | identity-cloning Copyright (C) 2020 Tamaghna Basu 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | identity-cloning Copyright (C) 2020 Tamaghna Basu 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Identity Clonning 3 | 4 | [![GitHub license](https://img.shields.io/github/license/titanlambda/identity-cloning)](https://github.com/titanlambda/identity-cloning/blob/master/LICENSE) [![Twitter](https://img.shields.io/twitter/url?style=social&url=https%3A%2F%2Fgithub.com%2Ftitanlambda%2Fidentity-cloning)](https://twitter.com/intent/tweet?text=Check%20out%20the%20Identity%20Cloning%20project%20to%20see%20how%20to%20clone%20yourself%20using%20next-generation%20AI%20to%20trigger%20a%20social%20engineering%20attack.%20%23security%20%23socialengineering%20%23phishing&url=https%3A%2F%2Fgithub.com%2Ftitanlambda%2Fidentity-cloning) 5 | [![GitHub forks](https://img.shields.io/github/forks/titanlambda/identity-cloning)](https://github.com/titanlambda/identity-cloning/network) 6 | 7 | I am releasing this project as part of my talk in Black Hat USA 2020 conference. More details here - https://www.blackhat.com/us-20/briefings/schedule/index.html#how-i-created-my-clone-using-ai---next-gen-social-engineering-19802 8 | 9 | Here is an interview with Dark Reading talking about this project: 10 | 11 | [![](https://i.vimeocdn.com/video/929512576.webp)](https://vimeo.com/441393679 "Dark Reading News Room - Attack of the clone") 12 | 13 | 14 | This project is inspired by the first episode of the season 2 of Black Mirror called "Be Right Back". Here we tried to create a pipeline using various AI projects to create a bot who talks like me and can be used to impersonate me online and do social engineering. The objective of this prototype is to simulate a Google hangout video call where someone can talk to the bot over a video call which will look like me and say in my voice with similar kind of response what I prefer to give based on my personality. 15 | 16 | ### Output: 17 | - Here are few sample output of text chat with the bot which is trained with my conversational data: 18 | ![](https://github.com/titanlambda/identity-cloning/blob/master/sample_output/text_demo.png) 19 | 20 | - Here is a video demonstration where someone is talking to the bot and the bot is trying to do a social engineering by asking for money. 21 | 22 | - [![](http://img.youtube.com/vi/-bhIL2qnXxc/0.jpg)](http://www.youtube.com/watch?v=-bhIL2qnXxc "Social engineering attempt with a bot making hangout call and asking for money") 23 | 24 | ### Pre-requisite: 25 | - We will be using virtualenv to create virtual environments. You can you other options like Conda if are familiar to that. 26 | - Python 3.7 used for this project 27 | - Here we will explain how to run all the componenets locally except the fake video generation server. For that we will require a server with GPU. 28 | 29 | 30 | ### Flow summary: 31 | ![](https://github.com/titanlambda/identity-cloning/blob/master/sample_output/flow.png) 32 | The entire project has mainly 3 componenets: 33 | - Brain - NLP engine which will respond to a question with a similar utterance of mine. 34 | - Voice - Voice cloning which will clone my voice and say the response generated in the previous step (Work In Progress, as of now we are using google text to speech engine.) 35 | - Face - Video generation where we used [LipGAN](https://github.com/Rudrabha/LipGAN) library to generate video at runtime and play in response of the question asked as if the user is talking to a person. 36 | 37 | ### Architecture: 38 | ![](https://github.com/titanlambda/identity-cloning/blob/master/sample_output/architecture.png) 39 | 40 | 41 | ### 1. Install virtualenv 42 | --- 43 | 44 | ``` 45 | pip install virtualenv 46 | ``` 47 | 48 | ### 2. Clone the repo 49 | --- 50 | 51 | ``` 52 | git clone https://github.com/titanlambda/identity-clonning.git 53 | cd identity-clonning/ 54 | ``` 55 | 56 | It has following componenets: 57 | 1. 1_data_processor - to process social network data - FB, hangouts, whatsapp and create data set to train the NLP engine 58 | 2. 2_rasa_chitchat - Rasa chatbot code to handle chitchat 59 | 3. 3_ParlAI - Generative model to handle random questions 60 | 4. 4_chatterbot - To handle historical questions trained with the social networking data 61 | 5. 5_pipeline - Audio/Video streamer and google hangout integration to make it live in action 62 | 63 | 64 | ### 3. Process Social Network data 65 | --- 66 | 67 | **Pre-requisite - export your social networking chat data from whatsapp, hangouts and FB.** 68 | - [Export Whatsapp data](https://www.zapptales.com/en/how-to-export-whatsapp-chat-android-iphone-ios/) 69 | - [Export FB data](https://www.zapptales.com/en/download-facebook-messenger-chat-history-how-to/) 70 | - [Export Hangout data](https://blog.jay2k1.com/2014/11/10/how-to-export-and-backup-your-google-hangouts-chat-history/) - use JSON format as exported format 71 | 72 | #### Create and activate virtual env 73 | ``` 74 | cd 1_data_processor 75 | virtualenv venv_data_processor 76 | source venv_data_processor/bin/activate 77 | pip install -r requirements.txt 78 | ``` 79 | ##### Copy the data files in data folders as per the names - 1_whatsapp_data, 2_hangout_data, 3_facebook_data then run the following command 80 | ``` 81 | python 1_whatsappParser.py 82 | python 2_hangoutJsonParser.py 83 | python 3_facebookParser.py 84 | python 4_mergeAllData.py 85 | ``` 86 | 87 | ##### You should get the final output data file "ALL_chatterbot_FINAL.csv" inside output folder. We will be using this file in step 4_chatterbot 88 | 89 | ![](https://github.com/titanlambda/identity-cloning/blob/master/sample_output/Categories%20of%20conversation.png) 90 | 91 | ### 4. Set up RASA chitchat server 92 | --- 93 | 94 | ![](https://github.com/titanlambda/identity-cloning/blob/master/sample_output/cat1_RASA.png) 95 | 96 | 97 | 0. Open a new terminal 98 | 99 | ``` 100 | cd 2_rasa_chitchat 101 | virtualenv venv_rasa_chitchat 102 | source venv_rasa_chitchat 103 | pip install -r requirements.txt 104 | rasa train 105 | ``` 106 | 107 | test - chat with the bot: 108 | ``` 109 | rasa shell 110 | ``` 111 | 112 | Run in production: 113 | ``` 114 | rasa run --enable-api 115 | ``` 116 | 117 | ### 5. Set up RASA Action server 118 | --- 119 | 120 | ![](https://github.com/titanlambda/identity-cloning/blob/master/sample_output/cat3_RASA_actions.png) 121 | 122 | **Pre-requisite - You need to get API keys as mentioned in the actions/actions.py file and put it there. Also you need to set up ParlAI and Chatterbot app server and mention the URLs of those servers in the actions.py file.** 123 | 124 | Open a new terminal 125 | 126 | ``` 127 | cd 2_rasa_chitchat 128 | source venv_rasa_chitchat 129 | cd actions 130 | pip install -r requirements.txt 131 | rasa run action 132 | ``` 133 | 134 | 135 | ### 6. Set up ParlAI server 136 | --- 137 | 138 | ![](https://github.com/titanlambda/identity-cloning/blob/master/sample_output/cat4_ParlAI.png) 139 | 140 | ``` 141 | git clone https://github.com/titanlambda/ParlAI.git 142 | cd ParlAI 143 | virtualenv venv_ParlAI 144 | source venv_ParlAI/bin/activate 145 | python setup.py develop 146 | pip install tornado 147 | pip install 'git+https://github.com/rsennrich/subword-nmt.git#egg=subword-nmt' 148 | ``` 149 | 150 | ### 7. Run ParlAI server 151 | --- 152 | 153 | ##### It has 2 server componenets - socket server on port 10001 and then http server on 8080 154 | 155 | 156 | #### Terminal 1: Open the socket server 157 | 158 | ``` 159 | cd ParlAI 160 | python parlai/chat_service/services/websocket/run.py --config-path parlai/chat_service/tasks/chatbot/config.yml --port 10001 161 | ``` 162 | #### Terminal 2: Open the http server 163 | 164 | ``` 165 | cd ParlAI 166 | python parlai/chat_service/services/browser_chat/client.py --port 10001 --host localhost --serving-port 8080 167 | ``` 168 | 169 | #### Test from the client 170 | 171 | ##### OPTION 1: Through Terminal 172 | ``` 173 | cd ParlAI 174 | python client_tb -m "Hi" 175 | ``` 176 | ##### OPTION 2: Through browser 177 | Open browser and go to http://localhost:8080 and start typing the message 178 | 179 | **IMP: Always type "begin" as the first message to start the server.** 180 | 181 | 182 | ### 8. Setup and run Chatterbot server 183 | --- 184 | 185 | ![](https://github.com/titanlambda/identity-cloning/blob/master/sample_output/cat2_chatterbot.png) 186 | 187 | Open a new terminal 188 | 189 | - Create a new virtual env 190 | ``` 191 | virtualenv venv_chatterbot 192 | ``` 193 | 194 | - Activate the venv 195 | ``` 196 | source venv_chatterbot 197 | ``` 198 | 199 | ``` 200 | cd 4_chatterbot 201 | pip install -r requirements.txt 202 | ``` 203 | 204 | - Train the model: copy "ALL_chatterbot_FINAL.csv" from data processor to the data folder here then run 205 | 206 | ``` 207 | python train.py 208 | ``` 209 | 210 | - Launch the app server on port 5000 211 | 212 | ``` 213 | python app.py 214 | ``` 215 | 216 | --- 217 | ### 9. Run the video streamer 218 | --- 219 | 220 | ![](https://github.com/titanlambda/identity-cloning/blob/master/sample_output/Video_Streamer_architecture.png) 221 | 222 | 223 | - In the pipeline folder, record one video of you sitting and doing nothing as if you are listening to the audio over the zoom call. Example given in the source folder called "silent.m4v". Make sure the video is of 480p resolution 224 | 225 | - ![](https://github.com/titanlambda/identity-cloning/blob/master/sample_output/silent.gif) 226 | 227 | - Go to google tesxt to speech service and register there to get an API key. It should be in a file called "key.json". Download the file and save it in this folder. 228 | 229 | Open a new terminal 230 | 231 | ``` 232 | cd 5_pipeline 233 | virtualenv venv_pipeline 234 | source venv_pipeline 235 | pip install -r requirements.txt 236 | python streamerV4.py 237 | ``` 238 | 239 | 240 | 241 | 242 | --- 243 | ### 10. Run the audio speech to text engine 244 | --- 245 | Open a new terminal 246 | 247 | ``` 248 | cd 5_pipeline 249 | source venv_pipeline 250 | pip install -r requirements.txt 251 | python audio_recognition.py 252 | ``` 253 | 254 | 255 | --- 256 | ### 11. Set up the server (with GPU) which will generate the lip-sync video. 257 | --- 258 | WORK IN PROGRESS. I WILL BE RELEASING THIS PART SOON... 259 | 260 | ## Contribution 261 | 262 | Please feel free to provide your: 263 | - feedback 264 | - suggestions 265 | - Any other comment 266 | - If you want to contribute or help me to improve it with some better componenets 267 | 268 | ## TO DO 269 | 270 | - Will improve the documentation 271 | - Improve API calling mechanism 272 | - Simpler deployment 273 | 274 | ## Future Roadmap 275 | 276 | Following features will be added in the future: 277 | - personality analysis 278 | - emotion and sentiment analysys 279 | - Adding knowledge base to improve the genuinity of the bot 280 | 281 | ## Contact 282 | 283 | - You can reach me at https://in.linkedin.com/in/tamaghnabasu, mention the repo name while connecting. 284 | 285 | 286 | 287 | -------------------------------------------------------------------------------- /sample_output/Categories of conversation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/sample_output/Categories of conversation.png -------------------------------------------------------------------------------- /sample_output/Video_Streamer_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/sample_output/Video_Streamer_architecture.png -------------------------------------------------------------------------------- /sample_output/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/sample_output/architecture.png -------------------------------------------------------------------------------- /sample_output/cat1_RASA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/sample_output/cat1_RASA.png -------------------------------------------------------------------------------- /sample_output/cat2_chatterbot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/sample_output/cat2_chatterbot.png -------------------------------------------------------------------------------- /sample_output/cat3_RASA_actions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/sample_output/cat3_RASA_actions.png -------------------------------------------------------------------------------- /sample_output/cat4_ParlAI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/sample_output/cat4_ParlAI.png -------------------------------------------------------------------------------- /sample_output/flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/sample_output/flow.png -------------------------------------------------------------------------------- /sample_output/full_demo.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/sample_output/full_demo.mov -------------------------------------------------------------------------------- /sample_output/silent.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/sample_output/silent.gif -------------------------------------------------------------------------------- /sample_output/text_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/sample_output/text_demo.png -------------------------------------------------------------------------------- /sample_output/video_generated.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titanlambda/identity-cloning-toolkit-ICT/c37b0dcda3378ff2705bfe14cbafef304514aca8/sample_output/video_generated.mp4 --------------------------------------------------------------------------------