Repository: RasaHQ/rasa
Pull request: Add option to output interactive learning stories in e2e format
**Proposed changes**:
- Fixes #3410 

**Status (please check what you already did)**:
- [x] made PR ready for code review
- [ ] added some tests for the functionality
- [ ] updated the documentation
- [x] updated the changelog
- [x] reformat files using `black` (please check [Readme](https://github.com/RasaHQ/rasa_nlu#code-style) for instructions)


Problem statement:
optionally output interactive learning stories in e2e format
In interactive learning, we already have user input and the intent, validated by the user. We could output these stories in end-to-end format if the user desires so that they don't have to write e2e stories or turn regular ones into e2e ones on their own.

Perhaps this could happen under the flag `rasa interactive --e2e`.

Hints from issue discussion:
@erohmensing Hi, i would like to work on this.
Awesome, @chidauri! Let me know if you need any help. I think [this function](https://github.com/RasaHQ/rasa/blob/0354dcf1dc46689f048d3f7dbfca51b6d27e638d/rasa/core/events/__init__.py#L289) will be super useful!

Commit message: code refactoring

Patch to review:
diff --git a/rasa/cli/interactive.py b/rasa/cli/interactive.py
index 0a4a01ea7258..6e34a5cba3ae 100644
--- a/rasa/cli/interactive.py
+++ b/rasa/cli/interactive.py
@@ -29,6 +29,9 @@ def add_subparser(
         "Rasa model by chatting.",
     )
     interactive_parser.set_defaults(func=interactive)
+    interactive_parser.add_argument(
+        "--e2e", action="store_true", help="save file in e2e format"
+    )
 
     interactive_subparsers = interactive_parser.add_subparsers()
     interactive_core_parser = interactive_subparsers.add_parser(
diff --git a/rasa/core/training/interactive.py b/rasa/core/training/interactive.py
index 24171380cddf..5eb08291a777 100644
--- a/rasa/core/training/interactive.py
+++ b/rasa/core/training/interactive.py
@@ -78,6 +78,8 @@
     "domain": "domain.yml",
 }
 
+SAVE_IN_E2E = {"value": False}
+
 # choose other intent, making sure this doesn't clash with an existing intent
 OTHER_INTENT = uuid.uuid4().hex
 OTHER_ACTION = uuid.uuid4().hex
@@ -801,7 +803,7 @@ async def _write_stories_to_file(
                 isinstance(event, UserUttered) for event in tracker.applied_events()
             ):
                 i += 1
-                f.write("\n" + tracker.export_stories())
+                f.write("\n" + tracker.export_stories(SAVE_IN_E2E["value"]))
 
 
 async def _write_nlu_to_file(
@@ -1551,6 +1553,8 @@ def run_interactive_learning(
     if server_args.get("domain"):
         PATHS["domain"] = server_args["domain"]
 
+    SAVE_IN_E2E["value"] = server_args["e2e"]
+
     if not skip_visualization:
         p = Process(target=start_visualization, args=("story_graph.dot",))
         p.daemon = True


Code review comments:
diff_hunk: @@ -29,6 +29,9 @@ def add_subparser(
         "Rasa model by chatting.",
     )
     interactive_parser.set_defaults(func=interactive)
+    interactive_parser.add_argument(
+        "--e2e", action="store_true", help="save file in e2e format"
path: rasa/cli/interactive.py
text: @user1:
```suggestion
        "--e2e", action="store_true", help="Save story files in e2e format. In this format user messages will be included in the stories."
```

diff_hunk: @@ -78,6 +78,8 @@
     "domain": "domain.yml",
 }
 
+SAVE_IN_E2E = {"value": False}
path: rasa/core/training/interactive.py
text: @user1:
is there any reason this needs to be a dict and can't just be a boolean?

@author:
Actually i need a global variable, and dict works fine but boolean doesn't in my case :(

@user1:
do you know why it doesn't work? (or can you tell me more about what you need it for?)

@author:
i am using server_args to pass e2e, and updating it here inside `run_interactive_learning` function, if i do something like `SAVE_IN_E2E = True` it doesn't affect the global boolean variable, so i need a dictionary
https://github.com/chidauri/rasa/blob/d8b2fe1fdd857dc1b2b233c30b3d3ad99a25faca/rasa/core/training/interactive.py#L1556

@user1:
ah right, you need to declare it to be global:

at the beginning of the `run_interactive_learning` function, just put `global SAVE_IN_E2E `