diff --git a/Makefile b/Makefile index 774d68a9..96d2d34f 100644 --- a/Makefile +++ b/Makefile @@ -29,11 +29,11 @@ build-coach: docker-compose build --no-cache coach build-analytics: - docker-compose up -d elasticsearch - docker-compose up -d rabbitmq - docker-compose up -d rabbitmq-consumer - docker-compose up -d kibana + make run-analytics make config-elastic + # This line should be removed ASAP + sleep 10 + # Run this command only when kibana is up and ready. A script is needed. make config-kibana config-elastic: @@ -45,6 +45,12 @@ config-kibana: $(info Acesse o KIBANA em: http://localhost:5601) $(info ) +run-analytics: + docker-compose up -d elasticsearch + docker-compose up -d rabbitmq + docker-compose up -d rabbitmq-consumer + docker-compose up -d kibana + run-shell: docker-compose run --rm --service-ports bot make shell @@ -55,18 +61,17 @@ run-actions: docker-compose run --rm --service-ports bot make actions run-x: - docker-compose run --rm --service-ports bot make x + docker-compose run --rm --service-ports x make x run-webchat: $(info ) $(info Executando Bot com Webchat.) $(info ) docker-compose run -d --rm --service-ports bot-webchat + docker-compose up -d webchat $(info ) - $(info Caso o FIREFOX não seja iniciado automáticamente, abra o seguinte arquivo com seu navegador:) - $(info modules/webchat/index.html) + $(info Acesse o WEBCHAT em: http://localhost:5010) $(info ) - firefox modules/webchat/index.html run-telegram: docker-compose run -d --rm --service-ports bot_telegram make telegram @@ -77,6 +82,12 @@ run-notebooks: $(info Acesse o KIBANA em: http://localhost:8888) $(info ) +run-rocket: + docker-compose up -d rocketchat bot-rocket + $(info ) + $(info Acesse o ROCKETCHAT em: http://localhost:5003) + $(info ) + train: mkdir -p bot/models docker-compose up --build coach diff --git a/bot/Makefile b/bot/Makefile index cf1e5dfe..2677c17f 100644 --- a/bot/Makefile +++ b/bot/Makefile @@ -36,17 +36,22 @@ validate: # MENSAGEIROS shell: - rasa shell -m models/ -vv --endpoints endpoints.yml --port 5004 + rasa shell -m models/ -vv --endpoints endpoints.yml --port 5006 telegram: rasa run -m models/ -vv --port 5001 --credentials credentials.yml \ --endpoints endpoints.yml webchat: - rasa run -m models/ -vv --endpoints endpoints.yml --credentials credentials.yml --port 5005 --cors '*' + rasa run -m models/ -vv --endpoints endpoints.yml --credentials credentials.yml --port 5007 --cors '*' api: - rasa run -m models/ -vv --endpoints endpoints.yml --enable-api + rasa run -m models/ -vv --endpoints endpoints.yml --enable-api --port 5006 + +rocket: + python /modules/rocketchat/bot_config.py + rasa run -m models/ -vv --endpoints endpoints.yml --credentials credentials.yml --port 5005 --cors '*' + # ACTIONS actions: diff --git a/bot/actions/action_telefone.py b/bot/actions/action_telefone.py index b618b516..0b6333c3 100644 --- a/bot/actions/action_telefone.py +++ b/bot/actions/action_telefone.py @@ -21,7 +21,7 @@ def run( domain: Dict[Text, Any], ) -> List[Dict[Text, Any]]: - telefone = tracker.get_slot('telefone') + telefone = tracker.get_slot("telefone") try: dispatcher.utter_message("O seu telefone é {}?".format(telefone)) diff --git a/bot/actions/forms.py b/bot/actions/forms.py index c64c1c38..470b8bb0 100644 --- a/bot/actions/forms.py +++ b/bot/actions/forms.py @@ -29,10 +29,10 @@ def required_slots(tracker: Tracker) -> List[Text]: def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]: """A dictionary to map required slots to - - an extracted entity - - intent: value pairs - - a whole message - or a list of them, where a first match will be picked""" + - an extracted entity + - intent: value pairs + - a whole message + or a list of them, where a first match will be picked""" return { "cpf": self.from_text(not_intent="cancelar"), "data_nascimento": self.from_text(not_intent="cancelar"), @@ -45,7 +45,7 @@ def submit( domain: Dict[Text, Any], ) -> List[Dict]: """Define what the login form will do after - all required slots are filled""" + all required slots are filled""" cpf = tracker.get_slot("cpf") data_nascimento = tracker.get_slot("data_nascimento") @@ -94,4 +94,3 @@ def validate_data_nascimento( # validation failed, set this slot to None, meaning the # user will be asked for the slot again return {"data_nascimento": None} - diff --git a/bot/credentials.yml b/bot/credentials.yml index 923995a4..827f866d 100644 --- a/bot/credentials.yml +++ b/bot/credentials.yml @@ -13,4 +13,10 @@ socketio: bot_message_evt: bot_uttered session_persistence: true + +rocketchat: + user: "bot" + password: "bot" + server_url: "http://rocketchat:3000" + rest: diff --git a/bot/domain.yml b/bot/domain.yml index 775c4c99..0d9668f9 100644 --- a/bot/domain.yml +++ b/bot/domain.yml @@ -1,5 +1,5 @@ session_config: - session_expiration_time: 60.0 + session_expiration_time: 60 carry_over_slots_to_new_session: true intents: - cumprimentar @@ -53,13 +53,14 @@ entities: - telefone - cpf - dada_nascimento +- relationship slots: - telefone: - type: unfeaturized cpf: type: unfeaturized data_nascimento: type: unfeaturized + telefone: + type: unfeaturized responses: utter_fallback: - text: "Desculpe, ainda não sei falar sobre isso ou talvez não consegui entender\ @@ -176,25 +177,28 @@ responses: \ aprender! Acessa lá: https://github.com/lappis-unb/rasa-ptbr-boilerplate\n\ \n Ah e eu sou Open Source ;)" utter_pergunta_cancelar: - - text: Entendi. Você deseja cancelar? + - text: Entendi. Você deseja cancelar? utter_login_form: - - text: Ok, Vou te pedir algumas informações. + - text: Ok, Vou te pedir algumas informações. utter_ask_cpf: - - text: Qual o seu CPF? + - text: Qual o seu CPF? utter_errado_cpf_formato: - - text: Desculpe, o formato informado do CPF não está correto, digite apenas números ou usando '000.000.000-00'. + - text: Desculpe, o formato informado do CPF não está correto, digite apenas números + ou usando '000.000.000-00'. utter_errado_cpf_invalido: - - text: Desculpe, o valor informado do CPF está inválido. + - text: Desculpe, o valor informado do CPF está inválido. utter_ask_data_nascimento: - - text: Qual a sua data de nascimento? + - text: Qual a sua data de nascimento? utter_errado_data_nascimento: - - text: Desculpe, o valor informado para a data de nascimento não está correto, digite usando 'dd/mm/aaaa'. + - text: Desculpe, o valor informado para a data de nascimento não está correto, + digite usando 'dd/mm/aaaa'. utter_finaliza_forms: - - text: Ótimo, seus dados estão armazenado nos meus slots. Terminei o formulário ;) + - text: Ótimo, seus dados estão armazenado nos meus slots. Terminei o formulário + ;) utter_forms_cancelado: - - text: Ok, forms cancelado. Podemos voltar a conversar sobre outros assuntos ;) + - text: Ok, forms cancelado. Podemos voltar a conversar sobre outros assuntos ;) actions: - action_teste - action_telefone forms: - - login_form +- login_form diff --git a/docker-compose.yml b/docker-compose.yml index b02c12ec..60b37bc1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,7 +22,7 @@ services: volumes: - ./bot/:/bot/ ports: - - 5004:5004 + - 5006:5006 depends_on: - actions @@ -37,6 +37,8 @@ services: - ./bot/:/bot/ ports: - 5002:5002 + env_file: + - env/rasax.env depends_on: - actions command: sh -c "make x" @@ -62,11 +64,25 @@ services: volumes: - ./bot/:/bot/ ports: - - 5005:5005 + - 5007:5007 depends_on: - actions command: sh -c "make webchat" + # ============================ WebChat Bot ================================= + # Specific Rasa bot integrated with WebChat. + bot-rocket: + build: + context: . + dockerfile: ./docker/bot.Dockerfile + volumes: + - ./bot/:/bot/ + ports: + - 5005:5005 + depends_on: + - actions + command: sh -c "make rocket" + # =============================== Analytics ================================= # Analitics ElasticSearch Stack. elasticsearch: @@ -125,6 +141,16 @@ services: - env/rabbitmq-consumer.env command: python3 /opt/scripts/consume_bot_messages.py + + # ============================ Webchat Page ================================= + # A container to run webchat html page + webchat: + image: nginx + ports: + - 5010:80 + volumes: + - ./modules/webchat:/usr/share/nginx/html + # ============================ Telegram Bot ================================= # Specific Rasa bot integrated with Telegram. bot_telegram: @@ -155,6 +181,60 @@ services: ports: - 8888:8888 + # =============================== Rocket.Chat ================================= + # Rocket.Chat instance and database + rocketchat: + image: rocketchat/rocket.chat:3.7.1 + command: > + bash -c + "for i in `seq 1 30`; do + node main.js && + s=$$? && break || s=$$?; + echo \"Tried $$i times. Waiting 5 secs...\"; + sleep 5; + done; (exit $$s)" + restart: unless-stopped + volumes: + - rocket_uploads:/app/uploads + environment: + - PORT=3000 + - ROOT_URL=http://localhost:3000 + - MONGO_URL=mongodb://mongo:27017/rocketchat + - MONGO_OPLOG_URL=mongodb://mongo:27017/local + - ADMIN_USERNAME=admin + - ADMIN_PASS=admin + - ADMIN_EMAIL=mail@mail.com + depends_on: + - mongo + - mongo-init-replica + ports: + - 5003:3000 + + mongo: + image: mongo:4.0 + restart: unless-stopped + volumes: + - mongo_data:/data/db + command: mongod --smallfiles --oplogSize 128 --replSet rs0 --storageEngine=mmapv1 + + # this container's job is just run the command to initialize the replica set. + # it will run the command and remove himself (it will not stay running) + mongo-init-replica: + image: mongo:4.0 + command: > + bash -c + "for i in `seq 1 30`; do + mongo mongo/rocketchat --eval \" + rs.initiate({ + _id: 'rs0', + members: [ { _id: 0, host: 'localhost:27017' } ]})\" && + s=$$? && break || s=$$?; + echo \"Tried $$i times. Waiting 5 secs...\"; + sleep 5; + done; (exit $$s)" + depends_on: + - mongo + volumes: notebook_models: mongo_data: @@ -162,3 +242,4 @@ volumes: esbackup: esdata: driver: local + rocket_uploads: diff --git a/docker/actions.Dockerfile b/docker/actions.Dockerfile index 9cf75871..6281b0c1 100644 --- a/docker/actions.Dockerfile +++ b/docker/actions.Dockerfile @@ -1,6 +1,6 @@ FROM botrequirements -COPY ./bot/actions/actions.py /bot/actions/actions.py +COPY ./bot/actions/ /bot/actions/ COPY ./bot/Makefile /bot/Makefile WORKDIR /bot diff --git a/docker/requirements.Dockerfile b/docker/requirements.Dockerfile index 37cebc2a..b6c58eb3 100644 --- a/docker/requirements.Dockerfile +++ b/docker/requirements.Dockerfile @@ -4,7 +4,7 @@ COPY ./requirements.txt /tmp COPY ./x-requirements.txt /tmp RUN apt-get update && \ - apt-get install -y gcc make build-essential && \ + apt-get install -y gcc make build-essential git && \ python -m pip install --upgrade pip && \ pip install --no-cache-dir -r /tmp/requirements.txt && \ pip install --no-cache-dir -r /tmp/x-requirements.txt && \ diff --git a/env/rasax.env b/env/rasax.env new file mode 100644 index 00000000..8c770771 --- /dev/null +++ b/env/rasax.env @@ -0,0 +1 @@ +GIT_PYTHON_REFRESH=quiet \ No newline at end of file diff --git a/modules/analytics/setup_elastic.py b/modules/analytics/setup_elastic.py index c1ec2869..aa61f296 100644 --- a/modules/analytics/setup_elastic.py +++ b/modules/analytics/setup_elastic.py @@ -45,7 +45,10 @@ if not es.indices.exists(index_name): logger.debug( es.indices.create( - index=index_name, ignore=400, params=param, body=settings, + index=index_name, + ignore=400, + params=param, + body=settings, ) ) logger.info("Created Index") diff --git a/modules/rabbitmq/consumer/consume_bot_messages.py b/modules/rabbitmq/consumer/consume_bot_messages.py index 2c776b38..0d91e868 100644 --- a/modules/rabbitmq/consumer/consume_bot_messages.py +++ b/modules/rabbitmq/consumer/consume_bot_messages.py @@ -29,7 +29,10 @@ connection = pika.BlockingConnection( pika.ConnectionParameters( - host="rabbitmq", credentials=credentials, connection_attempts=20, retry_delay=5, + host="rabbitmq", + credentials=credentials, + connection_attempts=20, + retry_delay=5, ) ) diff --git a/modules/rocketchat/bot_config.py b/modules/rocketchat/bot_config.py index c86b4bdd..c2dd4868 100755 --- a/modules/rocketchat/bot_config.py +++ b/modules/rocketchat/bot_config.py @@ -7,7 +7,7 @@ # == Log Config == -logger = logging.getLogger("Bot Config") +logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() @@ -44,7 +44,7 @@ admin_name = os.getenv("ROCKETCHAT_ADMIN_USERNAME", "admin") admin_password = os.getenv("ROCKETCHAT_ADMIN_PASSWORD", "admin") -rasa_url = os.getenv("RASA_URL", "http://bot:5005/webhooks/rocketchat/webhook") +rasa_url = os.getenv("RASA_URL", "http://bot-rocket:5005/webhooks/rocketchat/webhook") user_header = None @@ -117,44 +117,11 @@ def create_bot_user(): print("User already created.") api_post( - "users.setAvatar", {"avatarUrl": bot["avatar"], "username": bot["username"]}, + "users.setAvatar", + {"avatarUrl": bot["avatar"], "username": bot["username"]}, ) -def create_livechat_agent(): - response = api_post("livechat/users/agent", {"username": bot["username"]}) - return response["user"]["_id"] - - -def configure_livechat(): - # Enable Livechat - api_post("settings/Livechat_enabled", {"value": True}) - - # Disable show pre-registration form - api_post("settings/Livechat_registration_form", {"value": False}) - - # Change Livechat Color - api_post("settings/Livechat_title_color", {"value": "#039046", "editor": "color"}) - - # Change Livechat Title - api_post("settings/Livechat_title", {"value": bot["name"]}) - - # Disable Livechat Email display - api_post("settings/Livechat_show_agent_email", {"value": False}) - - # Disable file upload - api_post("settings/Livechat_fileupload_enabled", {"value": False}) - - # Change Livechat Webhook URL - api_post("settings/Livechat_webhookUrl", {"value": rasa_url}) - - # Activate Livechat Webhook Send Request on Visitor Message - api_post("settings/Livechat_webhook_on_visitor_message", {"value": True}) - - # Activate Livechat Webhook Send Request on Agent Messages - api_post("settings/Livechat_webhook_on_agent_message", {"value": True}) - - def configure_webhooks(): webooks = api_get("integrations.list") @@ -192,61 +159,36 @@ def configure_rocketchat(): api_post("settings/API_Enable_CORS", {"value": True}) -def create_department(bot_agent_id): - get_departments_url = host + "/api/v1/livechat/department" - - get_departments_response = requests.get(get_departments_url, headers=user_header) - - number_of_departments = len(get_departments_response.json()["departments"]) - - if number_of_departments == 0: - api_post( - "livechat/department", - { - "department": { - "enabled": True, - "showOnRegistration": True, - "name": "department", - "description": "default department", - }, - "agents": [ - { - "agentId": bot_agent_id, - "username": bot["username"], - "count": 0, - "order": 0, - } - ], - }, - ) - - if __name__ == "__main__": logger.info("===== Automatic env configuration =====") - try: - user_header = get_authentication_token() - except Exception: - print("\n\n --------- Rocket Chat Unavailable! --------\n\n") + rocket_available = False - if user_header: - logger.info(">> Create user") - create_bot_user() + while not rocket_available: + try: + user_header = get_authentication_token() + rocket_available = True + except Exception: + import time - logger.info(">> Create livechat agent") - bot_agent_id = create_livechat_agent() + logger.info("\n\n --------- Rocket Chat Unavailable! --------\n\n") + logger.info(">> Waiting for 3 seconds...") + time.sleep(3) - logger.info(">> Configure livechat") - configure_livechat() + logger.info(">> Connected to Rocket Instance") - logger.info(">> Configure Rocketchat") - configure_rocketchat() + if user_header: + try: + logger.info(">> Create user") + create_bot_user() - logger.info(">> Configure Webhooks") - configure_webhooks() + logger.info(">> Configure Rocketchat") + configure_rocketchat() - logger.info(">> Create livechat department") - create_department(bot_agent_id) + logger.info(">> Configure Webhooks") + configure_webhooks() + except Exception as e: + logger.error(f"Problem while trying to configure bot in Rocketchat: {e}") else: - logger.error("Login Failed") + logger.error(">> Login Failed") diff --git a/modules/webchat/index.html b/modules/webchat/index.html index a1c14504..6549aab5 100644 --- a/modules/webchat/index.html +++ b/modules/webchat/index.html @@ -6,12 +6,12 @@

Seja bem vindo ao BOILERPLATE integrado com webchat

Você deve ver uma bola azul no canto inferior direito do seu navegador.
- +