from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import argparse import json import logging from builtins import str from klein import Klein from rasa_core.agent import Agent from rasa_core.events import Event from rasa_core.version import __version__ from rasa_nlu.server import check_cors logger = logging.getLogger(__name__) def create_argument_parser(): parser = argparse.ArgumentParser( description='starts server to serve an agent') parser.add_argument( '-d', '--core', type=str, help="core model to run with the server") parser.add_argument( '-u', '--nlu', type=str, help="nlu model to run with the server") parser.add_argument( '-p', '--port', default=5005, help="port to run the server at") parser.add_argument( '-v', '--verbose', default=True, help="use verbose logging") parser.add_argument( '-o', '--log_file', type=str, default="rasa_core.log", help="store log file in specified file") return parser def convert_obj_2_tracker_events(serialized_events, domain): # Example format: {"event": "set_slot", "value": 5, "name": "my_slot"} deserialised = [] for e in serialized_events: etype = e.get("event") if etype is not None: del e["event"] deserialised.append(Event.from_parameters(etype, e, domain)) return deserialised class RasaCoreServer(object): """Class representing a Rasa Core HTTP server.""" app = Klein() def __init__(self, model_directory, nlu_model, verbose, log_file): logging.basicConfig(filename=log_file, level="DEBUG" if verbose else "INFO") logging.captureWarnings(True) self.agent = self._create_agent(model_directory, nlu_model) @staticmethod def _create_agent(model_directory, nlu_model): return Agent.load(model_directory, nlu_model) @app.route("/", methods=['GET', 'OPTIONS']) @check_cors def hello(self, request): """Check if the server is running and responds with the version.""" return "hello from Rasa Core: " + __version__ @app.route("/conversations/<cid>/continue", methods=['POST', 'OPTIONS']) @check_cors def continue_predicting(self, request, cid): request.setHeader('Content-Type', 'application/json') request_params = json.loads( request.content.read().decode('utf-8', 'strict')) encoded_events = request_params.get("events", []) executed_action = request_params.get("executed_action", None) events = convert_obj_2_tracker_events(encoded_events, self.agent.domain) response = self.agent.continue_message_handling(cid, executed_action, events) return json.dumps(response) @app.route("/conversations/<cid>/parse", methods=['GET', 'POST', 'OPTIONS']) @check_cors def parse(self, request, cid): request.setHeader('Content-Type', 'application/json') if request.method.decode('utf-8', 'strict') == 'GET': request_params = { key.decode('utf-8', 'strict'): value[0].decode('utf-8', 'strict') for key, value in request.args.items()} else: request_params = json.loads( request.content.read().decode('utf-8', 'strict')) if 'query' in request_params: message = request_params.pop('query') elif 'q' in request_params: message = request_params.pop('q') else: request.setResponseCode(404) return json.dumps({"error": "Invalid parse parameter specified"}) try: response = self.agent.start_message_handling(message, cid) request.setResponseCode(200) return json.dumps(response) except Exception as e: request.setResponseCode(500) logger.error("Caught an exception during " "parse: {}".format(e), exc_info=1) return json.dumps({"error": "{}".format(e)}) @app.route("/version", methods=['GET', 'OPTIONS']) @check_cors def version(self, request): """Respond with the version number of the installed Rasa Core.""" request.setHeader('Content-Type', 'application/json') return json.dumps({'version': __version__}) if __name__ == '__main__': # Running as standalone python application arg_parser = create_argument_parser() cmdline_args = arg_parser.parse_args() logging.basicConfig(level="DEBUG" if cmdline_args.verbose else "INFO") rasa = RasaCoreServer(cmdline_args.core, cmdline_args.nlu, cmdline_args.verbose, cmdline_args.log_file) logger.info("Started http server on port %s" % cmdline_args.port) rasa.app.run("0.0.0.0", cmdline_args.port)