From 29df75ca30f4d47a8d79afd3958d9a5ac6e1f25e Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Thu, 20 Jul 2023 10:23:21 +0200 Subject: [PATCH 01/33] naive port of moodbot to dm2 --- rasa/cli/initial_project/config.yml | 47 ++--------- rasa/cli/initial_project/data/flows.yml | 29 +++++++ rasa/cli/initial_project/data/nlu.yml | 96 ++--------------------- rasa/cli/initial_project/data/rules.yml | 13 --- rasa/cli/initial_project/data/stories.yml | 30 ------- 5 files changed, 45 insertions(+), 170 deletions(-) create mode 100644 rasa/cli/initial_project/data/flows.yml delete mode 100644 rasa/cli/initial_project/data/rules.yml delete mode 100644 rasa/cli/initial_project/data/stories.yml diff --git a/rasa/cli/initial_project/config.yml b/rasa/cli/initial_project/config.yml index eb54e60a86ce..256f73c51391 100644 --- a/rasa/cli/initial_project/config.yml +++ b/rasa/cli/initial_project/config.yml @@ -1,44 +1,13 @@ -# The config recipe. -# https://rasa.com/docs/rasa/model-configuration/ recipe: default.v1 - -# The assistant project unique identifier -# This default value must be replaced with a unique assistant name within your deployment -assistant_id: placeholder_default - -# Configuration for Rasa NLU. -# https://rasa.com/docs/rasa/nlu/components/ language: en - pipeline: -# # No configuration for the NLU pipeline was provided. The following default pipeline was used to train your model. -# # If you'd like to customize it, uncomment and adjust the pipeline. -# # See https://rasa.com/docs/rasa/tuning-your-model for more information. -# - name: WhitespaceTokenizer -# - name: RegexFeaturizer -# - name: LexicalSyntacticFeaturizer -# - name: CountVectorsFeaturizer -# - name: CountVectorsFeaturizer -# analyzer: char_wb -# min_ngram: 1 -# max_ngram: 4 -# - name: DIETClassifier -# epochs: 100 -# - name: EntitySynonymMapper -# - name: ResponseSelector -# epochs: 100 -# - name: FallbackClassifier -# threshold: 0.3 -# ambiguity_threshold: 0.1 + - name: LLMCommandClassifier + # llm: + # model_name: gpt-4 -# Configuration for Rasa Core. -# https://rasa.com/docs/rasa/core/policies/ policies: -# # No configuration for policies was provided. The following default policies were used to train your model. -# # If you'd like to customize them, uncomment and adjust the policies. -# # See https://rasa.com/docs/rasa/policies for more information. -# - name: MemoizationPolicy -# - name: TEDPolicy -# max_history: 5 -# epochs: 100 -# - name: RulePolicy + - name: rasa.core.policies.flow_policy.FlowPolicy +# - name: rasa_plus.ml.DocsearchPolicy +# - name: RulePolicy + +assistant_id: 20230405-114328-tranquil-mustard diff --git a/rasa/cli/initial_project/data/flows.yml b/rasa/cli/initial_project/data/flows.yml new file mode 100644 index 000000000000..e9c0551592a9 --- /dev/null +++ b/rasa/cli/initial_project/data/flows.yml @@ -0,0 +1,29 @@ +flows: + say_goodbye: + description: say goodbye to the user + steps: + - id: "0" + action: utter_goodbye + bot_challenge: + description: explain to the user that they are talking to a bot, if they ask + steps: + - id: "0" + action: utter_iamabot + greet: + description: greet the user and ask how they are doing. + steps: + - id: "0" + action: utter_greet + cheer_up: + description: if the user is doing poorly, cheer them up with a cute photo + steps: + - id: "0" + action: utter_cheer_up + next: "1" + - id: "1" + action: utter_did_that_help + happy: + description: tell the user you are glad they are doing well + steps: + - id: "0" + action: utter_happy \ No newline at end of file diff --git a/rasa/cli/initial_project/data/nlu.yml b/rasa/cli/initial_project/data/nlu.yml index 2f6c3f8c7d3e..edbbf36d42ad 100644 --- a/rasa/cli/initial_project/data/nlu.yml +++ b/rasa/cli/initial_project/data/nlu.yml @@ -1,91 +1,11 @@ version: "3.1" nlu: -- intent: greet - examples: | - - hey - - hello - - hi - - hello there - - good morning - - good evening - - moin - - hey there - - let's go - - hey dude - - goodmorning - - goodevening - - good afternoon - -- intent: goodbye - examples: | - - cu - - good by - - cee you later - - good night - - bye - - goodbye - - have a nice day - - see you around - - bye bye - - see you later - -- intent: affirm - examples: | - - yes - - y - - indeed - - of course - - that sounds good - - correct - -- intent: deny - examples: | - - no - - n - - never - - I don't think so - - don't like that - - no way - - not really - -- intent: mood_great - examples: | - - perfect - - great - - amazing - - feeling like a king - - wonderful - - I am feeling very good - - I am great - - I am amazing - - I am going to save the world - - super stoked - - extremely good - - so so perfect - - so good - - so perfect - -- intent: mood_unhappy - examples: | - - my day was horrible - - I am sad - - I don't feel very well - - I am disappointed - - super sad - - I'm so sad - - sad - - very sad - - unhappy - - not good - - not very good - - extremly sad - - so saad - - so sad - -- intent: bot_challenge - examples: | - - are you a bot? - - are you a human? - - am I talking to a bot? - - am I talking to a human? + - intent: affirm + examples: | + - yes + - yup + - intent: deny + examples: | + - no + - nope \ No newline at end of file diff --git a/rasa/cli/initial_project/data/rules.yml b/rasa/cli/initial_project/data/rules.yml deleted file mode 100644 index a9987ee2a3fb..000000000000 --- a/rasa/cli/initial_project/data/rules.yml +++ /dev/null @@ -1,13 +0,0 @@ -version: "3.1" - -rules: - -- rule: Say goodbye anytime the user says goodbye - steps: - - intent: goodbye - - action: utter_goodbye - -- rule: Say 'I am a bot' anytime the user challenges - steps: - - intent: bot_challenge - - action: utter_iamabot diff --git a/rasa/cli/initial_project/data/stories.yml b/rasa/cli/initial_project/data/stories.yml deleted file mode 100644 index 6ff78ee20864..000000000000 --- a/rasa/cli/initial_project/data/stories.yml +++ /dev/null @@ -1,30 +0,0 @@ -version: "3.1" - -stories: - -- story: happy path - steps: - - intent: greet - - action: utter_greet - - intent: mood_great - - action: utter_happy - -- story: sad path 1 - steps: - - intent: greet - - action: utter_greet - - intent: mood_unhappy - - action: utter_cheer_up - - action: utter_did_that_help - - intent: affirm - - action: utter_happy - -- story: sad path 2 - steps: - - intent: greet - - action: utter_greet - - intent: mood_unhappy - - action: utter_cheer_up - - action: utter_did_that_help - - intent: deny - - action: utter_goodbye From d4d21851f5536c8b6ce7499119047dfd1a39ce60 Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Thu, 20 Jul 2023 10:23:34 +0200 Subject: [PATCH 02/33] tweak prompt to avoid hallucination --- rasa/nlu/classifiers/flow_prompt_template.jinja2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rasa/nlu/classifiers/flow_prompt_template.jinja2 b/rasa/nlu/classifiers/flow_prompt_template.jinja2 index 946774553395..522c38142a3c 100644 --- a/rasa/nlu/classifiers/flow_prompt_template.jinja2 +++ b/rasa/nlu/classifiers/flow_prompt_template.jinja2 @@ -25,7 +25,7 @@ Here are the slots of the currently active flow with their names and values: {% endif %} {% else %} You are currently not in any flow and so there are no active slots. -In order to fill a slot, you first have to start the flow and then fill the slot. +This means you can only set a slot if you first start a flow that requires that slot. {% endif %} If you start a flow, first start the flow and then optionally fill that flow's slots with information the user provided in their message. From 12fba9c9731c6e736054588a484263bfafa517c0 Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Thu, 20 Jul 2023 10:24:13 +0200 Subject: [PATCH 03/33] domain for moodbot --- rasa/cli/initial_project/domain.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/rasa/cli/initial_project/domain.yml b/rasa/cli/initial_project/domain.yml index 2d24633677c7..762061952cb3 100644 --- a/rasa/cli/initial_project/domain.yml +++ b/rasa/cli/initial_project/domain.yml @@ -1,14 +1,5 @@ version: "3.1" -intents: - - greet - - goodbye - - affirm - - deny - - mood_great - - mood_unhappy - - bot_challenge - responses: utter_greet: - text: "Hey! How are you?" From c8eb92470f8652c34df1174c9970deb4321fb5df Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Thu, 20 Jul 2023 16:38:52 +0200 Subject: [PATCH 04/33] new start here docs page --- docs/docs/start-here.mdx | 11 +++++++++++ docs/sidebars.js | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 docs/docs/start-here.mdx diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx new file mode 100644 index 000000000000..45c90d840238 --- /dev/null +++ b/docs/docs/start-here.mdx @@ -0,0 +1,11 @@ +--- +id: start-here +sidebar_label: Start Here +title: Start Here +hide_table_of_contents: true +--- + + +## Getting Started with Rasa + + diff --git a/docs/sidebars.js b/docs/sidebars.js index 74f7cda05e55..e967043d36af 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -2,7 +2,7 @@ module.exports = { default: [ 'introduction', 'rasa-pro', - 'playground', + 'start-here', { type: 'category', label: 'Installation', From 0f3be911dc41a1d599480acdcf57b5a80eae058d Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Thu, 20 Jul 2023 16:41:24 +0200 Subject: [PATCH 05/33] trigger build From 3cc05132342345c4827ea3a8d7040f5560b88da4 Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Thu, 20 Jul 2023 16:49:52 +0200 Subject: [PATCH 06/33] updates to docs --- docs/docs/start-here.mdx | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index 45c90d840238..4488ff5fd00b 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -8,4 +8,31 @@ hide_table_of_contents: true ## Getting Started with Rasa +### Create an initial project + +The `init` command creates a new Rasa project for you. + +```bash +rasa init +``` + +Run the `train` command at any time to build an assistant from the current state of your project: + +```bash +rasa train +``` + +While the command is called `rasa train`, model training only happens if you've made changes that would affect your models. + +Use the `shell` command talk to your assistant on the command line: + +```bash +rasa shell +``` + +Adding the `debug` flag can be very helpful for understanding everything that's going on: + +```bash +rasa shell --debug +``` From ae031d5301e40fb0e18737947447bcc2c392f3df Mon Sep 17 00:00:00 2001 From: Tom Bocklisch Date: Thu, 20 Jul 2023 22:32:42 +0200 Subject: [PATCH 07/33] updated config --- rasa/cli/initial_project/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rasa/cli/initial_project/config.yml b/rasa/cli/initial_project/config.yml index 256f73c51391..b6638aca4dc7 100644 --- a/rasa/cli/initial_project/config.yml +++ b/rasa/cli/initial_project/config.yml @@ -1,7 +1,7 @@ recipe: default.v1 language: en pipeline: - - name: LLMCommandClassifier + - name: LLMCommandGenerator # llm: # model_name: gpt-4 From 322764172324f9babb4d5f09f77b10e653b2b331 Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Fri, 21 Jul 2023 10:21:52 +0200 Subject: [PATCH 08/33] more work on tutorial --- docs/docs/start-here.mdx | 113 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 1 deletion(-) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index 4488ff5fd00b..fb71b9f76870 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -8,7 +8,7 @@ hide_table_of_contents: true ## Getting Started with Rasa -### Create an initial project +### Create a project The `init` command creates a new Rasa project for you. @@ -30,9 +30,120 @@ Use the `shell` command talk to your assistant on the command line: rasa shell ``` +To stop the conversation, type `/stop` or use `control+C`. + Adding the `debug` flag can be very helpful for understanding everything that's going on: ```bash rasa shell --debug ``` +### Exploring what your assistant can do + +AI assistants often have to collect a few pieces of information from the user in order to achieve a goal. +Your start project contains an example flow which can recommend a restaurant, and collects the user's preferred cuisine, city, and price range to do so. + + +To try it out, start a conversation using `rasa shell`, and say something like "I'm looking for a restaurant". + +Out of the box, this assistant can already handle some pretty advanced conversations. Users can change their mind, +answer indirectly, or interject with questions. Try out some of these conversations yourself to get a feel for things. +If you want to allow your assistant to paraphrase its responses + + + + + Can you recommend somewhere to eat? + What kind of food are you looking for? + Indian food + in what price range? + cheap + and in which city? + Berlin + + + + + Can you recommend somewhere to eat? + What kind of food are you looking for? + Indian food + in what price range? + actually no I want Italian. A cheap spot + and in which city? + Berlin + + + + + +### Understanding flows + +The `data/flows/restaurants.yml` file defines the logic for this flow. In this example the logic is very simple +and walks the user through each of the steps in order. + +```yaml +flows: + recommend_restaurant: + description: This flow recommends a restaurant + steps: + - id: "0" + question: cuisine + skip_if_filled: true + next: "1" + - id: "1" + question: price_range + next: "2" + - id: "2" + question: part_of_town + next: "3" + - id: "3" + action: search_restaurants +``` + +To build more advanced flows, you can add conditional logic and linking to other flows. [add link] + +### Understanding DM2 + +If you've built AI assistants before, you might look at your project and think that many things are missing. + +* There is no NLU data with intents and entities +* There are no slot mappings +* There is no logic mapping an intent like "restaurant_search" to the start of the restaurant flow +* There is no explicit logic handling corrections, interruptions, or other unhappy paths. + +DM2 doesn't need any of these things to be able to handle the example conversations above. So, how does that work? + +Many developers are familiar with dialogue systems made up of separate NLU, dialogue, and NLG components. +DM2's modules are split differently. + +* The *conversation handling* component (name TBD) interprets the conversation so far and predicts +a series of commands to progress the state of the conversation. +* The *business logic* component executes those commands and the logic of your flows. + +The NLU systems you might know about take a single user message as input, and aim to represent +the meaning of that message by predicting intents and entities. +Instead, *conversation handling* considers the conversation as a whole (not just one message), +and predicts the *intended effect* of the user's message. + +As an example, let's look at using a yes/no question to fill a slot called `late_delivery`: + +> Has it been more than 10 business days since you placed your order? + +When a user answers "yes" or "no", the NLU model predicts an intent like `affirm` or `deny`. +Then there is a second step (usually handled by the dialogue manager) which maps the intents to +the `True/False` values of the `late_delivery` slot. + +Instead, the output of the *conversation handling* component is the command `SetSlot("late_delivery")`. + +The *conversation handling* approach requires much less work to set up, since you don't need to worry about +intents and entities and slot mappings. It is also more powerful because it allows us to break free from intents. + +For example, if the user's response requires context to be understood correctly: + + +Has it been more than 10 business days since you placed your order? +sadly + + +This kind of conversation illustrates the limitations of working with intents. It's perfectly clear +what the user means in this context, but in general the word "sadly" does not mean `affirm`. \ No newline at end of file From 263b6fe2f412f2abe5931bc0030e2cd7cbc7a731 Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Fri, 21 Jul 2023 10:55:17 +0200 Subject: [PATCH 09/33] more work on docs --- docs/docs/start-here.mdx | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index fb71b9f76870..a8bb0424d077 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -50,7 +50,7 @@ Out of the box, this assistant can already handle some pretty advanced conversat answer indirectly, or interject with questions. Try out some of these conversations yourself to get a feel for things. If you want to allow your assistant to paraphrase its responses - + Can you recommend somewhere to eat? @@ -60,8 +60,15 @@ If you want to allow your assistant to paraphrase its responses cheap and in which city? Berlin + Here's a recommendation: ... + + + I'm looking for a cheap Chinese restaurant in Amsterdam? + Here's a recommendation: ... + + Can you recommend somewhere to eat? @@ -71,8 +78,18 @@ If you want to allow your assistant to paraphrase its responses actually no I want Italian. A cheap spot and in which city? Berlin + Here's a recommendation: ... + + + Can you recommend somewhere to eat? + What kind of food are you looking for? + wait are you a bot? + I am a bot, powered by Rasa. + What kind of food are you looking for? + + @@ -101,6 +118,8 @@ flows: ``` To build more advanced flows, you can add conditional logic and linking to other flows. [add link] +The example project uses fixed responses defined in the `domain.yml` file. You can activate [contextual rephrasing]() +to have the assistant adapt each message to sound more natural and fluent. ### Understanding DM2 @@ -127,7 +146,10 @@ and predicts the *intended effect* of the user's message. As an example, let's look at using a yes/no question to fill a slot called `late_delivery`: -> Has it been more than 10 business days since you placed your order? + +Has it been more than 10 business days since you placed your order? + + When a user answers "yes" or "no", the NLU model predicts an intent like `affirm` or `deny`. Then there is a second step (usually handled by the dialogue manager) which maps the intents to @@ -146,4 +168,11 @@ For example, if the user's response requires context to be understood correctly: This kind of conversation illustrates the limitations of working with intents. It's perfectly clear -what the user means in this context, but in general the word "sadly" does not mean `affirm`. \ No newline at end of file +what the user means in this context, but in general the word "sadly" does not mean `affirm`. + +The example project above includes a definition of the core business logic for recommending a restaurant +and not much else. Yet, it can handle a number of advanced conversations right away. +The advantage of DM2 is that it makes chatbots much smarter and much easier to build, while still giving +you full control. + +To understand more about how \ No newline at end of file From f720f290713d13e6cee7c0c579b9ad8e849cb19a Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Fri, 21 Jul 2023 11:08:09 +0200 Subject: [PATCH 10/33] fix --- docs/docs/start-here.mdx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index a8bb0424d077..8b3d4d91f9c8 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -118,7 +118,7 @@ flows: ``` To build more advanced flows, you can add conditional logic and linking to other flows. [add link] -The example project uses fixed responses defined in the `domain.yml` file. You can activate [contextual rephrasing]() +The example project uses fixed responses defined in the `domain.yml` file. You can activate contextual rephrasing to have the assistant adapt each message to sound more natural and fluent. ### Understanding DM2 @@ -175,4 +175,8 @@ and not much else. Yet, it can handle a number of advanced conversations right a The advantage of DM2 is that it makes chatbots much smarter and much easier to build, while still giving you full control. -To understand more about how \ No newline at end of file +Learn more about DM2: + +* Advanced flow logic +* Disambiguation +* Contextual understanding From d8812002f78933772ba0113bcda5a070e97a943c Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Fri, 21 Jul 2023 11:21:10 +0200 Subject: [PATCH 11/33] more edits on docs --- docs/docs/start-here.mdx | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index 8b3d4d91f9c8..3fc1fdb36f46 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -8,6 +8,9 @@ hide_table_of_contents: true ## Getting Started with Rasa +This page will introduce you to the basics of Rasa. It's intended for newcomers and for people +familiar with earlier versions of Rasa looking to understand our new approach. + ### Create a project The `init` command creates a new Rasa project for you. @@ -43,12 +46,11 @@ rasa shell --debug AI assistants often have to collect a few pieces of information from the user in order to achieve a goal. Your start project contains an example flow which can recommend a restaurant, and collects the user's preferred cuisine, city, and price range to do so. - To try it out, start a conversation using `rasa shell`, and say something like "I'm looking for a restaurant". Out of the box, this assistant can already handle some pretty advanced conversations. Users can change their mind, answer indirectly, or interject with questions. Try out some of these conversations yourself to get a feel for things. -If you want to allow your assistant to paraphrase its responses +If you want your assistant to sound a bit more natural, you can activate [contextual rephrasing] of responses. @@ -118,22 +120,23 @@ flows: ``` To build more advanced flows, you can add conditional logic and linking to other flows. [add link] -The example project uses fixed responses defined in the `domain.yml` file. You can activate contextual rephrasing -to have the assistant adapt each message to sound more natural and fluent. +The example project uses fixed responses defined in the `domain.yml` file. ### Understanding DM2 +Rasa uses a new approach to building AI assistants called DM2 (name TBD). If you've built AI assistants before, you might look at your project and think that many things are missing. * There is no NLU data with intents and entities -* There are no slot mappings * There is no logic mapping an intent like "restaurant_search" to the start of the restaurant flow +* There are no slot mappings * There is no explicit logic handling corrections, interruptions, or other unhappy paths. DM2 doesn't need any of these things to be able to handle the example conversations above. So, how does that work? Many developers are familiar with dialogue systems made up of separate NLU, dialogue, and NLG components. -DM2's modules are split differently. +This is also how Rasa worked previously. +In DM2, the modules are split differently. * The *conversation handling* component (name TBD) interprets the conversation so far and predicts a series of commands to progress the state of the conversation. @@ -175,8 +178,11 @@ and not much else. Yet, it can handle a number of advanced conversations right a The advantage of DM2 is that it makes chatbots much smarter and much easier to build, while still giving you full control. -Learn more about DM2: +Learn more about how to use DM2 to build advanced assistants: * Advanced flow logic +* Search-based question-answering * Disambiguation -* Contextual understanding +* Contextual understanding and negation +* Chitchat and digressions + From e3d894c426e8f181867adf846ed36ebbbe29fb7d Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Fri, 21 Jul 2023 11:23:17 +0200 Subject: [PATCH 12/33] docs --- docs/docs/start-here.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index 3fc1fdb36f46..617c8cf40307 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -158,7 +158,7 @@ When a user answers "yes" or "no", the NLU model predicts an intent like `affirm Then there is a second step (usually handled by the dialogue manager) which maps the intents to the `True/False` values of the `late_delivery` slot. -Instead, the output of the *conversation handling* component is the command `SetSlot("late_delivery")`. +Instead, the output of the *conversation handling* component is a command like `SetSlot("late_delivery", True)`. The *conversation handling* approach requires much less work to set up, since you don't need to worry about intents and entities and slot mappings. It is also more powerful because it allows us to break free from intents. @@ -172,6 +172,7 @@ For example, if the user's response requires context to be understood correctly: This kind of conversation illustrates the limitations of working with intents. It's perfectly clear what the user means in this context, but in general the word "sadly" does not mean `affirm`. +However, the conversation handling component will still correctly output `SetSlot("late_delivery", True)`. The example project above includes a definition of the core business logic for recommending a restaurant and not much else. Yet, it can handle a number of advanced conversations right away. From 33994a97e24ea1241756c1150c4e022283123625 Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Fri, 21 Jul 2023 13:47:20 +0200 Subject: [PATCH 13/33] docs --- docs/docs/start-here.mdx | 70 +++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index 617c8cf40307..c9640c29f676 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -8,12 +8,14 @@ hide_table_of_contents: true ## Getting Started with Rasa -This page will introduce you to the basics of Rasa. It's intended for newcomers and for people -familiar with earlier versions of Rasa looking to understand our new approach. +This page provides an introduction to Rasa. It's intended for newcomers and for people +familiar with earlier versions of Rasa who want to understand the new DM2 approach (name TBD). +DM2 gives you the best of both worlds: the time-to-value and generality of LLMs, and the +controllability of intent-based approaches. -### Create a project +### Command Line Interface Basics -The `init` command creates a new Rasa project for you. +Once you have installed Rasa, you can run the `init` command to create a new Rasa project: ```bash rasa init @@ -25,9 +27,15 @@ Run the `train` command at any time to build an assistant from the current state rasa train ``` -While the command is called `rasa train`, model training only happens if you've made changes that would affect your models. +:::note Model Training -Use the `shell` command talk to your assistant on the command line: +While the command is called `rasa train`, building a new version of your assistant doesn't always +require training a model. Rasa uses a cache and only trains when necessary. + +::: + + +Run the `shell` command talk to your assistant on the command line: ```bash rasa shell @@ -35,16 +43,19 @@ rasa shell To stop the conversation, type `/stop` or use `control+C`. -Adding the `debug` flag can be very helpful for understanding everything that's going on: -```bash -rasa shell --debug -``` +:::note Debugging + +Adding the flag `rasa shell --debug` can be very helpful if you want to understand what is happening in detail. + +::: + ### Exploring what your assistant can do -AI assistants often have to collect a few pieces of information from the user in order to achieve a goal. -Your start project contains an example flow which can recommend a restaurant, and collects the user's preferred cuisine, city, and price range to do so. +Assistants often have to collect a few pieces of information from the user in order to complete a task. +This starter project contains an example flow which recommends restaurants. To do so, it asks the user +for their preferred cuisine, city, and price range. To try it out, start a conversation using `rasa shell`, and say something like "I'm looking for a restaurant". @@ -97,8 +108,11 @@ If you want your assistant to sound a bit more natural, you can activate [contex ### Understanding flows -The `data/flows/restaurants.yml` file defines the logic for this flow. In this example the logic is very simple -and walks the user through each of the steps in order. +Given the range of conversations this assistant can handle, you might expect the implementation to be complex. +In fact, there are only two small files that provide Rasa what it needs. + +The `data/flows/restaurants.yml` file defines the logic for this flow. In this example the logic is linear +and walks the user through each of the steps in order. Each of the `question` steps fills the corresponding slot. ```yaml flows: @@ -119,8 +133,9 @@ flows: action: search_restaurants ``` -To build more advanced flows, you can add conditional logic and linking to other flows. [add link] -The example project uses fixed responses defined in the `domain.yml` file. +To build more advanced flows, you can add conditional logic, link to other flows, and more. See [add link] + +In addition to the flows, the `domain.yml` file contains definitions of the slots and responses used in this flow. ### Understanding DM2 @@ -134,15 +149,16 @@ If you've built AI assistants before, you might look at your project and think t DM2 doesn't need any of these things to be able to handle the example conversations above. So, how does that work? -Many developers are familiar with dialogue systems made up of separate NLU, dialogue, and NLG components. -This is also how Rasa worked previously. -In DM2, the modules are split differently. +Many developers are familiar with dialogue systems made up of separate NLU, dialogue, and NLG components +(this is also how Rasa worked previously). + +In DM2, we have a different set of modules. * The *conversation handling* component (name TBD) interprets the conversation so far and predicts a series of commands to progress the state of the conversation. * The *business logic* component executes those commands and the logic of your flows. -The NLU systems you might know about take a single user message as input, and aim to represent +The NLU systems you might be familiar with take a single user message as input, and aim to represent the meaning of that message by predicting intents and entities. Instead, *conversation handling* considers the conversation as a whole (not just one message), and predicts the *intended effect* of the user's message. @@ -154,16 +170,17 @@ As an example, let's look at using a yes/no question to fill a slot called `late -When a user answers "yes" or "no", the NLU model predicts an intent like `affirm` or `deny`. -Then there is a second step (usually handled by the dialogue manager) which maps the intents to +When a user answers "yes" or "no", an NLU model predicts an intent like `affirm` or `deny`. +A second step (usually handled by the dialogue manager) then maps the intents to the `True/False` values of the `late_delivery` slot. -Instead, the output of the *conversation handling* component is a command like `SetSlot("late_delivery", True)`. +Instead, the *conversation handling* component directly outputs the command `SetSlot("late_delivery", True)`. The *conversation handling* approach requires much less work to set up, since you don't need to worry about intents and entities and slot mappings. It is also more powerful because it allows us to break free from intents. -For example, if the user's response requires context to be understood correctly: +For example, if the user's response requires context to be understood correctly and is a challenge for +intent-based systems: Has it been more than 10 business days since you placed your order? @@ -172,17 +189,18 @@ For example, if the user's response requires context to be understood correctly: This kind of conversation illustrates the limitations of working with intents. It's perfectly clear what the user means in this context, but in general the word "sadly" does not mean `affirm`. -However, the conversation handling component will still correctly output `SetSlot("late_delivery", True)`. +The *conversation handling* component will correctly output `SetSlot("late_delivery", True)`. The example project above includes a definition of the core business logic for recommending a restaurant and not much else. Yet, it can handle a number of advanced conversations right away. The advantage of DM2 is that it makes chatbots much smarter and much easier to build, while still giving -you full control. +you full control over your business logic, and the ability to override and customize all bahavior. Learn more about how to use DM2 to build advanced assistants: * Advanced flow logic * Search-based question-answering +* Context switching * Disambiguation * Contextual understanding and negation * Chitchat and digressions From 1ce611e1b51043ba586fd6b6a7d07eadf8778ecd Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 08:49:38 +0100 Subject: [PATCH 14/33] Update docs/docs/start-here.mdx Co-authored-by: Maxime Vdb --- docs/docs/start-here.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index c9640c29f676..e15c5f8eae35 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -31,6 +31,7 @@ rasa train While the command is called `rasa train`, building a new version of your assistant doesn't always require training a model. Rasa uses a cache and only trains when necessary. +More information on the [`rasa train` command reference](./command-line-interface.mdx#rasa-train). ::: From f93a40e2ad219264d0c5fcbba3c44b439ff8edab Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 08:50:06 +0100 Subject: [PATCH 15/33] Update docs/docs/start-here.mdx Co-authored-by: Maxime Vdb --- docs/docs/start-here.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index e15c5f8eae35..0cd970f24682 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -48,6 +48,7 @@ To stop the conversation, type `/stop` or use `control+C`. :::note Debugging Adding the flag `rasa shell --debug` can be very helpful if you want to understand what is happening in detail. +More information on the [`rasa shell` command reference](./command-line-interface.mdx#rasa-shell) ::: From 1dff43a0dfdc84f28155eef8a2224e20ed231a60 Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 08:50:38 +0100 Subject: [PATCH 16/33] Update docs/docs/start-here.mdx Co-authored-by: Maxime Vdb --- docs/docs/start-here.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index 0cd970f24682..97780a0eae60 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -63,7 +63,7 @@ To try it out, start a conversation using `rasa shell`, and say something like " Out of the box, this assistant can already handle some pretty advanced conversations. Users can change their mind, answer indirectly, or interject with questions. Try out some of these conversations yourself to get a feel for things. -If you want your assistant to sound a bit more natural, you can activate [contextual rephrasing] of responses. +If you want your assistant to sound a bit more natural, you can activate [contextual rephrasing](./llms/llm-nlg.mdx) of responses. From 185f5b9376d1c6dbf89f1f6cc9559bcb3fce092b Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 08:52:45 +0100 Subject: [PATCH 17/33] Update docs/docs/start-here.mdx Co-authored-by: Maxime Vdb --- docs/docs/start-here.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index 97780a0eae60..790bc685057f 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -65,7 +65,7 @@ Out of the box, this assistant can already handle some pretty advanced conversat answer indirectly, or interject with questions. Try out some of these conversations yourself to get a feel for things. If you want your assistant to sound a bit more natural, you can activate [contextual rephrasing](./llms/llm-nlg.mdx) of responses. - + Can you recommend somewhere to eat? From acf5525a8c10aa7ff643897139f235536acb1794 Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 10:35:41 +0100 Subject: [PATCH 18/33] put back playground and move dm2 getting started page to llms --- docs/sidebars.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/sidebars.js b/docs/sidebars.js index e967043d36af..26e20d715a37 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -2,7 +2,7 @@ module.exports = { default: [ 'introduction', 'rasa-pro', - 'start-here', + 'playground', { type: 'category', label: 'Installation', @@ -265,6 +265,7 @@ module.exports = { }, ], "llms": [ + 'start-here', 'llms/large-language-models', 'llms/llm-setup', { From 061b3400bb7cc941adf9dbdb7c9470724aea6b0b Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 10:37:15 +0100 Subject: [PATCH 19/33] Update docs/docs/start-here.mdx Co-authored-by: Maxime Vdb --- docs/docs/start-here.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index 790bc685057f..1018ae360deb 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -36,7 +36,7 @@ More information on the [`rasa train` command reference](./command-line-interfac ::: -Run the `shell` command talk to your assistant on the command line: +Run the `shell` command to talk to your assistant on the command line: ```bash rasa shell From b7b6a1de85cbd76b989defbf7ab918bab956f5e9 Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 10:40:06 +0100 Subject: [PATCH 20/33] Update docs/docs/start-here.mdx Co-authored-by: Maxime Vdb --- docs/docs/start-here.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index 1018ae360deb..ae0c13bfb1ac 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -172,7 +172,7 @@ As an example, let's look at using a yes/no question to fill a slot called `late -When a user answers "yes" or "no", an NLU model predicts an intent like `affirm` or `deny`. +When a user answers "yes" or "no", a traditional NLU model predicts an intent like `affirm` or `deny`. A second step (usually handled by the dialogue manager) then maps the intents to the `True/False` values of the `late_delivery` slot. From d5257821cd92730bf05afa3b5d78682ee99e2e91 Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 10:44:16 +0100 Subject: [PATCH 21/33] link to blog post --- docs/docs/start-here.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index ae0c13bfb1ac..e16703869cb8 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -179,7 +179,8 @@ the `True/False` values of the `late_delivery` slot. Instead, the *conversation handling* component directly outputs the command `SetSlot("late_delivery", True)`. The *conversation handling* approach requires much less work to set up, since you don't need to worry about -intents and entities and slot mappings. It is also more powerful because it allows us to break free from intents. +intents and entities and slot mappings. It is also more powerful because it allows us to +[break free from intents](https://rasa.com/blog/its-about-time-we-get-rid-of-intents/). For example, if the user's response requires context to be understood correctly and is a challenge for intent-based systems: From 6341eaa51039c7fbe5ef6f6fa3d12ee4160e5014 Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 10:46:50 +0100 Subject: [PATCH 22/33] Update docs/docs/start-here.mdx Co-authored-by: Maxime Vdb --- docs/docs/start-here.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index e16703869cb8..097cb48f726f 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -176,7 +176,7 @@ When a user answers "yes" or "no", a traditional NLU model predicts an intent li A second step (usually handled by the dialogue manager) then maps the intents to the `True/False` values of the `late_delivery` slot. -Instead, the *conversation handling* component directly outputs the command `SetSlot("late_delivery", True)`. +Instead, the *conversation handling* component directly outputs a command to set the `late_delivery` slot to `True`. The *conversation handling* approach requires much less work to set up, since you don't need to worry about intents and entities and slot mappings. It is also more powerful because it allows us to From d1ce8aebe8f561f0713cd4f67c6505fe06628cef Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 10:56:13 +0100 Subject: [PATCH 23/33] docs edits --- docs/docs/start-here.mdx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index e16703869cb8..a39d311bad64 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -15,7 +15,7 @@ controllability of intent-based approaches. ### Command Line Interface Basics -Once you have installed Rasa, you can run the `init` command to create a new Rasa project: +Once you have installed Rasa, you can run the `init` command to create a starter project: ```bash rasa init @@ -61,8 +61,10 @@ for their preferred cuisine, city, and price range. To try it out, start a conversation using `rasa shell`, and say something like "I'm looking for a restaurant". -Out of the box, this assistant can already handle some pretty advanced conversations. Users can change their mind, -answer indirectly, or interject with questions. Try out some of these conversations yourself to get a feel for things. +Out of the box, this assistant can already handle a variety of conversations. The first is what we call the "happy path", +where the user provides all the important when it's requested. +But if users change their mind, answer indirectly, or interject with questions, this assistant can handle those cases as well. +Try out some of these conversations yourself to get a feel for things. If you want your assistant to sound a bit more natural, you can activate [contextual rephrasing](./llms/llm-nlg.mdx) of responses. @@ -197,7 +199,7 @@ The *conversation handling* component will correctly output `SetSlot("late_deliv The example project above includes a definition of the core business logic for recommending a restaurant and not much else. Yet, it can handle a number of advanced conversations right away. The advantage of DM2 is that it makes chatbots much smarter and much easier to build, while still giving -you full control over your business logic, and the ability to override and customize all bahavior. +you full control over your business logic, and the ability to override and customize all behavior. Learn more about how to use DM2 to build advanced assistants: From a2ac90d4e01221a504bc86fe4844fb752cd3d396 Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 11:00:57 +0100 Subject: [PATCH 24/33] Update docs/docs/start-here.mdx Co-authored-by: Maxime Vdb --- docs/docs/start-here.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index b0cb554f1a80..038870bc8250 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -137,7 +137,7 @@ flows: action: search_restaurants ``` -To build more advanced flows, you can add conditional logic, link to other flows, and more. See [add link] +To build more advanced flows, you can add conditional logic, link to other flows, and more. Read more on how to handle [Business Logic with Flows](./flows.mdx) In addition to the flows, the `domain.yml` file contains definitions of the slots and responses used in this flow. From 3d8ad7e161b3b3b92d3fc8664883021354589cfc Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 11:07:06 +0100 Subject: [PATCH 25/33] initial project - dm2 --- .../initial_project_dm2/actions/__init__.py | 0 .../initial_project_dm2/actions/actions.py | 27 ++++++ rasa/cli/initial_project_dm2/config.yml | 13 +++ rasa/cli/initial_project_dm2/credentials.yml | 33 +++++++ rasa/cli/initial_project_dm2/data/flows.yml | 44 +++++++++ rasa/cli/initial_project_dm2/data/nlu.yml | 11 +++ rasa/cli/initial_project_dm2/domain.yml | 63 +++++++++++++ rasa/cli/initial_project_dm2/endpoints.yml | 42 +++++++++ .../tests/test_stories.yml | 91 +++++++++++++++++++ 9 files changed, 324 insertions(+) create mode 100644 rasa/cli/initial_project_dm2/actions/__init__.py create mode 100644 rasa/cli/initial_project_dm2/actions/actions.py create mode 100644 rasa/cli/initial_project_dm2/config.yml create mode 100644 rasa/cli/initial_project_dm2/credentials.yml create mode 100644 rasa/cli/initial_project_dm2/data/flows.yml create mode 100644 rasa/cli/initial_project_dm2/data/nlu.yml create mode 100644 rasa/cli/initial_project_dm2/domain.yml create mode 100644 rasa/cli/initial_project_dm2/endpoints.yml create mode 100644 rasa/cli/initial_project_dm2/tests/test_stories.yml diff --git a/rasa/cli/initial_project_dm2/actions/__init__.py b/rasa/cli/initial_project_dm2/actions/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/rasa/cli/initial_project_dm2/actions/actions.py b/rasa/cli/initial_project_dm2/actions/actions.py new file mode 100644 index 000000000000..8bf1f757f851 --- /dev/null +++ b/rasa/cli/initial_project_dm2/actions/actions.py @@ -0,0 +1,27 @@ +# This files contains your custom actions which can be used to run +# custom Python code. +# +# See this guide on how to implement these action: +# https://rasa.com/docs/rasa/custom-actions + + +# This is a simple example for a custom action which utters "Hello World!" + +# from typing import Any, Text, Dict, List +# +# from rasa_sdk import Action, Tracker +# from rasa_sdk.executor import CollectingDispatcher +# +# +# class ActionHelloWorld(Action): +# +# def name(self) -> Text: +# return "action_hello_world" +# +# def run(self, dispatcher: CollectingDispatcher, +# tracker: Tracker, +# domain: Dict[Text, Any]) -> List[Dict[Text, Any]]: +# +# dispatcher.utter_message(text="Hello World!") +# +# return [] diff --git a/rasa/cli/initial_project_dm2/config.yml b/rasa/cli/initial_project_dm2/config.yml new file mode 100644 index 000000000000..b6638aca4dc7 --- /dev/null +++ b/rasa/cli/initial_project_dm2/config.yml @@ -0,0 +1,13 @@ +recipe: default.v1 +language: en +pipeline: + - name: LLMCommandGenerator + # llm: + # model_name: gpt-4 + +policies: + - name: rasa.core.policies.flow_policy.FlowPolicy +# - name: rasa_plus.ml.DocsearchPolicy +# - name: RulePolicy + +assistant_id: 20230405-114328-tranquil-mustard diff --git a/rasa/cli/initial_project_dm2/credentials.yml b/rasa/cli/initial_project_dm2/credentials.yml new file mode 100644 index 000000000000..e9f12911e3cf --- /dev/null +++ b/rasa/cli/initial_project_dm2/credentials.yml @@ -0,0 +1,33 @@ +# This file contains the credentials for the voice & chat platforms +# which your bot is using. +# https://rasa.com/docs/rasa/messaging-and-voice-channels + +rest: +# # you don't need to provide anything here - this channel doesn't +# # require any credentials + + +#facebook: +# verify: "" +# secret: "" +# page-access-token: "" + +#slack: +# slack_token: "" +# slack_channel: "" +# slack_signing_secret: "" + +#socketio: +# user_message_evt: +# bot_message_evt: +# session_persistence: + +#mattermost: +# url: "https:///api/v4" +# token: "" +# webhook_url: "" + +# This entry is needed if you are using Rasa Enterprise. The entry represents credentials +# for the Rasa Enterprise "channel", i.e. Talk to your bot and Share with guest testers. +rasa: + url: "http://localhost:5002/api" diff --git a/rasa/cli/initial_project_dm2/data/flows.yml b/rasa/cli/initial_project_dm2/data/flows.yml new file mode 100644 index 000000000000..9dd3a1ea6f65 --- /dev/null +++ b/rasa/cli/initial_project_dm2/data/flows.yml @@ -0,0 +1,44 @@ +flows: + say_goodbye: + description: say goodbye to the user + steps: + - id: "0" + action: utter_goodbye + bot_challenge: + description: explain to the user that they are talking to a bot, if they ask + steps: + - id: "0" + action: utter_iamabot + greet: + description: greet the user and ask how they are doing. cheer them up if needed. + steps: + - id: "0" + question: good_mood + description: "can be true or false" + next: + - if: good_mood + then: "doing_great" + - else: "cheer_up" + - id: "doing_great" + action: utter_happy + - id: "cheer_up" + action: utter_cheer_up + next: "did_that_help" + - id: "did_that_help" + action: utter_did_that_help + recommend_restaurant: + description: This flow recommends a restaurant + steps: + - id: "0" + question: cuisine + skip_if_filled: true + next: "1" + - id: "1" + question: price_range + next: "2" + - id: "2" + question: part_of_town + next: "3" + - id: "3" + action: search_restaurants + diff --git a/rasa/cli/initial_project_dm2/data/nlu.yml b/rasa/cli/initial_project_dm2/data/nlu.yml new file mode 100644 index 000000000000..edbbf36d42ad --- /dev/null +++ b/rasa/cli/initial_project_dm2/data/nlu.yml @@ -0,0 +1,11 @@ +version: "3.1" + +nlu: + - intent: affirm + examples: | + - yes + - yup + - intent: deny + examples: | + - no + - nope \ No newline at end of file diff --git a/rasa/cli/initial_project_dm2/domain.yml b/rasa/cli/initial_project_dm2/domain.yml new file mode 100644 index 000000000000..f75cfd45cdd9 --- /dev/null +++ b/rasa/cli/initial_project_dm2/domain.yml @@ -0,0 +1,63 @@ +version: "3.1" + +slots: + good_mood: + type: bool + mappings: + - type: custom + cuisine: + type: text + mappings: + - type: custom + price_range: + type: text + mappings: + - type: custom + part_of_town: + type: text + mappings: + - type: custom + + +responses: + utter_greet: + - text: "Hey!" + + utter_ask_good_mood: + - text: "How are you?" + + utter_ask_cuisine: + - text: "What kind of food are you looking for?" + + utter_ask_price_range: + - text: "in what price range?" + + utter_ask_part_of_town: + - text: "and in which part of town?" + + utter_cheer_up: + - text: "Here is something to cheer you up:" + image: "https://i.imgur.com/nGF1K8f.jpg" + + utter_did_that_help: + - text: "Did that help you?" + + utter_flow_continue_interrupted: + - text: Let's continue with the previous topic {flow_name}. + metadata: {allow_variation: True} + + utter_happy: + - text: "Great, carry on!" + + utter_goodbye: + - text: "Bye" + + utter_iamabot: + - text: "I am a bot, powered by Rasa." + +actions: + - search_restaurants + +session_config: + session_expiration_time: 60 + carry_over_slots_to_new_session: true diff --git a/rasa/cli/initial_project_dm2/endpoints.yml b/rasa/cli/initial_project_dm2/endpoints.yml new file mode 100644 index 000000000000..5f65275b8802 --- /dev/null +++ b/rasa/cli/initial_project_dm2/endpoints.yml @@ -0,0 +1,42 @@ +# This file contains the different endpoints your bot can use. + +# Server where the models are pulled from. +# https://rasa.com/docs/rasa/model-storage#fetching-models-from-a-server + +#models: +# url: http://my-server.com/models/default_core@latest +# wait_time_between_pulls: 10 # [optional](default: 100) + +# Server which runs your custom actions. +# https://rasa.com/docs/rasa/custom-actions + +action_endpoint: + url: "http://localhost:5055/webhook" + +# Tracker store which is used to store the conversations. +# By default the conversations are stored in memory. +# https://rasa.com/docs/rasa/tracker-stores + +#tracker_store: +# type: redis +# url: +# port: +# db: +# password: +# use_ssl: + +#tracker_store: +# type: mongod +# url: +# db: +# username: +# password: + +# Event broker which all conversation events should be streamed to. +# https://rasa.com/docs/rasa/event-brokers + +#event_broker: +# url: localhost +# username: username +# password: password +# queue: queue diff --git a/rasa/cli/initial_project_dm2/tests/test_stories.yml b/rasa/cli/initial_project_dm2/tests/test_stories.yml new file mode 100644 index 000000000000..d46e39b3ea06 --- /dev/null +++ b/rasa/cli/initial_project_dm2/tests/test_stories.yml @@ -0,0 +1,91 @@ +#### This file contains tests to evaluate that your bot behaves as expected. +#### If you want to learn more, please see the docs: https://rasa.com/docs/rasa/testing-your-assistant + +stories: +- story: happy path 1 + steps: + - user: | + hello there! + intent: greet + - action: utter_greet + - user: | + amazing + intent: mood_great + - action: utter_happy + +- story: happy path 2 + steps: + - user: | + hello there! + intent: greet + - action: utter_greet + - user: | + amazing + intent: mood_great + - action: utter_happy + - user: | + bye-bye! + intent: goodbye + - action: utter_goodbye + +- story: sad path 1 + steps: + - user: | + hello + intent: greet + - action: utter_greet + - user: | + not good + intent: mood_unhappy + - action: utter_cheer_up + - action: utter_did_that_help + - user: | + yes + intent: affirm + - action: utter_happy + +- story: sad path 2 + steps: + - user: | + hello + intent: greet + - action: utter_greet + - user: | + not good + intent: mood_unhappy + - action: utter_cheer_up + - action: utter_did_that_help + - user: | + not really + intent: deny + - action: utter_goodbye + +- story: sad path 3 + steps: + - user: | + hi + intent: greet + - action: utter_greet + - user: | + very terrible + intent: mood_unhappy + - action: utter_cheer_up + - action: utter_did_that_help + - user: | + no + intent: deny + - action: utter_goodbye + +- story: say goodbye + steps: + - user: | + bye-bye! + intent: goodbye + - action: utter_goodbye + +- story: bot challenge + steps: + - user: | + are you a bot? + intent: bot_challenge + - action: utter_iamabot From 88eaef111afcad16594cb72ca22bc30635bb7962 Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 11:09:05 +0100 Subject: [PATCH 26/33] restored original initial_proejct --- rasa/cli/initial_project/config.yml | 47 +++++++++-- rasa/cli/initial_project/data/nlu.yml | 96 +++++++++++++++++++++-- rasa/cli/initial_project/data/rules.yml | 13 +++ rasa/cli/initial_project/data/stories.yml | 30 +++++++ rasa/cli/initial_project/domain.yml | 9 +++ 5 files changed, 179 insertions(+), 16 deletions(-) create mode 100644 rasa/cli/initial_project/data/rules.yml create mode 100644 rasa/cli/initial_project/data/stories.yml diff --git a/rasa/cli/initial_project/config.yml b/rasa/cli/initial_project/config.yml index b6638aca4dc7..eb54e60a86ce 100644 --- a/rasa/cli/initial_project/config.yml +++ b/rasa/cli/initial_project/config.yml @@ -1,13 +1,44 @@ +# The config recipe. +# https://rasa.com/docs/rasa/model-configuration/ recipe: default.v1 + +# The assistant project unique identifier +# This default value must be replaced with a unique assistant name within your deployment +assistant_id: placeholder_default + +# Configuration for Rasa NLU. +# https://rasa.com/docs/rasa/nlu/components/ language: en + pipeline: - - name: LLMCommandGenerator - # llm: - # model_name: gpt-4 +# # No configuration for the NLU pipeline was provided. The following default pipeline was used to train your model. +# # If you'd like to customize it, uncomment and adjust the pipeline. +# # See https://rasa.com/docs/rasa/tuning-your-model for more information. +# - name: WhitespaceTokenizer +# - name: RegexFeaturizer +# - name: LexicalSyntacticFeaturizer +# - name: CountVectorsFeaturizer +# - name: CountVectorsFeaturizer +# analyzer: char_wb +# min_ngram: 1 +# max_ngram: 4 +# - name: DIETClassifier +# epochs: 100 +# - name: EntitySynonymMapper +# - name: ResponseSelector +# epochs: 100 +# - name: FallbackClassifier +# threshold: 0.3 +# ambiguity_threshold: 0.1 +# Configuration for Rasa Core. +# https://rasa.com/docs/rasa/core/policies/ policies: - - name: rasa.core.policies.flow_policy.FlowPolicy -# - name: rasa_plus.ml.DocsearchPolicy -# - name: RulePolicy - -assistant_id: 20230405-114328-tranquil-mustard +# # No configuration for policies was provided. The following default policies were used to train your model. +# # If you'd like to customize them, uncomment and adjust the policies. +# # See https://rasa.com/docs/rasa/policies for more information. +# - name: MemoizationPolicy +# - name: TEDPolicy +# max_history: 5 +# epochs: 100 +# - name: RulePolicy diff --git a/rasa/cli/initial_project/data/nlu.yml b/rasa/cli/initial_project/data/nlu.yml index edbbf36d42ad..2f6c3f8c7d3e 100644 --- a/rasa/cli/initial_project/data/nlu.yml +++ b/rasa/cli/initial_project/data/nlu.yml @@ -1,11 +1,91 @@ version: "3.1" nlu: - - intent: affirm - examples: | - - yes - - yup - - intent: deny - examples: | - - no - - nope \ No newline at end of file +- intent: greet + examples: | + - hey + - hello + - hi + - hello there + - good morning + - good evening + - moin + - hey there + - let's go + - hey dude + - goodmorning + - goodevening + - good afternoon + +- intent: goodbye + examples: | + - cu + - good by + - cee you later + - good night + - bye + - goodbye + - have a nice day + - see you around + - bye bye + - see you later + +- intent: affirm + examples: | + - yes + - y + - indeed + - of course + - that sounds good + - correct + +- intent: deny + examples: | + - no + - n + - never + - I don't think so + - don't like that + - no way + - not really + +- intent: mood_great + examples: | + - perfect + - great + - amazing + - feeling like a king + - wonderful + - I am feeling very good + - I am great + - I am amazing + - I am going to save the world + - super stoked + - extremely good + - so so perfect + - so good + - so perfect + +- intent: mood_unhappy + examples: | + - my day was horrible + - I am sad + - I don't feel very well + - I am disappointed + - super sad + - I'm so sad + - sad + - very sad + - unhappy + - not good + - not very good + - extremly sad + - so saad + - so sad + +- intent: bot_challenge + examples: | + - are you a bot? + - are you a human? + - am I talking to a bot? + - am I talking to a human? diff --git a/rasa/cli/initial_project/data/rules.yml b/rasa/cli/initial_project/data/rules.yml new file mode 100644 index 000000000000..a9987ee2a3fb --- /dev/null +++ b/rasa/cli/initial_project/data/rules.yml @@ -0,0 +1,13 @@ +version: "3.1" + +rules: + +- rule: Say goodbye anytime the user says goodbye + steps: + - intent: goodbye + - action: utter_goodbye + +- rule: Say 'I am a bot' anytime the user challenges + steps: + - intent: bot_challenge + - action: utter_iamabot diff --git a/rasa/cli/initial_project/data/stories.yml b/rasa/cli/initial_project/data/stories.yml new file mode 100644 index 000000000000..6ff78ee20864 --- /dev/null +++ b/rasa/cli/initial_project/data/stories.yml @@ -0,0 +1,30 @@ +version: "3.1" + +stories: + +- story: happy path + steps: + - intent: greet + - action: utter_greet + - intent: mood_great + - action: utter_happy + +- story: sad path 1 + steps: + - intent: greet + - action: utter_greet + - intent: mood_unhappy + - action: utter_cheer_up + - action: utter_did_that_help + - intent: affirm + - action: utter_happy + +- story: sad path 2 + steps: + - intent: greet + - action: utter_greet + - intent: mood_unhappy + - action: utter_cheer_up + - action: utter_did_that_help + - intent: deny + - action: utter_goodbye diff --git a/rasa/cli/initial_project/domain.yml b/rasa/cli/initial_project/domain.yml index 762061952cb3..2d24633677c7 100644 --- a/rasa/cli/initial_project/domain.yml +++ b/rasa/cli/initial_project/domain.yml @@ -1,5 +1,14 @@ version: "3.1" +intents: + - greet + - goodbye + - affirm + - deny + - mood_great + - mood_unhappy + - bot_challenge + responses: utter_greet: - text: "Hey! How are you?" From 4a310144c8f708a7dcdf60d2918db5c62d40ccde Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 11:25:55 +0100 Subject: [PATCH 27/33] remove flows file from initial project --- rasa/cli/initial_project/data/flows.yml | 29 ------------------------- 1 file changed, 29 deletions(-) delete mode 100644 rasa/cli/initial_project/data/flows.yml diff --git a/rasa/cli/initial_project/data/flows.yml b/rasa/cli/initial_project/data/flows.yml deleted file mode 100644 index e9c0551592a9..000000000000 --- a/rasa/cli/initial_project/data/flows.yml +++ /dev/null @@ -1,29 +0,0 @@ -flows: - say_goodbye: - description: say goodbye to the user - steps: - - id: "0" - action: utter_goodbye - bot_challenge: - description: explain to the user that they are talking to a bot, if they ask - steps: - - id: "0" - action: utter_iamabot - greet: - description: greet the user and ask how they are doing. - steps: - - id: "0" - action: utter_greet - cheer_up: - description: if the user is doing poorly, cheer them up with a cute photo - steps: - - id: "0" - action: utter_cheer_up - next: "1" - - id: "1" - action: utter_did_that_help - happy: - description: tell the user you are glad they are doing well - steps: - - id: "0" - action: utter_happy \ No newline at end of file From eb8035e2c59b822f9b14b912a1e204a80bd3d551 Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 11:27:49 +0100 Subject: [PATCH 28/33] mention dm2 flag in docs --- docs/docs/start-here.mdx | 2 +- rasa/cli/scaffold.py | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index 038870bc8250..5023e6456f6d 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -18,7 +18,7 @@ controllability of intent-based approaches. Once you have installed Rasa, you can run the `init` command to create a starter project: ```bash -rasa init +rasa init --dm2 ``` Run the `train` command at any time to build an assistant from the current state of your project: diff --git a/rasa/cli/scaffold.py b/rasa/cli/scaffold.py index b5f0f1e50f56..627c81abd62f 100644 --- a/rasa/cli/scaffold.py +++ b/rasa/cli/scaffold.py @@ -42,7 +42,11 @@ def add_subparser( default=None, help="Directory where your project should be initialized.", ) - + scaffold_parser.add_argument( + "--dm2", + action="store_true", + help="Temporary. Whether to create a DM2 project or a classic one", + ) scaffold_parser.set_defaults(func=run) @@ -127,21 +131,22 @@ def print_run_or_instructions(args: argparse.Namespace) -> None: def init_project(args: argparse.Namespace, path: Text) -> None: """Inits project.""" os.chdir(path) - create_initial_project(".") + create_initial_project(".", args.dm2) print(f"Created project directory at '{os.getcwd()}'.") print_train_or_instructions(args) -def create_initial_project(path: Text) -> None: +def create_initial_project(path: Text, is_dm2: bool=False) -> None: """Creates directory structure and templates for initial project.""" from distutils.dir_util import copy_tree - copy_tree(scaffold_path(), path) + copy_tree(scaffold_path(is_dm2), path) -def scaffold_path() -> Text: +def scaffold_path(is_dm2: bool=False) -> Text: import pkg_resources - + if is_dm2: + return pkg_resources.resource_filename(__name__, "initial_project_dm2") return pkg_resources.resource_filename(__name__, "initial_project") From 19a119035081e229a9c5fb8042dfe57a4d380469 Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 16:43:49 +0100 Subject: [PATCH 29/33] some docs updates --- docs/docs/start-here.mdx | 7 +++---- rasa/cli/initial_project_dm2/data/flows.yml | 6 ++++-- rasa/cli/initial_project_dm2/domain.yml | 11 ++++++----- .../e2e_tests/complete_request.yml | 5 +++++ rasa/cli/initial_project_dm2/e2e_tests/happy.yml | 11 +++++++++++ 5 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 rasa/cli/initial_project_dm2/e2e_tests/complete_request.yml create mode 100644 rasa/cli/initial_project_dm2/e2e_tests/happy.yml diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index 5023e6456f6d..adfed5ccf9f0 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -15,7 +15,7 @@ controllability of intent-based approaches. ### Command Line Interface Basics -Once you have installed Rasa, you can run the `init` command to create a starter project: +Once you have instalgled Rasa, you can run the `init` command to create a starter project: ```bash rasa init --dm2 @@ -62,7 +62,7 @@ for their preferred cuisine, city, and price range. To try it out, start a conversation using `rasa shell`, and say something like "I'm looking for a restaurant". Out of the box, this assistant can already handle a variety of conversations. The first is what we call the "happy path", -where the user provides all the important when it's requested. +where the user always provides the information the assistant requests. But if users change their mind, answer indirectly, or interject with questions, this assistant can handle those cases as well. Try out some of these conversations yourself to get a feel for things. If you want your assistant to sound a bit more natural, you can activate [contextual rephrasing](./llms/llm-nlg.mdx) of responses. @@ -184,8 +184,7 @@ The *conversation handling* approach requires much less work to set up, since yo intents and entities and slot mappings. It is also more powerful because it allows us to [break free from intents](https://rasa.com/blog/its-about-time-we-get-rid-of-intents/). -For example, if the user's response requires context to be understood correctly and is a challenge for -intent-based systems: +For example, intent-based approaches struggle when context is required to understand what the user means: Has it been more than 10 business days since you placed your order? diff --git a/rasa/cli/initial_project_dm2/data/flows.yml b/rasa/cli/initial_project_dm2/data/flows.yml index 9dd3a1ea6f65..f7a4f7e6b5f4 100644 --- a/rasa/cli/initial_project_dm2/data/flows.yml +++ b/rasa/cli/initial_project_dm2/data/flows.yml @@ -35,10 +35,12 @@ flows: next: "1" - id: "1" question: price_range + skip_if_filled: true next: "2" - id: "2" - question: part_of_town + question: city + skip_if_filled: true next: "3" - id: "3" - action: search_restaurants + action: utter_recommend_restaurant diff --git a/rasa/cli/initial_project_dm2/domain.yml b/rasa/cli/initial_project_dm2/domain.yml index f75cfd45cdd9..eb308f751812 100644 --- a/rasa/cli/initial_project_dm2/domain.yml +++ b/rasa/cli/initial_project_dm2/domain.yml @@ -13,7 +13,7 @@ slots: type: text mappings: - type: custom - part_of_town: + city: type: text mappings: - type: custom @@ -32,8 +32,11 @@ responses: utter_ask_price_range: - text: "in what price range?" - utter_ask_part_of_town: - - text: "and in which part of town?" + utter_ask_city: + - text: "and in which city?" + + utter_recommend_restaurant: + - text: "Here's a recommendation ..." utter_cheer_up: - text: "Here is something to cheer you up:" @@ -55,8 +58,6 @@ responses: utter_iamabot: - text: "I am a bot, powered by Rasa." -actions: - - search_restaurants session_config: session_expiration_time: 60 diff --git a/rasa/cli/initial_project_dm2/e2e_tests/complete_request.yml b/rasa/cli/initial_project_dm2/e2e_tests/complete_request.yml new file mode 100644 index 000000000000..b0a93f5bfe37 --- /dev/null +++ b/rasa/cli/initial_project_dm2/e2e_tests/complete_request.yml @@ -0,0 +1,5 @@ +test_cases: + - test_case: user corrects recipient in the next message + steps: + - user: I'm looking for a cheap Chinese restaurant in Amsterdam + - utter: utter_recommend_restaurant \ No newline at end of file diff --git a/rasa/cli/initial_project_dm2/e2e_tests/happy.yml b/rasa/cli/initial_project_dm2/e2e_tests/happy.yml new file mode 100644 index 000000000000..2181e9d2bb7d --- /dev/null +++ b/rasa/cli/initial_project_dm2/e2e_tests/happy.yml @@ -0,0 +1,11 @@ +test_cases: + - test_case: user corrects recipient in the next message + steps: + - user: Please recommend a restaurant + - utter: utter_ask_cuisine + - user: Indian food + - utter: utter_ask_price_range + - user: cheap + - utter: utter_ask_city + - user: Berlin + - utter: utter_recommend_restaurant \ No newline at end of file From e4826e5b2f27be353b666418e213fd3d50f50a2a Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 16:44:48 +0100 Subject: [PATCH 30/33] remove check for slotmapping type ENTITY for whether a slot is extractable --- .../command_generator/llm_command_generator.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/rasa/cdu/command_generator/llm_command_generator.py b/rasa/cdu/command_generator/llm_command_generator.py index 4c6673aeb356..229e7c348580 100644 --- a/rasa/cdu/command_generator/llm_command_generator.py +++ b/rasa/cdu/command_generator/llm_command_generator.py @@ -246,15 +246,14 @@ def is_extractable(q: QuestionFlowStep, tracker: DialogueStateTracker) -> bool: return False for mapping in slot.mappings: - if mapping.get(MAPPING_TYPE) == str(SlotMappingType.FROM_ENTITY): - conditions = mapping.get(MAPPING_CONDITIONS, []) - if len(conditions) == 0: - return True - else: - for condition in conditions: - active_loop = condition.get(ACTIVE_LOOP) - if active_loop and active_loop == tracker.active_loop_name: - return True + conditions = mapping.get(MAPPING_CONDITIONS, []) + if len(conditions) == 0: + return True + else: + for condition in conditions: + active_loop = condition.get(ACTIVE_LOOP) + if active_loop and active_loop == tracker.active_loop_name: + return True return False def render_template( From 3248dc7859749f161eed1a8cf3e3d2d426478655 Mon Sep 17 00:00:00 2001 From: Alan Nichol Date: Tue, 25 Jul 2023 17:11:44 +0100 Subject: [PATCH 31/33] Update docs/docs/start-here.mdx Co-authored-by: Maxime Vdb --- docs/docs/start-here.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/start-here.mdx b/docs/docs/start-here.mdx index adfed5ccf9f0..428ffecc02a4 100644 --- a/docs/docs/start-here.mdx +++ b/docs/docs/start-here.mdx @@ -15,7 +15,7 @@ controllability of intent-based approaches. ### Command Line Interface Basics -Once you have instalgled Rasa, you can run the `init` command to create a starter project: +Once you have installed Rasa, you can run the `init` command to create a starter project: ```bash rasa init --dm2 From 59086664a59e10e5d3c113f46749b4908d921017 Mon Sep 17 00:00:00 2001 From: Tom Bocklisch Date: Tue, 25 Jul 2023 21:47:17 +0200 Subject: [PATCH 32/33] formatted --- rasa/cli/scaffold.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rasa/cli/scaffold.py b/rasa/cli/scaffold.py index 627c81abd62f..b6715519b896 100644 --- a/rasa/cli/scaffold.py +++ b/rasa/cli/scaffold.py @@ -136,15 +136,16 @@ def init_project(args: argparse.Namespace, path: Text) -> None: print_train_or_instructions(args) -def create_initial_project(path: Text, is_dm2: bool=False) -> None: +def create_initial_project(path: Text, is_dm2: bool = False) -> None: """Creates directory structure and templates for initial project.""" from distutils.dir_util import copy_tree copy_tree(scaffold_path(is_dm2), path) -def scaffold_path(is_dm2: bool=False) -> Text: +def scaffold_path(is_dm2: bool = False) -> Text: import pkg_resources + if is_dm2: return pkg_resources.resource_filename(__name__, "initial_project_dm2") return pkg_resources.resource_filename(__name__, "initial_project") From a34388a1be6d7cdd7add0dea6b3874ba723d37a1 Mon Sep 17 00:00:00 2001 From: Tom Bocklisch Date: Tue, 25 Jul 2023 21:53:36 +0200 Subject: [PATCH 33/33] fixed remaining issues --- rasa/cdu/command_generator/llm_command_generator.py | 2 -- tests/cli/test_rasa_init.py | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/rasa/cdu/command_generator/llm_command_generator.py b/rasa/cdu/command_generator/llm_command_generator.py index f35a7fd76253..f07b6ed0c205 100644 --- a/rasa/cdu/command_generator/llm_command_generator.py +++ b/rasa/cdu/command_generator/llm_command_generator.py @@ -21,8 +21,6 @@ from rasa.engine.storage.resource import Resource from rasa.engine.storage.storage import ModelStorage from rasa.shared.core.constants import ( - MAPPING_TYPE, - SlotMappingType, MAPPING_CONDITIONS, ACTIVE_LOOP, ) diff --git a/tests/cli/test_rasa_init.py b/tests/cli/test_rasa_init.py index b7f45cb856da..62932d5039e3 100644 --- a/tests/cli/test_rasa_init.py +++ b/tests/cli/test_rasa_init.py @@ -46,7 +46,7 @@ def test_init_help(run: Callable[..., RunResult]): help_text = f"""usage: {RASA_EXE} init [-h] [-v] [-vv] [--quiet] [--logging-config-file LOGGING_CONFIG_FILE] [--no-prompt] - [--init-dir INIT_DIR]""" + [--init-dir INIT_DIR] [--dm2]""" lines = help_text.split("\n") # expected help text lines should appear somewhere in the output