Skip to content

Commit

Permalink
Merge branch 'master' of gitlab.com:pencillabs/ej/ej-bot
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiola-m committed Feb 15, 2021
2 parents 886dfe4 + 3c7bc61 commit 80b7ff1
Show file tree
Hide file tree
Showing 27 changed files with 425 additions and 246 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
./bot/models
./bot/train_test_split
./bot/results/
*/__pycache__/
.pytest_cache/
*.pyc
*.log
*.db
*.db-shm
*.db-wal
models
results/
train_test_split
18 changes: 14 additions & 4 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
image: docker:stable
image: docker:latest

services:
- docker:dind
Expand All @@ -11,18 +11,28 @@ style:
image: python:3.7-alpine
stage: test
before_script:
- apk add musl-dev gcc
- pip install black
stage: test
script:
- black --check .


test:
image: python:3.7-alpine
before_script:
- apt update && apt install -y gcc make
- make first-run
- docker info
- apk update
- apk upgrade
- 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
- make run-test-core
- make test-actions
15 changes: 13 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,40 +21,51 @@ 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

build-bot:
docker-compose build --no-cache bot

build-x:
docker-compose build --no-cache x

build-coach:
docker-compose build --no-cache 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

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
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

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

Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
```


9 changes: 8 additions & 1 deletion bot/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -20,8 +24,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
Expand Down
Empty file added bot/__init__.py
Empty file.
1 change: 1 addition & 0 deletions bot/actions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .actions import ActionSetupConversation, ActionAskVote, FormValidationAction
100 changes: 82 additions & 18 deletions bot/actions/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +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'

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 []
class ActionAskVote(Action):
def name(self) -> Text:
return "action_ask_vote"

def run(
self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
) -> List[EventType]:
buttons = [
{"title": "Concordar", "payload": "Concordar"},
{"title": "Discordar", "payload": "Discordar"},
{"title": "Pular", "payload": "Pular"},
]

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 ["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")
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}
18 changes: 17 additions & 1 deletion bot/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,20 @@ pipeline:
- name: DIETClassifier
epochs: 55
- name: EntitySynonymMapper
- name: ResponseSelector
- 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
30 changes: 30 additions & 0 deletions bot/data/nlu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ nlu:
- intent: start
examples: |
- começar a conversar
- oi
- olá
- hey
- Bom dia
- Boa tarde
- Boa noite
- Oi, tudo bem?
- alo
- ois
- oie
- intent: agree
examples: |
Expand All @@ -24,9 +34,29 @@ nlu:
- jamais
- discordo
- discordar
- não concordo
- intent: pass
examples: |
- não sei
- pular
- pulo
- passa
- próxima pergunta
- 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
4 changes: 4 additions & 0 deletions bot/data/rules.yml
Original file line number Diff line number Diff line change
@@ -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
25 changes: 10 additions & 15 deletions bot/data/stories.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
- intent: agree
- action: action_setup_conversation
- action: vote_form
- active_loop: vote_form
- active_loop: null
- slot_was_set:
- vote: null
Loading

0 comments on commit 80b7ff1

Please sign in to comment.