def initNLU(self): ############################################################### # # Initiates the NLU setting up the data, NLU / entities models # and required modules such as context and extensions. # ############################################################### self.Data = Data() self.trainingData = self.Data.loadTrainingData() self.trainedData = self.Data.loadTrainedData() self.Model = Model() self.Context = Context() self.Extensions = Extensions() self.restoreData() self.restoreNER() self.restoreNLU() self.initiateSession() self.setThresholds()
def setup(self): self.Logging.logMessage(self.LogFile, "NLU", "INFO", "NLU Classifier Initiating") self.Data = Data(self.Logging, self.LogFile) self.Model = Model() self.Context = Context() self.user = {} self.ner = None self.trainingData = self.Data.loadTrainingData() self.trainedData = self.Data.loadTrainedData() self.trainedWords = self.trainedData["words"] self.trainedClasses = self.trainedData["classes"] self.x = self.trainedData["x"] self.y = self.trainedData["y"] self.intentMap = self.trainedData["iMap"][0] self.restoreEntitiesModel() self.restoreModel() self.Logging.logMessage(self.LogFile, "NLU", "INFO", "NLU Ready")
class NLU(): def __init__(self): ############################################################### # # Sets up all default requirements and placeholders # needed for the NLU engine to run. # # - Helpers: Useful global functions # - JumpWay/jumpWayClient: iotJumpWay class and connection # - Logging: Logging class # ############################################################### self.isTraining = False self.ner = None self.Helpers = Helpers() self._confs = self.Helpers.loadConfigs() self.user = {} self.LogFile = self.Helpers.setLogFile(self._confs["aiCore"]["Logs"] + "NLU/") self.ChatLogFile = self.Helpers.setLogFile( self._confs["aiCore"]["Logs"] + "Chat/") self.jumpWay = JumpWay() self.jumpWayClient = self.jumpWay.startMQTT() self.jumpWayClient.subscribeToDeviceChannel( self._confs["iotJumpWay"]["Channels"]["Commands"]) self.jumpWayClient.deviceCommandsCallback = self.commandsCallback def initiateSession(self): ############################################################### # # Initiates empty guest user session, GeniSys will ask the user # verify their GeniSys user by speaking or typing if it does # not know who it is speaking to. # ############################################################### self.userID = 0 if not self.userID in self.user: self.user[self.userID] = {} self.user[self.userID]["history"] = {} def initNLU(self): ############################################################### # # Initiates the NLU setting up the data, NLU / entities models # and required modules such as context and extensions. # ############################################################### self.Data = Data() self.trainingData = self.Data.loadTrainingData() self.trainedData = self.Data.loadTrainedData() self.Model = Model() self.Context = Context() self.Extensions = Extensions() self.restoreData() self.restoreNER() self.restoreNLU() self.initiateSession() self.setThresholds() def commandsCallback(self, topic, payload): ############################################################### # # The callback function that is triggerend in the event of a # command communication from the iotJumpWay. # ############################################################### self.Helpers.logMessage( self.LogFile, "iotJumpWay", "INFO", "Recieved iotJumpWay Command Data : " + str(payload)) commandData = json.loads(payload.decode("utf-8")) def restoreData(self): ############################################################### # # Sets the local trained data using data retrieved above # ############################################################### self.trainedWords = self.trainedData["words"] self.trainedClasses = self.trainedData["classes"] self.x = self.trainedData["x"] self.y = self.trainedData["y"] self.intentMap = self.trainedData["intentMap"][0] def loadEntityController(self): ############################################################### # # Initiates the entity extractor class from tools # ############################################################### self.entityController = Entities() def restoreNER(self): ############################################################### # # Loads entity controller and restores the NER model # ############################################################### self.loadEntityController() self.ner = self.entityController.restoreNER() def restoreNLU(self): ############################################################### # # Restores the NLU model # ############################################################### self.tmodel = self.Model.buildDNN(self.x, self.y) def setThresholds(self): ############################################################### # # Sets the threshold for the NLU engine, this can be changed # using arguments to commandline programs or paramters for # API calls. # ############################################################### self.threshold = self._confs["NLU"]["Threshold"] self.entityThrshld = self._confs["NLU"]["Mitie"]["Threshold"] def communicate(self, sentence): ############################################################### # # First checks to ensure that the program is not training, # then parses any entities that may be in the intent, then # checks context and extensions before providing a response. # ############################################################### if self.isTraining == False: parsed, fallback, entityHolder, parsedSentence = self.entityController.parseEntities( sentence, self.ner, self.trainingData) classification = self.Model.predict(self.tmodel, parsedSentence, self.trainedWords, self.trainedClasses) if len(classification) > 0: clearEntities = False theIntent = self.trainingData["intents"][self.intentMap[ classification[0][0]]] if len(entityHolder) and not len(theIntent["entities"]): clearEntities = True if (self.Context.checkSessionContext(self.user[self.userID], theIntent)): if self.Context.checkClearContext(theIntent, 0): self.user[self.userID]["context"] = "" contextIn, contextOut, contextCurrent = self.Context.setContexts( theIntent, self.user[self.userID]) if not len(entityHolder) and len(theIntent["entities"]): response, entities = self.entityController.replaceResponseEntities( random.choice(theIntent["fallbacks"]), entityHolder) extension, extensionResponses, exEntities = self.Extensions.setExtension( theIntent) elif clearEntities: entityHolder = [] response = random.choice(theIntent["responses"]) extension, extensionResponses, exEntities = self.Extensions.setExtension( theIntent) else: response, entities = self.entityController.replaceResponseEntities( random.choice(theIntent["responses"]), entityHolder) extension, extensionResponses, exEntities = self.Extensions.setExtension( theIntent) if extension != None: classParts = extension.split(".") classFolder = classParts[0] className = classParts[1] theEntities = None if exEntities != False: theEntities = entities module = __import__( classParts[0] + "." + classParts[1], globals(), locals(), [className]) extensionClass = getattr(module, className)() response = getattr(extensionClass, classParts[2])(extensionResponses, theEntities) return { "Response": "OK", "ResponseData": [{ "Received": sentence, "Intent": classification[0][0], "Confidence": str(classification[0][1]), "Response": response, "Context": [{ "In": contextIn, "Out": contextOut, "Current": contextCurrent }], "Extension": extension, "Entities": entityHolder }] } else: self.user[self.userID]["context"] = "" contextIn, contextOut, contextCurrent = self.Context.setContexts( theIntent, self.user[self.userID]) if fallback and fallback in theIntent and len( theIntent["fallbacks"]): response = self.entityController.replaceResponseEntities( random.choice(theIntent["fallbacks"]), entityHolder) extension, extensionResponses = None, [] else: response = self.entityController.replaceResponseEntities( random.choice(theIntent["responses"]), entityHolder) extension, extensionResponses, exEntities = self.Extensions.setExtension( theIntent) if extension != None: classParts = extension.split(".") classFolder = classParts[0] className = classParts[1] theEntities = None if exEntities != False: theEntities = entities module = __import__( classParts[0] + "." + classParts[1], globals(), locals(), [className]) extensionClass = getattr(module, className)() response = getattr(extensionClass, classParts[2])(extensionResponses, theEntities) else: response = self.entityController.replaceResponseEntities( random.choice(theIntent["responses"]), entityHolder) return { "Response": "OK", "ResponseData": [{ "Received": sentence, "Intent": classification[0][0], "Confidence": str(classification[0][1]), "Response": response, "Context": [{ "In": contextIn, "Out": contextOut, "Current": contextCurrent }], "Extension": extension, "Entities": entityHolder }] } else: contextCurrent = self.Context.getCurrentContext( self.user[self.userID]) return { "Response": "FAILED", "ResponseData": [{ "Received": sentence, "Intent": "UNKNOWN", "Confidence": "NA", "Responses": [], "Response": random.choice(self._confs["NLU"]["defaultResponses"]), "Context": [{ "In": "NA", "Out": "NA", "Current": contextCurrent }], "Extension": "NA", "Entities": entityHolder }] } else: return { "Response": "FAILED", "ResponseData": [{ "Status": "Training", "Message": "NLU Engine is currently training" }] }
class NLU(): def __init__(self): self.Helpers = Helpers() self.Logging = Logging() self._confs = self.Helpers.loadConfigs() self.LogFile = self.Logging.setLogFile(self._confs["AI"]["Logs"] + "NLU/") self.ChatLogFile = self.Logging.setLogFile(self._confs["AI"]["Logs"] + "Chat/") self.Logging.logMessage(self.LogFile, "NLU", "INFO", "NLU Classifier LogFile Set") self.startMQTT() def commandsCallback(self, topic, payload): self.Logging.logMessage( self.LogFile, "iotJumpWay", "INFO", "Recieved iotJumpWay Command Data : " + str(payload)) commandData = json.loads(payload.decode("utf-8")) def startMQTT(self): try: self.jumpwayClient = jumpWayDevice.DeviceConnection({ "locationID": self._confs["iotJumpWay"]["Location"], "zoneID": self._confs["iotJumpWay"]["Zone"], "deviceId": self._confs["iotJumpWay"]["Device"], "deviceName": self._confs["iotJumpWay"]["DeviceName"], "username": self._confs["iotJumpWay"]["MQTT"]["Username"], "password": self._confs["iotJumpWay"]["MQTT"]["Password"] }) self.jumpwayClient.connectToDevice() self.jumpwayClient.subscribeToDeviceChannel("Commands") self.jumpwayClient.deviceCommandsCallback = self.commandsCallback self.Logging.logMessage(self.LogFile, "iotJumpWay", "INFO", "iotJumpWay Client Ready") except Exception as e: self.Logging.logMessage(self.LogFile, "iotJumpWay", "INFO", "iotJumpWay Client Initiation Failed") print(str(e)) sys.exit() def setup(self): self.Logging.logMessage(self.LogFile, "NLU", "INFO", "NLU Classifier Initiating") self.Data = Data(self.Logging, self.LogFile) self.Model = Model() self.Context = Context() self.user = {} self.ner = None self.trainingData = self.Data.loadTrainingData() self.trainedData = self.Data.loadTrainedData() self.trainedWords = self.trainedData["words"] self.trainedClasses = self.trainedData["classes"] self.x = self.trainedData["x"] self.y = self.trainedData["y"] self.intentMap = self.trainedData["iMap"][0] self.restoreEntitiesModel() self.restoreModel() self.Logging.logMessage(self.LogFile, "NLU", "INFO", "NLU Ready") def restoreEntitiesModel(self): if os.path.exists(self._confs["ClassifierSettings"]["EntitiesDat"]): self.ner = named_entity_extractor( self._confs["ClassifierSettings"]["EntitiesDat"]) self.Logging.logMessage(self.LogFile, "NER", "OK", "Restored NLU NER Model") def restoreModel(self): self.tmodel = self.Model.buildDNN(self.x, self.y) self.Logging.logMessage(self.LogFile, "NLU", "INFO", "Restored NLU Model") def setupEntities(self): if self._confs["ClassifierSettings"]["Entities"] == "Mitie": self.entityExtractor = Entities() self.Logging.logMessage(self.LogFile, "NER", "INFO", "NLU Entity Extractor Initiated") def initiateSession(self, userID): self.userID = userID if not self.userID in self.user: self.user[self.userID] = {} self.user[self.userID]["history"] = {} self.Logging.logMessage(self.LogFile, "Session", "INFO", "NLU Session Ready For User #" + self.userID) def setThresholds(self, threshold): self.threshold = float(threshold) self.entityThrshld = self._confs["ClassifierSettings"]["Mitie"][ "Threshold"] def predict(self, parsedSentence): predictions = [[index, confidence] for index, confidence in enumerate( self.tmodel.predict([ self.Data.makeInferenceBag(parsedSentence, self.trainedWords) ])[0]) if confidence > self.threshold] predictions.sort(key=lambda x: x[1], reverse=True) classification = [] for prediction in predictions: classification.append( (self.trainedClasses[prediction[0]], prediction[1])) return classification def talk(self, sentence, debug=False): self.Logging.logMessage(self.LogFile, "GeniSys", "STATUS", "Processing") parsed, fallback, entityHolder, parsedSentence = self.entityExtractor.parseEntities( sentence, self.ner, self.trainingData) classification = self.predict(parsedSentence) if len(classification) > 0: clearEntities = False theIntent = self.trainingData["intents"][self.intentMap[ classification[0][0]]] if len(entityHolder) and not len(theIntent["entities"]): clearEntities = True if (self.Context.checkSessionContext(self.user[self.userID], theIntent)): if self.Context.checkClearContext(theIntent, 0): self.user[self.userID]["context"] = "" contextIn, contextOut, contextCurrent = self.Context.setContexts( theIntent, self.user[self.userID]) if fallback and "fallbacks" in theIntent and len( theIntent["fallbacks"]): response = self.entityExtractor.replaceResponseEntities( random.choice(theIntent["fallbacks"]), entityHolder) action, actionResponses = self.Helpers.setAction(theIntent) elif "entityType" in theIntent and theIntent[ "entityType"] == "Numbers": response = random.choice(theIntent["responses"]) action, actionResponses = self.Helpers.setAction(theIntent) elif not len(entityHolder) and len(theIntent["entities"]): response = self.entityExtractor.replaceResponseEntities( random.choice(theIntent["fallbacks"]), entityHolder) action, actionResponses = self.Helpers.setAction(theIntent) elif clearEntities: entityHolder = [] response = random.choice(theIntent["responses"]) action, actionResponses = self.Helpers.setAction(theIntent) else: response = self.entityExtractor.replaceResponseEntities( random.choice(theIntent["responses"]), entityHolder) action, actionResponses = self.Helpers.setAction(theIntent) if action != None: classParts = action.split(".") classFolder = classParts[0] className = classParts[1] module = __import__(classParts[0] + "." + classParts[1], globals(), locals(), [className]) actionClass = getattr(module, className)() response = getattr(actionClass, classParts[2])( random.choice(actionResponses)) return { "Response": "OK", "ResponseData": [{ "Received": sentence, "Intent": classification[0][0], "Confidence": str(classification[0][1]), "Response": response, "ContextIn": contextIn, "ContextOut": contextOut, "Context": contextCurrent, "Action": action, "Entities": entityHolder }] } else: self.user[self.userID]["context"] = "" contextIn, contextOut, contextCurrent = self.Context.setContexts( theIntent, self.user[self.userID]) if fallback and fallback in theIntent and len( theIntent["fallbacks"]): response = self.entityExtractor.replaceResponseEntities( random.choice(theIntent["fallbacks"]), entityHolder) action, actionResponses = None, [] else: response = self.entityExtractor.replaceResponseEntities( random.choice(theIntent["responses"]), entityHolder) action, actionResponses = self.Helpers.setAction(theIntent) if action != None: classParts = action.split(".") classFolder = classParts[0] className = classParts[1] module = __import__(classParts[0] + "." + classParts[1], globals(), locals(), [className]) actionClass = getattr(module, className)() response = getattr(actionClass, classParts[2])( random.choice(actionResponses)) else: response = self.entityExtractor.replaceResponseEntities( random.choice(theIntent["responses"]), entityHolder) return { "Response": "OK", "ResponseData": [{ "Received": sentence, "Intent": classification[0][0], "Confidence": str(classification[0][1]), "Response": response, "ContextIn": contextIn, "ContextOut": contextOut, "ContextCurrent": contextCurrent, "Action": action, "Entities": entityHolder }] } else: contextCurrent = self.Context.getCurrentContext( self.user[self.userID]) return { "Response": "FAILED", "ResponseData": [{ "Received": sentence, "Intent": "UNKNOWN", "Confidence": "NA", "Responses": [], "Response": random.choice( self._confs["ClassifierSettings"]["defaultResponses"]), "ContextIn": "NA", "ContextOut": "NA", "ContextCurrent": contextCurrent, "Action": "NA", "Entities": entityHolder }] }