def integrate(self, query): if "options" in query and query["options"] is not None: if re.search("integrate=.+", query["options"]): integrate_option = query["options"] eprint(integrate_option) target_string = re.sub("integrate=", "", integrate_option) targets = re.split(",", target_string) eprint(targets) final_message = Message() for reasoner_id in targets: eprint("Looping with reasoner_id=" + reasoner_id) query["options"] = "foo" url = None if reasoner_id == "RTX": url = "https://arax.rtx.ai/devED/api/rtx/v1/query" elif reasoner_id == "Robokop": url = "http://robokop.renci.org:6011/api/query" elif reasoner_id == "Indigo": url = "https://indigo.ncats.io/reasoner/api/v0/query" url = None else: eprint("ERROR: Unrecognized target '" + target + "'") if url is not None: eprint("Querying url " + url) message_content = requests.post( url, headers={'accept': 'application/json'}, json=query) status_code = message_content.status_code message_dict = message_content.json() message = Message.from_dict(message_dict) if reasoner_id == "RTX": final_message = message if reasoner_id == "Robokop" or reasoner_id == "Indigo": #if reasoner_id == "Robokop": eprint("Merging in " + reasoner_id) message = self.fix_message(query, message, reasoner_id) if message.results is not None: final_message = self.merge_message2( final_message, message) return (final_message) return (None) return (None)
def add_message(agentIdPath, body): # noqa: E501 """Add a new message (to the agent's multichain stream) Adds a new Message # noqa: E501 :param agentIdPath: ID of marketplace agent :type agentIdPath: str :param body: Message that should to be added to the blockchain :type body: dict | bytes :rtype: Message """ if connexion.request.is_json: json_body = connexion.request.get_json() body = Message.from_dict(json_body) # noqa: E501 body.indexkeys.append('id:'+body.id) json_body['indexkeys'].append('id:'+json_body['id']) multichain_client.publish(agentIdPath,body.indexkeys, json_body) return Response(status=201, mimetype='application/json') else: return Response(status=405, mimetype='application/json')
def message(message=None): # noqa: E501 """requesting chatbot to handle task ask bot # noqa: E501 :param message: :type message: dict | bytes :rtype: InlineResponse200 """ if connexion.request.is_json: message = Message.from_dict(connexion.request.get_json()) # noqa: E501 msg = message._message bot = RiveScript() path = os.path.dirname(os.path.realpath(__file__))+'/brain' bot.load_directory(path) bot.sort_replies() reply = bot.reply("localuser", msg) if reply == '[ERR: No Reply Matched]': reply = "The bot can not understand you question:(" return reply , 200, None
def processExternalPreviousMessageProcessingPlan(self, inputEnvelope): debug = 1 if debug: eprint( "DEBUG: Entering processExternalPreviousMessageProcessingPlan") messages = [] finalMessage = None finalMessage_id = None query = None #### Pull out the main processing plan envelope envelope = PreviousMessageProcessingPlan.from_dict( inputEnvelope["previous_message_processing_plan"]) #### If there are URIs provided, try to load them if envelope.previous_message_uris is not None: if debug: eprint("DEBUG: Got previous_message_uris") for uri in envelope.previous_message_uris: if debug: eprint("DEBUG: messageURI=" + uri) matchResult = re.match( r'http[s]://arax.ncats.io/.*api/rtx/.+/message/(\d+)', uri, re.M | re.I) if matchResult: message_id = matchResult.group(1) if debug: eprint( "DEBUG: Found local ARAX identifier corresponding to message_id " + message_id) if debug: eprint("DEBUG: Loading message_id " + message_id) message = self.getMessage(message_id) #eprint(type(message)) if not isinstance(message, tuple): if debug: eprint("DEBUG: Original question was: " + message["original_question"]) messages.append(message) finalMessage_id = message_id query = { "query_type_id": message["query_type_id"], "restated_question": message["restated_question"], "terms": message["terms"] } else: eprint("ERROR: Unable to load message_id " + message_id) return ({ "status": 404, "title": "Message not found", "detail": "There is no local message corresponding to message_id=" + str(message_id), "type": "about:blank" }, 404) #### If there are one or more previous_messages embedded in the POST, process them if envelope.previous_messages is not None: if debug: eprint("DEBUG: Got previous_messages") for uploadedMessage in envelope.previous_messages: if debug: eprint("DEBUG: uploadedMessage is a " + str(uploadedMessage.__class__)) if str(uploadedMessage.__class__ ) == "<class 'swagger_server.models.message.Message'>": if uploadedMessage.results: message = ast.literal_eval(repr(uploadedMessage)) messages.append(message) if message["terms"] is None: message["terms"] = {"dummyTerm": "giraffe"} if message["query_type_id"] is None: message["query_type_id"] = "UnknownQ" if message["restated_question"] is None: message["restated_question"] = "What is life?" if message["original_question"] is None: message["original_question"] = "what is life" query = { "query_type_id": message["query_type_id"], "restated_question": message["restated_question"], "original_question": message["original_question"], "terms": message["terms"] } else: eprint( "Uploaded message does not contain a results. May be the wrong format" ) return ({ "status": 404, "title": "Bad uploaded Message", "detail": "There is no results in the uploaded Message object=", "type": "about:blank" }, 404) else: eprint( "Uploaded message is not of type Message. It is of type" + str(uploadedMessage.__class__)) return ({ "status": 404, "title": "Bad uploaded Message", "detail": "Uploaded message is not of type Message. It is of type" + str(uploadedMessage.__class__), "type": "about:blank" }, 404) #### Take different actions based on the number of messages we now have in hand n_messages = len(messages) if n_messages == 0: return ({ "status": 499, "title": "No Messages", "detail": "Did not get any useful Message objects", "type": "about:blank" }, 499) elif n_messages == 1: finalMessage = messages[0] else: finalMessage = TxMessage.from_dict(messages[0]) counter = 1 while counter < n_messages: messageToMerge = TxMessage.from_dict(messages[counter]) if messageToMerge.reasoner_id is None: messageToMerge.reasoner_id = "Unknown" if messageToMerge.reasoner_id != "ARAX": messageToMerge = self.fix_message( query, messageToMerge, messageToMerge.reasoner_id) finalMessage = self.merge_message(finalMessage, messageToMerge) counter += 1 finalMessage = ast.literal_eval(repr(finalMessage)) #return( { "status": 498, "title": "Multiple Messages", "detail": "I have multiple messages. Merging code awaits!", "type": "about:blank" }, 498) #### Examine the options that were provided and act accordingly optionsDict = {} if envelope.options: if debug: eprint("DEBUG: Got options") for option in envelope.options: if debug: eprint("DEBUG: option=" + option) optionsDict[option] = 1 #### If there are processing_actions, then fulfill those processing_actions = [] if envelope.processing_actions: if debug: eprint("DEBUG: Found processing_actions") actions_parser = ActionsParser() result = actions_parser.parse(envelope.processing_actions) if result.error_code != 'OK': eprint(result) raise () #### Message suffers from a dual life as a dict and an object. above we seem to treat it as a dict. Fix that. FIXME #### Below we start treating it as and object. This should be the way forward. #### This is not a good place to do this, but may need to convert here from ARAX_messenger import ARAXMessenger finalMessage = ARAXMessenger().from_dict(finalMessage) #### Process each action in order action_stats = {} actions = result.data['actions'] for action in actions: if debug: eprint( f"DEBUG: Considering action '{action['command']}' with parameters {action['parameters']}" ) #### If we encounter a return, then this is the end of the line if action['command'] == 'return': action_stats['return_action'] = action break if action['command'] == 'filter': filter = ARAXFilter() result = filter.apply(finalMessage, action['parameters']) if result.error_code != 'OK': response = result break else: if debug: eprint( f"DEBUG: Action '{action['command']}' is not known" ) #### At the end, process the explicit return() action, or implicitly perform one return_action = { 'command': 'return', 'parameters': { 'message': 'false', 'store': 'false' } } if action is not None and action['command'] == 'return': return_action = action #### If an explicit one left out some parameters, set the defaults if 'store' not in return_action['parameters']: return_action['parameters']['store'] == 'false' if 'message' not in return_action['parameters']: return_action['parameters']['message'] == 'false' #if "AnnotateDrugs" in optionsDict: # if debug: eprint("DEBUG: Annotating drugs") # annotate_std_results(finalMessage) if return_action['parameters']['store'] == 'true': if debug: eprint("DEBUG: Storing resulting Message") finalMessage_id = self.addNewMessage( TxMessage.from_dict(finalMessage), query) #### If requesting a full redirect to the resulting message display. This doesn't really work I don't think #if "RedirectToMessage" in optionsDict: # #redirect("https://arax.ncats.io/api/rtx/v1/message/"+str(finalMessage_id), code=302) # #return( { "status": 302, "redirect": "https://arax.ncats.io/api/rtx/v1/message/"+str(finalMessage_id) }, 302) # return( "Location: https://arax.ncats.io/api/rtx/v1/message/"+str(finalMessage_id), 302) #### If asking for the full message back if return_action['parameters']['message'] == 'true': return (finalMessage) #### Else just the id is returned else: #return( { "status": 200, "message_id": str(finalMessage_id), "n_results": finalMessage['n_results'], "url": "https://arax.ncats.io/api/rtx/v1/message/"+str(finalMessage_id) }, 200) return ({ "status": 200, "message_id": str(finalMessage_id), "n_results": finalMessage.n_results, "url": "https://arax.ncats.io/api/rtx/v1/message/" + str(finalMessage_id) }, 200)
def query(self, query): #### Get our configuration information #### Create a Message object as a response response = Message() execution_string = None #### Determine a plan for what to do based on the input result = self.examine_incoming_query(query) if result["message_code"] != "OK": response.message_code = result["message_code"] response.code_description = result["code_description"] return response #### If we have a previous message processing plan, handle that if "have_previous_message_processing_plan" in result: rtxFeedback = RTXFeedback( ) # FIXME. This should be a separate class I think, not the Feedback class. TODO: Separate them rtxFeedback.connect() message = rtxFeedback.processExternalPreviousMessageProcessingPlan( query) rtxFeedback.disconnect() return (message) #### If we have a query_graph, pass this on to the QueryGraphReasoner if "have_query_graph" in result: qgr = QueryGraphReasoner() message = qgr.answer(query["message"]["query_graph"], TxltrApiFormat=True) #self.log_query(query,message,'new') rtxFeedback = RTXFeedback() rtxFeedback.connect() rtxFeedback.addNewMessage(message, query) rtxFeedback.disconnect() self.limit_message(message, query) return (message) #### Otherwise extract the id and the terms from the incoming parameters else: id = query["message"]["query_type_id"] terms = query["message"]["terms"] #### Check to see if the query_options indicates to query named resource and integrate the results if "have_query_type_id_and_terms" in result and "message" in query and "query_options" in query[ "message"] and "integrate" in query["message"]["query_options"]: response = self.integrate(query) #self.log_query(query,response,'remote') return response #### Create an RTX Feedback management object #eprint(query) rtxFeedback = RTXFeedback() rtxFeedback.connect() cachedMessage = rtxFeedback.getCachedMessage(query) #### If we can find a cached message for this query and this version of RTX, then return the cached message if (cachedMessage is not None): apiMessage = Message().from_dict(cachedMessage) rtxFeedback.disconnect() self.limit_message(apiMessage, query) if apiMessage.message_code is None: if apiMessage.result_code is not None: apiMessage.message_code = apiMessage.result_code else: apiMessage.message_code = "wha??" self.log_query(query, apiMessage, 'cached') return apiMessage #### Still have special handling for Q0 if id == 'Q0': q0 = Q0() message = q0.answer(terms["term"], use_json=True) if 'original_question' in query["message"]: message.original_question = query["message"][ "original_question"] message.restated_question = query["message"][ "restated_question"] message.query_type_id = query["message"]["query_type_id"] message.terms = query["message"]["terms"] id = message.id codeString = message.message_code self.log_query(query, message, 'new') rtxFeedback.addNewMessage(message, query) rtxFeedback.disconnect() self.limit_message(message, query) return (message) #### Else call out to original solution scripts for an answer else: #### If some previous processing has determined what the solution script to use is, then use that if execution_string is not None: command = "python3 " + execution_string #### Else use the ParseQuestion system to determine what the execution_string should be else: txltr = ParseQuestion() command = "python3 " + txltr.get_execution_string(id, terms) #### Set CWD to the QuestioningAnswering area and then invoke from the shell the Q1Solution code cwd = os.getcwd() os.chdir( os.path.dirname(os.path.abspath(__file__)) + "/../../../reasoningtool/QuestionAnswering") eprint(command) returnedText = subprocess.run([command], stdout=subprocess.PIPE, shell=True) os.chdir(cwd) #### reformat the stdout result of the shell command into a string reformattedText = returnedText.stdout.decode('utf-8') #eprint(reformattedText) #### Try to decode that string into a message object try: #data = ast.literal_eval(reformattedText) data = json.loads(reformattedText) message = Message.from_dict(data) if message.message_code is None: if message.result_code is not None: message.message_code = message.result_code else: message.message_code = "wha??" #### If it fails, the just create a new Message object with a notice about the failure except: message = Message() message.message_code = "InternalError" message.code_description = "Error parsing the message from the reasoner. This is an internal bug that needs to be fixed. Unable to respond to this question at this time. The unparsable message was: " + reformattedText #print(query) if 'original_question' in query["message"]: message.original_question = query["message"][ "original_question"] message.restated_question = query["message"][ "restated_question"] message.query_type_id = query["message"]["query_type_id"] message.terms = query["message"]["terms"] #### Log the result and return the Message object self.log_query(query, message, 'new') rtxFeedback.addNewMessage(message, query) rtxFeedback.disconnect() #### Limit message self.limit_message(message, query) return (message) #### If the query type id is not triggered above, then return an error message = Message() message.message_code = "UnsupportedQueryTypeID" message.code_description = "The specified query id '" + id + "' is not supported at this time" rtxFeedback.disconnect() return (message)