From adb6168c33ec5eb4b38f726ac69b13a0cf09f2a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Mon, 1 Feb 2021 17:44:21 -0300 Subject: [PATCH 01/36] Add docker image in gitlabci --- .gitlab-ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 63dd2ec..9e2cc16 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,7 @@ -image: python:3.7-slim +image: docker:stable + +services: + - docker:dind stages: - style From dfac01599a273a029a039100fe1b44a2c5021d8e Mon Sep 17 00:00:00 2001 From: Martha Date: Tue, 2 Feb 2021 13:33:06 -0300 Subject: [PATCH 02/36] Especify spacy version and change name of packege --- bot/data/nlu.yml | 1 + docker/requirements.Dockerfile | 2 +- docker/requirements.txt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/bot/data/nlu.yml b/bot/data/nlu.yml index d894722..5e1a078 100644 --- a/bot/data/nlu.yml +++ b/bot/data/nlu.yml @@ -24,6 +24,7 @@ nlu: - jamais - discordo - discordar + - não concordo - intent: pass examples: | diff --git a/docker/requirements.Dockerfile b/docker/requirements.Dockerfile index fe9dece..1680377 100644 --- a/docker/requirements.Dockerfile +++ b/docker/requirements.Dockerfile @@ -8,5 +8,5 @@ COPY ./docker/ /tmp RUN pip install --no-cache-dir -r ./tmp/requirements.txt RUN python -c "import nltk; nltk.download('stopwords');" -RUN python -m spacy download pt +RUN python -m spacy download pt_core_news_sm RUN find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf diff --git a/docker/requirements.txt b/docker/requirements.txt index e8f6790..e192b40 100644 --- a/docker/requirements.txt +++ b/docker/requirements.txt @@ -1,5 +1,5 @@ rasa~=2.0.2 # when updating, check the sdk version in the Dockerfile as well! nltk==3.4.5 -spacy +spacy==3.0.0 -r requirements-actions.txt From 9d0731874d432ec744a785b347ef2fdaccb540ad Mon Sep 17 00:00:00 2001 From: Martha Date: Tue, 2 Feb 2021 14:52:38 -0300 Subject: [PATCH 03/36] Fix comunication between action server and bot Co-authored-by: fabiolamfleury --- bot/endpoints.yml | 2 +- docker-compose.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bot/endpoints.yml b/bot/endpoints.yml index d0d3ca6..c29d650 100644 --- a/bot/endpoints.yml +++ b/bot/endpoints.yml @@ -1,2 +1,2 @@ action_endpoint: - url: http://localhost:5055/webhook \ No newline at end of file + url: http://actions:5055/webhook \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index fd18a95..734fc7d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -29,6 +29,7 @@ services: # ================================= Actions ================================= # Rasa middleware used to connect with external APIs. actions: + container_name: actions build: context: . dockerfile: ./docker/actions.Dockerfile From cd51a1ad8678c2fe394f12ec24357be611b3b2bf Mon Sep 17 00:00:00 2001 From: Martha Date: Tue, 2 Feb 2021 14:56:14 -0300 Subject: [PATCH 04/36] Add more example of start intent and response bot Co-authored-by: fabiolamfleury Signed-off-by: Martha --- bot/data/nlu.yml | 7 +++++++ bot/domain.yml | 2 ++ 2 files changed, 9 insertions(+) diff --git a/bot/data/nlu.yml b/bot/data/nlu.yml index 5e1a078..f7700d1 100644 --- a/bot/data/nlu.yml +++ b/bot/data/nlu.yml @@ -4,6 +4,13 @@ nlu: - intent: start examples: | - começar a conversar + - oi + - olá + - hey + - Bom dia + - Boa tarde + - Boa noite + - Oi, tudo bem? - intent: agree examples: | diff --git a/bot/domain.yml b/bot/domain.yml index c83984b..e50fe3d 100644 --- a/bot/domain.yml +++ b/bot/domain.yml @@ -20,6 +20,8 @@ responses: payload: "/disagree" - title: "Pular" payload: "/pass" + utter_vote_received: + - text: "Voto computado!" actions: - action_random_comment From 4741cd40b23a2d88f187f6d1be6e7557c0e4ccc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Tue, 2 Feb 2021 15:48:16 -0300 Subject: [PATCH 05/36] Add vote form and slots MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: marthadntas Signed-off-by: Fabíola Fleury --- bot/config.yml | 5 ++++- bot/data/rules.yml | 5 +++++ bot/domain.yml | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/bot/config.yml b/bot/config.yml index 1b472d7..97bcbc1 100644 --- a/bot/config.yml +++ b/bot/config.yml @@ -11,4 +11,7 @@ pipeline: - name: DIETClassifier epochs: 55 - name: EntitySynonymMapper - - name: ResponseSelector \ No newline at end of file + - name: ResponseSelector + +policies: + - name: RulePolicy \ No newline at end of file diff --git a/bot/data/rules.yml b/bot/data/rules.yml index 94483ed..6bcda3f 100644 --- a/bot/data/rules.yml +++ b/bot/data/rules.yml @@ -1,3 +1,8 @@ version: "2.0" rules: +- rule: Activate form + steps: + - intent: start + - action: vote_form + - active_loop: vote_form \ No newline at end of file diff --git a/bot/domain.yml b/bot/domain.yml index e50fe3d..1657b84 100644 --- a/bot/domain.yml +++ b/bot/domain.yml @@ -6,6 +6,18 @@ intents: - pass - start +slots: + conversation_id: + type: float + vote: + type: text + number_comments: + type: float + number_voted_comments: + type: float + current_comment_id: + type: float + responses: utter_start: - text: "Olá, gostaria de participar?" @@ -27,6 +39,27 @@ actions: - action_random_comment - action_send_vote +forms: + vote_form: + conversation_id: + - type: from_entity + entity: float + vote: + - type: categorical + values: + - agree + - disagree + - pass + number_comments: + - type: from_entity + entity: float + number_voted_comments: + - type: from_entity + entity: float + current_comment_id: + - type: from_entity + entity: float + session_config: session_expiration_time: 60 carry_over_slots_to_new_session: true From 5707b5e7630a515dce2c9b387ce59cb003b122b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Mon, 1 Feb 2021 17:44:21 -0300 Subject: [PATCH 06/36] Add docker image in gitlabci --- .gitlab-ci.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 63dd2ec..97cd0a7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,20 +1,27 @@ -image: python:3.7-slim +image: docker:stable + +services: + - docker:dind stages: - style - test style: - stage: test + image: python:3.7-alpine before_script: + - apk add musl-dev gcc - pip install black + stage: test script: - black --check . test: before_script: - - apt update && apt install -y gcc make + - apk add gcc make + - apk add python python-dev py-pip build-base + - pip install docker-compose - make first-run - make train stage: test From 39ad69a1cfc26ef340478bc9687f7829596c52d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Wed, 3 Feb 2021 10:57:22 -0300 Subject: [PATCH 07/36] Add docker-compose installation to gitlab ci --- .gitlab-ci.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 97cd0a7..9942460 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -19,8 +19,12 @@ style: test: before_script: - - apk add gcc make - - apk add python python-dev py-pip build-base + - docker info + - apk update + - apk upgrade + - apk add curl jq python3 python3-dev build-base libffi-dev libressl-dev gettext + - curl -O https://bootstrap.pypa.io/get-pip.py + - python3 get-pip.py - pip install docker-compose - make first-run - make train From 419f3b5764056a82a4ff89fe552c64ff3c1c49e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Wed, 3 Feb 2021 10:57:22 -0300 Subject: [PATCH 08/36] Add docker-compose installation to gitlab ci --- .gitlab-ci.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 97cd0a7..b2db4d7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -19,10 +19,14 @@ style: test: before_script: - - apk add gcc make - - apk add python python-dev py-pip build-base + - docker info + - apk update + - apk upgrade + - apk add curl jq python3 python3-dev build-base libffi-dev libressl-dev gettext + - curl -O https://bootstrap.pypa.io/get-pip.py + - python3 get-pip.py - pip install docker-compose - - make first-run + - make build - make train stage: test script: From 4009b4a8ae9767d2f52a72c7c542ad19cb75a48e Mon Sep 17 00:00:00 2001 From: Martha Date: Tue, 2 Feb 2021 13:33:06 -0300 Subject: [PATCH 09/36] Especify spacy version and change name of packege --- bot/data/nlu.yml | 1 + docker/requirements.Dockerfile | 2 +- docker/requirements.txt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/bot/data/nlu.yml b/bot/data/nlu.yml index d894722..5e1a078 100644 --- a/bot/data/nlu.yml +++ b/bot/data/nlu.yml @@ -24,6 +24,7 @@ nlu: - jamais - discordo - discordar + - não concordo - intent: pass examples: | diff --git a/docker/requirements.Dockerfile b/docker/requirements.Dockerfile index fe9dece..1680377 100644 --- a/docker/requirements.Dockerfile +++ b/docker/requirements.Dockerfile @@ -8,5 +8,5 @@ COPY ./docker/ /tmp RUN pip install --no-cache-dir -r ./tmp/requirements.txt RUN python -c "import nltk; nltk.download('stopwords');" -RUN python -m spacy download pt +RUN python -m spacy download pt_core_news_sm RUN find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf diff --git a/docker/requirements.txt b/docker/requirements.txt index e8f6790..e192b40 100644 --- a/docker/requirements.txt +++ b/docker/requirements.txt @@ -1,5 +1,5 @@ rasa~=2.0.2 # when updating, check the sdk version in the Dockerfile as well! nltk==3.4.5 -spacy +spacy==3.0.0 -r requirements-actions.txt From 68d85aeed0ebf76bc04bac85e1add217cac51490 Mon Sep 17 00:00:00 2001 From: Martha Date: Tue, 2 Feb 2021 14:52:38 -0300 Subject: [PATCH 10/36] Fix comunication between action server and bot Co-authored-by: fabiolamfleury --- bot/endpoints.yml | 2 +- docker-compose.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bot/endpoints.yml b/bot/endpoints.yml index d0d3ca6..c29d650 100644 --- a/bot/endpoints.yml +++ b/bot/endpoints.yml @@ -1,2 +1,2 @@ action_endpoint: - url: http://localhost:5055/webhook \ No newline at end of file + url: http://actions:5055/webhook \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index fd18a95..734fc7d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -29,6 +29,7 @@ services: # ================================= Actions ================================= # Rasa middleware used to connect with external APIs. actions: + container_name: actions build: context: . dockerfile: ./docker/actions.Dockerfile From 3c0a0c85ea6134921d9f9f234e8ccdf857387ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Wed, 3 Feb 2021 12:01:28 -0300 Subject: [PATCH 11/36] Update file using black formatter --- bot/actions/actions.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/bot/actions/actions.py b/bot/actions/actions.py index 7f82c1e..f8c041d 100644 --- a/bot/actions/actions.py +++ b/bot/actions/actions.py @@ -14,22 +14,23 @@ # class ActionRandomComment(Action): def name(self): - return 'action_random_comment' + return "action_random_comment" def run(self, dispatcher, tracker, domain): # TODO: Add code to get comment from EJ server - comment = 'Comment text here' + comment = "Comment text here" dispatcher.utter_message(comment) dispatcher.utter_message(template="utter_vote") return [] + class ActionSendVote(Action): def name(self): - return 'action_send_vote' + return "action_send_vote" def run(self, dispatcher, tracker, domain): # TODO: Add code to send request to EJ with vote value - vote = tracker.latest_message['intent'].get('name') + vote = tracker.latest_message["intent"].get("name") dispatcher.utter_message(vote) dispatcher.utter_message(template="utter_vote_received") - return [] \ No newline at end of file + return [] From a09b80bfc3c7b4776507a10e16765e7557f1abb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Thu, 4 Feb 2021 14:34:56 -0300 Subject: [PATCH 12/36] Update ej voting flow in bot --- bot/actions/actions.py | 19 +++++++++++++++++++ bot/data/nlu.yml | 20 ++++++++++++++++++++ bot/data/rules.yml | 11 +++++++---- bot/data/stories.yml | 14 +++++++++++++- bot/domain.yml | 26 ++++++++------------------ 5 files changed, 67 insertions(+), 23 deletions(-) diff --git a/bot/actions/actions.py b/bot/actions/actions.py index 7f82c1e..81988b5 100644 --- a/bot/actions/actions.py +++ b/bot/actions/actions.py @@ -9,16 +9,33 @@ # from rasa_sdk import Action, Tracker from rasa_sdk.executor import CollectingDispatcher +from rasa_sdk.events import SlotSet # # +class ActionSetConversationId(Action): + def name(self): + return 'action_set_conversation_id' + + def run(self, dispatcher, tracker, domain): + # TODO: get values from EJ server + conversation_id = 1 + number_comments = 10 + number_voted_comments = 1 + SlotSet("conversation_id", conversation_id) + SlotSet("number_comments", number_comments) + SlotSet("number_voted_comments", number_voted_comments) + class ActionRandomComment(Action): def name(self): return 'action_random_comment' def run(self, dispatcher, tracker, domain): # TODO: Add code to get comment from EJ server + # current_conversation = tracker.get_slot("conversation_id") comment = 'Comment text here' + comment_id = 53 + SlotSet("current_comment_id", comment_id) dispatcher.utter_message(comment) dispatcher.utter_message(template="utter_vote") return [] @@ -31,5 +48,7 @@ def run(self, dispatcher, tracker, domain): # TODO: Add code to send request to EJ with vote value vote = tracker.latest_message['intent'].get('name') dispatcher.utter_message(vote) + voted_comments = tracker.get_slot("number_voted_comments") + SlotSet("number_voted_comments", voted_comments + 1 ) dispatcher.utter_message(template="utter_vote_received") return [] \ No newline at end of file diff --git a/bot/data/nlu.yml b/bot/data/nlu.yml index f7700d1..d7c1232 100644 --- a/bot/data/nlu.yml +++ b/bot/data/nlu.yml @@ -38,3 +38,23 @@ nlu: - não sei - pular - pulo + +- intent: out_of_context + examples: | + - 4 + 2 = ? + - Queria pedir uma pizza + - Como tá o tempo? + - Como vc tá? + - você é um robô? + - Fala alguma coisa + - asdfgasd + - chega + - para + - parar + - pausa + - tempo + - stop + +- intent: votar + examples: | + - quero votar \ No newline at end of file diff --git a/bot/data/rules.yml b/bot/data/rules.yml index 6bcda3f..b042fca 100644 --- a/bot/data/rules.yml +++ b/bot/data/rules.yml @@ -1,8 +1,11 @@ version: "2.0" rules: -- rule: Activate form +- rule: Activate next vote form whenever a vote is computed steps: - - intent: start - - action: vote_form - - active_loop: vote_form \ No newline at end of file + - action: action_send_vote + - slot_was_set: + - vote: null + # - action: action_random_comment + # - action: vote_form + # - active_loop: vote_form diff --git a/bot/data/stories.yml b/bot/data/stories.yml index a62725e..02f5c15 100644 --- a/bot/data/stories.yml +++ b/bot/data/stories.yml @@ -22,7 +22,19 @@ stories: - action: action_send_vote - action: utter_goodbye -- story: sad path + +- story: happy path with out of context message 2 + steps: + - intent: start + - action: utter_start + - intent: agree + - action: action_random_comment + - intent: disagree + - action: action_send_vote + - intent: out_of_context + - action: utter_out_of_context + +- story: User don't want to participate sad path steps: - intent: start - action: utter_start diff --git a/bot/domain.yml b/bot/domain.yml index 1657b84..6576767 100644 --- a/bot/domain.yml +++ b/bot/domain.yml @@ -5,7 +5,8 @@ intents: - disagree - pass - start - + - out_of_context + - votar slots: conversation_id: type: float @@ -22,7 +23,7 @@ responses: utter_start: - text: "Olá, gostaria de participar?" utter_goodbye: - - text: "Sua participação foi computada! Até logo" + - text: "Agradeço pela participação! Até logo" utter_vote: - text: "Voto" buttons: @@ -34,31 +35,20 @@ responses: payload: "/pass" utter_vote_received: - text: "Voto computado!" - + utter_out_of_context: + - text: "Desculpe, não sei como posso te ajudar com isso." actions: - action_random_comment - action_send_vote forms: vote_form: - conversation_id: - - type: from_entity - entity: float vote: - type: categorical values: - - agree - - disagree - - pass - number_comments: - - type: from_entity - entity: float - number_voted_comments: - - type: from_entity - entity: float - current_comment_id: - - type: from_entity - entity: float + - Concordar + - Discordar + - Pular session_config: session_expiration_time: 60 From 738b909a454d05d2a570159f0970276fb01d43b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Thu, 4 Feb 2021 15:49:45 -0300 Subject: [PATCH 13/36] Add vote form validation and out of context rule --- bot/actions/actions.py | 20 ++++++++++++++++++-- bot/data/nlu.yml | 4 ---- bot/data/rules.yml | 10 +++------- bot/domain.yml | 3 ++- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/bot/actions/actions.py b/bot/actions/actions.py index 81988b5..5acff92 100644 --- a/bot/actions/actions.py +++ b/bot/actions/actions.py @@ -7,7 +7,7 @@ import requests # -from rasa_sdk import Action, Tracker +from rasa_sdk import Action, Tracker, FormValidationAction from rasa_sdk.executor import CollectingDispatcher from rasa_sdk.events import SlotSet @@ -36,6 +36,7 @@ def run(self, dispatcher, tracker, domain): comment = 'Comment text here' comment_id = 53 SlotSet("current_comment_id", comment_id) + SlotSet("loop_comment", True) dispatcher.utter_message(comment) dispatcher.utter_message(template="utter_vote") return [] @@ -51,4 +52,19 @@ def run(self, dispatcher, tracker, domain): voted_comments = tracker.get_slot("number_voted_comments") SlotSet("number_voted_comments", voted_comments + 1 ) dispatcher.utter_message(template="utter_vote_received") - return [] \ No newline at end of file + return [] + +class ValidateVoteForm(FormValidationAction): + def name(self): + return "validate_vote_form" + + def validate_vote(self, slot_value, dispatcher, tracker, domain): + """Validate vote value.""" + dispatcher.utter_message(slot_value) + if False: + # validation succeeded, set the value of the "cuisine" slot to value + return {"vote": slot_value} + else: + # validation failed, set this slot to None so that the + # user will be asked for the slot again + return {"vote": None} \ No newline at end of file diff --git a/bot/data/nlu.yml b/bot/data/nlu.yml index d7c1232..1611e61 100644 --- a/bot/data/nlu.yml +++ b/bot/data/nlu.yml @@ -54,7 +54,3 @@ nlu: - pausa - tempo - stop - -- intent: votar - examples: | - - quero votar \ No newline at end of file diff --git a/bot/data/rules.yml b/bot/data/rules.yml index b042fca..be42792 100644 --- a/bot/data/rules.yml +++ b/bot/data/rules.yml @@ -1,11 +1,7 @@ version: "2.0" rules: -- rule: Activate next vote form whenever a vote is computed +- rule: User ask a out of context question steps: - - action: action_send_vote - - slot_was_set: - - vote: null - # - action: action_random_comment - # - action: vote_form - # - active_loop: vote_form + - intent: out_of_context + - action: utter_out_of_context \ No newline at end of file diff --git a/bot/domain.yml b/bot/domain.yml index 6576767..b890371 100644 --- a/bot/domain.yml +++ b/bot/domain.yml @@ -6,7 +6,7 @@ intents: - pass - start - out_of_context - - votar + slots: conversation_id: type: float @@ -40,6 +40,7 @@ responses: actions: - action_random_comment - action_send_vote + - validate_vote_form forms: vote_form: From 369138a20512b444c59d0c218a03cd22a21e3e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Thu, 4 Feb 2021 18:49:15 -0300 Subject: [PATCH 14/36] Update config policies for Rules to work --- bot/config.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/bot/config.yml b/bot/config.yml index 97bcbc1..cb7b27c 100644 --- a/bot/config.yml +++ b/bot/config.yml @@ -14,4 +14,15 @@ pipeline: - name: ResponseSelector policies: - - name: RulePolicy \ No newline at end of file + - name: TEDPolicy + max_history: 10 + epochs: 20 + batch_size: + - 32 + - 64 + - max_history: 6 + name: AugmentedMemoizationPolicy + - name: RulePolicy + core_fallback_threshold: 0.3 + core_fallback_action_name: "action_default_fallback" + enable_fallback_prediction: True From 89f5235d2446fc6dd68c6818455a851d0657f7d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Thu, 4 Feb 2021 19:12:14 -0300 Subject: [PATCH 15/36] Update vote form values and utter --- bot/actions/actions.py | 17 ++++++++++------- bot/data/stories.yml | 32 ++++++-------------------------- bot/domain.yml | 26 ++++++++++++++------------ 3 files changed, 30 insertions(+), 45 deletions(-) diff --git a/bot/actions/actions.py b/bot/actions/actions.py index 5acff92..f5093b7 100644 --- a/bot/actions/actions.py +++ b/bot/actions/actions.py @@ -5,12 +5,12 @@ # https://rasa.com/docs/rasa/custom-actions import requests - +from typing import Text, List, Any, Dict # from rasa_sdk import Action, Tracker, FormValidationAction from rasa_sdk.executor import CollectingDispatcher from rasa_sdk.events import SlotSet - +from rasa_sdk.types import DomainDict # # class ActionSetConversationId(Action): @@ -35,10 +35,9 @@ def run(self, dispatcher, tracker, domain): # current_conversation = tracker.get_slot("conversation_id") comment = 'Comment text here' comment_id = 53 + SlotSet("comment_text", comment) SlotSet("current_comment_id", comment_id) SlotSet("loop_comment", True) - dispatcher.utter_message(comment) - dispatcher.utter_message(template="utter_vote") return [] class ActionSendVote(Action): @@ -55,12 +54,16 @@ def run(self, dispatcher, tracker, domain): return [] class ValidateVoteForm(FormValidationAction): - def name(self): + def name (self) -> Text: return "validate_vote_form" - def validate_vote(self, slot_value, dispatcher, tracker, domain): + def validate_vote( self, + slot_value: Any, + dispatcher: CollectingDispatcher, + tracker: Tracker, + domain: DomainDict, + ) -> Dict[Text, Any]: """Validate vote value.""" - dispatcher.utter_message(slot_value) if False: # validation succeeded, set the value of the "cuisine" slot to value return {"vote": slot_value} diff --git a/bot/data/stories.yml b/bot/data/stories.yml index 02f5c15..24d8b04 100644 --- a/bot/data/stories.yml +++ b/bot/data/stories.yml @@ -6,37 +6,17 @@ stories: steps: - intent: start - action: utter_start - - intent: agree - - action: action_random_comment - - intent: agree - - action: action_send_vote - -- story: happy path 2 +- story: User don't want to participate sad path steps: - intent: start - action: utter_start - - intent: agree - - action: action_random_comment - intent: disagree - - action: action_send_vote - action: utter_goodbye - -- story: happy path with out of context message 2 - steps: - - intent: start - - action: utter_start - - intent: agree - - action: action_random_comment - - intent: disagree - - action: action_send_vote - - intent: out_of_context - - action: utter_out_of_context - -- story: User don't want to participate sad path +- story: Activate vote form steps: - - intent: start - - action: utter_start - - intent: disagree - - action: utter_goodbye \ No newline at end of file + - intent: agree + - action: action_random_comment + - action: vote_form + - active_loop: vote_form \ No newline at end of file diff --git a/bot/domain.yml b/bot/domain.yml index b890371..18426ad 100644 --- a/bot/domain.yml +++ b/bot/domain.yml @@ -18,25 +18,27 @@ slots: type: float current_comment_id: type: float + comment_text: + type: text responses: utter_start: - text: "Olá, gostaria de participar?" utter_goodbye: - text: "Agradeço pela participação! Até logo" - utter_vote: - - text: "Voto" - buttons: - - title: "Concordar" - payload: "/agree" - - title: "Discordar" - payload: "/disagree" - - title: "Pular" - payload: "/pass" utter_vote_received: - text: "Voto computado!" utter_out_of_context: - text: "Desculpe, não sei como posso te ajudar com isso." + utter_ask_vote: + - text: "{comment_text}" + buttons: + - title: "Concordar" + payload: "agree" + - title: "Discordar" + payload: "disagree" + - title: "Pular" + payload: "pass" actions: - action_random_comment - action_send_vote @@ -47,9 +49,9 @@ forms: vote: - type: categorical values: - - Concordar - - Discordar - - Pular + - "agree" + - "disagree" + - "pass" session_config: session_expiration_time: 60 From 25320462cd275cd67ea1b834032e05a224f5d83e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Thu, 4 Feb 2021 21:37:45 -0300 Subject: [PATCH 16/36] Add infinite vote loop form --- bot/actions/actions.py | 18 +++++++++--------- bot/config.yml | 6 ++++-- bot/data/stories.yml | 5 ++++- bot/domain.yml | 12 ++++++------ 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/bot/actions/actions.py b/bot/actions/actions.py index f5093b7..c41d316 100644 --- a/bot/actions/actions.py +++ b/bot/actions/actions.py @@ -22,9 +22,9 @@ def run(self, dispatcher, tracker, domain): conversation_id = 1 number_comments = 10 number_voted_comments = 1 - SlotSet("conversation_id", conversation_id) - SlotSet("number_comments", number_comments) - SlotSet("number_voted_comments", number_voted_comments) + return [SlotSet("number_voted_comments", number_voted_comments), + SlotSet("conversation_id", conversation_id), + SlotSet("number_comments", number_comments)] class ActionRandomComment(Action): def name(self): @@ -35,10 +35,10 @@ def run(self, dispatcher, tracker, domain): # current_conversation = tracker.get_slot("conversation_id") comment = 'Comment text here' comment_id = 53 - SlotSet("comment_text", comment) - SlotSet("current_comment_id", comment_id) - SlotSet("loop_comment", True) - return [] + return [SlotSet("comment_text", comment), + SlotSet("current_comment_id", comment_id), + SlotSet("number_voted_comments", 0), + ] class ActionSendVote(Action): def name(self): @@ -49,9 +49,8 @@ def run(self, dispatcher, tracker, domain): vote = tracker.latest_message['intent'].get('name') dispatcher.utter_message(vote) voted_comments = tracker.get_slot("number_voted_comments") - SlotSet("number_voted_comments", voted_comments + 1 ) dispatcher.utter_message(template="utter_vote_received") - return [] + return [SlotSet("number_voted_comments", voted_comments + 1 )] class ValidateVoteForm(FormValidationAction): def name (self) -> Text: @@ -64,6 +63,7 @@ def validate_vote( self, domain: DomainDict, ) -> Dict[Text, Any]: """Validate vote value.""" + dispatcher.utter_message(slot_value) if False: # validation succeeded, set the value of the "cuisine" slot to value return {"vote": slot_value} diff --git a/bot/config.yml b/bot/config.yml index cb7b27c..494c390 100644 --- a/bot/config.yml +++ b/bot/config.yml @@ -24,5 +24,7 @@ policies: name: AugmentedMemoizationPolicy - name: RulePolicy core_fallback_threshold: 0.3 - core_fallback_action_name: "action_default_fallback" - enable_fallback_prediction: True + core_fallback_action_name: action_default_fallback + enable_fallback_prediction: true + restrict_rules: true + check_for_contradictions: true \ No newline at end of file diff --git a/bot/data/stories.yml b/bot/data/stories.yml index 24d8b04..9ceacc7 100644 --- a/bot/data/stories.yml +++ b/bot/data/stories.yml @@ -19,4 +19,7 @@ stories: - intent: agree - action: action_random_comment - action: vote_form - - active_loop: vote_form \ No newline at end of file + - active_loop: vote_form + - active_loop: null + - slot_was_set: + - requested_slot: null \ No newline at end of file diff --git a/bot/domain.yml b/bot/domain.yml index 18426ad..511365c 100644 --- a/bot/domain.yml +++ b/bot/domain.yml @@ -11,7 +11,11 @@ slots: conversation_id: type: float vote: - type: text + type: categorical + values: + - "agree" + - "disagree" + - "pass" number_comments: type: float number_voted_comments: @@ -47,11 +51,7 @@ actions: forms: vote_form: vote: - - type: categorical - values: - - "agree" - - "disagree" - - "pass" + - type: from_text session_config: session_expiration_time: 60 From 500196d5b38d38106e4d405d66261d2ba1a2b5da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Fri, 5 Feb 2021 08:23:19 -0300 Subject: [PATCH 17/36] Add infinite vote form loop --- bot/actions/actions.py | 18 +++++++++--------- bot/config.yml | 6 ++++-- bot/data/stories.yml | 5 ++++- bot/domain.yml | 12 ++++++------ 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/bot/actions/actions.py b/bot/actions/actions.py index f5093b7..c41d316 100644 --- a/bot/actions/actions.py +++ b/bot/actions/actions.py @@ -22,9 +22,9 @@ def run(self, dispatcher, tracker, domain): conversation_id = 1 number_comments = 10 number_voted_comments = 1 - SlotSet("conversation_id", conversation_id) - SlotSet("number_comments", number_comments) - SlotSet("number_voted_comments", number_voted_comments) + return [SlotSet("number_voted_comments", number_voted_comments), + SlotSet("conversation_id", conversation_id), + SlotSet("number_comments", number_comments)] class ActionRandomComment(Action): def name(self): @@ -35,10 +35,10 @@ def run(self, dispatcher, tracker, domain): # current_conversation = tracker.get_slot("conversation_id") comment = 'Comment text here' comment_id = 53 - SlotSet("comment_text", comment) - SlotSet("current_comment_id", comment_id) - SlotSet("loop_comment", True) - return [] + return [SlotSet("comment_text", comment), + SlotSet("current_comment_id", comment_id), + SlotSet("number_voted_comments", 0), + ] class ActionSendVote(Action): def name(self): @@ -49,9 +49,8 @@ def run(self, dispatcher, tracker, domain): vote = tracker.latest_message['intent'].get('name') dispatcher.utter_message(vote) voted_comments = tracker.get_slot("number_voted_comments") - SlotSet("number_voted_comments", voted_comments + 1 ) dispatcher.utter_message(template="utter_vote_received") - return [] + return [SlotSet("number_voted_comments", voted_comments + 1 )] class ValidateVoteForm(FormValidationAction): def name (self) -> Text: @@ -64,6 +63,7 @@ def validate_vote( self, domain: DomainDict, ) -> Dict[Text, Any]: """Validate vote value.""" + dispatcher.utter_message(slot_value) if False: # validation succeeded, set the value of the "cuisine" slot to value return {"vote": slot_value} diff --git a/bot/config.yml b/bot/config.yml index cb7b27c..494c390 100644 --- a/bot/config.yml +++ b/bot/config.yml @@ -24,5 +24,7 @@ policies: name: AugmentedMemoizationPolicy - name: RulePolicy core_fallback_threshold: 0.3 - core_fallback_action_name: "action_default_fallback" - enable_fallback_prediction: True + core_fallback_action_name: action_default_fallback + enable_fallback_prediction: true + restrict_rules: true + check_for_contradictions: true \ No newline at end of file diff --git a/bot/data/stories.yml b/bot/data/stories.yml index 24d8b04..9ceacc7 100644 --- a/bot/data/stories.yml +++ b/bot/data/stories.yml @@ -19,4 +19,7 @@ stories: - intent: agree - action: action_random_comment - action: vote_form - - active_loop: vote_form \ No newline at end of file + - active_loop: vote_form + - active_loop: null + - slot_was_set: + - requested_slot: null \ No newline at end of file diff --git a/bot/domain.yml b/bot/domain.yml index 18426ad..511365c 100644 --- a/bot/domain.yml +++ b/bot/domain.yml @@ -11,7 +11,11 @@ slots: conversation_id: type: float vote: - type: text + type: categorical + values: + - "agree" + - "disagree" + - "pass" number_comments: type: float number_voted_comments: @@ -47,11 +51,7 @@ actions: forms: vote_form: vote: - - type: categorical - values: - - "agree" - - "disagree" - - "pass" + - type: from_text session_config: session_expiration_time: 60 From 7f9308ce47be80de4ca75cea478cc6aead73c9b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Fri, 5 Feb 2021 13:06:11 -0300 Subject: [PATCH 18/36] Update tests directory location and add TODOs in validate vote form --- .gitignore | 1 + bot/actions/actions.py | 67 +++++++++++++------------- bot/data/stories.yml | 2 +- bot/domain.yml | 2 +- {tests => bot/tests}/post.py | 0 bot/tests/test_actions.py | 0 bot/tests/test_stories.yml | 26 +++++++++++ tests/test_stories.yml | 91 ------------------------------------ 8 files changed, 64 insertions(+), 125 deletions(-) rename {tests => bot/tests}/post.py (100%) create mode 100644 bot/tests/test_actions.py create mode 100644 bot/tests/test_stories.yml delete mode 100644 tests/test_stories.yml diff --git a/.gitignore b/.gitignore index 3958fc8..a4e0cb0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ ./bot/models +./bot/results */__pycache__/ .pytest_cache/ *.pyc diff --git a/bot/actions/actions.py b/bot/actions/actions.py index c41d316..edb5dce 100644 --- a/bot/actions/actions.py +++ b/bot/actions/actions.py @@ -4,70 +4,73 @@ # See this guide on how to implement these action: # https://rasa.com/docs/rasa/custom-actions -import requests from typing import Text, List, Any, Dict + # from rasa_sdk import Action, Tracker, FormValidationAction from rasa_sdk.executor import CollectingDispatcher from rasa_sdk.events import SlotSet from rasa_sdk.types import DomainDict + # # -class ActionSetConversationId(Action): +class ActionSetupConversation(Action): def name(self): - return 'action_set_conversation_id' + return "action_setup_conversation" def run(self, dispatcher, tracker, domain): # TODO: get values from EJ server conversation_id = 1 number_comments = 10 number_voted_comments = 1 - return [SlotSet("number_voted_comments", number_voted_comments), - SlotSet("conversation_id", conversation_id), - SlotSet("number_comments", number_comments)] - -class ActionRandomComment(Action): - def name(self): - return 'action_random_comment' - - def run(self, dispatcher, tracker, domain): - # TODO: Add code to get comment from EJ server - # current_conversation = tracker.get_slot("conversation_id") - comment = 'Comment text here' + first_comment = "Comment text here" comment_id = 53 - return [SlotSet("comment_text", comment), - SlotSet("current_comment_id", comment_id), - SlotSet("number_voted_comments", 0), - ] + return [ + SlotSet("number_voted_comments", number_voted_comments), + SlotSet("conversation_id", conversation_id), + SlotSet("number_comments", number_comments), + SlotSet("comment_text", first_comment), + SlotSet("current_comment_id", comment_id), + ] + class ActionSendVote(Action): def name(self): - return 'action_send_vote' + return "action_send_vote" def run(self, dispatcher, tracker, domain): # TODO: Add code to send request to EJ with vote value - vote = tracker.latest_message['intent'].get('name') + vote = tracker.latest_message["intent"].get("name") dispatcher.utter_message(vote) voted_comments = tracker.get_slot("number_voted_comments") dispatcher.utter_message(template="utter_vote_received") - return [SlotSet("number_voted_comments", voted_comments + 1 )] + return [SlotSet("number_voted_comments", voted_comments + 1)] + class ValidateVoteForm(FormValidationAction): - def name (self) -> Text: + def name(self) -> Text: return "validate_vote_form" - def validate_vote( self, + def validate_vote( + self, slot_value: Any, dispatcher: CollectingDispatcher, tracker: Tracker, domain: DomainDict, ) -> Dict[Text, Any]: """Validate vote value.""" - dispatcher.utter_message(slot_value) - if False: - # validation succeeded, set the value of the "cuisine" slot to value - return {"vote": slot_value} - else: - # validation failed, set this slot to None so that the - # user will be asked for the slot again - return {"vote": None} \ No newline at end of file + vote_value = dispatcher.utter_message(slot_value) + if vote_value in ["agree", "disagree", "pass"]: + # TODO: Send vote value to EJ server + voted_comments = tracker.get_slot("number_voted_comments") + 1 + total_comments = tracker.get_slot("number_comments") + + # TODO: Get next random comment + # was_sent = send_vote(vote_value) + # next_comment = get_random_comment() + if voted_comments == total_comments: + # user voted in all comments, can exit loop + return {"vote": slot_value} + + # user still has comments to vote, remain in loop OR did not send expected vote value + return {"vote": None} diff --git a/bot/data/stories.yml b/bot/data/stories.yml index 9ceacc7..198d50f 100644 --- a/bot/data/stories.yml +++ b/bot/data/stories.yml @@ -2,7 +2,7 @@ version: "2.0" stories: -- story: happy path +- story: Greet user steps: - intent: start - action: utter_start diff --git a/bot/domain.yml b/bot/domain.yml index 511365c..e1fa063 100644 --- a/bot/domain.yml +++ b/bot/domain.yml @@ -44,7 +44,7 @@ responses: - title: "Pular" payload: "pass" actions: - - action_random_comment + - action_setup_conversation - action_send_vote - validate_vote_form diff --git a/tests/post.py b/bot/tests/post.py similarity index 100% rename from tests/post.py rename to bot/tests/post.py diff --git a/bot/tests/test_actions.py b/bot/tests/test_actions.py new file mode 100644 index 0000000..e69de29 diff --git a/bot/tests/test_stories.yml b/bot/tests/test_stories.yml new file mode 100644 index 0000000..9e8071a --- /dev/null +++ b/bot/tests/test_stories.yml @@ -0,0 +1,26 @@ +#### 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: Greet user + steps: + - user: | + oi + intent: start + - action: utter_start + - user: | + sim + intent: agree + - action: action_random_comment + - action: vote_form + +- story: User don't want to participate sad path + steps: + - user: | + olá + intent: start + - action: utter_start + - user: | + não + intent: disagree + - action: utter_goodbye \ No newline at end of file diff --git a/tests/test_stories.yml b/tests/test_stories.yml deleted file mode 100644 index d46e39b..0000000 --- a/tests/test_stories.yml +++ /dev/null @@ -1,91 +0,0 @@ -#### 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 ce93cd3560fd9ed39dfc418a6a5f1b13c5f27dfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Fri, 5 Feb 2021 20:01:43 -0300 Subject: [PATCH 19/36] Update vote form logic to better accomodate ej comunication --- bot/actions/actions.py | 58 ++++++++++++++++++++++++++---------------- bot/data/stories.yml | 2 +- bot/domain.yml | 19 +++++++------- 3 files changed, 47 insertions(+), 32 deletions(-) diff --git a/bot/actions/actions.py b/bot/actions/actions.py index edb5dce..f7a5bd8 100644 --- a/bot/actions/actions.py +++ b/bot/actions/actions.py @@ -9,9 +9,8 @@ # from rasa_sdk import Action, Tracker, FormValidationAction from rasa_sdk.executor import CollectingDispatcher -from rasa_sdk.events import SlotSet +from rasa_sdk.events import SlotSet, FollowupAction, EventType from rasa_sdk.types import DomainDict - # # class ActionSetupConversation(Action): @@ -21,7 +20,7 @@ def name(self): def run(self, dispatcher, tracker, domain): # TODO: get values from EJ server conversation_id = 1 - number_comments = 10 + number_comments = 3 number_voted_comments = 1 first_comment = "Comment text here" comment_id = 53 @@ -31,21 +30,34 @@ def run(self, dispatcher, tracker, domain): SlotSet("number_comments", number_comments), SlotSet("comment_text", first_comment), SlotSet("current_comment_id", comment_id), + SlotSet("change_comment", False), + FollowupAction("vote_form") ] +class ActionAskVote(Action): + def name(self) -> Text: + return "action_ask_vote" -class ActionSendVote(Action): - def name(self): - return "action_send_vote" - - def run(self, dispatcher, tracker, domain): - # TODO: Add code to send request to EJ with vote value - vote = tracker.latest_message["intent"].get("name") - dispatcher.utter_message(vote) - voted_comments = tracker.get_slot("number_voted_comments") - dispatcher.utter_message(template="utter_vote_received") - return [SlotSet("number_voted_comments", voted_comments + 1)] + def run( + self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict + ) -> List[EventType]: + buttons = [{"title": "Concordar", "payload": "agree"}, {"title": "Discordar", "payload": "disagree"}, {"title": "Pular", "payload": "pass"},] + if tracker.get_slot("change_comment"): + # TODO: get values from EJ server + # next_comment = get_random_comment() + new_comment = "novo comentário com outro id" + dispatcher.utter_message(text=new_comment, buttons=buttons) + number_voted_comments = tracker.get_slot("number_comments") + 1 + comment_id = 22 + return [ + SlotSet("number_voted_comments", number_voted_comments), + SlotSet("comment_text", new_comment), + SlotSet("current_comment_id", comment_id), + ] + else: + dispatcher.utter_message(text=tracker.get_slot("comment_text"), buttons=buttons) + return [SlotSet("change_comment", True)] class ValidateVoteForm(FormValidationAction): def name(self) -> Text: @@ -59,18 +71,20 @@ def validate_vote( domain: DomainDict, ) -> Dict[Text, Any]: """Validate vote value.""" - vote_value = dispatcher.utter_message(slot_value) - if vote_value in ["agree", "disagree", "pass"]: + if str(slot_value) in ["agree", "disagree", "pass"]: # TODO: Send vote value to EJ server - voted_comments = tracker.get_slot("number_voted_comments") + 1 + voted_comments = tracker.get_slot("number_voted_comments") total_comments = tracker.get_slot("number_comments") - + dispatcher.utter_message(template="utter_vote_received") # TODO: Get next random comment # was_sent = send_vote(vote_value) - # next_comment = get_random_comment() if voted_comments == total_comments: # user voted in all comments, can exit loop - return {"vote": slot_value} - - # user still has comments to vote, remain in loop OR did not send expected vote value + return [{"vote": slot_value}] + else: + # user still has comments to vote, remain in loop + return {"vote": None} + else: + dispatcher.utter_message(template="utter_out_of_context") + # did not send expected vote value return {"vote": None} diff --git a/bot/data/stories.yml b/bot/data/stories.yml index 198d50f..067940b 100644 --- a/bot/data/stories.yml +++ b/bot/data/stories.yml @@ -17,7 +17,7 @@ stories: - story: Activate vote form steps: - intent: agree - - action: action_random_comment + - action: action_setup_conversation - action: vote_form - active_loop: vote_form - active_loop: null diff --git a/bot/domain.yml b/bot/domain.yml index e1fa063..77ef493 100644 --- a/bot/domain.yml +++ b/bot/domain.yml @@ -16,14 +16,22 @@ slots: - "agree" - "disagree" - "pass" + influence_conversation: false number_comments: type: float + influence_conversation: false number_voted_comments: type: float + influence_conversation: false current_comment_id: type: float + influence_conversation: false comment_text: type: text + influence_conversation: false + change_comment: + type: bool + influence_conversation: false responses: utter_start: @@ -35,17 +43,10 @@ responses: utter_out_of_context: - text: "Desculpe, não sei como posso te ajudar com isso." utter_ask_vote: - - text: "{comment_text}" - buttons: - - title: "Concordar" - payload: "agree" - - title: "Discordar" - payload: "disagree" - - title: "Pular" - payload: "pass" + - text: "uai" actions: - action_setup_conversation - - action_send_vote + - action_ask_vote - validate_vote_form forms: From 77b3439b2907dde378a5f445668dd2588809dc58 Mon Sep 17 00:00:00 2001 From: Martha Date: Mon, 8 Feb 2021 21:05:02 -0300 Subject: [PATCH 20/36] create test of action setupConversation and askVote Signed-off-by: Martha Co-authored-by: fabiola --- bot/tests/test_actions.py | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/bot/tests/test_actions.py b/bot/tests/test_actions.py index e69de29..28e6602 100644 --- a/bot/tests/test_actions.py +++ b/bot/tests/test_actions.py @@ -0,0 +1,42 @@ +import pytest + +from typing import Text, List, Any, Dict + +from actions import ActionSetupConversation, ActionAskVote +from rasa_sdk.executor import CollectingDispatcher +from rasa_sdk.events import SlotSet, FollowupAction +from rasa.shared.core.trackers import DialogueStateTracker + + +EMPTY_TRACKER = None + +@pytest.fixture +def dispatcher(): + return CollectingDispatcher() + +@pytest.fixture +def domain(): + return dict() + +def test_action_setup_conversation(dispatcher, domain): + tracker = EMPTY_TRACKER + action = ActionSetupConversation() + events = action.run(dispatcher, tracker, domain) + expected_events = [ + SlotSet("number_voted_comments", 1), + SlotSet("conversation_id", 1), + SlotSet("number_comments", 3), + SlotSet("comment_text", "Comment text here"), + SlotSet("current_comment_id", 53), + SlotSet("change_comment", False), + FollowupAction("vote_form") + ] + assert events == expected_events + +def test_action_ask_vote(dispatcher, domain): + tracker = DialogueStateTracker.from_dict(sender_id="1", events_as_dict=List[Dict["action": 1]], slots=[List[change_comment],False]) + action = ActionAskVote() + events = action.run(dispatcher, tracker, domain) + expected_events = [SlotSet("change_comment", True)] + + assert events == expected_events \ No newline at end of file From 3d41d544576c5a36e678dc4f787acdaa160a087d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Tue, 9 Feb 2021 11:11:09 -0300 Subject: [PATCH 21/36] Add make commands for running actions tests and fix pytest requirements --- Makefile | 4 ++++ bot/Makefile | 3 +++ bot/__init__.py | 0 bot/actions/__init__.py | 1 + bot/tests/test_actions.py | 4 ++-- docker/requirements.Dockerfile | 2 +- 6 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 bot/__init__.py diff --git a/Makefile b/Makefile index 03c1038..d4f91b3 100644 --- a/Makefile +++ b/Makefile @@ -49,12 +49,16 @@ train: test: docker-compose run --rm bot make test +test-actions: + docker-compose run --rm bot make test-actions + run-test-nlu: docker-compose run --rm bot make test-nlu run-test-core: docker-compose run --rm bot make test-core + validate: docker-compose run --rm bot rasa data validate --domain domain.yml --data data/ -vv diff --git a/bot/Makefile b/bot/Makefile index 438741a..2fe579f 100644 --- a/bot/Makefile +++ b/bot/Makefile @@ -20,6 +20,9 @@ train: test: rasa test --out results/ +test-actions: + python -m pytest + test-nlu: rasa test nlu --out results/results-nlu-test diff --git a/bot/__init__.py b/bot/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bot/actions/__init__.py b/bot/actions/__init__.py index e69de29..7ba83fa 100644 --- a/bot/actions/__init__.py +++ b/bot/actions/__init__.py @@ -0,0 +1 @@ +from .actions import ActionSetupConversation, ActionAskVote, FormValidationAction \ No newline at end of file diff --git a/bot/tests/test_actions.py b/bot/tests/test_actions.py index 28e6602..2e91ec4 100644 --- a/bot/tests/test_actions.py +++ b/bot/tests/test_actions.py @@ -5,7 +5,7 @@ from actions import ActionSetupConversation, ActionAskVote from rasa_sdk.executor import CollectingDispatcher from rasa_sdk.events import SlotSet, FollowupAction -from rasa.shared.core.trackers import DialogueStateTracker +from rasa.shared.core.trackers import DialogueStateTracker, AnySlotDict EMPTY_TRACKER = None @@ -34,7 +34,7 @@ def test_action_setup_conversation(dispatcher, domain): assert events == expected_events def test_action_ask_vote(dispatcher, domain): - tracker = DialogueStateTracker.from_dict(sender_id="1", events_as_dict=List[Dict["action": 1]], slots=[List[change_comment],False]) + tracker = DialogueStateTracker(sender_id="1", slots=AnySlotDict()) action = ActionAskVote() events = action.run(dispatcher, tracker, domain) expected_events = [SlotSet("change_comment", True)] diff --git a/docker/requirements.Dockerfile b/docker/requirements.Dockerfile index 1680377..02e52d1 100644 --- a/docker/requirements.Dockerfile +++ b/docker/requirements.Dockerfile @@ -6,7 +6,7 @@ RUN python -m pip install --upgrade pip COPY ./docker/ /tmp -RUN pip install --no-cache-dir -r ./tmp/requirements.txt +RUN pip install --no-cache-dir -r ./tmp/requirements-development.txt RUN python -c "import nltk; nltk.download('stopwords');" RUN python -m spacy download pt_core_news_sm RUN find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf From cf7a198ad75414caacebd7babc04b5a5359f444d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Tue, 9 Feb 2021 11:35:48 -0300 Subject: [PATCH 22/36] Add more test cases and update gitlab ci --- .gitlab-ci.yml | 3 ++- bot/Makefile | 2 +- bot/actions/__init__.py | 2 +- bot/actions/actions.py | 15 ++++++++++--- bot/tests/test_actions.py | 44 +++++++++++++++++++++----------------- bot/tests/test_stories.yml | 8 ++++++- 6 files changed, 47 insertions(+), 27 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b2db4d7..1a1245a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -31,4 +31,5 @@ test: stage: test script: - make run-test-nlu - - make run-test-core \ No newline at end of file + - make run-test-core + - make test-actions \ No newline at end of file diff --git a/bot/Makefile b/bot/Makefile index 2fe579f..1edb1a9 100644 --- a/bot/Makefile +++ b/bot/Makefile @@ -24,7 +24,7 @@ test-actions: python -m pytest test-nlu: - rasa test nlu --out results/results-nlu-test + rasa test nlu --nlu data/nlu.yml --cross-validation test-core: rasa test core --fail-on-prediction-errors --out results/results-core-test diff --git a/bot/actions/__init__.py b/bot/actions/__init__.py index 7ba83fa..a29afc7 100644 --- a/bot/actions/__init__.py +++ b/bot/actions/__init__.py @@ -1 +1 @@ -from .actions import ActionSetupConversation, ActionAskVote, FormValidationAction \ No newline at end of file +from .actions import ActionSetupConversation, ActionAskVote, FormValidationAction diff --git a/bot/actions/actions.py b/bot/actions/actions.py index f7a5bd8..a6412cc 100644 --- a/bot/actions/actions.py +++ b/bot/actions/actions.py @@ -11,6 +11,7 @@ from rasa_sdk.executor import CollectingDispatcher from rasa_sdk.events import SlotSet, FollowupAction, EventType from rasa_sdk.types import DomainDict + # # class ActionSetupConversation(Action): @@ -31,9 +32,10 @@ def run(self, dispatcher, tracker, domain): SlotSet("comment_text", first_comment), SlotSet("current_comment_id", comment_id), SlotSet("change_comment", False), - FollowupAction("vote_form") + FollowupAction("vote_form"), ] + class ActionAskVote(Action): def name(self) -> Text: return "action_ask_vote" @@ -41,7 +43,11 @@ def name(self) -> Text: def run( self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict ) -> List[EventType]: - buttons = [{"title": "Concordar", "payload": "agree"}, {"title": "Discordar", "payload": "disagree"}, {"title": "Pular", "payload": "pass"},] + buttons = [ + {"title": "Concordar", "payload": "agree"}, + {"title": "Discordar", "payload": "disagree"}, + {"title": "Pular", "payload": "pass"}, + ] if tracker.get_slot("change_comment"): # TODO: get values from EJ server @@ -56,9 +62,12 @@ def run( SlotSet("current_comment_id", comment_id), ] else: - dispatcher.utter_message(text=tracker.get_slot("comment_text"), buttons=buttons) + dispatcher.utter_message( + text=tracker.get_slot("comment_text"), buttons=buttons + ) return [SlotSet("change_comment", True)] + class ValidateVoteForm(FormValidationAction): def name(self) -> Text: return "validate_vote_form" diff --git a/bot/tests/test_actions.py b/bot/tests/test_actions.py index 2e91ec4..5e66d91 100644 --- a/bot/tests/test_actions.py +++ b/bot/tests/test_actions.py @@ -10,33 +10,37 @@ EMPTY_TRACKER = None + @pytest.fixture def dispatcher(): - return CollectingDispatcher() + return CollectingDispatcher() + @pytest.fixture def domain(): - return dict() + return dict() + def test_action_setup_conversation(dispatcher, domain): - tracker = EMPTY_TRACKER - action = ActionSetupConversation() - events = action.run(dispatcher, tracker, domain) - expected_events = [ - SlotSet("number_voted_comments", 1), - SlotSet("conversation_id", 1), - SlotSet("number_comments", 3), - SlotSet("comment_text", "Comment text here"), - SlotSet("current_comment_id", 53), - SlotSet("change_comment", False), - FollowupAction("vote_form") - ] - assert events == expected_events + tracker = EMPTY_TRACKER + action = ActionSetupConversation() + events = action.run(dispatcher, tracker, domain) + expected_events = [ + SlotSet("number_voted_comments", 1), + SlotSet("conversation_id", 1), + SlotSet("number_comments", 3), + SlotSet("comment_text", "Comment text here"), + SlotSet("current_comment_id", 53), + SlotSet("change_comment", False), + FollowupAction("vote_form"), + ] + assert events == expected_events + def test_action_ask_vote(dispatcher, domain): - tracker = DialogueStateTracker(sender_id="1", slots=AnySlotDict()) - action = ActionAskVote() - events = action.run(dispatcher, tracker, domain) - expected_events = [SlotSet("change_comment", True)] + tracker = DialogueStateTracker(sender_id="1", slots=AnySlotDict()) + action = ActionAskVote() + events = action.run(dispatcher, tracker, domain) + expected_events = [SlotSet("change_comment", True)] - assert events == expected_events \ No newline at end of file + assert events == expected_events diff --git a/bot/tests/test_stories.yml b/bot/tests/test_stories.yml index 9e8071a..b662ea0 100644 --- a/bot/tests/test_stories.yml +++ b/bot/tests/test_stories.yml @@ -11,8 +11,14 @@ stories: - user: | sim intent: agree - - action: action_random_comment + - action: action_setup_conversation + - slot_was_set: + - number_voted_comments: 1 - action: vote_form + - active_loop: vote_form + - user: | + agree + - action: validate_vote_form - story: User don't want to participate sad path steps: From 7d0e8a7b262bf465df53181818572c696b79227a Mon Sep 17 00:00:00 2001 From: Martha Date: Tue, 9 Feb 2021 14:56:03 -0300 Subject: [PATCH 23/36] create stories' tests of validade_form, out_of_context and ask_vote actions Signed-off-by: Martha Co-authored-by: fabiola --- .gitignore | 3 ++- bot/actions/actions.py | 10 +++++----- bot/data/nlu.yml | 1 + bot/tests/test_actions.py | 3 +-- bot/tests/test_stories.yml | 37 +++++++++++++++++++++++++++++++++++++ 5 files changed, 46 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index a4e0cb0..566ba9c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ ./bot/models -./bot/results +./bot/results/ */__pycache__/ .pytest_cache/ *.pyc *.log models +results/ \ No newline at end of file diff --git a/bot/actions/actions.py b/bot/actions/actions.py index a6412cc..590caf0 100644 --- a/bot/actions/actions.py +++ b/bot/actions/actions.py @@ -21,7 +21,7 @@ def name(self): def run(self, dispatcher, tracker, domain): # TODO: get values from EJ server conversation_id = 1 - number_comments = 3 + number_comments = 2 number_voted_comments = 1 first_comment = "Comment text here" comment_id = 53 @@ -87,12 +87,12 @@ def validate_vote( dispatcher.utter_message(template="utter_vote_received") # TODO: Get next random comment # was_sent = send_vote(vote_value) - if voted_comments == total_comments: - # user voted in all comments, can exit loop - return [{"vote": slot_value}] - else: + if voted_comments < total_comments: # user still has comments to vote, remain in loop return {"vote": None} + else: + # user voted in all comments, can exit loop + return [{"vote": slot_value}] else: dispatcher.utter_message(template="utter_out_of_context") # did not send expected vote value diff --git a/bot/data/nlu.yml b/bot/data/nlu.yml index 1611e61..6bc4293 100644 --- a/bot/data/nlu.yml +++ b/bot/data/nlu.yml @@ -54,3 +54,4 @@ nlu: - pausa - tempo - stop + - sair diff --git a/bot/tests/test_actions.py b/bot/tests/test_actions.py index 5e66d91..6188c1e 100644 --- a/bot/tests/test_actions.py +++ b/bot/tests/test_actions.py @@ -28,7 +28,7 @@ def test_action_setup_conversation(dispatcher, domain): expected_events = [ SlotSet("number_voted_comments", 1), SlotSet("conversation_id", 1), - SlotSet("number_comments", 3), + SlotSet("number_comments", 2), SlotSet("comment_text", "Comment text here"), SlotSet("current_comment_id", 53), SlotSet("change_comment", False), @@ -36,7 +36,6 @@ def test_action_setup_conversation(dispatcher, domain): ] assert events == expected_events - def test_action_ask_vote(dispatcher, domain): tracker = DialogueStateTracker(sender_id="1", slots=AnySlotDict()) action = ActionAskVote() diff --git a/bot/tests/test_stories.yml b/bot/tests/test_stories.yml index b662ea0..7f3aa40 100644 --- a/bot/tests/test_stories.yml +++ b/bot/tests/test_stories.yml @@ -8,17 +8,54 @@ stories: oi intent: start - action: utter_start + +- story: User votes + steps: - user: | sim intent: agree - action: action_setup_conversation - slot_was_set: - number_voted_comments: 1 + - conversation_id: 1 + - number_comments: 2 + - comment_text: "Comment text here" + - comment_id: 53 - action: vote_form - active_loop: vote_form + - action: action_ask_vote + - user: | + agree + - action: validate_vote_form + - slot_was_set: + - vote: null + - action: action_ask_vote + - slot_was_set: + - number_voted_comments: 2 + - conversation_id: 1 + - number_comments: 2 + - comment_text: "novo comentário com outro id" + - comment_id: 22 - user: | agree - action: validate_vote_form + - slot_was_set: + vote: "agree" + +- story: User votes out of context, value of vote + steps: + - user: | + sair + - action: validate_vote_form + - slot_was_set: + vote: null + +- story: User votes out of context + steps: + - user: | + não entendi + intent: out_of_context + - action: utter_out_of_context - story: User don't want to participate sad path steps: From 66e2334925128a26a15836bba64540737958e264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Tue, 9 Feb 2021 15:26:24 -0300 Subject: [PATCH 24/36] Update dockerfile pip version and tests style and story name --- bot/tests/test_actions.py | 1 + bot/tests/test_stories.yml | 2 +- docker/requirements.Dockerfile | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/bot/tests/test_actions.py b/bot/tests/test_actions.py index 6188c1e..717b3ef 100644 --- a/bot/tests/test_actions.py +++ b/bot/tests/test_actions.py @@ -36,6 +36,7 @@ def test_action_setup_conversation(dispatcher, domain): ] assert events == expected_events + def test_action_ask_vote(dispatcher, domain): tracker = DialogueStateTracker(sender_id="1", slots=AnySlotDict()) action = ActionAskVote() diff --git a/bot/tests/test_stories.yml b/bot/tests/test_stories.yml index 7f3aa40..90238f5 100644 --- a/bot/tests/test_stories.yml +++ b/bot/tests/test_stories.yml @@ -50,7 +50,7 @@ stories: - slot_was_set: vote: null -- story: User votes out of context +- story: User utters out of context steps: - user: | não entendi diff --git a/docker/requirements.Dockerfile b/docker/requirements.Dockerfile index 02e52d1..e40de00 100644 --- a/docker/requirements.Dockerfile +++ b/docker/requirements.Dockerfile @@ -2,7 +2,7 @@ FROM python:3.7-slim RUN apt update && apt install -y gcc make -RUN python -m pip install --upgrade pip +RUN python -m pip install --upgrade pip==20.2 COPY ./docker/ /tmp From 24ed612870711f2245a6837314577287eacbd158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Tue, 9 Feb 2021 15:33:55 -0300 Subject: [PATCH 25/36] Update pip version in gitlabci build --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1a1245a..76f1ad1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,6 +25,7 @@ test: - apk add curl jq python3 python3-dev build-base libffi-dev libressl-dev gettext - curl -O https://bootstrap.pypa.io/get-pip.py - python3 get-pip.py + - pip install --upgrade pip - pip install docker-compose - make build - make train From bbeb62bdd970acf39cb24857cac818f1cfce81ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Tue, 9 Feb 2021 16:07:18 -0300 Subject: [PATCH 26/36] Add rust in test dependency on gitlabci --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 76f1ad1..a424b8e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ test: - docker info - apk update - apk upgrade - - apk add curl jq python3 python3-dev build-base libffi-dev libressl-dev gettext + - apk add curl jq python3 python3-dev build-base libffi-dev libressl-dev gettext rust cargo - curl -O https://bootstrap.pypa.io/get-pip.py - python3 get-pip.py - pip install --upgrade pip From 1190c76e1a1e614194bc0d84e9605ba83c582f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Tue, 9 Feb 2021 16:15:14 -0300 Subject: [PATCH 27/36] Change docker image on gitlabci --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a424b8e..d636540 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: docker:stable +image: docker:latest services: - docker:dind From 7221431bf73f516555c431c8a11428f177c3ba48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Tue, 9 Feb 2021 18:10:44 -0300 Subject: [PATCH 28/36] Update project readme and deleted unused file --- README.md | 6 ++++-- bot/tests/post.py | 19 ------------------- 2 files changed, 4 insertions(+), 21 deletions(-) delete mode 100644 bot/tests/post.py diff --git a/README.md b/README.md index db26f94..3bd3a3b 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ A execução de testes também é realizada por meio de comandos make, listados - make test - make run-test-nlu - make run-test-core +- make test-actions # Estrutura básica do projeto @@ -59,8 +60,9 @@ Abaixo, segue em destaque na estrutura de pastas os arquivos que serão mais uti - stories.yml # cada story é um fluxo que deve ocorrer entre o usuário e o bot -- domain.yml # são definidas as utter, respostas do bot que são apenas texto e também descreve o domínio do bot, que inclue intents, entities, slots, templates e actions que o bot deve ter consciência. -- endpoints.yml # arquivo que contém a configuração do webhook para uma ação personalizada --- tests/ - - test_stories.yml # testes dos fluxos de conversas + -- tests/ + - test_stories.yml # testes dos fluxos de conversas + - test_actions.py # teste das ações e outros recursos, usando pytest ``` diff --git a/bot/tests/post.py b/bot/tests/post.py deleted file mode 100644 index 9e113fb..0000000 --- a/bot/tests/post.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -This file is used to test bot post requests -To use it, you must have the actions server and bot running -And execute -$ python3 post.py -""" - -import requests -import json - -post_url = "http://localhost:5005/webhooks/rest/webhook" - -headers = {"content-type": "application/json"} - -params = {"message": "constante"} - -r = requests.post(post_url, data=json.dumps(params), headers=headers) - -print(r.text) From 39e4c9267815d6c402e48b6f8eaca97333da163c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Tue, 9 Feb 2021 18:33:20 -0300 Subject: [PATCH 29/36] Update pip version on dockerfile --- docker/requirements.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/requirements.Dockerfile b/docker/requirements.Dockerfile index e40de00..02e52d1 100644 --- a/docker/requirements.Dockerfile +++ b/docker/requirements.Dockerfile @@ -2,7 +2,7 @@ FROM python:3.7-slim RUN apt update && apt install -y gcc make -RUN python -m pip install --upgrade pip==20.2 +RUN python -m pip install --upgrade pip COPY ./docker/ /tmp From b32308b0301513e6461e4384acb41b0eeb739702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Wed, 10 Feb 2021 16:48:42 -0300 Subject: [PATCH 30/36] Add rasa x to environment --- Makefile | 2 ++ bot/Makefile | 4 ++++ bot/data/nlu.yml | 2 ++ docker-compose.yml | 19 ++++++++++++++++++- docker/requirements.Dockerfile | 7 ++++--- docker/x-requirements.txt | 2 ++ 6 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 docker/x-requirements.txt diff --git a/Makefile b/Makefile index d4f91b3..fab5bee 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,8 @@ train: mkdir -p bot/models docker-compose up --build coach +run-x: + docker-compose run --rm --service-ports x make x ############################## TESTS ############################## test: docker-compose run --rm bot make test diff --git a/bot/Makefile b/bot/Makefile index 1edb1a9..c87e6ba 100644 --- a/bot/Makefile +++ b/bot/Makefile @@ -8,6 +8,10 @@ install: pip install -r ../requirements.txt && \ pip install -r ../x-requirements.txt +# RASA X +x: + rasa x + # NLU train-nlu: rasa train nlu -vv diff --git a/bot/data/nlu.yml b/bot/data/nlu.yml index 6bc4293..dbcedf4 100644 --- a/bot/data/nlu.yml +++ b/bot/data/nlu.yml @@ -38,6 +38,8 @@ nlu: - não sei - pular - pulo + - passa + - próxima pergunta - intent: out_of_context examples: | diff --git a/docker-compose.yml b/docker-compose.yml index 734fc7d..6bf3f2d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -37,4 +37,21 @@ services: - 5055:5055 volumes: - ./bot/actions:/bot/actions - command: sh -c "make actions" \ No newline at end of file + command: sh -c "make actions" + + # ================================= RASA X ================================== + # Rasa X container + x: + build: + context: . + dockerfile: ./docker/bot.Dockerfile + restart: unless-stopped + volumes: + - ./bot/:/bot/ + ports: + - 5002:5002 + environment: + - GIT_PYTHON_REFRESH=quiet + depends_on: + - actions + command: sh -c "make x" \ No newline at end of file diff --git a/docker/requirements.Dockerfile b/docker/requirements.Dockerfile index 02e52d1..d811415 100644 --- a/docker/requirements.Dockerfile +++ b/docker/requirements.Dockerfile @@ -1,12 +1,13 @@ -FROM python:3.7-slim +FROM python:3.7-slim-buster RUN apt update && apt install -y gcc make - +RUN apt install -y python3.7-dev RUN python -m pip install --upgrade pip COPY ./docker/ /tmp -RUN pip install --no-cache-dir -r ./tmp/requirements-development.txt +RUN pip install --no-cache-dir -r ./tmp/requirements-development.txt && \ + pip install --use-deprecated=legacy-resolver --no-cache-dir -r /tmp/x-requirements.txt RUN python -c "import nltk; nltk.download('stopwords');" RUN python -m spacy download pt_core_news_sm RUN find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf diff --git a/docker/x-requirements.txt b/docker/x-requirements.txt new file mode 100644 index 0000000..4b33537 --- /dev/null +++ b/docker/x-requirements.txt @@ -0,0 +1,2 @@ +--extra-index-url https://pypi.rasa.com/simple +rasa-x==0.35.1 \ No newline at end of file From 0b2f0f41b9b0a3d0a2316070244b3328de3e6be2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Wed, 10 Feb 2021 20:08:53 -0300 Subject: [PATCH 31/36] Update rasa version on requirements, domain structure and bot vocabulary --- .gitignore | 7 ++- bot/data/nlu.yml | 1 + bot/data/stories.yml | 2 +- bot/domain.yml | 107 +++++++++++++++++++++++++--------------- docker/requirements.txt | 2 +- 5 files changed, 75 insertions(+), 44 deletions(-) diff --git a/.gitignore b/.gitignore index 566ba9c..794703a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,13 @@ ./bot/models +./bot/train_test_split ./bot/results/ */__pycache__/ .pytest_cache/ *.pyc *.log +*.db +*.db-shm +*.db-wal models -results/ \ No newline at end of file +results/ +train_test_split \ No newline at end of file diff --git a/bot/data/nlu.yml b/bot/data/nlu.yml index dbcedf4..30c7838 100644 --- a/bot/data/nlu.yml +++ b/bot/data/nlu.yml @@ -11,6 +11,7 @@ nlu: - Boa tarde - Boa noite - Oi, tudo bem? + - alo - intent: agree examples: | diff --git a/bot/data/stories.yml b/bot/data/stories.yml index 067940b..16e5be6 100644 --- a/bot/data/stories.yml +++ b/bot/data/stories.yml @@ -22,4 +22,4 @@ stories: - active_loop: vote_form - active_loop: null - slot_was_set: - - requested_slot: null \ No newline at end of file + - vote: null \ No newline at end of file diff --git a/bot/domain.yml b/bot/domain.yml index 77ef493..6849f81 100644 --- a/bot/domain.yml +++ b/bot/domain.yml @@ -1,59 +1,84 @@ -version: "2.0" - +config: + store_entities_as_slots: true +session_config: + session_expiration_time: 60 + carry_over_slots_to_new_session: true intents: - - agree - - disagree - - pass - - start - - out_of_context - +- agree: + use_entities: true +- disagree: + use_entities: true +- pass: + use_entities: true +- start: + use_entities: true +- out_of_context: + use_entities: true +entities: [] slots: + change_comment: + type: rasa.shared.core.slots.BooleanSlot + initial_value: null + auto_fill: true + influence_conversation: false + comment_text: + type: rasa.shared.core.slots.TextSlot + initial_value: null + auto_fill: true + influence_conversation: false conversation_id: - type: float - vote: - type: categorical - values: - - "agree" - - "disagree" - - "pass" + type: rasa.shared.core.slots.FloatSlot + initial_value: null + auto_fill: true + influence_conversation: true + max_value: 1.0 + min_value: 0.0 + current_comment_id: + type: rasa.shared.core.slots.FloatSlot + initial_value: null + auto_fill: true influence_conversation: false + max_value: 1.0 + min_value: 0.0 number_comments: - type: float + type: rasa.shared.core.slots.FloatSlot + initial_value: null + auto_fill: true influence_conversation: false + max_value: 1.0 + min_value: 0.0 number_voted_comments: - type: float + type: rasa.shared.core.slots.FloatSlot + initial_value: null + auto_fill: true influence_conversation: false - current_comment_id: - type: float - influence_conversation: false - comment_text: - type: text - influence_conversation: false - change_comment: - type: bool + max_value: 1.0 + min_value: 0.0 + vote: + type: rasa.shared.core.slots.CategoricalSlot + initial_value: null + auto_fill: true influence_conversation: false - + values: + - agree + - disagree + - pass responses: utter_start: - - text: "Olá, gostaria de participar?" + - text: Olá, estou coletando opiniões, gostaria de participar? utter_goodbye: - - text: "Agradeço pela participação! Até logo" + - text: Agradeço pela participação! Até logo utter_vote_received: - - text: "Voto computado!" + - text: Seus votos foram computados, agradeço! utter_out_of_context: - - text: "Desculpe, não sei como posso te ajudar com isso." - utter_ask_vote: - - text: "uai" + - text: Desculpe, não sei como posso te ajudar com isso. actions: - - action_setup_conversation - - action_ask_vote - - validate_vote_form - +- action_setup_conversation +- action_ask_vote +- validate_vote_form forms: vote_form: vote: - - type: from_text - -session_config: - session_expiration_time: 60 - carry_over_slots_to_new_session: true + - type: from_text +e2e_actions: [] +version: '2.0' diff --git a/docker/requirements.txt b/docker/requirements.txt index e192b40..b931eb1 100644 --- a/docker/requirements.txt +++ b/docker/requirements.txt @@ -1,5 +1,5 @@ -rasa~=2.0.2 # when updating, check the sdk version in the Dockerfile as well! +rasa~=2.2.10 # when updating, check the sdk version in the Dockerfile as well! nltk==3.4.5 spacy==3.0.0 -r requirements-actions.txt From a4cff3fe316613b06b96de1fc5766fd39382ff0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Thu, 11 Feb 2021 11:31:50 -0300 Subject: [PATCH 32/36] Refactor requirements, changed mapping in rasa x service and updated makefile --- Makefile | 6 +++++- docker-compose.yml | 1 + docker/{ => dependencies}/requirements-actions.txt | 0 docker/{ => dependencies}/requirements-development.txt | 0 docker/{ => dependencies}/requirements.txt | 0 docker/{ => dependencies}/x-requirements.txt | 0 docker/requirements.Dockerfile | 4 ++-- 7 files changed, 8 insertions(+), 3 deletions(-) rename docker/{ => dependencies}/requirements-actions.txt (100%) rename docker/{ => dependencies}/requirements-development.txt (100%) rename docker/{ => dependencies}/requirements.txt (100%) rename docker/{ => dependencies}/x-requirements.txt (100%) diff --git a/Makefile b/Makefile index fab5bee..753f018 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ build: ## Build base requirements dockerfile and coach and bot services make build-requirements make build-coach make build-bot + make build-x build-requirements: docker build . --no-cache -f docker/requirements.Dockerfile -t botrequirements @@ -28,6 +29,9 @@ build-requirements: build-bot: docker-compose build --no-cache bot +build-x: + docker-compose build --no-cache x + build-coach: docker-compose build --no-cache coach @@ -39,7 +43,7 @@ run-api: docker-compose run --rm --service-ports bot make api run-actions: - docker-compose run --rm --service-ports bot make actions + docker-compose run --rm --service-ports actions make actions train: mkdir -p bot/models diff --git a/docker-compose.yml b/docker-compose.yml index 6bf3f2d..f692a3a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -48,6 +48,7 @@ services: restart: unless-stopped volumes: - ./bot/:/bot/ + - /bot/tests/:/bot/tests/ ports: - 5002:5002 environment: diff --git a/docker/requirements-actions.txt b/docker/dependencies/requirements-actions.txt similarity index 100% rename from docker/requirements-actions.txt rename to docker/dependencies/requirements-actions.txt diff --git a/docker/requirements-development.txt b/docker/dependencies/requirements-development.txt similarity index 100% rename from docker/requirements-development.txt rename to docker/dependencies/requirements-development.txt diff --git a/docker/requirements.txt b/docker/dependencies/requirements.txt similarity index 100% rename from docker/requirements.txt rename to docker/dependencies/requirements.txt diff --git a/docker/x-requirements.txt b/docker/dependencies/x-requirements.txt similarity index 100% rename from docker/x-requirements.txt rename to docker/dependencies/x-requirements.txt diff --git a/docker/requirements.Dockerfile b/docker/requirements.Dockerfile index d811415..5468910 100644 --- a/docker/requirements.Dockerfile +++ b/docker/requirements.Dockerfile @@ -6,8 +6,8 @@ RUN python -m pip install --upgrade pip COPY ./docker/ /tmp -RUN pip install --no-cache-dir -r ./tmp/requirements-development.txt && \ - pip install --use-deprecated=legacy-resolver --no-cache-dir -r /tmp/x-requirements.txt +RUN pip install --no-cache-dir -r ./tmp/dependencies/requirements-development.txt && \ + pip install --use-deprecated=legacy-resolver --no-cache-dir -r /tmp/dependencies/x-requirements.txt RUN python -c "import nltk; nltk.download('stopwords');" RUN python -m spacy download pt_core_news_sm RUN find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf From 66bcc721612fb272445c5c0d6f4709d0db23a530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Thu, 11 Feb 2021 11:33:25 -0300 Subject: [PATCH 33/36] Update vote button values for a better user interaction --- bot/actions/actions.py | 8 ++++---- bot/domain.yml | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/bot/actions/actions.py b/bot/actions/actions.py index 590caf0..65b6498 100644 --- a/bot/actions/actions.py +++ b/bot/actions/actions.py @@ -44,9 +44,9 @@ def run( self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict ) -> List[EventType]: buttons = [ - {"title": "Concordar", "payload": "agree"}, - {"title": "Discordar", "payload": "disagree"}, - {"title": "Pular", "payload": "pass"}, + {"title": "Concordar", "payload": "Concordar"}, + {"title": "Discordar", "payload": "Discordas"}, + {"title": "Pular", "payload": "Pular"}, ] if tracker.get_slot("change_comment"): @@ -80,7 +80,7 @@ def validate_vote( domain: DomainDict, ) -> Dict[Text, Any]: """Validate vote value.""" - if str(slot_value) in ["agree", "disagree", "pass"]: + if str(slot_value) in ["Concordar", "Discordar", "Pular"]: # TODO: Send vote value to EJ server voted_comments = tracker.get_slot("number_voted_comments") total_comments = tracker.get_slot("number_comments") diff --git a/bot/domain.yml b/bot/domain.yml index 6849f81..5e9d4ad 100644 --- a/bot/domain.yml +++ b/bot/domain.yml @@ -1,3 +1,4 @@ +version: '2.0' config: store_entities_as_slots: true session_config: @@ -60,9 +61,9 @@ slots: auto_fill: true influence_conversation: false values: - - agree - - disagree - - pass + - Concordar + - Discordar + - Pular responses: utter_start: - text: Olá, estou coletando opiniões, gostaria de participar? @@ -81,4 +82,3 @@ forms: vote: - type: from_text e2e_actions: [] -version: '2.0' From 159f65ae3b87158a7096e72e37e015f1a774fcb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Thu, 11 Feb 2021 15:19:23 -0300 Subject: [PATCH 34/36] Update environments.yml location to inside bot --- environments.yml => bot/environments.yml | 0 install.sh | 57 ------------------------ 2 files changed, 57 deletions(-) rename environments.yml => bot/environments.yml (100%) delete mode 100644 install.sh diff --git a/environments.yml b/bot/environments.yml similarity index 100% rename from environments.yml rename to bot/environments.yml diff --git a/install.sh b/install.sh deleted file mode 100644 index 473b8e6..0000000 --- a/install.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash -set -Eeuo pipefail - -####################################### -# -# installing ansible and roles -# -####################################### - -source /etc/os-release - -RUN_ANSIBLE=${RUN_ANSIBLE:-true} - -echo "Installing pip and ansible" - -if [[ $ID =~ centos|rhel ]]; then - - sudo yum update -y - sudo yum install -y python3 - sudo yum install -y python3-distutils || : # if the package is not available and the command fails, do nothing, - # the distutils are already installed -elif [[ $ID =~ ubuntu|debian ]]; then - sudo apt-get update -y - sudo apt-get install -y python3 - sudo apt-get install -y python3-distutils || : # if the package is not available and the command fails, do nothing, - # the distutils are already installed - sudo apt-get install -y wget || : # wget may already be installed; do nothing if it is -fi - -curl -O https://bootstrap.pypa.io/get-pip.py -sudo python3 get-pip.py -sudo /usr/local/bin/pip install "ansible>-2.9, <2.10" - -echo "Installing docker role" -sudo /usr/local/bin/ansible-galaxy install geerlingguy.docker -echo "Docker role for ansible has been installed" - - -if [[ "$RUN_ANSIBLE" == "true" ]]; then - ####################################### - # - # downloading the ansible playbook - # for the passed in version or latest - # - ####################################### - echo "Downloading Rasa X playbook" - wget -qO rasa_x_playbook.yml https://storage.googleapis.com/rasa-x-releases/0.35.0/rasa_x_playbook.yml - - ####################################### - # - # running the ansible playbook - # (starts docker und serves Rasa X) - # - ####################################### - echo "Running playbook" - sudo /usr/local/bin/ansible-playbook -i "localhost," -c local rasa_x_playbook.yml -fi From 2ba0d4875d094486f2895fe97c455a14bd267dd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fab=C3=ADola=20Fleury?= Date: Thu, 11 Feb 2021 18:35:10 +0000 Subject: [PATCH 35/36] Create simple bot domain for communication with user, using votes and comments structure. - closes #204 --- .gitignore | 2 + .gitlab-ci.yml | 8 +-- Makefile | 4 ++ README.md | 6 ++- bot/Makefile | 5 +- bot/__init__.py | 0 bot/actions/__init__.py | 1 + bot/actions/actions.py | 99 +++++++++++++++++++++++++++------- bot/config.yml | 18 ++++++- bot/data/nlu.yml | 24 +++++++++ bot/data/rules.yml | 4 ++ bot/data/stories.yml | 25 ++++----- bot/domain.yml | 55 ++++++++++++++----- bot/tests/test_actions.py | 46 ++++++++++++++++ bot/tests/test_stories.yml | 69 ++++++++++++++++++++++++ docker/requirements.Dockerfile | 2 +- tests/post.py | 19 ------- tests/test_stories.yml | 91 ------------------------------- 18 files changed, 314 insertions(+), 164 deletions(-) create mode 100644 bot/__init__.py create mode 100644 bot/tests/test_actions.py create mode 100644 bot/tests/test_stories.yml delete mode 100644 tests/post.py delete mode 100644 tests/test_stories.yml diff --git a/.gitignore b/.gitignore index 3958fc8..566ba9c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ ./bot/models +./bot/results/ */__pycache__/ .pytest_cache/ *.pyc *.log models +results/ \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b2db4d7..d636540 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: docker:stable +image: docker:latest services: - docker:dind @@ -22,13 +22,15 @@ test: - docker info - apk update - apk upgrade - - apk add curl jq python3 python3-dev build-base libffi-dev libressl-dev gettext + - apk add curl jq python3 python3-dev build-base libffi-dev libressl-dev gettext rust cargo - curl -O https://bootstrap.pypa.io/get-pip.py - python3 get-pip.py + - pip install --upgrade pip - pip install docker-compose - make build - make train stage: test script: - make run-test-nlu - - make run-test-core \ No newline at end of file + - make run-test-core + - make test-actions \ No newline at end of file diff --git a/Makefile b/Makefile index 03c1038..d4f91b3 100644 --- a/Makefile +++ b/Makefile @@ -49,12 +49,16 @@ train: test: docker-compose run --rm bot make test +test-actions: + docker-compose run --rm bot make test-actions + run-test-nlu: docker-compose run --rm bot make test-nlu run-test-core: docker-compose run --rm bot make test-core + validate: docker-compose run --rm bot rasa data validate --domain domain.yml --data data/ -vv diff --git a/README.md b/README.md index db26f94..3bd3a3b 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ A execução de testes também é realizada por meio de comandos make, listados - make test - make run-test-nlu - make run-test-core +- make test-actions # Estrutura básica do projeto @@ -59,8 +60,9 @@ Abaixo, segue em destaque na estrutura de pastas os arquivos que serão mais uti - stories.yml # cada story é um fluxo que deve ocorrer entre o usuário e o bot -- domain.yml # são definidas as utter, respostas do bot que são apenas texto e também descreve o domínio do bot, que inclue intents, entities, slots, templates e actions que o bot deve ter consciência. -- endpoints.yml # arquivo que contém a configuração do webhook para uma ação personalizada --- tests/ - - test_stories.yml # testes dos fluxos de conversas + -- tests/ + - test_stories.yml # testes dos fluxos de conversas + - test_actions.py # teste das ações e outros recursos, usando pytest ``` diff --git a/bot/Makefile b/bot/Makefile index 438741a..1edb1a9 100644 --- a/bot/Makefile +++ b/bot/Makefile @@ -20,8 +20,11 @@ train: test: rasa test --out results/ +test-actions: + python -m pytest + test-nlu: - rasa test nlu --out results/results-nlu-test + rasa test nlu --nlu data/nlu.yml --cross-validation test-core: rasa test core --fail-on-prediction-errors --out results/results-core-test diff --git a/bot/__init__.py b/bot/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bot/actions/__init__.py b/bot/actions/__init__.py index e69de29..a29afc7 100644 --- a/bot/actions/__init__.py +++ b/bot/actions/__init__.py @@ -0,0 +1 @@ +from .actions import ActionSetupConversation, ActionAskVote, FormValidationAction diff --git a/bot/actions/actions.py b/bot/actions/actions.py index f8c041d..590caf0 100644 --- a/bot/actions/actions.py +++ b/bot/actions/actions.py @@ -4,33 +4,96 @@ # See this guide on how to implement these action: # https://rasa.com/docs/rasa/custom-actions -import requests +from typing import Text, List, Any, Dict # -from rasa_sdk import Action, Tracker +from rasa_sdk import Action, Tracker, FormValidationAction from rasa_sdk.executor import CollectingDispatcher +from rasa_sdk.events import SlotSet, FollowupAction, EventType +from rasa_sdk.types import DomainDict # # -class ActionRandomComment(Action): +class ActionSetupConversation(Action): def name(self): - return "action_random_comment" + return "action_setup_conversation" def run(self, dispatcher, tracker, domain): - # TODO: Add code to get comment from EJ server - comment = "Comment text here" - dispatcher.utter_message(comment) - dispatcher.utter_message(template="utter_vote") - return [] + # TODO: get values from EJ server + conversation_id = 1 + number_comments = 2 + number_voted_comments = 1 + first_comment = "Comment text here" + comment_id = 53 + return [ + SlotSet("number_voted_comments", number_voted_comments), + SlotSet("conversation_id", conversation_id), + SlotSet("number_comments", number_comments), + SlotSet("comment_text", first_comment), + SlotSet("current_comment_id", comment_id), + SlotSet("change_comment", False), + FollowupAction("vote_form"), + ] -class ActionSendVote(Action): - def name(self): - return "action_send_vote" +class ActionAskVote(Action): + def name(self) -> Text: + return "action_ask_vote" - def run(self, dispatcher, tracker, domain): - # TODO: Add code to send request to EJ with vote value - vote = tracker.latest_message["intent"].get("name") - dispatcher.utter_message(vote) - dispatcher.utter_message(template="utter_vote_received") - return [] + def run( + self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict + ) -> List[EventType]: + buttons = [ + {"title": "Concordar", "payload": "agree"}, + {"title": "Discordar", "payload": "disagree"}, + {"title": "Pular", "payload": "pass"}, + ] + + if tracker.get_slot("change_comment"): + # TODO: get values from EJ server + # next_comment = get_random_comment() + new_comment = "novo comentário com outro id" + dispatcher.utter_message(text=new_comment, buttons=buttons) + number_voted_comments = tracker.get_slot("number_comments") + 1 + comment_id = 22 + return [ + SlotSet("number_voted_comments", number_voted_comments), + SlotSet("comment_text", new_comment), + SlotSet("current_comment_id", comment_id), + ] + else: + dispatcher.utter_message( + text=tracker.get_slot("comment_text"), buttons=buttons + ) + return [SlotSet("change_comment", True)] + + +class ValidateVoteForm(FormValidationAction): + def name(self) -> Text: + return "validate_vote_form" + + def validate_vote( + self, + slot_value: Any, + dispatcher: CollectingDispatcher, + tracker: Tracker, + domain: DomainDict, + ) -> Dict[Text, Any]: + """Validate vote value.""" + if str(slot_value) in ["agree", "disagree", "pass"]: + # TODO: Send vote value to EJ server + voted_comments = tracker.get_slot("number_voted_comments") + total_comments = tracker.get_slot("number_comments") + dispatcher.utter_message(template="utter_vote_received") + # TODO: Get next random comment + # was_sent = send_vote(vote_value) + if voted_comments < total_comments: + # user still has comments to vote, remain in loop + return {"vote": None} + else: + # user voted in all comments, can exit loop + return [{"vote": slot_value}] + else: + dispatcher.utter_message(template="utter_out_of_context") + # did not send expected vote value + return {"vote": None} diff --git a/bot/config.yml b/bot/config.yml index 1b472d7..494c390 100644 --- a/bot/config.yml +++ b/bot/config.yml @@ -11,4 +11,20 @@ pipeline: - name: DIETClassifier epochs: 55 - name: EntitySynonymMapper - - name: ResponseSelector \ No newline at end of file + - name: ResponseSelector + +policies: + - name: TEDPolicy + max_history: 10 + epochs: 20 + batch_size: + - 32 + - 64 + - max_history: 6 + name: AugmentedMemoizationPolicy + - name: RulePolicy + core_fallback_threshold: 0.3 + core_fallback_action_name: action_default_fallback + enable_fallback_prediction: true + restrict_rules: true + check_for_contradictions: true \ No newline at end of file diff --git a/bot/data/nlu.yml b/bot/data/nlu.yml index 5e1a078..6bc4293 100644 --- a/bot/data/nlu.yml +++ b/bot/data/nlu.yml @@ -4,6 +4,13 @@ nlu: - intent: start examples: | - começar a conversar + - oi + - olá + - hey + - Bom dia + - Boa tarde + - Boa noite + - Oi, tudo bem? - intent: agree examples: | @@ -31,3 +38,20 @@ nlu: - não sei - pular - pulo + +- intent: out_of_context + examples: | + - 4 + 2 = ? + - Queria pedir uma pizza + - Como tá o tempo? + - Como vc tá? + - você é um robô? + - Fala alguma coisa + - asdfgasd + - chega + - para + - parar + - pausa + - tempo + - stop + - sair diff --git a/bot/data/rules.yml b/bot/data/rules.yml index 94483ed..be42792 100644 --- a/bot/data/rules.yml +++ b/bot/data/rules.yml @@ -1,3 +1,7 @@ version: "2.0" rules: +- rule: User ask a out of context question + steps: + - intent: out_of_context + - action: utter_out_of_context \ No newline at end of file diff --git a/bot/data/stories.yml b/bot/data/stories.yml index a62725e..067940b 100644 --- a/bot/data/stories.yml +++ b/bot/data/stories.yml @@ -2,29 +2,24 @@ version: "2.0" stories: -- story: happy path +- story: Greet user steps: - intent: start - action: utter_start - - intent: agree - - action: action_random_comment - - intent: agree - - action: action_send_vote - -- story: happy path 2 +- story: User don't want to participate sad path steps: - intent: start - action: utter_start - - intent: agree - - action: action_random_comment - intent: disagree - - action: action_send_vote - action: utter_goodbye -- story: sad path +- story: Activate vote form steps: - - intent: start - - action: utter_start - - intent: disagree - - action: utter_goodbye \ No newline at end of file + - intent: agree + - action: action_setup_conversation + - action: vote_form + - active_loop: vote_form + - active_loop: null + - slot_was_set: + - requested_slot: null \ No newline at end of file diff --git a/bot/domain.yml b/bot/domain.yml index c83984b..77ef493 100644 --- a/bot/domain.yml +++ b/bot/domain.yml @@ -5,25 +5,54 @@ intents: - disagree - pass - start + - out_of_context + +slots: + conversation_id: + type: float + vote: + type: categorical + values: + - "agree" + - "disagree" + - "pass" + influence_conversation: false + number_comments: + type: float + influence_conversation: false + number_voted_comments: + type: float + influence_conversation: false + current_comment_id: + type: float + influence_conversation: false + comment_text: + type: text + influence_conversation: false + change_comment: + type: bool + influence_conversation: false responses: utter_start: - text: "Olá, gostaria de participar?" utter_goodbye: - - text: "Sua participação foi computada! Até logo" - utter_vote: - - text: "Voto" - buttons: - - title: "Concordar" - payload: "/agree" - - title: "Discordar" - payload: "/disagree" - - title: "Pular" - payload: "/pass" - + - text: "Agradeço pela participação! Até logo" + utter_vote_received: + - text: "Voto computado!" + utter_out_of_context: + - text: "Desculpe, não sei como posso te ajudar com isso." + utter_ask_vote: + - text: "uai" actions: - - action_random_comment - - action_send_vote + - action_setup_conversation + - action_ask_vote + - validate_vote_form + +forms: + vote_form: + vote: + - type: from_text session_config: session_expiration_time: 60 diff --git a/bot/tests/test_actions.py b/bot/tests/test_actions.py new file mode 100644 index 0000000..717b3ef --- /dev/null +++ b/bot/tests/test_actions.py @@ -0,0 +1,46 @@ +import pytest + +from typing import Text, List, Any, Dict + +from actions import ActionSetupConversation, ActionAskVote +from rasa_sdk.executor import CollectingDispatcher +from rasa_sdk.events import SlotSet, FollowupAction +from rasa.shared.core.trackers import DialogueStateTracker, AnySlotDict + + +EMPTY_TRACKER = None + + +@pytest.fixture +def dispatcher(): + return CollectingDispatcher() + + +@pytest.fixture +def domain(): + return dict() + + +def test_action_setup_conversation(dispatcher, domain): + tracker = EMPTY_TRACKER + action = ActionSetupConversation() + events = action.run(dispatcher, tracker, domain) + expected_events = [ + SlotSet("number_voted_comments", 1), + SlotSet("conversation_id", 1), + SlotSet("number_comments", 2), + SlotSet("comment_text", "Comment text here"), + SlotSet("current_comment_id", 53), + SlotSet("change_comment", False), + FollowupAction("vote_form"), + ] + assert events == expected_events + + +def test_action_ask_vote(dispatcher, domain): + tracker = DialogueStateTracker(sender_id="1", slots=AnySlotDict()) + action = ActionAskVote() + events = action.run(dispatcher, tracker, domain) + expected_events = [SlotSet("change_comment", True)] + + assert events == expected_events diff --git a/bot/tests/test_stories.yml b/bot/tests/test_stories.yml new file mode 100644 index 0000000..90238f5 --- /dev/null +++ b/bot/tests/test_stories.yml @@ -0,0 +1,69 @@ +#### 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: Greet user + steps: + - user: | + oi + intent: start + - action: utter_start + +- story: User votes + steps: + - user: | + sim + intent: agree + - action: action_setup_conversation + - slot_was_set: + - number_voted_comments: 1 + - conversation_id: 1 + - number_comments: 2 + - comment_text: "Comment text here" + - comment_id: 53 + - action: vote_form + - active_loop: vote_form + - action: action_ask_vote + - user: | + agree + - action: validate_vote_form + - slot_was_set: + - vote: null + - action: action_ask_vote + - slot_was_set: + - number_voted_comments: 2 + - conversation_id: 1 + - number_comments: 2 + - comment_text: "novo comentário com outro id" + - comment_id: 22 + - user: | + agree + - action: validate_vote_form + - slot_was_set: + vote: "agree" + +- story: User votes out of context, value of vote + steps: + - user: | + sair + - action: validate_vote_form + - slot_was_set: + vote: null + +- story: User utters out of context + steps: + - user: | + não entendi + intent: out_of_context + - action: utter_out_of_context + +- story: User don't want to participate sad path + steps: + - user: | + olá + intent: start + - action: utter_start + - user: | + não + intent: disagree + - action: utter_goodbye \ No newline at end of file diff --git a/docker/requirements.Dockerfile b/docker/requirements.Dockerfile index 1680377..02e52d1 100644 --- a/docker/requirements.Dockerfile +++ b/docker/requirements.Dockerfile @@ -6,7 +6,7 @@ RUN python -m pip install --upgrade pip COPY ./docker/ /tmp -RUN pip install --no-cache-dir -r ./tmp/requirements.txt +RUN pip install --no-cache-dir -r ./tmp/requirements-development.txt RUN python -c "import nltk; nltk.download('stopwords');" RUN python -m spacy download pt_core_news_sm RUN find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf diff --git a/tests/post.py b/tests/post.py deleted file mode 100644 index 9e113fb..0000000 --- a/tests/post.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -This file is used to test bot post requests -To use it, you must have the actions server and bot running -And execute -$ python3 post.py -""" - -import requests -import json - -post_url = "http://localhost:5005/webhooks/rest/webhook" - -headers = {"content-type": "application/json"} - -params = {"message": "constante"} - -r = requests.post(post_url, data=json.dumps(params), headers=headers) - -print(r.text) diff --git a/tests/test_stories.yml b/tests/test_stories.yml deleted file mode 100644 index d46e39b..0000000 --- a/tests/test_stories.yml +++ /dev/null @@ -1,91 +0,0 @@ -#### 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 bf4888e8e62e0f141f37e3d727d7bc009b44b0fc Mon Sep 17 00:00:00 2001 From: Martha Date: Thu, 11 Feb 2021 16:31:27 -0300 Subject: [PATCH 36/36] Create network for bot and actions servers to comunicate and improve how we run bot Signed-off-by: Martha Co-authored-by: fabiola --- Makefile | 3 ++- docker-compose.yml | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 753f018..6e9ee1e 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,8 @@ build-coach: run-shell: ## Run bot in shell, sucessful when shows "Bot loaded. Type a message and press enter (use '/stop' to exit): " - docker-compose run --rm --service-ports bot make shell + docker-compose run -d actions make actions + docker-compose run bot make shell run-api: docker-compose run --rm --service-ports bot make api diff --git a/docker-compose.yml b/docker-compose.yml index f692a3a..c585b00 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,6 +19,8 @@ services: restart: unless-stopped volumes: - ./bot/:/bot/ + networks: + - bot-network ports: - 5006:5006 - 5004:5004 @@ -33,6 +35,8 @@ services: build: context: . dockerfile: ./docker/actions.Dockerfile + networks: + - bot-network ports: - 5055:5055 volumes: @@ -55,4 +59,8 @@ services: - GIT_PYTHON_REFRESH=quiet depends_on: - actions - command: sh -c "make x" \ No newline at end of file + command: sh -c "make x" + +networks: + bot-network: + driver: bridge \ No newline at end of file