Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for story/rules reading and writing for both formats #7033

Merged
merged 9 commits into from
Oct 20, 2020
2 changes: 2 additions & 0 deletions changelog/7033.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Fix `YAMLStoryReader` not being able to represent OR statements in conversion mode.
federicotdn marked this conversation as resolved.
Show resolved Hide resolved
- Fix `MarkdownStoryWriter` not being able to write stories with OR statements (when loaded in conversion mode).
federicotdn marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,9 @@ def _parse_or_statement(self, step: Dict[Text, Any]) -> None:
)
return

self.current_step_builder.add_user_messages(utterances)
self.current_step_builder.add_user_messages(
utterances, self.is_used_for_conversion
federicotdn marked this conversation as resolved.
Show resolved Hide resolved
)

def _user_intent_from_step(self, step: Dict[Text, Any]) -> Text:
user_intent = step.get(KEY_USER_INTENT, "").strip()
Expand Down
12 changes: 12 additions & 0 deletions rasa/shared/core/training_data/structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,13 @@ def _user_string(story_step_element: UserUttered, e2e: bool) -> Text:
def _bot_string(story_step_element: Event) -> Text:
return f" - {story_step_element.as_story_string()}\n"

@staticmethod
def _or_string(story_step_element: List[Event], e2e: bool) -> Text:
result = " OR ".join(
[element.as_story_string(e2e) for element in story_step_element]
federicotdn marked this conversation as resolved.
Show resolved Hide resolved
)
return f"* {result}\n"

def as_story_string(self, flat: bool = False, e2e: bool = False) -> Text:
# if the result should be flattened, we
# will exclude the caption and any checkpoints.
Expand All @@ -156,6 +163,11 @@ def as_story_string(self, flat: bool = False, e2e: bool = False) -> Text:
converted = s.as_story_string() # pytype: disable=attribute-error
if converted:
result += self._bot_string(s)
elif isinstance(s, list):
# The story reader classes support reading stories in
# conversion mode. When this mode is enabled, OR statements
# are represented as lists of events.
result += self._or_string(s, e2e)
else:
raise Exception(f"Unexpected element in story step: {s}")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,3 +359,28 @@ def test_read_mixed_training_data_file(default_domain: Domain):
with pytest.warns(None) as record:
reader.read_from_parsed_yaml(yaml_content)
assert not len(record)


def test_or_statement_conversion_mode():
federicotdn marked this conversation as resolved.
Show resolved Hide resolved
stories = """
stories:
- story: hello world
steps:
- or:
- intent: intent1
- intent: intent2
- action: some_action
"""

reader = YAMLStoryReader(is_used_for_conversion=True)
yaml_content = rasa.shared.utils.io.read_yaml(stories)

steps = reader.read_from_parsed_yaml(yaml_content)

assert len(steps) == 1

or_statement = steps[0].events[0]
assert isinstance(or_statement, list)

assert or_statement[0].intent["name"] == "intent1"
assert or_statement[1].intent["name"] == "intent2"
federicotdn marked this conversation as resolved.
Show resolved Hide resolved
35 changes: 35 additions & 0 deletions tests/shared/core/training_data/test_structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,41 @@ def test_session_start_is_not_serialised(default_domain: Domain):
assert story.as_story_string(flat=True) == expected


def test_as_story_string_or_statement():
from rasa.shared.core.training_data.story_reader.yaml_story_reader import (
YAMLStoryReader,
)

import rasa.shared.utils.io

stories = """
stories:
- story: hello world
steps:
- or:
- intent: intent1
- intent: intent2
- intent: intent3
- action: some_action
"""

reader = YAMLStoryReader(is_used_for_conversion=True)
yaml_content = rasa.shared.utils.io.read_yaml(stories)

steps = reader.read_from_parsed_yaml(yaml_content)

assert len(steps) == 1

assert (
steps[0].as_story_string()
== """
## hello world
* intent1 OR intent2 OR intent3
- some_action
"""
)


def test_cap_length():
assert (
rasa.shared.core.training_data.structures._cap_length("mystring", 6) == "mys..."
Expand Down