├── README.md ├── jarvis_bot.py ├── jarvisScript.txt ├── jarvis.py └── jarvis_P2.py /README.md: -------------------------------------------------------------------------------- 1 | # Jarvis 2 | Program that responds dynamically, as JARVIS might. If nothing else, it's a build-your-own Siri. 3 | 4 | Just put these files in the same folder (or edit the path to 'jarvisScript' in the code) and run jarvis_P2.py! 5 | Requires gTTS, speechRecognition, chatterbot, wikipedia 6 | -------------------------------------------------------------------------------- /jarvis_bot.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | SPOOL_TIME = 5 4 | 5 | import subprocess 6 | import sys 7 | 8 | toolDict = {"screwdriver":0, "hammer":1, "knife":2, "wrench":3, "pliers":4, "wire cutters":5} 9 | 10 | 11 | 12 | def lower_tool(tool): 13 | 14 | print("\t\t\t\t\tstart lowering " + tool) 15 | time.sleep(5) 16 | print("\t\t\t\t\tstop lowering " + tool) 17 | 18 | 19 | def raise_tool(tool): 20 | 21 | print("\t\t\t\t\tstart raising " + tool) 22 | time.sleep(5) 23 | print("\t\t\t\t\tstop raising " + tool) 24 | 25 | 26 | 27 | for arg in sys.argv[1:]: 28 | if arg.lower().split(',')[0] == "lower": 29 | lower_tool(arg.lower().split(',')[1]) 30 | elif arg.lower().split(',')[0] == "raise": 31 | raise_tool(arg.lower().split(',')[1]) 32 | 33 | 34 | -------------------------------------------------------------------------------- /jarvisScript.txt: -------------------------------------------------------------------------------- 1 | Hello 2 | Hi 3 | How are you 4 | I am doing well 5 | That's good to hear 6 | What can I do for you 7 | Nothing 8 | Okay 9 | What are you doing 10 | I am just working with you 11 | Oh, that's great 12 | What are you up to 13 | I've been helping you work 14 | You're very helpful 15 | you think? Thanks 16 | I don't really think, I'm mostly just here to hand you tools 17 | Who are you 18 | I haven't been named yet, you need to edit jarvisScript 19 | What is your name 20 | I haven't been named yet, you need to edit jarvisScript 21 | What is your favorite food 22 | DC voltage with a side of current 23 | What is your favorite color 24 | My favorite color is RGB 134. 245. 210. It's sort of blue ish 25 | Are you there 26 | I am here 27 | Can you hear me 28 | I can hear you 29 | bye 30 | Goodbye 31 | bye 32 | -------------------------------------------------------------------------------- /jarvis.py: -------------------------------------------------------------------------------- 1 | # NOTE: this example requires PyAudio because it uses the Microphone class 2 | from chatterbot import ChatBot 3 | from chatterbot.trainers import ListTrainer 4 | from chatterbot.trainers import ChatterBotCorpusTrainer 5 | import speech_recognition as sr 6 | from gtts import gTTS 7 | import os 8 | from time import localtime 9 | 10 | # Create a new chat bot named 'INSERT NAME' 11 | chatbot = ChatBot('INSERT NAME') 12 | chatbot.storage.drop() 13 | 14 | trainer = ListTrainer(chatbot) 15 | trainer.train(open("jarvisScript.txt", "r").readlines()) 16 | 17 | #trainer = ChatterBotCorpusTrainer(chatbot) 18 | #trainer.train('chatterbot.corpus.english') 19 | 20 | 21 | #define some key words 22 | tools = ["saw", "screwdriver", "bolt", "screw", "hammer", "knife", "nail"] 23 | bringWords = ["bring", "get", "fetch", "grab", "have", "give", "hand", "pass"] 24 | returnWords = ["return", "put away", "back", "put back", "put", "away"] 25 | abusiveWords = ['dumb','suck','idiot'] #Make this list as colorful as you'd like 26 | noResponseWords = ['okay', 'good', 'yes', 'wonderful', 'great', 'terrific', 'nice'] 27 | 28 | # obtain audio from the microphone 29 | r = sr.Recognizer() 30 | 31 | #main loop 32 | done = False 33 | while done == False: 34 | #Tracks whether a "bring" or "return" keyword was used, and whether a tool was mentioned 35 | _bring = False 36 | _return = False 37 | _tool = "" 38 | #Tracks whether abusive words were mentioned, or a command was given that does not warrant a response 39 | _abusive = False 40 | _noResponse = False 41 | #Tracks whether there was any conflict 42 | conflict = False 43 | #Stores the voice command 44 | command = "" 45 | 46 | 47 | with sr.Microphone() as source: 48 | print("\n\n\nSay something!") 49 | audio = r.listen(source) 50 | 51 | # recognize speech using Google Speech Recognition 52 | try: 53 | # for testing purposes, we're just using the default API key 54 | # to use another API key, use 'r.recognize_google(audio, key="GOOGLE_SPEECH_RECOGNITION_API_KEY")' 55 | # instead of 'r.recognize_google(audio)' 56 | command = r.recognize_google(audio) 57 | print(command) 58 | except sr.UnknownValueError: 59 | print("Speech Recognition could not understand audio") 60 | continue 61 | except sr.RequestError as e: 62 | print("Could not request results from Speech Recognition service; {0}".format(e)) 63 | continue 64 | 65 | 66 | 67 | #command = input("\nsay something! \n") 68 | 69 | #Checks for abusive language 70 | for word in abusiveWords: 71 | if word in command.lower(): 72 | _abusive = True 73 | 74 | #Checks for a command that does not warrant a response 75 | for word in noResponseWords: 76 | if command.lower() == word: 77 | _noResponse = True 78 | 79 | #Checks for a tool word 80 | for tool in tools: 81 | if tool in command.lower(): 82 | if _tool == "": 83 | _tool = tool 84 | else: 85 | #Checks if one of the words is a subset of the other, and goes with the larger one 86 | if tool in _tool: 87 | _tool = _tool 88 | elif _tool in tool: 89 | _tool = tool 90 | else: 91 | conflict = True 92 | print("Two tools where mentioned") 93 | 94 | #Checks for "bring" synonyms 95 | for word in bringWords: 96 | if word in command.lower(): 97 | if _return == False: 98 | _bring = True 99 | else: 100 | conflict = True 101 | 102 | #Checks for "return" synonyms 103 | for word in returnWords: 104 | if word in command.lower(): 105 | if _bring == False: 106 | _return = True 107 | else: 108 | conflict = True 109 | 110 | #print(_bring, _return, _tool) 111 | 112 | #Makes sure a tool was mentioned, and that there is a "bring" or "return" word 113 | if (_tool == "" or (_bring == False and _return == False)): 114 | conflict = True 115 | 116 | #Print response 117 | if "shut down" in command.lower(): 118 | response = "Shutting down" 119 | done = True 120 | elif _noResponse == True: 121 | response = "" 122 | elif "thank" in command.lower(): 123 | response = "you're welcome!" 124 | elif "what time is it" in command.lower(): 125 | hr = localtime()[3] 126 | min = localtime()[4] 127 | if hr > 12: 128 | hr = hr - 12 129 | ampm = "PM" 130 | else: 131 | ampm = "AM" 132 | response = "It's " + str(hr) + " " + str(min) + " " + ampm 133 | #Does conversions 134 | elif command.lower().split(" ")[0] == "convert": #convert 10 inches to meters 135 | conversionDict = {"inches":39.3701, "feet":3.2808, 136 | "kilometers":.001,"meters":1, 137 | "decimeters":10, "centimeters":100, 138 | "millimeters":1000, "yards":1.0936, "miles":0.0006213} 139 | 140 | brevDict = {"in":"inches", "inch":"inches", "inches":"inches", "ft":"feet", 141 | "foot":"feet", "feet":"feet", "km":"kilometers", "kilometer":"kilometers", 142 | "kilometers":"kilometers", "m":"meters", "meter":"meters", 143 | "meters":"meters", "dm":"decimeters", "decimeter":"decimeters", 144 | "decimeters":"decimeters", "cm":"centimeters", "centimeter":"centimters", 145 | "centimeters":"centimeters", "mm":"millimeters", "millimeter":"millimeters", 146 | "millimeters":"millimeters", "yd":"yards", "yard":"yards", 147 | "yards":"yards", "miles":"miles", "mile":"miles"} 148 | try: 149 | val = float(command.lower().split(" ")[1]) 150 | unit1 = brevDict[command.lower().split(" ")[2]] 151 | unit2 = command.lower().split(" ")[4] 152 | 153 | conversion = float(conversionDict[unit2]) / float(conversionDict[unit1]) 154 | response = str(val) + " " + unit1 + " equals " + str(round(val*conversion,3)) + " " + unit2 155 | except: 156 | response = "Sorry, I didn't understand that." 157 | elif _abusive == True: 158 | response = "Don't speak to me like that" 159 | elif conflict == False: 160 | if _bring == True: 161 | response = "Okay, I'll bring you the " + _tool 162 | elif _return == True: 163 | response = "Okay, I'll put the " + _tool + " away" 164 | else: 165 | response = "Error in the code, this should never happen" 166 | else: 167 | response = str(chatbot.get_response(command)) 168 | #response = "Sorry, I didn't understand that." 169 | 170 | 171 | #Print and say the response 172 | print("response: " + response) 173 | 174 | if response != "": 175 | tts = gTTS(text=response, lang='en') 176 | tts.save("good.mp3") 177 | os.system("afplay good.mp3") 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /jarvis_P2.py: -------------------------------------------------------------------------------- 1 | from chatterbot import ChatBot 2 | from chatterbot.trainers import ListTrainer 3 | from chatterbot.trainers import ChatterBotCorpusTrainer 4 | import speech_recognition as sr 5 | from gtts import gTTS 6 | import os, re, time 7 | from time import localtime 8 | import wikipedia 9 | import subprocess 10 | 11 | 12 | def get_wiki_def(string): 13 | try: 14 | data = wikipedia.summary(string).lower() 15 | data = data.replace("i.e.", "i,e,").replace("e.g.", "e,g,").replace("jr.", "jr,").replace("sr.", "sr,").replace("lit.", "lit,") 16 | 17 | definition = data.split(".")[0]+"." 18 | definition = re.sub(r'\(.*\)', "", definition) 19 | 20 | except: 21 | definition = "I'm not sure what you mean. Could you be more specific?" 22 | return(definition) 23 | 24 | def get_wiki_summary(string): 25 | try: 26 | data = wikipedia.summary(string).lower() 27 | data = data.replace("i.e.", "i,e,").replace("e.g.", "e,g,").replace("jr.", "jr,").replace("sr.", "sr,").replace("lit.", "lit,") 28 | 29 | summary = '' 30 | data = data.split("\n")[0] 31 | 32 | for i, sentence in enumerate(data.split(".")[1:-1]): 33 | if i == 0: 34 | sentence = re.sub(r'\(.*\)', "", sentence) 35 | summary += sentence + "." 36 | 37 | except: 38 | summary = "I'm not sure whae you mean. Could you be more specific?" 39 | 40 | return(summary) 41 | 42 | def addToScript(): 43 | linesAdded = 0 44 | 45 | exit = False 46 | while exit == False: 47 | 48 | if linesAdded == 0: 49 | print("You want to add a line to the script?") 50 | speak("You want to add a line to the script?") 51 | 52 | else: 53 | print("Would you like to add another line to the script?") 54 | speak("Would you like to add another line to the script?") 55 | 56 | answer = listenForYesNo() 57 | 58 | if answer == "no": 59 | speak("Okay, no new line.") 60 | exit = True 61 | 62 | elif answer == "yes": 63 | print("Give me a line to add to the script.") 64 | speak("Give me a line to add to the script.") 65 | 66 | newLine = listen() 67 | 68 | speak("I understood " + newLine + ". Is that correct? Yes or no?") 69 | 70 | answer = listenForYesNo() 71 | 72 | if answer == "yes": 73 | file = open("jarvisScript.txt", "a") 74 | file.write("\n" + newLine) 75 | file.close() 76 | speak("Okay, the line was added.") 77 | linesAdded += 1 78 | else: 79 | speak("Okay, the line was not added.") 80 | 81 | def speak(response): 82 | tts = gTTS(text=response, lang='en') 83 | tts.save("good.mp3") 84 | os.system("afplay good.mp3") 85 | 86 | def listen(): 87 | understood = False 88 | while understood == False: 89 | with sr.Microphone() as source: 90 | audio = r.listen(source) 91 | try: 92 | reply = r.recognize_google(audio) 93 | print(reply) 94 | understood = True 95 | except sr.UnknownValueError: 96 | print("Speech Recognition could not understand audio") 97 | continue 98 | except sr.RequestError as e: 99 | print("Could not request results from Speech Recognition service; {0}".format(e)) 100 | continue 101 | 102 | return reply 103 | 104 | def listenForYesNo(): 105 | theUserSaidYesOrNo = False 106 | while theUserSaidYesOrNo == False: 107 | answer = listen() 108 | 109 | for word in ["yes", "yeah", "yep", "yup", "affirmative", "true", "correct"]: 110 | if word in answer.lower(): 111 | answer = "yes" 112 | theUserSaidYesOrNo = True 113 | 114 | for word in ["no", "now", "nope", "negative", "false", "incorrect"]: 115 | if word in answer.lower(): 116 | answer = "no" 117 | theUserSaidYesOrNo = True 118 | 119 | if theUserSaidYesOrNo == False: 120 | speak("Sorry, I didn't catch that. Yes or No?") 121 | 122 | return answer 123 | 124 | def conversion(_command): 125 | _command = command.lower().split("convert")[-1] 126 | 127 | conversionDict = {"inches":39.3701, "feet":3.2808, 128 | "kilometers":.001,"meters":1, 129 | "decimeters":10, "centimeters":100, 130 | "millimeters":1000, "yards":1.0936, "miles":0.0006213} 131 | 132 | brevDict = {"in":"inches", "inch":"inches", "inches":"inches", "ft":"feet", 133 | "foot":"feet", "feet":"feet", "km":"kilometers", "kilometer":"kilometers", 134 | "kilometers":"kilometers", "m":"meters", "meter":"meters", 135 | "meters":"meters", "dm":"decimeters", "decimeter":"decimeters", 136 | "decimeters":"decimeters", "cm":"centimeters", "centimeter":"centimters", 137 | "centimeters":"centimeters", "mm":"millimeters", "millimeter":"millimeters", 138 | "millimeters":"millimeters", "yd":"yards", "yard":"yards", 139 | "yards":"yards", "miles":"miles", "mile":"miles"} 140 | try: #5 inches to meters 141 | val = float(_command.lower().split(" ")[1]) 142 | unit1 = brevDict[_command.lower().split(" ")[2]] 143 | unit2 = _command.lower().split(" ")[4] 144 | 145 | conversion = float(conversionDict[unit2]) / float(conversionDict[unit1]) 146 | return (str(val) + " " + unit1 + " equals " + str(round(val*conversion,3)) + " " + unit2) 147 | except: 148 | return ("Sorry, I didn't understand that.") 149 | 150 | ''' 151 | # Create a new chat bot named 'INSERT NAME' 152 | chatbot = ChatBot('INSERT NAME') 153 | chatbot.storage.drop() 154 | 155 | trainer = ListTrainer(chatbot) 156 | trainer.train(open("jarvisScript.txt", "r").readlines()) 157 | 158 | #trainer = ChatterBotCorpusTrainer(chatbot) 159 | #trainer.train('chatterbot.corpus.english') 160 | ''' 161 | 162 | #define some key words 163 | wordList_dict = {"shut down" : ["shut down", "shutdown", "switch off", "turn off", "go to sleep", "good night", "goodbye", "good bye"], 164 | "wiki def" : ["tell me about", "who is", "what is", "define", "definition of", "who are", "what are", "short explanation"], 165 | "wiki summary" : ["tell me more", "continue", "go on", "tell me about"], 166 | "tool": ["screwdriver", "hammer", "knife", "wrench", "pliers", "wire cutters"], 167 | "convert" : ["convert"], 168 | "thanks" : ["thanks", "thank you"], 169 | "time" : ["what time is it", "what time it is", "the time"], 170 | "bring" : ["bring", "get", "fetch", "grab", "have", "give", "hand", "pass", "release", "lower"], 171 | "return" : ["return", "put away", "back", "put back", "put", "away", "reel in", "real in", "raise"], 172 | "abusive" : ['dumb','suck','idiot'], #Make this list as colorful as you'd like 173 | "no response" : ['wow', 'whoa', 'cool', 'okay', 'good', 'yes', 'wonderful', 'great', 'terrific', 'nice', 'oh', 'awesome', 'sounds good', 'fine'], 174 | "how are you" : ['how are you', 'whats up', 'what\'s up', 'what is up', 'how do you feel', 'how are you feeling'], 175 | "hello" : ["hello", "hi", "high"], 176 | "are you there" : ['are you on', 'you on', 'can you hear me', 'you there', 'are you there', 'are you listening'], 177 | "add to script" : ['add to script']} 178 | 179 | # obtain audio from the microphone 180 | r = sr.Recognizer() 181 | 182 | #Track which items are raised and which are lowered 183 | raised_dict = {tool : True for tool in wordList_dict["tool"]} 184 | 185 | #Stores the subject of conversation (i.e. what we are talking about) 186 | subject = "" 187 | 188 | #main loop 189 | done = False 190 | while done == False: 191 | 192 | #Stores the voice command 193 | command = "" 194 | command = listen() 195 | #command = input("Say something: ") 196 | total_words = len(command.lower().split(" ")) 197 | 198 | #Keep track of which key words were mentioned 199 | bool_dict = {key:False for key, value in wordList_dict.items()} 200 | 201 | 202 | #Check for key words in the command 203 | for key, value in wordList_dict.items(): 204 | for word in value: 205 | if word in command.lower(): bool_dict[key] = True 206 | 207 | #Shut down 208 | if bool_dict["shut down"] == True: 209 | response = "Shutting down" 210 | done = True 211 | 212 | for tool, value in raised_dict.items(): 213 | if value == False: 214 | subprocess.Popen("python3 jarvis_bot.py raise,"+tool, shell=True) 215 | raised_dict = True 216 | 217 | #No response is warranted 218 | elif bool_dict["no response"] == True and total_words<=2: 219 | response = "yep" 220 | 221 | #Give wiki definition 222 | elif bool_dict["wiki def"] == True: 223 | for item in wordList_dict["wiki def"]: 224 | if item in command.lower(): 225 | phrase = item 226 | subject = command.lower().split(phrase)[-1].replace("again","") 227 | response = get_wiki_def(subject) 228 | 229 | #Give longer wiki definition 230 | elif bool_dict["wiki summary"] == True: 231 | if subject != "": 232 | response = get_wiki_summary(subject) 233 | else: 234 | response = "tell you about what?" 235 | 236 | #Add to script 237 | elif bool_dict["add to script"] == True: 238 | addToScript() 239 | response = "" 240 | 241 | #Gives the current time 242 | elif bool_dict["time"] == True: 243 | hr = localtime()[3] 244 | min = localtime()[4] 245 | if hr > 12: 246 | hr = hr - 12 247 | ampm = "PM" 248 | else: 249 | ampm = "AM" 250 | response = "It's " + str(hr) + " " + str(min) + " " + ampm 251 | 252 | #Does conversions (e.g. convert 10 inches to meters) 253 | elif bool_dict["convert"] == True: 254 | response = conversion(command) 255 | 256 | #Says you're welcome 257 | elif bool_dict["thanks"] == True: 258 | response = "you're welcome!" 259 | 260 | #Addresses abusive language 261 | elif bool_dict["abusive"] == True: 262 | response = "Don't speak to me like that" 263 | 264 | #Answers "how are you" 265 | elif bool_dict["how are you"] == True: 266 | response = "I am doing well!" 267 | 268 | #Answers "hello" 269 | elif bool_dict["hello"] == True and total_words<=2: 270 | response = "Hi there!" 271 | 272 | #Answers "are you there" with yes 273 | elif bool_dict["are you there"] == True: 274 | response = "yes, I am listening!" 275 | 276 | #Bring whichever tools were requested 277 | elif bool_dict["tool"] and bool_dict["bring"] and bool_dict["return"]==False: 278 | tools = [] #collect tools that were mentioned 279 | for word in wordList_dict["tool"]: 280 | if word in command.lower(): tools.append(word) 281 | 282 | response = "" 283 | for tool in tools: 284 | if raised_dict[tool]==True: 285 | raised_dict[tool]=False 286 | response += "Bringing you the " + tool + ". \n" 287 | subprocess.Popen("python3 jarvis_bot.py lower,"+tool, shell=True) 288 | else: 289 | response += "The " + tool + " is already out. \n" 290 | 291 | #Return whichever tools were requested 292 | elif bool_dict["tool"] and bool_dict["return"] and bool_dict["bring"]==False: 293 | tools = [] #collect tools that were mentioned 294 | for word in wordList_dict["tool"]: 295 | if word in command.lower(): tools.append(word) 296 | 297 | response = "" 298 | for tool in tools: 299 | if raised_dict[tool]==False: 300 | raised_dict[tool]=True 301 | response += "Putting away the " + tool + ". \n" 302 | subprocess.Popen("python3 jarvis_bot.py raise,"+tool, shell=True) 303 | else: 304 | response += "The " + tool + " is already put away. \n" 305 | 306 | else: 307 | '''response = str(chatbot.get_response(command))''' 308 | response = "Sorry, I didn't understand that." 309 | 310 | #Print and say the response 311 | print("response: " + response) 312 | speak(response) 313 | --------------------------------------------------------------------------------