Skip to content

Commit

Permalink
Merge pull request #4834 from RasaHQ/interactive-core
Browse files Browse the repository at this point in the history
let `rasa interactive` automatically do `rasa interactive core` when no nlu data
  • Loading branch information
tmbo committed Dec 18, 2019
2 parents 10b68fe + 97cbf53 commit 701958b
Show file tree
Hide file tree
Showing 8 changed files with 262 additions and 165 deletions.
1 change: 1 addition & 0 deletions changelog/4799.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Running ``rasa interactive`` with no NLU data now works, with the functionality of ``rasa interactive core``.
5 changes: 5 additions & 0 deletions changelog/4834.improvement.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Made it explicit that interactive learning does not work with NLU-only models.

Interactive learning no longer trains NLU-only models if no model is provided
and no core data is provided.

111 changes: 53 additions & 58 deletions rasa/cli/interactive.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import argparse
import asyncio
import logging
import os
from typing import List, Text
from typing import List, Optional, Text

from rasa.cli import utils
import rasa.cli.train as train
from rasa.cli.arguments import interactive as arguments
from rasa import data, model

from rasa import model

# noinspection PyProtectedMember
from rasa.cli.utils import get_validated_path, print_error
from rasa.constants import (
DEFAULT_DATA_PATH,
DEFAULT_MODELS_PATH,
DEFAULT_ENDPOINTS_PATH,
)
from rasa.model import get_latest_model
from rasa.constants import DEFAULT_MODELS_PATH, DEFAULT_ENDPOINTS_PATH
from rasa.importers.importer import TrainingDataImporter

logger = logging.getLogger(__name__)


def add_subparser(
Expand All @@ -28,7 +27,7 @@ def add_subparser(
help="Starts an interactive learning session to create new training data for a "
"Rasa model by chatting.",
)
interactive_parser.set_defaults(func=interactive)
interactive_parser.set_defaults(func=interactive, core_only=False)
interactive_parser.add_argument(
"--e2e",
action="store_true",
Expand All @@ -45,80 +44,76 @@ def add_subparser(
"for a Rasa Core model by chatting. Uses the 'RegexInterpreter', i.e. "
"`/<intent>` input format.",
)
interactive_core_parser.set_defaults(func=interactive_core)
interactive_core_parser.set_defaults(func=interactive, core_only=True)

arguments.set_interactive_arguments(interactive_parser)
arguments.set_interactive_core_arguments(interactive_core_parser)


def interactive(args: argparse.Namespace):
def interactive(args: argparse.Namespace) -> None:
_set_not_required_args(args)
file_importer = TrainingDataImporter.load_from_config(
args.config, args.domain, args.data
)

if args.model is None:
check_training_data(args)
zipped_model = train.train(args)
loop = asyncio.get_event_loop()
story_graph = loop.run_until_complete(file_importer.get_stories())
if not story_graph or story_graph.is_empty():
utils.print_error_and_exit(
"Could not run interactive learning without either core data or a model containing core data."
)

zipped_model = train.train_core(args) if args.core_only else train.train(args)
if not zipped_model:
utils.print_error_and_exit(
"Could not train an initial model. Either pass paths "
"to the relevant training files (`--data`, `--config`, `--domain`), "
"or use 'rasa train' to train a model."
)
else:
zipped_model = get_provided_model(args.model)
if not (zipped_model and os.path.exists(zipped_model)):
utils.print_error_and_exit(
f"Interactive learning process cannot be started as no initial model was "
f"found at path '{args.model}'. Use 'rasa train' to train a model."
)
if not args.skip_visualization:
logger.info(f"Loading visualization data from {args.data}.")

perform_interactive_learning(args, zipped_model)
perform_interactive_learning(args, zipped_model, file_importer)


def _set_not_required_args(args: argparse.Namespace) -> None:
args.fixed_model_name = None
args.store_uncompressed = False


def interactive_core(args: argparse.Namespace):
_set_not_required_args(args)

if args.model is None:
zipped_model = train.train_core(args)
else:
zipped_model = get_provided_model(args.model)

perform_interactive_learning(args, zipped_model)


def perform_interactive_learning(args, zipped_model) -> None:
def perform_interactive_learning(
args: argparse.Namespace, zipped_model: Text, file_importer: TrainingDataImporter
) -> None:
from rasa.core.train import do_interactive_learning

if zipped_model and os.path.exists(zipped_model):
args.model = zipped_model

with model.unpack_model(zipped_model) as model_path:
args.core, args.nlu = model.get_model_subdirectories(model_path)
stories_directory = data.get_core_directory(args.data)
args.model = zipped_model

args.endpoints = get_validated_path(
args.endpoints, "endpoints", DEFAULT_ENDPOINTS_PATH, True
with model.unpack_model(zipped_model) as model_path:
args.core, args.nlu = model.get_model_subdirectories(model_path)
if args.core is None:
utils.print_error_and_exit(
"Can not run interactive learning on an NLU-only model."
)

do_interactive_learning(args, stories_directory)
else:
print_error(
"Interactive learning process cannot be started as no initial model was "
"found. Use 'rasa train' to train a model."
args.endpoints = utils.get_validated_path(
args.endpoints, "endpoints", DEFAULT_ENDPOINTS_PATH, True
)

do_interactive_learning(args, file_importer)


def get_provided_model(arg_model: Text):
model_path = get_validated_path(arg_model, "model", DEFAULT_MODELS_PATH)
def get_provided_model(arg_model: Text) -> Optional[Text]:
model_path = utils.get_validated_path(arg_model, "model", DEFAULT_MODELS_PATH)

if os.path.isdir(model_path):
model_path = get_latest_model(model_path)
model_path = model.get_latest_model(model_path)

return model_path


def check_training_data(args) -> None:
training_files = [
get_validated_path(f, "data", DEFAULT_DATA_PATH, none_is_valid=True)
for f in args.data
]
story_files, nlu_files = data.get_core_nlu_files(training_files)
if not story_files or not nlu_files:
print_error(
"Cannot train initial Rasa model. Please provide NLU and Core data "
"using the '--data' argument."
)
exit(1)
9 changes: 3 additions & 6 deletions rasa/core/train.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
import rasa.utils.io
from rasa.constants import NUMBER_OF_TRAINING_STORIES_FILE, PERCENTAGE_KEY
from rasa.core.domain import Domain
from rasa.importers.importer import TrainingDataImporter
from rasa.utils.common import TempDirectoryPath

if typing.TYPE_CHECKING:
from rasa.core.interpreter import NaturalLanguageInterpreter
from rasa.core.utils import AvailableEndpoints
from rasa.importers.importer import TrainingDataImporter


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -173,17 +173,14 @@ async def do_compare_training(


def do_interactive_learning(
args: argparse.Namespace,
stories: Optional[Text] = None,
additional_arguments: Dict[Text, typing.Any] = None,
args: argparse.Namespace, file_importer: TrainingDataImporter,
):
from rasa.core.training import interactive

interactive.run_interactive_learning(
stories,
file_importer=file_importer,
skip_visualization=args.skip_visualization,
server_args=args.__dict__,
additional_arguments=additional_arguments,
)


Expand Down
Loading

0 comments on commit 701958b

Please sign in to comment.