def shell(args: argparse.Namespace) -> None: from rasa.cli.utils import get_validated_path from rasa.shared.constants import DEFAULT_MODELS_PATH from rasa.model import get_model, get_model_subdirectories args.connector = "cmdline" model = get_validated_path(args.model, "model", DEFAULT_MODELS_PATH) try: model_path = get_model(model) except ModelNotFound: print_error( "No model found. Train a model before running the " "server using `rasa train`." ) return core_model, nlu_model = get_model_subdirectories(model_path) if not core_model: import rasa.nlu.run telemetry.track_shell_started("nlu") rasa.nlu.run.run_cmdline(nlu_model) else: import rasa.cli.run telemetry.track_shell_started("rasa") rasa.cli.run.run(args)
def _get_valid_config( config: Optional[Text], mandatory_keys: List[Text], default_config: Text = DEFAULT_CONFIG_PATH, ) -> Text: """Get a config from a config file and check if it is valid. Exit if the config isn't valid. Args: config: Path to the config file. mandatory_keys: The keys that have to be specified in the config file. default_config: default config to use if the file at `config` doesn't exist. Returns: The path to the config file if the config is valid. """ config = get_validated_path(config, "config", default_config) if not os.path.exists(config): print_error( "The config file '{}' does not exist. Use '--config' to specify a " "valid config file." "".format(config)) exit(1) missing_keys = missing_config_keys(config, mandatory_keys) if missing_keys: print_error( "The config file '{}' is missing mandatory parameters: " "'{}'. Add missing parameters to config file and try again." "".format(config, "', '".join(missing_keys))) exit(1) return config # pytype: disable=bad-return-type
async def _train_nlu_async( config: Text, nlu_data: Text, output: Text, train_path: Optional[Text] = None, fixed_model_name: Optional[Text] = None, persist_nlu_training_data: bool = False, additional_arguments: Optional[Dict] = None, ): if not nlu_data: print_error( "No NLU data given. Please provide NLU data in order to train " "a Rasa NLU model using the '--nlu' argument.") return # training NLU only hence the training files still have to be selected file_importer = TrainingDataImporter.load_nlu_importer_from_config( config, training_data_paths=[nlu_data]) training_datas = await file_importer.get_nlu_data() if training_datas.is_empty(): print_error(f"Path '{nlu_data}' doesn't contain valid NLU data in it. " f"Please verify the data format. " f"The NLU model training will be skipped now.") return return await _train_nlu_with_validated_data( file_importer, output=output, train_path=train_path, fixed_model_name=fixed_model_name, persist_nlu_training_data=persist_nlu_training_data, additional_arguments=additional_arguments, )
def shell(args: argparse.Namespace) -> None: """Talk with a bot though the command line.""" from rasa.cli.utils import get_validated_path from rasa.shared.constants import DEFAULT_MODELS_PATH args.connector = "cmdline" model = get_validated_path(args.model, "model", DEFAULT_MODELS_PATH) try: model = get_latest_model(model) except ModelNotFound: print_error("No model found. Train a model before running the " "server using `rasa train`.") return metadata = LocalModelStorage.metadata_from_archive(model) if metadata.training_type == TrainingType.NLU: import rasa.nlu.run telemetry.track_shell_started("nlu") rasa.nlu.run.run_cmdline(model) else: import rasa.cli.run telemetry.track_shell_started("rasa") rasa.cli.run.run(args)
def convert_training_data(data_file: Union[list, Text], out_file: Text, output_format: Text, language: Text) -> None: """Convert training data. Args: data_file (Union[list, Text]): Path to the file or directory containing Rasa data. out_file (Text): File or existing path where to save training data in Rasa format. output_format (Text): Output format the training data should be converted into. language (Text): Language of the data. """ if isinstance(data_file, list): data_file = data_file[0] if not os.path.exists(str(data_file)): print_error( "Data file '{}' does not exist. Provide a valid NLU data file using " "the '--data' argument.".format(data_file)) return td = rasa.shared.nlu.training_data.loading.load_data(data_file, language) if output_format == "json": output = td.nlu_as_json(indent=2) else: output = RasaYAMLWriter().dumps(td) write_to_file(out_file, output)
def shell_nlu(args: argparse.Namespace): from rasa.cli.utils import get_validated_path from rasa.constants import DEFAULT_MODELS_PATH from rasa.model import get_model, get_model_subdirectories import rasa.nlu.run args.connector = "cmdline" model = get_validated_path(args.model, "model", DEFAULT_MODELS_PATH) try: model_path = get_model(model) except ModelNotFound: print_error("No model found. Train a model before running the " "server using `rasa train nlu`.") return _, nlu_model = get_model_subdirectories(model_path) if not nlu_model: print_error("No NLU model found. Train a model before running the " "server using `rasa train nlu`.") return rasa.nlu.run.run_cmdline(nlu_model)
def run(args: argparse.Namespace): import rasa.run args.endpoints = get_validated_path(args.endpoints, "endpoints", DEFAULT_ENDPOINTS_PATH, True) args.credentials = get_validated_path(args.credentials, "credentials", DEFAULT_CREDENTIALS_PATH, True) if args.enable_api: if not args.remote_storage: args.model = _validate_model_path(args.model, "model", DEFAULT_MODELS_PATH) rasa.run(**vars(args)) return # if the API is not enable you cannot start without a model # make sure either a model server, a remote storage, or a local model is # configured from rasa.model import get_model from rasa.core.utils import AvailableEndpoints # start server if remote storage is configured if args.remote_storage is not None: rasa.run(**vars(args)) return # start server if model server is configured endpoints = AvailableEndpoints.read_endpoints(args.endpoints) model_server = endpoints.model if endpoints and endpoints.model else None if model_server is not None: rasa.run(**vars(args)) return # start server if local model found args.model = _validate_model_path(args.model, "model", DEFAULT_MODELS_PATH) local_model_set = True try: get_model(args.model) except ModelNotFound: local_model_set = False if local_model_set: rasa.run(**vars(args)) return print_error( "No model found. You have three options to provide a model:\n" "1. Configure a model server in the endpoint configuration and provide " "the configuration via '--endpoints'.\n" "2. Specify a remote storage via '--remote-storage' to load the model " "from.\n" "3. Train a model before running the server using `rasa train` and " "use '--model' to provide the model path.\n" "For more information check {}.".format( DOCS_BASE_URL + "/user-guide/configuring-http-api/"))
def visualize( domain_path: Text, stories_path: Text, nlu_data_path: Text, output_path: Text, max_history: int, ) -> None: """Visualizes stories as graph. Args: domain_path: Path to the domain file. stories_path: Path to the stories files. nlu_data_path: Path to the NLU training data which can be used to interpolate intents with actual examples in the graph. output_path: Path where the created graph should be persisted. max_history: Max history to use for the story visualization. """ import rasa.shared.core.training_data.visualization try: domain = Domain.load(domain_path) except InvalidDomain as e: print_error( f"Could not load domain due to: '{e}'. To specify a valid domain path use " f"the '--domain' argument.") return # this is optional, only needed if the `/greet` type of # messages in the stories should be replaced with actual # messages (e.g. `hello`) if nlu_data_path is not None: import rasa.shared.nlu.training_data.loading nlu_training_data = rasa.shared.nlu.training_data.loading.load_data( nlu_data_path) else: nlu_training_data = None logger.info("Starting to visualize stories...") telemetry.track_visualization() story_steps = loading.load_data_from_resource(stories_path, domain) rasa.shared.core.training_data.visualization.visualize_stories( story_steps, domain, output_path, max_history, nlu_training_data=nlu_training_data, ) full_output_path = "file://{}".format(os.path.abspath(output_path)) logger.info(f"Finished graph creation. Saved into {full_output_path}") import webbrowser webbrowser.open(full_output_path)
async def train_core_async( domain: Union[Domain, Text], config: Text, stories: Text, output: Text, train_path: Optional[Text] = None, fixed_model_name: Optional[Text] = None, additional_arguments: Optional[Dict] = None, ) -> Optional[Text]: """Trains a Core model. Args: domain: Path to the domain file. config: Path to the config file for Core. stories: Path to the Core training data. output: Output path. train_path: If `None` the model will be trained in a temporary directory, otherwise in the provided directory. fixed_model_name: Name of model to be stored. additional_arguments: Additional training parameters. Returns: If `train_path` is given it returns the path to the model archive, otherwise the path to the directory with the trained model files. """ file_importer = TrainingDataImporter.load_core_importer_from_config( config, domain, [stories] ) domain = await file_importer.get_domain() if domain.is_empty(): print_error( "Core training was skipped because no valid domain file was found. " "Please specify a valid domain using '--domain' argument or check " "if the provided domain file exists." ) return None if not await file_importer.get_stories(): print_error( "No stories given. Please provide stories in order to " "train a Rasa Core model using the '--stories' argument." ) return return await _train_core_with_validated_data( file_importer, output=output, train_path=train_path, fixed_model_name=fixed_model_name, additional_arguments=additional_arguments, )
async def visualize( config_path: Text, domain_path: Text, stories_path: Text, nlu_data_path: Text, output_path: Text, max_history: int, ): from rasa.core.agent import Agent from rasa.core import config try: policies = config.load(config_path) except ValueError as e: print_error( "Could not load config due to: '{}'. To specify a valid config file use " "the '--config' argument.".format(e)) return try: agent = Agent(domain=domain_path, policies=policies) except InvalidDomain as e: print_error( "Could not load domain due to: '{}'. To specify a valid domain path use " "the '--domain' argument.".format(e)) return # this is optional, only needed if the `/greet` type of # messages in the stories should be replaced with actual # messages (e.g. `hello`) if nlu_data_path is not None: import rasa.shared.nlu.training_data.loading nlu_training_data = rasa.shared.nlu.training_data.loading.load_data( nlu_data_path) else: nlu_training_data = None logger.info("Starting to visualize stories...") telemetry.track_visualization() await agent.visualize(stories_path, output_path, max_history, nlu_training_data=nlu_training_data) full_output_path = "file://{}".format(os.path.abspath(output_path)) logger.info(f"Finished graph creation. Saved into {full_output_path}") import webbrowser webbrowser.open(full_output_path)
def chat( model_path: Optional[Text] = None, endpoints: Optional[Text] = None, agent: Optional["Agent"] = None, interpreter: Optional[NaturalLanguageInterpreter] = None, ) -> None: """Chat to the bot within a Jupyter notebook. Args: model_path: Path to a combined Rasa model. endpoints: Path to a yaml with the action server is custom actions are defined. agent: Rasa Core agent (used if no Rasa model given). interpreter: Rasa NLU interpreter (used with Rasa Core agent if no Rasa model is given). """ if model_path: from rasa.run import create_agent agent = create_agent(model_path, endpoints) elif agent is not None and interpreter is not None: # HACK: this skips loading the interpreter and directly # sets it afterwards nlu_interpreter = RasaNLUInterpreter( "skip this and use given interpreter", lazy_init=True) nlu_interpreter.interpreter = interpreter agent.interpreter = interpreter else: print_error( "You either have to define a model path or an agent and an interpreter." ) return print( "Your bot is ready to talk! Type your messages here or send '/stop'.") loop = asyncio.get_event_loop() while True: message = input() if message == "/stop": break responses = loop.run_until_complete(agent.handle_text(message)) for response in responses: _display_bot_response(response)
def main() -> None: """Run as standalone python application.""" parse_last_positional_argument_as_model_path() arg_parser = create_argument_parser() cmdline_arguments = arg_parser.parse_args() log_level = ( cmdline_arguments.loglevel if hasattr(cmdline_arguments, "loglevel") else None ) configure_logging_and_warnings( log_level, warn_only_once=True, filter_repeated_logs=True ) tf_env.setup_tf_environment() tf_env.check_deterministic_ops() # insert current path in syspath so custom modules are found sys.path.insert(1, os.getcwd()) try: if hasattr(cmdline_arguments, "func"): rasa.utils.io.configure_colored_logging(log_level) rasa.telemetry.initialize_telemetry() rasa.telemetry.initialize_error_reporting() cmdline_arguments.func(cmdline_arguments) elif hasattr(cmdline_arguments, "version"): print_version() else: # user has not provided a subcommand, let's print the help logger.error("No command specified.") arg_parser.print_help() sys.exit(1) except RasaException as e: # these are exceptions we expect to happen (e.g. invalid training data format) # it doesn't make sense to print a stacktrace for these if we are not in # debug mode logger.debug("Failed to run CLI command due to an exception.", exc_info=e) print_error(f"{e.__class__.__name__}: {e}") sys.exit(1)
def convert_training_data( data_file: Union[list, Text], out_file: Text, output_format: Text, language: Text ) -> None: """Convert training data. Args: data_file (Union[list, Text]): Path to the file or directory containing Rasa data. out_file (Text): File or existing path where to save training data in Rasa format. output_format (Text): Output format the training data should be converted into. language (Text): Language of the data. """ if isinstance(data_file, list): data_file = data_file[0] if not os.path.exists(str(data_file)): print_error( "Data file '{}' does not exist. Provide a valid NLU data file using " "the '--data' argument.".format(data_file) ) return if output_format == "json": td = rasa.shared.nlu.training_data.loading.load_data(data_file, language) output = td.nlu_as_json(indent=2) elif output_format == "md": td = rasa.shared.nlu.training_data.loading.load_data(data_file, language) output = td.nlu_as_markdown() else: print_error( "Did not recognize output format. Supported output formats: 'json' and " "'md'. Specify the desired output format with '--format'." ) return write_to_file(out_file, output)
def convert_training_data(data_file: Text, out_file: Text, output_format: Text, language: Text) -> None: if not os.path.exists(data_file): print_error( "Data file '{}' does not exist. Provide a valid NLU data file using " "the '--data' argument.".format(data_file)) return if output_format == "json": td = rasa.shared.nlu.training_data.loading.load_data( data_file, language) output = td.nlu_as_json(indent=2) elif output_format == "md": td = rasa.shared.nlu.training_data.loading.load_data( data_file, language) output = td.nlu_as_markdown() else: print_error( "Did not recognize output format. Supported output formats: 'json' and " "'md'. Specify the desired output format with '--format'.") return write_to_file(out_file, output)
async def _train_async_internal( file_importer: TrainingDataImporter, train_path: Text, output_path: Text, force_training: bool, fixed_model_name: Optional[Text], persist_nlu_training_data: bool, core_additional_arguments: Optional[Dict] = None, nlu_additional_arguments: Optional[Dict] = None, ) -> Optional[Text]: """Trains a Rasa model (Core and NLU). Use only from `train_async`. Args: file_importer: `TrainingDataImporter` which supplies the training data. train_path: Directory in which to train the model. output_path: Output path. force_training: If `True` retrain model even if data has not changed. fixed_model_name: Name of model to be stored. persist_nlu_training_data: `True` if the NLU training data should be persisted with the model. core_additional_arguments: Additional training parameters for core training. nlu_additional_arguments: Additional training parameters forwarded to training method of each NLU component. Returns: Path of the trained model archive. """ stories, nlu_data = await asyncio.gather(file_importer.get_stories(), file_importer.get_nlu_data()) if stories.is_empty() and nlu_data.is_empty(): print_error( "No training data given. Please provide stories and NLU data in " "order to train a Rasa model using the '--data' argument.") return if stories.is_empty(): print_warning( "No stories present. Just a Rasa NLU model will be trained.") return await _train_nlu_with_validated_data( file_importer, output=output_path, fixed_model_name=fixed_model_name, persist_nlu_training_data=persist_nlu_training_data, additional_arguments=nlu_additional_arguments, ) if nlu_data.is_empty(): print_warning( "No NLU data present. Just a Rasa Core model will be trained.") return await _train_core_with_validated_data( file_importer, output=output_path, fixed_model_name=fixed_model_name, additional_arguments=core_additional_arguments, ) new_fingerprint = await model.model_fingerprint(file_importer) old_model = model.get_latest_model(output_path) fingerprint_comparison = FingerprintComparisonResult( force_training=force_training) if not force_training: fingerprint_comparison = model.should_retrain(new_fingerprint, old_model, train_path) if fingerprint_comparison.is_training_required(): await _do_training( file_importer, output_path=output_path, train_path=train_path, fingerprint_comparison_result=fingerprint_comparison, fixed_model_name=fixed_model_name, persist_nlu_training_data=persist_nlu_training_data, core_additional_arguments=core_additional_arguments, nlu_additional_arguments=nlu_additional_arguments, old_model_zip_path=old_model, ) return model.package_model( fingerprint=new_fingerprint, output_directory=output_path, train_path=train_path, fixed_model_name=fixed_model_name, ) print_success("Nothing changed. You can use the old model stored at '{}'." "".format(os.path.abspath(old_model))) return old_model