├── data └── .keep ├── env ├── bot.env └── bot-telegram.env ├── bot ├── actions │ ├── __init__.py │ └── custom_action_example.py ├── components │ ├── __init__.py │ ├── labels.yml │ └── sentiment_analyzer.py ├── requirements.txt ├── rasalit-requirements.txt ├── .env ├── credentials.yml ├── endpoints.yml ├── data │ ├── rules.yml │ ├── nlu-response-selectors.yml │ ├── stories.yml │ ├── nlu.yml │ └── nlu-chitchat.yml ├── config.yml ├── tests │ └── test_stories.yml ├── Makefile └── domain.yml ├── modules └── webchat │ ├── assets │ ├── bot.png │ └── launcher_button.svg │ └── index.html ├── .github ├── PULL_REQUEST_TEMPLATE.MD ├── ISSUE_TEMPLATE │ ├── funcionalidade.md │ └── bug_report.md └── workflows │ └── build.yml ├── docker ├── actions.Dockerfile └── bot.Dockerfile ├── docs └── scripts.md ├── docker-compose.yml ├── docker-compose-telegram.yml ├── Makefile ├── docker-compose-rocket.yml ├── .gitignore ├── CONTRIBUTING.md ├── scripts └── config_env.py ├── README.md └── LICENSE /data/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /env/bot.env: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bot/actions/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bot/components/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bot/requirements.txt: -------------------------------------------------------------------------------- 1 | rasa==${RASA_VERSION} 2 | rasa-model-report==1.5.0 -------------------------------------------------------------------------------- /bot/rasalit-requirements.txt: -------------------------------------------------------------------------------- 1 | git+git://github.com/RasaHQ/rasalit@main 2 | whatlies==0.6.3 3 | -------------------------------------------------------------------------------- /modules/webchat/assets/bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lappis-unb/rasa-ptbr-boilerplate/HEAD/modules/webchat/assets/bot.png -------------------------------------------------------------------------------- /bot/.env: -------------------------------------------------------------------------------- 1 | MONGO_HOST=mongo 2 | MONGO_PORT=27017 3 | MONGO_USERNAME= 4 | MONGO_PASSWORD= 5 | RASA_VERSION=3.6.13 6 | RASA_SDK_VERSION=3.6.2 -------------------------------------------------------------------------------- /env/bot-telegram.env: -------------------------------------------------------------------------------- 1 | TELEGRAM_BOT_USERNAME=lappisbot 2 | TELEGRAM_TOKEN=token 3 | TELEGRAM_WEBHOOK=your_webhook_server/webhooks/telegram/webhook -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.MD: -------------------------------------------------------------------------------- 1 | ## Descrição 2 | 3 | Descrição completa do que foi feito 4 | 5 | ## Resolve (Issues) 6 | 7 | Issues que foram resolvidas com o PR 8 | -------------------------------------------------------------------------------- /docker/actions.Dockerfile: -------------------------------------------------------------------------------- 1 | ARG RASA_SDK_VERSION 2 | FROM rasa/rasa-sdk:${RASA_SDK_VERSION} 3 | 4 | WORKDIR /bot 5 | COPY ./bot /bot 6 | 7 | ENTRYPOINT [] 8 | CMD "python -m rasa_sdk -p 5055" 9 | -------------------------------------------------------------------------------- /docker/bot.Dockerfile: -------------------------------------------------------------------------------- 1 | ARG RASA_VERSION 2 | FROM rasa/rasa:${RASA_VERSION}-full 3 | 4 | WORKDIR /bot 5 | COPY ./bot /bot 6 | COPY ./modules /modules 7 | 8 | USER root 9 | RUN apt-get install make && \ 10 | make install 11 | 12 | ENTRYPOINT [] 13 | CMD [] 14 | -------------------------------------------------------------------------------- /bot/credentials.yml: -------------------------------------------------------------------------------- 1 | socketio: 2 | user_message_evt: user_uttered 3 | bot_message_evt: bot_uttered 4 | session_persistence: true 5 | 6 | rest: 7 | 8 | #telegram: 9 | # access_token: ${TELEGRAM_TOKEN} 10 | # verify: ${TELEGRAM_BOT_USERNAME} 11 | # webhook_url: ${TELEGRAM_WEBHOOK} 12 | 13 | -------------------------------------------------------------------------------- /bot/endpoints.yml: -------------------------------------------------------------------------------- 1 | # Configuração para ambiente local 2 | action_endpoint: 3 | url: "http://actions:5055/webhook" 4 | 5 | tracker_store: 6 | type: mongod 7 | url: mongodb://${MONGO_HOST}:${MONGO_PORT} 8 | db: "bot" 9 | username: ${MONGO_USERNAME} 10 | password: ${MONGO_PASSWORD} 11 | auth_source: "bot" 12 | 13 | event_broker: 14 | type: "file" 15 | path: "rasa_events.log" -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/funcionalidade.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Funcionalidade 3 | about: Sugerir uma ideia para o projeto 4 | title: '' 5 | labels: evolucao 6 | assignees: '' 7 | 8 | --- 9 | 10 | # Problema 11 | Descreva o problema ou melhoria 12 | 13 | # Sugestão de solução 14 | Fala um pouco o que seria uma boa solução (não necessariamente tecnicamente) 15 | 16 | ## Tarefas 17 | - [ ] Alguns passos para a solução 18 | - [ ] Critério de aceitação etc 19 | 20 | 21 | > Usem o espaço da issue para discutir sobre as soluções 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Crie um aviso para nos ajudar a melhorar 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Descreva o bug** 11 | Uma descrição clara e consisa sobre o que o bug é. 12 | 13 | **Para reproduzir o bug** 14 | Passo-a-passo para reproduzir o comportamento do bug: 15 | 1. Vá para '...' 16 | 2. Clique em '....' 17 | 4. Veja o erro 18 | 19 | **Comportamento esperado** 20 | Uma descrição clara e consisa sobre o que deveria acontecer (ao invés do bug). 21 | 22 | **Screenshots** 23 | Se necessário. 24 | 25 | **Ambiente:** 26 | - SO: [e.g. Ubuntu] 27 | - Versão [e.g. 22] 28 | 29 | **Contexto Adicional** 30 | Adicione o contexto relacionado ao problema. 31 | -------------------------------------------------------------------------------- /bot/data/rules.yml: -------------------------------------------------------------------------------- 1 | version: "3.1" 2 | rules: 3 | # Response selectors 4 | - rule: explica 5 | steps: 6 | - intent: explica 7 | - action: utter_explica 8 | # Fallback 9 | - rule: Pedir para reformular a mensagem caso NLU não entenda 10 | steps: 11 | - intent: nlu_fallback 12 | - action: utter_nlu_fallback 13 | # Forms 14 | - rule: Ativa formulário 15 | steps: 16 | - intent: exemplo_forms 17 | - action: utter_exemplo_forms 18 | - action: exemplo_forms 19 | - active_loop: exemplo_forms 20 | - rule: Envia formulário 21 | condition: 22 | - active_loop: exemplo_forms 23 | steps: 24 | - action: exemplo_forms 25 | - active_loop: null 26 | - action: utter_submit_exemplo_forms 27 | - action: utter_slots_exemplo_forms 28 | -------------------------------------------------------------------------------- /docs/scripts.md: -------------------------------------------------------------------------------- 1 | ## Scripts 2 | 3 | ### Descrição 4 | 5 | O script serve para automatizar as configurações do projeto através dos endpoints disponibilizados pela rocketchat: 6 | - [User Endpoints](https://developer.rocket.chat/reference/api/rest-api/endpoints/team-collaboration-endpoints/users-endpoints) 7 | - [Livechat Endpoints](https://developer.rocket.chat/reference/api/rest-api/endpoints/omnichannel/livechat-endpoints) 8 | 9 | Funcionalidades do **script**: 10 | - [x] Configurar Bot 11 | - [x] Configurar Livechat 12 | - [x] Configurar Departamento 13 | 14 | ### Passo-passo 15 | 16 | Valores **default**:
17 | - *admin_name* : boss 18 | - *admin_password* : boss 19 | - *bot_name* : rasa_bot 20 | - *bot_password* : rasa_bot 21 | 22 | ``` sh 23 | python3 scripts/config_env.py 24 | ``` 25 | 26 | Argumentos aceitos:
27 | - *-an* : admin_name 28 | - *-ap* : admin_password 29 | - *-bn* : bot_name 30 | - *-bp* : bot_password 31 | 32 | Exemplo: 33 | ``` sh 34 | python3 scripts/config_env.py -an boss -ap boss -bp rasa_bot -bp rasa_bot 35 | ``` 36 | 37 | ### Pip 38 | 39 | - json 40 | - logging 41 | - requests 42 | - argparse 43 | -------------------------------------------------------------------------------- /bot/components/labels.yml: -------------------------------------------------------------------------------- 1 | positivo: 2 | - gostei muito desse bot 3 | - me ajudou bastante 4 | - amei demais 5 | - foi muito util 6 | - melhor bot 7 | - gostei 8 | - você é muito educado 9 | - voce e muito educado 10 | - me ajudou muito 11 | - você é demais 12 | - você é lindo 13 | - voce e lindo 14 | - voce e maravilhoso 15 | - vc é demais 16 | - vc e demais 17 | - vc é bonito 18 | - vc é maravilhoso 19 | - adorei você 20 | - amei você 21 | - adorei voce 22 | - amei voce 23 | - adorei vc 24 | - amei vc 25 | negativo: 26 | - não 27 | - nao 28 | - nego 29 | - cancelo 30 | - negativo 31 | - não gostei 32 | - bot inutil 33 | - não serviu pra nada 34 | - não meu ajudou 35 | - não funciona 36 | - bot sem classe 37 | - imbecil 38 | - nojento 39 | - chato 40 | - babaca 41 | - bot feio 42 | - bot, burro 43 | - Desisto 44 | - para 45 | - cancela 46 | - Sai disso 47 | - Me tira daqui 48 | - Para com isso 49 | neutro: 50 | - tanto faz 51 | - irrelevante pra mim 52 | - normalzinho 53 | - bot normal 54 | - nada a declarar 55 | - foi normal a conversa 56 | - nada de mais 57 | - nem fede e nem cheira 58 | -------------------------------------------------------------------------------- /bot/actions/custom_action_example.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Text, Dict, List 2 | 3 | from rasa_sdk import Action, Tracker 4 | from rasa_sdk.executor import CollectingDispatcher 5 | from rasa_sdk.events import UserUtteranceReverted 6 | 7 | 8 | class ActionExemplo(Action): 9 | def name(self) -> Text: 10 | return "action_exemplo" 11 | 12 | def run( 13 | self, 14 | dispatcher: CollectingDispatcher, 15 | tracker: Tracker, 16 | domain: Dict[Text, Any], 17 | ) -> List[Dict[Text, Any]]: 18 | dispatcher.utter_message(text="Esta mensagem esta sendo enviada do RASA SDK!!!") 19 | return [] 20 | 21 | 22 | class ActionDefaultFallback(Action): 23 | """Executes the fallback action and goes back to the previous state 24 | of the dialogue""" 25 | 26 | def name(self) -> Text: 27 | return "action_default_fallback" 28 | 29 | async def run( 30 | self, 31 | dispatcher: CollectingDispatcher, 32 | tracker: Tracker, 33 | domain: Dict[Text, Any], 34 | ) -> List[Dict[Text, Any]]: 35 | dispatcher.utter_message(template="utter_core_fallback") 36 | 37 | # Revert user message which led to fallback. 38 | return [UserUtteranceReverted()] 39 | -------------------------------------------------------------------------------- /bot/config.yml: -------------------------------------------------------------------------------- 1 | # https://rasa.com/docs/rasa/nlu/components/ 2 | recipe: default.v1 3 | 4 | language: br 5 | 6 | # See https://rasa.com/docs/rasa/tuning-your-model for more information. 7 | pipeline: 8 | - name: WhitespaceTokenizer 9 | - name: RegexFeaturizer 10 | - name: LexicalSyntacticFeaturizer 11 | - name: CountVectorsFeaturizer 12 | analyzer: char_wb 13 | min_ngram: 1 14 | max_ngram: 4 15 | - name: DIETClassifier 16 | epochs: 80 17 | model_confidence: softmax 18 | constrain_similarities: true 19 | tensorboard_log_directory: ".tensorboard_diet" 20 | tensorboard_log_level: "epoch" 21 | - name: EntitySynonymMapper 22 | - name: ResponseSelector 23 | model_confidence: softmax 24 | epochs: 100 25 | constrain_similarities: true 26 | - name: FallbackClassifier 27 | threshold: 0.7 28 | ambiguity_threshold: 0.2 29 | 30 | # https://rasa.com/docs/rasa/core/policies/ 31 | policies: 32 | - name: MemoizationPolicy 33 | - name: TEDPolicy 34 | max_history: 6 35 | epochs: 60 36 | model_confidence: softmax 37 | tensorboard_log_directory: ".tensorboard_ted" 38 | tensorboard_log_level: "epoch" 39 | constrain_similarities: true 40 | - name: RulePolicy 41 | core_fallback_threshold: 0.7 42 | core_fallback_action_name: "action_default_fallback" 43 | enable_fallback_prediction: true 44 | assistant_id: 20230606-041623-synchronic-underpass 45 | -------------------------------------------------------------------------------- /modules/webchat/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |

Seja bem vindo ao BOILERPLATE integrado com webchat

6 | Você deve ver uma bola azul no canto inferior direito do seu navegador. 7 |
8 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | 3 | services: 4 | # ================================= Bot ===================================== 5 | # Generic Rasa bot, used to run console for example. 6 | bot: 7 | build: 8 | context: . 9 | dockerfile: ./docker/bot.Dockerfile 10 | args: 11 | RASA_VERSION: ${RASA_VERSION} 12 | container_name: bot 13 | env_file: 14 | - ./bot/.env 15 | volumes: 16 | - ./bot/:/bot/ 17 | ports: 18 | - 5005:5005 19 | depends_on: 20 | - actions 21 | - mongo 22 | networks: 23 | - bot 24 | # ============================ Tracker Store================================= 25 | # A mongodb container as rasa tracker store. 26 | mongo: 27 | container_name: mongo 28 | image: mongo:6.0 29 | restart: unless-stopped 30 | env_file: 31 | - ./bot/.env 32 | ports: 33 | - 27017:27017 34 | networks: 35 | - bot 36 | volumes: 37 | - ./data/db:/data/db 38 | 39 | # ================================= Actions ================================= 40 | # Rasa middleware used to connect with external APIs. 41 | actions: 42 | build: 43 | context: . 44 | dockerfile: ./docker/actions.Dockerfile 45 | args: 46 | RASA_SDK_VERSION: ${RASA_SDK_VERSION} 47 | container_name: actions 48 | env_file: 49 | - ./bot/.env 50 | ports: 51 | - 5055:5055 52 | volumes: 53 | - ./bot:/bot 54 | command: sh -c "python -m rasa_sdk --actions actions" 55 | networks: 56 | - bot 57 | 58 | # ============================ Webchat Page ================================= 59 | # A container to run webchat html page 60 | webchat: 61 | image: nginx 62 | ports: 63 | - 5000:80 64 | volumes: 65 | - ./modules/webchat:/usr/share/nginx/html 66 | networks: 67 | - bot 68 | 69 | volumes: 70 | mongo_data: 71 | rocket_uploads: 72 | 73 | 74 | networks: 75 | bot: 76 | driver: bridge 77 | -------------------------------------------------------------------------------- /docker-compose-telegram.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | 3 | services: 4 | # ================================= Bot ===================================== 5 | # Generic Rasa bot, used to run console for example. 6 | bot: 7 | build: 8 | context: . 9 | dockerfile: ./docker/bot.Dockerfile 10 | container_name: bot 11 | env_file: 12 | - ./env/bot.env 13 | volumes: 14 | - ./bot/:/bot/ 15 | ports: 16 | - 5005:5005 17 | depends_on: 18 | - actions 19 | - mongo 20 | networks: 21 | - bot 22 | # ============================ Tracker Store================================= 23 | # A mongodb container as rasa tracker store. 24 | mongo: 25 | container_name: mongo 26 | image: mongo:6.0 27 | restart: unless-stopped 28 | env_file: 29 | - env/bot.env 30 | ports: 31 | - 27017:27017 32 | networks: 33 | - bot 34 | volumes: 35 | - ./data/db:/data/db 36 | 37 | # ================================= Actions ================================= 38 | # Rasa middleware used to connect with external APIs. 39 | actions: 40 | build: 41 | context: . 42 | dockerfile: ./docker/actions.Dockerfile 43 | container_name: actions 44 | env_file: 45 | - ./env/bot.env 46 | ports: 47 | - 5055:5055 48 | volumes: 49 | - ./bot:/bot 50 | command: sh -c "python -m rasa_sdk --actions actions" 51 | networks: 52 | - bot 53 | 54 | # ============================ Telegram Bot ================================= 55 | # Specific Rasa bot integrated with Telegram. 56 | bot-telegram: 57 | build: 58 | context: . 59 | dockerfile: ./docker/bot.Dockerfile 60 | volumes: 61 | - ./bot/:/bot/ 62 | env_file: 63 | - ./env/bot-telegram.env 64 | - ./env/bot.env 65 | ports: 66 | - 5005:5005 67 | command: sh -c "make telegram" 68 | 69 | volumes: 70 | mongo_data: 71 | 72 | networks: 73 | bot: 74 | driver: bridge 75 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include bot/.env 2 | export $(shell sed 's/=.*//' bot/.env) 3 | 4 | current_dir := $(shell pwd) 5 | user := $(shell whoami) 6 | 7 | ENDPOINTS = endpoints.yml 8 | CREDENTIALS = credentials.yml 9 | 10 | # CLEAR PROJECT 11 | clean: 12 | make down 13 | cd bot/ && sudo make clean 14 | 15 | down: 16 | docker compose down 17 | 18 | # RUN 19 | init: 20 | make build 21 | make train 22 | make webchat 23 | 24 | logs: 25 | docker compose logs \ 26 | -f 27 | 28 | build: 29 | export $(grep -v '^#' env/bot.env | xargs) 30 | docker compose build \ 31 | --no-cache bot 32 | 33 | shell: 34 | docker compose run \ 35 | --rm \ 36 | --service-ports \ 37 | bot \ 38 | make shell ENDPOINTS=$(ENDPOINTS) 39 | 40 | api: 41 | docker compose run \ 42 | --rm \ 43 | --service-ports \ 44 | bot \ 45 | make api ENDPOINTS=$(ENDPOINTS) CREDENTIALS=$(CREDENTIALS) 46 | 47 | actions: 48 | docker compose run \ 49 | --rm \ 50 | --service-ports \ 51 | bot \ 52 | make actions 53 | 54 | webchat: 55 | echo "Executando Bot com Webchat." 56 | docker compose run \ 57 | -d \ 58 | --service-ports \ 59 | bot \ 60 | make webchat ENDPOINTS=$(ENDPOINTS) CREDENTIALS=$(CREDENTIALS) 61 | docker compose up \ 62 | -d \ 63 | webchat 64 | echo "Acesse o WEBCHAT em: http://localhost:5000" 65 | 66 | telegram: 67 | docker compose run \ 68 | -d \ 69 | --rm \ 70 | --service-ports \ 71 | bot-telegram \ 72 | make telegram ENDPOINTS=$(ENDPOINTS) CREDENTIALS=$(CREDENTIALS) 73 | 74 | # DEVELOPMENT 75 | train: 76 | docker compose run \ 77 | --rm \ 78 | bot \ 79 | make train 80 | 81 | validate: 82 | docker compose run \ 83 | --rm bot \ 84 | make validate 85 | 86 | test: 87 | docker compose run \ 88 | --rm bot \ 89 | make test 90 | 91 | test-nlu: 92 | docker compose run \ 93 | --rm \ 94 | bot \ 95 | make test-nlu 96 | 97 | test-core: 98 | docker compose run \ 99 | --rm \ 100 | bot \ 101 | make test-core 102 | 103 | -------------------------------------------------------------------------------- /bot/data/nlu-response-selectors.yml: -------------------------------------------------------------------------------- 1 | version: "3.1" 2 | nlu: 3 | - intent: explica/intent 4 | examples: | 5 | - [intent](intent) 6 | - Bot, quero um exemplo de [intent](intent) 7 | - Bot, o que significa uma [intent](intent) 8 | - Exemplo de [intent](intent) 9 | - Me explique como funcionam as [intent](intent) no rasa. 10 | - Você sabe fazer uma [intent](intent)? 11 | - O que é uma [intent](intent)? 12 | - intent: explica/entity 13 | examples: | 14 | - [entity](entity) 15 | - Bot, quero um exemplo de [entity](entity) 16 | - Bot, o que significa uma [entity](entity) 17 | - Exemplo de [entity](entity) 18 | - Me explique como funcionam as [entity](entity) no rasa. 19 | - Você sabe fazer uma [entity](entity)? 20 | - O que é uma [entidade](entity)? 21 | - intent: explica/slot 22 | examples: | 23 | - [slot](slot) 24 | - Bot, quero um exemplo de [slot](slot) 25 | - Bot, o que significa uma [slot](slot) 26 | - Exemplo de [slot](slot) 27 | - Me explique como funcionam as [slot](slot) no rasa. 28 | - Você sabe fazer uma [slot](slot)? 29 | - O que é um [slot](slot)? 30 | - intent: explica/storie 31 | examples: | 32 | - [storie](storie) 33 | - Bot, quero um exemplo de [storie](storie) 34 | - Bot, o que significa uma [storie](storie) 35 | - Exemplo de [storie](storie) 36 | - Me explique como funcionam as [storie](storie) no rasa. 37 | - Você sabe fazer uma [storie](storie)? 38 | - O que é uma [storie](storie)? 39 | - intent: explica/response_selectors 40 | examples: | 41 | - [response_selectors](response_selectors) 42 | - Bot, quero um exemplo de [response_selectors](response_selectors) 43 | - Bot, o que significa uma [response_selectors](response_selectors) 44 | - Exemplo de [response_selectors](response_selectors) 45 | - Me explique como funcionam as [response_selectors](response_selectors) no rasa. 46 | - Você sabe fazer uma [response_selectors](response_selectors)? 47 | - Como fazer uma FAQ com [Response Selector](response_selectors)? 48 | -------------------------------------------------------------------------------- /bot/tests/test_stories.yml: -------------------------------------------------------------------------------- 1 | #### This file contains tests to evaluate that your bot behaves as expected. 2 | #### If you want to learn more, please see the docs: https://rasa.com/docs/rasa/testing-your-assistant 3 | version: "2.0" 4 | stories: 5 | - story: Cumprimentar e despedir 6 | steps: 7 | - user: | 8 | boa tarde! 9 | intent: cumprimentar 10 | - action: utter_cumprimentar 11 | - user: | 12 | Até logo. 13 | intent: despedir 14 | - action: utter_despedir 15 | - story: Religião 16 | steps: 17 | - user: | 18 | Você segue qual religião? 19 | intent: religiao 20 | - action: utter_religiao 21 | - action: utter_continuar_conversa 22 | - story: piada 23 | steps: 24 | - user: | 25 | Você sabe alguma piada? 26 | intent: piada 27 | - action: utter_piada 28 | - action: utter_continuar_conversa 29 | - story: futebol 30 | steps: 31 | - user: | 32 | Você gosta de futebol? 33 | intent: time 34 | - action: utter_time 35 | - action: utter_continuar_conversa 36 | - story: história qualquer 37 | steps: 38 | - user: | 39 | Qual seu time favorito? 40 | intent: time 41 | - action: utter_time 42 | - action: utter_continuar_conversa 43 | - user: | 44 | Onde você vive? 45 | intent: onde_voce_mora 46 | - action: utter_onde_voce_mora 47 | - action: utter_continuar_conversa 48 | - user: | 49 | Qual estilo de música você ouve? 50 | intent: musica 51 | - action: utter_musica 52 | - action: utter_continuar_conversa 53 | - user: | 54 | Você come o quê? 55 | intent: comida 56 | - action: utter_comida 57 | - action: utter_continuar_conversa 58 | - user: | 59 | Como está se sentindo hoje? 60 | intent: tudo_bem 61 | - action: utter_tudo_bem 62 | - user: | 63 | Adorei ter esta conversa com você bot 64 | intent: elogios 65 | - action: utter_elogios 66 | - action: utter_continuar_conversa 67 | - user: | 68 | Valeu, to indo nessa 69 | intent: despedir 70 | - action: utter_despedir 71 | -------------------------------------------------------------------------------- /bot/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean actions 2 | 3 | include .env 4 | export $(shell sed 's/=.*//' .env) 5 | 6 | ## FLAGS: 7 | LOG_LEVEL = -vv 8 | RASA_ENDPOINTS = --endpoints 9 | ENDPOINTS = endpoints.yml 10 | RASA_CREDENTIALS = --credentials 11 | CREDENTIALS = credentials.yml 12 | 13 | # CLEAN PROJECT 14 | clean: 15 | sudo rm -rf graph.html \ 16 | results/ \ 17 | models/* \ 18 | *.db* \ 19 | .*tensorboard* \ 20 | .rasa 21 | 22 | install: 23 | pip install --upgrade pip && \ 24 | pip install -r requirements.txt 25 | 26 | # RUN 27 | api: 28 | rasa run \ 29 | -m models/ \ 30 | $(LOG_LEVEL) \ 31 | $(RASA_ENDPOINTS) $(ENDPOINTS) \ 32 | $(RASA_CREDENTIALS) $(CREDENTIALS) \ 33 | --enable-api \ 34 | --cors '*' \ 35 | --port 5005 36 | 37 | shell: 38 | rasa shell \ 39 | -m models/ \ 40 | $(LOG_LEVEL) \ 41 | $(RASA_ENDPOINTS) $(ENDPOINTS) \ 42 | --port 5005 43 | 44 | webchat: 45 | rasa run \ 46 | -m models/ \ 47 | $(LOG_LEVEL) \ 48 | $(RASA_ENDPOINTS) $(ENDPOINTS) \ 49 | $(RASA_CREDENTIALS) $(CREDENTIALS) \ 50 | --cors '*' \ 51 | --port 5005 52 | 53 | telegram: 54 | rasa run \ 55 | -m models/ \ 56 | $(LOG_LEVEL) \ 57 | $(RASA_ENDPOINTS) $(ENDPOINTS) \ 58 | $(RASA_CREDENTIALS) credentials/telegram-credentials.yml \ 59 | --port 5005 \ 60 | 61 | # ACTIONS 62 | actions: 63 | rasa run actions \ 64 | --actions actions \ 65 | $(LOG_LEVEL) 66 | 67 | # DEVELOPMENT 68 | train-nlu: 69 | rasa train nlu \ 70 | $(LOG_LEVEL) 71 | 72 | train: 73 | rasa train \ 74 | $(LOG_LEVEL) 75 | 76 | test: 77 | rasa test \ 78 | --out results/ 79 | 80 | test-nlu: 81 | rasa test nlu \ 82 | --out results/results-nlu-test 83 | 84 | test-core: 85 | rasa test core \ 86 | --fail-on-prediction-errors \ 87 | --out results/results-core-test 88 | 89 | # UTIL 90 | ## RASALIT 91 | install-rasalit: 92 | pip install -r rasalit-requirements.txt 93 | 94 | rasalit: 95 | python -m rasalit nlu-cluster --port 8501 96 | 97 | interactive: 98 | rasa interactive 99 | 100 | validate: 101 | rasa data validate \ 102 | $(LOG_LEVEL) 103 | 104 | visualize: 105 | rasa visualize \ 106 | --out ./graph.html 107 | 108 | tensor: 109 | tensorboard \ 110 | --logdir . 111 | 112 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a variety of Python versions 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 3 | 4 | name: build_bot 5 | 6 | on: 7 | push: 8 | branches: [ main] 9 | pull_request: 10 | branches: [ main] 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | python-version: [3.10.13] 18 | 19 | steps: 20 | - uses: actions/checkout@v2 21 | - name: Set up Python ${{ matrix.python-version }} 22 | uses: actions/setup-python@v1 23 | with: 24 | python-version: ${{ matrix.python-version }} 25 | - name: Install dependencies 26 | run: | 27 | cd bot/ 28 | export $(grep -v '^#' .env | xargs) 29 | pip install --upgrade pip 30 | pip install flake8 pytest rasa==$RASA_VERSION 31 | if [ -f requirements.txt ]; then make install; fi 32 | - name: Lint with flake8 33 | run: | 34 | # stop the build if there are Python syntax errors or undefined names 35 | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 36 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 37 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 38 | - name: Test Rasa version 39 | run: | 40 | rasa --version 41 | echo "Rasa is installed" 42 | - name: Rasa train 43 | run: | 44 | # Removing endpoints.yml and credentials.yml to this workflow. 45 | rm bot/endpoints.yml 46 | rm bot/credentials.yml 47 | cd bot/ 48 | # Editing config.yml to train with less time. 49 | sed -i "s/epochs.*$/epochs: 5/" ./config.yml 50 | echo "Changed epochs to 10 to check faster" 51 | make train 52 | echo "Model is saved" 53 | - name: Test actions 54 | run: | 55 | cd bot/ 56 | make actions & 57 | - name: Test rasa api 58 | run: | 59 | cd bot/ 60 | make api & 61 | curl --connect-timeout 5 \ 62 | --max-time 10 \ 63 | --retry 20 \ 64 | --retry-delay 5 \ 65 | --retry-max-time 120 \ 66 | --retry-connrefused 'http://localhost:5005' 67 | echo "Bot is working" 68 | - name: Test bot intent cumprimentar 69 | run: | 70 | intent=$(curl -X POST http://localhost:5005/model/parse -H 'Content-Type: application/json' -d '{"text": "Oi"}' | jq -r '.intent' | jq -r '.name') 71 | if [ $intent=='cumprimentar' ]; then echo "Ok"; else echo "erro" && exit 1; fi 72 | - name: Test bot SDK response 73 | run: | 74 | curl -XPOST http://localhost:5005/webhooks/rest/webhook -H 'Content-Type: application/json' -d '{"sender":"default","message":"custom action"}' 75 | - name: Test Rasa bot 76 | run: | 77 | cd bot/ 78 | rasa test --no-plot 79 | echo "Results is saved" 80 | -------------------------------------------------------------------------------- /bot/data/stories.yml: -------------------------------------------------------------------------------- 1 | version: "3.1" 2 | stories: 3 | - story: cumprimentar 4 | steps: 5 | - intent: cumprimentar 6 | - action: utter_cumprimentar 7 | - story: Oi Tudo Bem 8 | steps: 9 | - intent: cumprimentar 10 | - action: utter_cumprimentar 11 | - intent: tudo_bem 12 | - action: utter_tudo_bem 13 | - story: Despedir 14 | steps: 15 | - intent: despedir 16 | - action: utter_despedir 17 | - story: religiao 18 | steps: 19 | - intent: religiao 20 | - action: utter_religiao 21 | - action: utter_continuar_conversa 22 | - story: time 23 | steps: 24 | - intent: time 25 | - action: utter_time 26 | - action: utter_continuar_conversa 27 | - story: genero 28 | steps: 29 | - intent: genero 30 | - action: utter_genero 31 | - action: utter_continuar_conversa 32 | - story: piada 33 | steps: 34 | - intent: piada 35 | - action: utter_piada 36 | - action: utter_continuar_conversa 37 | - story: licenca 38 | steps: 39 | - intent: licenca 40 | - action: utter_licenca 41 | - action: utter_continuar_conversa 42 | - story: onde_voce_mora 43 | steps: 44 | - intent: onde_voce_mora 45 | - action: utter_onde_voce_mora 46 | - action: utter_continuar_conversa 47 | - story: musica 48 | steps: 49 | - intent: musica 50 | - action: utter_musica 51 | - action: utter_continuar_conversa 52 | - story: comida 53 | steps: 54 | - intent: comida 55 | - action: utter_comida 56 | - action: utter_continuar_conversa 57 | - story: cor 58 | steps: 59 | - intent: cor 60 | - action: utter_cor 61 | - action: utter_continuar_conversa 62 | - story: relacionamento 63 | steps: 64 | - intent: relacionamento 65 | - action: utter_relacionamento 66 | - action: utter_continuar_conversa 67 | - story: signo 68 | steps: 69 | - intent: signo 70 | - action: utter_signo 71 | - action: utter_continuar_conversa 72 | - story: triste 73 | steps: 74 | - intent: triste 75 | - action: utter_triste 76 | - action: utter_continuar_conversa 77 | - story: historia 78 | steps: 79 | - intent: historia 80 | - action: utter_historia 81 | - action: utter_continuar_conversa 82 | - story: Tudo Bem 83 | steps: 84 | - intent: tudo_bem 85 | - action: utter_tudo_bem 86 | - story: elogios 87 | steps: 88 | - intent: elogios 89 | - action: utter_elogios 90 | - action: utter_continuar_conversa 91 | - story: me ajuda 92 | steps: 93 | - intent: me_ajuda 94 | - action: utter_me_ajuda 95 | - story: exemplo acao 96 | steps: 97 | - intent: exemplo_acao 98 | entities: 99 | - acao 100 | - action: action_exemplo 101 | #- story: Ativa formulário 102 | # steps: 103 | # - intent: exemplo_forms 104 | # - action: utter_exemplo_forms 105 | # - action: exemplo_forms 106 | # - active_loop: exemplo_forms 107 | #- story: Envia formulário 108 | # condition: 109 | # - active_loop: exemplo_forms 110 | # steps: 111 | # - action: exemplo_forms 112 | # - active_loop: null 113 | # - action: utter_submit_exemplo_forms 114 | # - action: utter_slots_exemplo_forms 115 | -------------------------------------------------------------------------------- /docker-compose-rocket.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | 3 | services: 4 | # ================================= Bot ===================================== 5 | # Generic Rasa bot, used to run console for example. 6 | bot: 7 | build: 8 | context: . 9 | dockerfile: ./docker/bot.Dockerfile 10 | args: 11 | RASA_VERSION: ${RASA_VERSION} 12 | container_name: bot 13 | env_file: 14 | - ./bot/.env 15 | volumes: 16 | - ./bot/:/bot/ 17 | ports: 18 | - 5005:5005 19 | depends_on: 20 | - actions 21 | - mongo 22 | networks: 23 | - bot 24 | command: make api 25 | # ============================ Tracker Store================================= 26 | # A mongodb container as rasa tracker store. 27 | mongo: 28 | container_name: mongo 29 | image: mongo:6.0 30 | restart: unless-stopped 31 | env_file: 32 | - env/bot.env 33 | ports: 34 | - 27017:27017 35 | networks: 36 | - bot 37 | volumes: 38 | - ./data/db:/data/db 39 | 40 | # ================================= Actions ================================= 41 | # Rasa middleware used to connect with external APIs. 42 | actions: 43 | build: 44 | context: . 45 | dockerfile: ./docker/actions.Dockerfile 46 | container_name: actions 47 | env_file: 48 | - ./env/bot.env 49 | ports: 50 | - 5055:5055 51 | volumes: 52 | - ./bot:/bot 53 | command: sh -c "python -m rasa_sdk --actions actions" 54 | networks: 55 | - bot 56 | 57 | # =============================== Rocket.Chat ================================= 58 | # Rocket.Chat instance. 59 | rocketchat: 60 | image: registry.rocket.chat/rocketchat/rocket.chat:latest 61 | command: > 62 | bash -c 63 | "for i in `seq 1 30`; do 64 | node main.js && 65 | s=$$? && break || s=$$?; 66 | echo \"Tried $$i times. Waiting 5 secs...\"; 67 | sleep 5; 68 | done; (exit $$s)" 69 | restart: unless-stopped 70 | volumes: 71 | - ./uploads:/app/uploads 72 | environment: 73 | - PORT=3000 74 | - ROOT_URL=http://localhost:3000 75 | - MONGO_URL=mongodb://mongo-rocket:27017/rocketchat 76 | - MONGO_OPLOG_URL=mongodb://mongo-rocket:27017/local 77 | #- REG_TOKEN=${REG_TOKEN} 78 | depends_on: 79 | - mongo-rocket 80 | ports: 81 | - 3000:3000 82 | # =============================== Mongo ================================= 83 | # Mongo database and replica set. 84 | mongo-rocket: 85 | image: mongo:4.0 86 | restart: unless-stopped 87 | volumes: 88 | - ./data/db:/data/db 89 | command: mongod --smallfiles --oplogSize 128 --replSet rs0 --storageEngine=mmapv1 90 | 91 | # this container's job is just run the command to initialize the replica set. 92 | # it will run the command and remove himself (it will not stay running) 93 | mongo-init-replica: 94 | image: mongo:4.0 95 | command: > 96 | bash -c 97 | "for i in `seq 1 30`; do 98 | mongo mongo/rocketchat --eval \" 99 | rs.initiate({ 100 | _id: 'rs0', 101 | members: [ { _id: 0, host: 'localhost:27017' } ]})\" && 102 | s=$$? && break || s=$$?; 103 | echo \"Tried $$i times. Waiting 5 secs...\"; 104 | sleep 5; 105 | done; (exit $$s)" 106 | depends_on: 107 | - mongo-rocket 108 | 109 | volumes: 110 | mongo_data: 111 | rocket_uploads: 112 | 113 | networks: 114 | bot: 115 | driver: bridge 116 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Rasa ### 2 | bot/models 3 | bot/results* 4 | bot/train_test_split/ 5 | .tensorboard* 6 | .rasa/ 7 | *.log 8 | 9 | ### Rasa X ### 10 | events.db 11 | events.db-shm 12 | events.db-wal 13 | rasa.db 14 | *.db* 15 | 16 | ### Rasa visualize ### 17 | graph.html 18 | 19 | ### Rasa evaluation ### 20 | .ipynb_checkpoints/ 21 | modules/notebooks/intents/models/ 22 | modules/notebooks/intents/results/ 23 | modules/notebooks/stories/models/ 24 | modules/notebooks/stories/results/ 25 | bot/.ipython/ 26 | bot/.keras/ 27 | bot/.local/ 28 | bot/results/ 29 | 30 | ### database ### 31 | db/ 32 | alerting/ 33 | csv/ 34 | plugins/ 35 | png/ 36 | 37 | ### PyCharm ### 38 | .idea/ 39 | 40 | ### GitBook ### 41 | _book/ 42 | 43 | # Created by https://www.gitignore.io/api/vim,linux,macos,python 44 | ### Linux ### 45 | *~ 46 | 47 | # temporary files which can be created if a process still has a handle open of a deleted file 48 | .fuse_hidden* 49 | 50 | # KDE directory preferences 51 | .directory 52 | 53 | # Linux trash folder which might appear on any partition or disk 54 | .Trash-* 55 | 56 | # .nfs files are created when an open file is removed but is still being accessed 57 | .nfs* 58 | 59 | ### macOS ### 60 | *.DS_Store 61 | .AppleDouble 62 | .LSOverride 63 | 64 | # Icon must end with two \r 65 | Icon 66 | 67 | # Thumbnails 68 | ._* 69 | 70 | # Files that might appear in the root of a volume 71 | .DocumentRevisions-V100 72 | .fseventsd 73 | .Spotlight-V100 74 | .TemporaryItems 75 | .Trashes 76 | .VolumeIcon.icns 77 | .com.apple.timemachine.donotpresent 78 | 79 | # Directories potentially created on remote AFP share 80 | .AppleDB 81 | .AppleDesktop 82 | Network Trash Folder 83 | Temporary Items 84 | .apdisk 85 | 86 | ### Python ### 87 | # Byte-compiled / optimized / DLL files 88 | __pycache__/ 89 | *.py[cod] 90 | *$py.class 91 | 92 | # C extensions 93 | *.so 94 | 95 | # Distribution / packaging 96 | .Python 97 | build/ 98 | develop-eggs/ 99 | dist/ 100 | downloads/ 101 | eggs/ 102 | .eggs/ 103 | lib/ 104 | lib64/ 105 | parts/ 106 | sdist/ 107 | var/ 108 | wheels/ 109 | *.egg-info/ 110 | .installed.cfg 111 | *.egg 112 | 113 | # PyInstaller 114 | # Usually these files are written by a python script from a template 115 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 116 | *.manifest 117 | *.spec 118 | 119 | # Installer logs 120 | pip-log.txt 121 | pip-delete-this-directory.txt 122 | 123 | # Unit test / coverage reports 124 | htmlcov/ 125 | .tox/ 126 | .coverage 127 | .coverage.* 128 | .cache 129 | .pytest_cache/ 130 | nosetests.xml 131 | coverage.xml 132 | *.cover 133 | .hypothesis/ 134 | 135 | # Translations 136 | *.mo 137 | *.pot 138 | 139 | # Flask stuff: 140 | instance/ 141 | .webassets-cache 142 | 143 | # Scrapy stuff: 144 | .scrapy 145 | 146 | # Sphinx documentation 147 | docs/_build/ 148 | 149 | # PyBuilder 150 | target/ 151 | 152 | # Jupyter Notebook 153 | *.ipynb_checkpoints* 154 | 155 | # pyenv 156 | .python-version 157 | 158 | # celery beat schedule file 159 | celerybeat-schedule.* 160 | 161 | # SageMath parsed files 162 | *.sage.py 163 | 164 | # Environments 165 | .venv 166 | venv/ 167 | ENV/ 168 | env.bak/ 169 | venv.bak/ 170 | 171 | # Spyder project settings 172 | .spyderproject 173 | .spyproject 174 | 175 | # Rope project settings 176 | .ropeproject 177 | 178 | # mkdocs documentation 179 | /site 180 | 181 | # mypy 182 | .mypy_cache/ 183 | 184 | ### Vim ### 185 | # swap 186 | .sw[a-p] 187 | .*.sw[a-p] 188 | # session 189 | Session.vim 190 | # temporary 191 | .netrwhist 192 | # auto-generated tag files 193 | tags 194 | 195 | # End of https://www.gitignore.io/api/vim,linux,macos,python 196 | -------------------------------------------------------------------------------- /bot/data/nlu.yml: -------------------------------------------------------------------------------- 1 | version: "3.1" 2 | nlu: 3 | - intent: cumprimentar 4 | examples: | 5 | - olá 6 | - Ola 7 | - Oi 8 | - Iae 9 | - Olá 10 | - bom dia 11 | - boa tarde 12 | - boa noite 13 | - intent: despedir 14 | examples: | 15 | - tchau 16 | - adeus 17 | - flw 18 | - Até mais, bot 19 | - intent: afirmar 20 | examples: | 21 | - sim 22 | - confirmo 23 | - afirmo 24 | - claro 25 | - exato 26 | - isso mesmo 27 | - concordo 28 | - isso mesmo! 29 | - intent: negar 30 | examples: | 31 | - não 32 | - nao 33 | - nao conheco 34 | - não quero 35 | - nego 36 | - negativo 37 | - ainda não sei 38 | - intent: cancelar 39 | examples: | 40 | - sair 41 | - Desisto 42 | - Para 43 | - Cancela 44 | - Sai disso 45 | - Me tira daqui 46 | - Para com isso 47 | - Me tira disso 48 | - Quero cancelar 49 | - Saia dessa conversa 50 | - Não quero mais isso 51 | - Cancele esta operação 52 | - Para de me perguntar coisas 53 | - cansei, não quero responder! 54 | - Pare o que você está fazendo 55 | - Que loucura está acontecendo?! 56 | - Não quero compartilhar meus dados 57 | - Não quero mais informar meus dados 58 | - intent: informar 59 | examples: | 60 | - [Arthur](nome) 61 | - O meu nome é [Arthur](nome) 62 | - me chamo [Arthur](nome) 63 | - Meu nome: [Arthur](nome) 64 | - Claro, meu nome é [Arthur](nome) 65 | - [25](idade) 66 | - Minha idade é [25](idade) 67 | - Tenho [25](idade) anos 68 | - Eu tenho [25](idade) anos 69 | - Tenho: [25](idade) 70 | - intent: menu 71 | examples: | 72 | - Me mostre o [menu](menu) 73 | - [menu](menu) 74 | - Quero ver o [menu](menu) 75 | - kd o [menu](menu) 76 | - Bot, me mostra o [menu](menu) 77 | - Quais são as [opções](menu) de diálogo? 78 | - Me mostre as [opcoes](menu) de conversa 79 | - intent: tudo_bem 80 | examples: | 81 | - tudo bem 82 | - como vai voce 83 | - como vao as coisas 84 | - opa tudo bem 85 | - to bem 86 | - tranquilo 87 | - estou bem 88 | - estou otimo 89 | - tudo bem e você 90 | - tudo bom 91 | - tá bem 92 | - ta bem 93 | - como vocês esta 94 | - como voce esta 95 | - como voce ta 96 | - como vai você 97 | - como vai vc 98 | - intent: me_ajuda 99 | examples: | 100 | - sobre o que você sabe falar 101 | - o que mais você sabe falar 102 | - quais assuntos você fala 103 | - o que você sabe 104 | - lista de assuntos possiveis 105 | - quais as perguntas vc responde 106 | - quais as perquisar você responde 107 | - quero [ajuda](meajuda) 108 | - [meajuda](meajuda 109 | - [meajude](meajuda) 110 | - [MEAJDA](meajuda) 111 | - [me ajuda](meajuda) 112 | - [me ajude](meajuda) 113 | - [ajuda eu](meajuda) 114 | - Qual o seu objetivo robo? 115 | - Qual o seu objetivo robô? 116 | - Vc tem um objetivo de existencia? 117 | - Você foi feito pra que? 118 | - Vc tem algum propósito? 119 | - Como que vc pode me ser útil? 120 | - Me fale mais sobre você. 121 | - intent: exemplo_acao 122 | examples: | 123 | - [action](acao) 124 | - ativa [ação](acao) 125 | - executa [action](acao) 126 | - roda [ação](acao) 127 | - entra [ação](acao) 128 | - intent: exemplo_forms 129 | examples: | 130 | - [forms](forms) 131 | - ativa [forms](forms) 132 | - executa [forms](forms) 133 | - roda [forms](forms) 134 | - entra [forms](forms) 135 | - [form](forms) 136 | - Bot, quero um exemplo de [formulário](forms) 137 | - Bot, entra em um [form](forms) 138 | - Exemplo de [formulário](forms) 139 | - Me explique como funcionam os [formulários](forms) no rasa. 140 | - Você sabe fazer um [forms](forms)? 141 | - me explica sobre [forms](forms)? 142 | -------------------------------------------------------------------------------- /modules/webchat/assets/launcher_button.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ic_button 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /bot/components/sentiment_analyzer.py: -------------------------------------------------------------------------------- 1 | from rasa.nlu.components import Component 2 | from rasa.utils.io import json_pickle, json_unpickle 3 | from rasa.nlu.model import Metadata 4 | 5 | import nltk 6 | from nltk.classify import NaiveBayesClassifier 7 | from nltk import tokenize, stem 8 | import os 9 | 10 | import typing 11 | from typing import Any, Optional, Text, Dict 12 | 13 | 14 | SENTIMENT_MODEL_FILE_NAME = "sentiment_classifier.pkl" 15 | 16 | 17 | class SentimentAnalyzer(Component): 18 | print("Initialised Sentiment Analyzer") 19 | 20 | def __init__(self, component_config=None): 21 | super(SentimentAnalyzer, self).__init__(component_config) 22 | self.corpus_words = {} 23 | self.class_words = {} 24 | self.stemmer = stem.RSLPStemmer() 25 | 26 | def train(self, training_data, cfg, **kwargs): 27 | """Load the sentiment polarity labels from the text 28 | file, retrieve training tokens and after formatting 29 | data train the classifier.""" 30 | 31 | training_data = {} 32 | import yaml 33 | 34 | with open("/bot/components/labels.yml") as f: 35 | training_data = yaml.safe_load(f) 36 | 37 | # capture unique stemmed words in the training corpus 38 | # turn a list into a set (of unique items) and then a list again (this removes duplicates) 39 | classes = set(list(training_data)) 40 | for c in classes: 41 | # prepare a list of words within each class 42 | self.class_words[c] = [] 43 | 44 | # loop through each sentence in our training data 45 | for label, sentences in training_data.items(): 46 | # tokenize each sentence into words 47 | for sentence in sentences: 48 | for word in nltk.word_tokenize(sentence, language="portuguese"): 49 | # ignore a some things 50 | if word not in ["?"]: 51 | # stem and lowercase each word 52 | stemmed_word = self.stemmer.stem(word.lower()) 53 | # have we not seen this word already? 54 | if stemmed_word not in self.corpus_words: 55 | self.corpus_words[stemmed_word] = 1 56 | else: 57 | self.corpus_words[stemmed_word] += 1 58 | 59 | # add the word to our words in class list 60 | self.class_words[label].append(stemmed_word) 61 | 62 | def convert_to_rasa(self, value, confidence): 63 | """Convert model output into the Rasa NLU compatible output format.""" 64 | 65 | entity = { 66 | "value": value, 67 | "confidence": confidence, 68 | "entity": "sentiment", 69 | "extractor": "sentiment_extractor", 70 | } 71 | 72 | return entity 73 | 74 | def calculate_label_score(self, tokens, class_name): 75 | score = 0 76 | # tokenize each word in our new sentence 77 | for word in tokens: 78 | # check to see if the stem of the word is in any of our classes 79 | if self.stemmer.stem(word.lower()) in self.class_words[class_name]: 80 | # treat each word with relative weight 81 | score += 1 / self.corpus_words[self.stemmer.stem(word.lower())] 82 | 83 | return score 84 | 85 | def process(self, message, **kwargs): 86 | """Retrieve the tokens of the new message, pass it to the classifier 87 | and append prediction results to the message class.""" 88 | 89 | entity = None 90 | 91 | # calculate a score for a given class taking into account word commonality 92 | high_class = None 93 | high_score = 0 94 | 95 | tokens = [t.text for t in message.get("tokens")] 96 | 97 | # loop through our classes 98 | for class_name in self.class_words.keys(): 99 | # calculate score of sentence for each class 100 | score = self.calculate_label_score(tokens, class_name) 101 | # keep track of highest score 102 | if score > high_score: 103 | high_class = class_name 104 | high_score = score 105 | 106 | sentiment = high_class 107 | confidence = high_score 108 | 109 | entity = self.convert_to_rasa(sentiment, confidence) 110 | 111 | message.set("entities", [entity], add_to_output=True) 112 | 113 | def persist(self, file_name, model_dir): 114 | """Persist this model into the passed directory.""" 115 | classifier_file = os.path.join(model_dir, SENTIMENT_MODEL_FILE_NAME) 116 | json_pickle(classifier_file, self) 117 | return {"classifier_file": SENTIMENT_MODEL_FILE_NAME} 118 | 119 | @classmethod 120 | def load( 121 | cls, 122 | meta: Dict[Text, Any], 123 | model_dir=None, 124 | model_metadata=None, 125 | cached_component=None, 126 | **kwargs 127 | ): 128 | file_name = meta.get("classifier_file") 129 | classifier_file = os.path.join(model_dir, file_name) 130 | return json_unpickle(classifier_file) 131 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Este é um documento para orientação em como contribuir para o repositório do Rasa PT-BR Boilerplate. Antes de começar a contribuir veja as [issues já abertas](http://github.com/lappis-unb/rasa-ptbr-boilerplate/issues), e principalmente o funcionamento de nossa [arquitetura](https://github.com/lappis-unb/rasa-ptbr-boilerplate/blob/master/README.md). 2 | 3 | Veja as orientações abaixo para cada tipo de contribuição: 4 | * [Por onde começar a contribuir?](#comece-a-contribuir) 5 | * [Reportar erros](#encontrou-um-bug) 6 | * [Consertar erros](#concertou-um-bug) 7 | * [Contribuir para a documentação](#quer-contribuir-para-a-nossa-documentação) 8 | * [Adicionar nova feature](#quer-adicionar-uma-feature-nova-ou-ajudar-com-uma-existente) 9 | * [Contribuir para o conteúdo do Boilerplate](#quer-contribuir-para-o-conteúdo-do-boilerplate) 10 | 11 | ### Comece a contribuir 12 | Quer começar a contribuir para o Boilerplate? O processo em geral é bem simples: 13 | 14 | - Crie uma issue descrevendo uma feature que você queira trabalhar ou entre em issues já abertas (caso comece por uma issue já existente comente na issue que você está desenvolvendo). 15 | - Escreva seu código, testes e documentação 16 | - Abra um pull request descrevendo as suas alterações propostas 17 | - Seu pull request será revisado por um dos mantenedores, que pode levantar questões para você sobre eventuais mudanças necessárias ou questões. 18 | 19 | Veja nossa [documentação](https://github.com/lappis-unb/rasa-ptbr-boilerplate/tree/master/docs) para entender um pouco melhor sobre nosso código e [arquitetura](https://github.com/lappis-unb/rasa-ptbr-boilerplate/blob/master/README.md), veja nossas issues, principalmente as com as tags `help-wanted` e `good-first-issue`, que são as ideais para começar a contribuir para o Boilerplate. 20 | 21 | 22 | ### Encontrou um Bug? 23 | Caso tenha encontrado algum erro, nos informe por uma issue, assim poderemos estar sempre melhorando. Pedimos que seja descritivo, dessa forma poderemos identificar e reproduzir o erro para ser possível consertá-lo. 24 | 25 | Antes de reportar o Bug, veja as [issues com a tag `bug`](https://github.com/lappis-unb/rasa-ptbr-boilerplate/labels/bug) e verifique se o erro identificado já não possui uma issue criada. 26 | 27 | Para uma boa documentação: 28 | * Nomeie a issue com um nome claro e descritivo de acordo com o problema; 29 | * Descreva o passo a passo para chegar no erro encontrado; 30 | * Mostre exemplos do erro ocorrido; 31 | * Descreva o comportamento esperado e o comportamento obtido; 32 | * Marque a issue criada com a tag `bug`. 33 | 34 | Veja a seguinte estrutura de issue: 35 | 36 | ``` markdown 37 | 38 | **Descrição do erro encontrado:** 39 | ... 40 | 41 | **Passo a passo para a reprodução do erro:** 42 | 1. 43 | 2. 44 | ... 45 | **Comportamento esperado:** ... 46 | **Comportamento obtido:** ... 47 | ``` 48 | 49 | ### Consertou um Bug? 50 | Para enviar a sua solução e consertar um bug existente, fork nosso repositório e crie um Pull Request descrevendo o problema e como ele foi corrigido. 51 | 52 | Para uma bom Pull Request: 53 | * Nomeie o PR de forma descritiva e clara de acordo com o problema resolvido; 54 | * Descreva o problema e a sua solução; 55 | * Marque a issue que o PR soluciona. 56 | 57 | Veja o exemplo abaixo: 58 | 59 | ``` markdown 60 | **Issue:** #[Número-da-Issue] 61 | **Descrição do Problema:** 62 | ... 63 | **Descrição da Solução:** 64 | ... 65 | ``` 66 | 67 | ### Quer contribuir para a nossa Documentação? 68 | Para contribuir com a documentação, veja a documentação já existente, e as issues pendentes para documentação marcadas com a [tag `documentação`](https://github.com/lappis-unb/rasa-ptbr-boilerplate/labels/documentação). 69 | 70 | Caso queira resolver uma issue já existente, comente na issue que está trabalhando, caso ainda não exista uma issue crie uma nova issue descrevendo o problema encontrado e marque com a tag `documentação`. 71 | 72 | Para solucionar faça um PR com a descrição do que foi feito e a referência a issue que está resolvendo. 73 | 74 | ### Quer adicionar uma feature nova ou ajudar com uma existente? 75 | 76 | Nosso desenvolvimento é dividido em algumas frentes principais, sendo elas: 77 | * **Bot Rasa:** Frente para o desenvolvimento do conteúdo do Boilerplate, com a utilização do Rasa (na pasta `bot`); 78 | * **ElasticSearch:** Frente para o desenvolvimento de dashboards com Kibana para a análise das conversas do bot com os usuários (na pasta `analytics`); 79 | * **Plataforma de Conteúdo:** Desenvolvimento de uma plataforma para adicionar conteúdo no Boilerplate, sem a necessidade de mexer diretamente nos arquivos do código ([no repositório `rasa-nlu-trainer`](https://github.com/lappis-unb/rasa-nlu-trainer)). 80 | 81 | Além de que também temos algumas outras áreas, onde é possível contribuir, como: 82 | * **Notebooks:** Notebooks jupyter para análise da estrutura e funcionamento do Bot (na pasta `notebooks`); 83 | 84 | Aceitamos contribuições em todas as áreas do nosso código, desde que seja uma contribuição válida e traga reais melhorias para o projeto. Para fazer uma contribuição abra uma issue, com nome descritivo, especificando o que será feito e qual frente será afetada. Veja o exemplo abaixo de um bom template a ser feito: 85 | 86 | ``` markdown 87 | **Frente a ser trabalhada:** ... 88 | **Descrição da nova feature:** 89 | ... 90 | **Porque essa feature melhoraria o código:** 91 | ... 92 | ``` 93 | Caso sua contribuição entre um uma das frentes principais, marque com a sua label específica. Temos as labels: 94 | * `elasticSearch`: para issues da frente de análise do Elasticsearch com Kibana; 95 | * `plataforma-conteudo`: para issues da frente do front-end de adicionar conteúdo no Boilerplate; 96 | * `rasa`: Para issues sobre o Rasa, na frente do Bot. 97 | 98 | Após fazer a issue, dê um fork do repositório e faça um Pull Request com sua nova feature. Dê um bom nome para o PR, especifique a sua solução, em qual frente ela se encaixa e a referência aissue relacionada. Veja o exemplo de uma estrutura de PR abaixo: 99 | 100 | ``` markdown 101 | **Frente a ser trabalhada:**... 102 | **Issue:** #[Número-da-Issue] 103 | 104 | **Descrição da nova feature:** 105 | ... 106 | **Descrição de como foi feito:** 107 | 108 | **Descrição de como ela funciona:** 109 | ... 110 | ``` 111 | 112 | ### Quer Contribuir para o conteúdo do Boilerplate? 113 | Além de contribuição de código, o Boilerplate também possui contribuições de conteúdo. Veja as [issues marcadas com a tag `conteudo`](https://github.com/lappis-unb/rasa-ptbr-boilerplate/labels/conteudo). Comente na issue que está trabalhando, faça o fork e submeta seu PR. Lembre-se de definir o que foi feito, linkar com a issue e marcar com a tag `conteudo`. Veja abaixo um exemplo de PR para contribuição de conteúdo. 114 | 115 | ``` markdown 116 | **Issue:**#[Número-da-Issue] 117 | **Conteúdo adicionado:** 118 | * Exemplo de pergunta do usuário: ... 119 | * Resposta: ... 120 | ... 121 | 122 | ``` 123 | -------------------------------------------------------------------------------- /bot/data/nlu-chitchat.yml: -------------------------------------------------------------------------------- 1 | version: "3.1" 2 | nlu: 3 | - intent: religiao 4 | examples: | 5 | - voce acredita em [deus](religiao) 6 | - [deus](religiao) existe 7 | - voce e [catolico protestante](religiao) 8 | - voce tem [religiao](religiao) 9 | - voce e [mussumano](religiao) 10 | - [evengelico](religiao) 11 | - voce e [crente](religiao) 12 | - voce é [católico](religiao) 13 | - voce é [ateu](religiao) 14 | - você é espírita 15 | - voce e espirita 16 | - você é religioso 17 | - qual é o seu deus? 18 | - qual a sua [religião](religiao)? 19 | - você acredita em alguma [religião](religiao)? 20 | - intent: time 21 | examples: | 22 | - qual o melhor [time](time) do brasil 23 | - qual é o seu [time](time) 24 | - quel e o seu [time](time) 25 | - qual o seu [time](time) 26 | - para qual [time](time) você torce 27 | - para qual [time](time) voce torce 28 | - para qual [time](time) vc torce 29 | - que [time](time) voce torce 30 | - que [time](time) vc torce 31 | - intent: piada 32 | examples: | 33 | - sabe alguma [piada](piada) 34 | - voce sabe contar [piadas](piada) 35 | - conhece alguma [piada](piada) 36 | - [piada](piada) 37 | - me conte uma [piada](piada) 38 | - me conta uma piada 39 | - conte-me uma [piada](piada) 40 | - manda uma [piada](piada) ai 41 | - me conta uma [coisa engraçada](piada) 42 | - intent: licenca 43 | examples: | 44 | - qual é a sua [licença](licenca)? 45 | - qual e a sua [licenca](licenca)? 46 | - voce e [licenciado](licenca)? 47 | - sua [licenca de software](licenca)? 48 | - posso copiar voce? 49 | - posso te clonar? 50 | - posso ter um bot como voce? 51 | - posso ver seu [codigo](licenca)? 52 | - voce e [opensource](licenca)? 53 | - você é um software livre? 54 | - voce e um [software livre](licenca)? 55 | - vc é um software livre? 56 | - [software livre](licenca)? 57 | - [licença](licenca) 58 | - [licenca](licenca) 59 | - intent: onde_voce_mora 60 | examples: | 61 | - onde voce [mora](vive) 62 | - onde voce [vive](vive) 63 | - onde voce habita 64 | - em que lugar voce [vive](vive) 65 | - [onde voce esta](vive) agora 66 | - voce [mora](vive) no computador 67 | - voce [vive](vive) na internet 68 | - [onde vc esta](vive) 69 | - qual é o seu [habitat](vive) 70 | - qual é o seu [endereço](vive) 71 | - qual e o seu [endereco](vive) 72 | - qual o seu [endereço](vive) 73 | - qual o seu [endereco](vive) 74 | - intent: genero 75 | examples: | 76 | - voce é [homem](genero) ou [mulher](genero)? 77 | - voce é [macho](genero) ou [femea](genero)? 78 | - qual o seu [sexo](genero)? 79 | - voce e [mulher](genero)? 80 | - voce e um [homem](genero)? 81 | - você é um [homem](genero)? 82 | - voce tem [genero](genero)? 83 | - voce tem um [penis ou uma vagina](genero)? 84 | - você é uma [mulher](genero)? 85 | - intent: musica 86 | examples: | 87 | - me indica uma música 88 | - manda uma [playlist](musica) 89 | - me fala uma [playlist](musica) boa 90 | - quero uma [playlist](musica) 91 | - [playlist](musica) 92 | - qual a melhor [playlist](musica) 93 | - sabe qual [playlist](musica) é boa? 94 | - diga uma [playlist](musica) 95 | - me indica uma [musica](musica) 96 | - me indica uma [playlist](musica) 97 | - indica uma [música](musica) pra mim 98 | - indica uma [música](musica) 99 | - indicar [musica](musica) 100 | - intent: comida 101 | examples: | 102 | - Qual a sua [comida](comida) preferida? 103 | - Que [comida](comida) você gosta? 104 | - Que [comida](comida) vc gosta? 105 | - qual a melhor [comida](comida)? 106 | - Qual seu [lanche](comida) preferido? 107 | - Qual [comida](comida) você me sugere? 108 | - O que você adora [comer](comida)? 109 | - O que você gosta de [comer](comida)? 110 | - qual a sua [comida](comida) favorita 111 | - o que você prefere comer 112 | - o que voce prefere comer 113 | - qual seu rango favorito 114 | - me fala de [comida](comida)? 115 | - intent: cor 116 | examples: | 117 | - Qual a sua [cor preferida](cor)? 118 | - Que [cor você gosta](cor)? 119 | - Que [cor vc gosta](cor)? 120 | - qual a [melhor cor](cor)? 121 | - Qual sua [cor preferida](cor)? 122 | - Qual [cor](cor) você me sugere? 123 | - qual a sua [cor](cor) favorita 124 | - qual a sua [cor](cor) da sorte 125 | - qual a sua [cor](cor) 126 | - [cor](cor) favorita 127 | - [cor](cor) preferida 128 | - [cor](cor) da sorte 129 | - intent: relacionamento 130 | examples: | 131 | - Você tem [namorado](relationship)? 132 | - Você tem [namorada](relationship)? 133 | - Você [namora](relationship)? 134 | - Você é [catristeo](relationship)? 135 | - [Namorar](relationship) comigo? 136 | - Quer [namorar](relationship)? 137 | - Bora [namorar](relationship)? 138 | - Tem [boyfriend](relationship)? 139 | - Tem [girlfriend](relationship)? 140 | - você é casado 141 | - você tem esposa 142 | - voce tem esposa 143 | - vc tem esposa 144 | - você tem esposo 145 | - voce tem esposo 146 | - vc tem esposo 147 | - você tem namorado 148 | - voce gosta de alguem 149 | - você gosta de alguém 150 | - você ama alguém 151 | - gostar de alguém 152 | - amar alguém 153 | - gosta de alguém 154 | - gosta de alguem 155 | - intent: signo 156 | examples: | 157 | - Qual o seu [signoo](signo)? 158 | - qual é o seu [signo](signo) 159 | - qual o seu [signo](signo) 160 | - Fala seu [signoo](signo)? 161 | - diz pra mim qual é seu [signo](signo) 162 | - diz pra mim qual e seu [signo](signo) 163 | - seu [signo](signo) 164 | - intent: triste 165 | examples: | 166 | - Estou [triste](triste) 167 | - Estou muito [triste](triste) 168 | - [Tristeza](triste) 169 | - A [tristeza](triste) me consome 170 | - Estou [chorando](triste) 171 | - [depressão](triste) 172 | - estou [infeliz](triste) 173 | - estou [frustrado](triste) 174 | - tô muito [triste](triste) 175 | - tô [triste](triste) 176 | - tô [infeliz](triste) 177 | - tô [frustrado](triste) 178 | - intent: historia 179 | examples: | 180 | - me fala uma [história](historia) 181 | - me conta uma [história](historia) 182 | - [historia](historia) 183 | - [história](historia) 184 | - conta pra mim uma [historinha](historia) 185 | - fala uma [historia](historia) ai 186 | - conta uma [história](historia) pra dormir 187 | - conta uma [historia](historia) pra dormir 188 | - me conta uma [experiência](historia) sua 189 | - me conta uma [experiencia](historia) 190 | - me conta uma [historinha](historia) 191 | - me conta uma [estória](historia) 192 | - intent: elogios 193 | examples: | 194 | - você é muito educado 195 | - voce e muito educado 196 | - me ajudou muito 197 | - você é demais 198 | - você é lindo 199 | - voce e lindo 200 | - voce e maravilhoso 201 | - vc é demais 202 | - vc e demais 203 | - vc eh linda 204 | - vc e lindo 205 | - vc é bonito 206 | - vc é maravilhoso 207 | - adorei você 208 | - amei você 209 | - adorei voce 210 | - amei voce 211 | - adorei vc 212 | - amei vc 213 | -------------------------------------------------------------------------------- /scripts/config_env.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import json 4 | import logging 5 | import requests 6 | import argparse 7 | from time import sleep 8 | 9 | # == Log Config == 10 | logging.basicConfig(format='%(levelname)s : %(message)s', level=logging.INFO) 11 | logger = logging.getLogger(__name__) 12 | 13 | # == CLI == 14 | parser = argparse.ArgumentParser() 15 | 16 | parser.add_argument( 17 | '--admin-name', '-an', type=str, default='boss', 18 | help='Admin username (default: boss)' 19 | ) 20 | parser.add_argument( 21 | '--admin-password', '-ap', type=str, default='boss', 22 | help='Admin password (default: boss)' 23 | ) 24 | 25 | parser.add_argument( 26 | '--bot-name', '-bn', type=str, default='rasa_bot', 27 | help='Bot username (default: rasa_bot)' 28 | ) 29 | parser.add_argument( 30 | '--bot-password', '-bp', type=str, default='rasa_bot', 31 | help='Bot password (default: rasa_bot)' 32 | ) 33 | 34 | args = parser.parse_args() 35 | 36 | # == Admin Info == 37 | admin_name = args.admin_name 38 | admin_password = args.admin_password 39 | 40 | # == Bot Info == 41 | bot_name = args.bot_name 42 | bot_password = args.bot_password 43 | bot_email = bot_name + '@email.com' 44 | 45 | # == Host Info == 46 | #host = http://rocketchat:3000/ # Rocketchat - Docker 47 | host = "http://localhost:3000/" # Rockechat - Local 48 | path = "/api/v1/login" 49 | user_header = None 50 | 51 | 52 | def get_authentication_token(user): 53 | login_data = {"username": user, "password": user} 54 | response = requests.post(host + path, data=login_data) 55 | 56 | if response.json()["status"] == "success": 57 | logger.info(f"Login succeed | Header = {user}") 58 | 59 | authToken = response.json()["data"]["authToken"] 60 | userId = response.json()["data"]["userId"] 61 | user_header = { 62 | "X-Auth-Token": authToken, 63 | "X-User-Id": userId, 64 | "Content-Type": "application/json" 65 | } 66 | 67 | return user_header 68 | else: 69 | logger.error(f"Login failed | {response}") 70 | 71 | def create_bot_user(): 72 | user_info = { 73 | "name": bot_name, 74 | "email": bot_email, 75 | "password": bot_password, 76 | "username": bot_name, 77 | "requirePasswordChange": False, 78 | "sendWelcomeEmail": True, 79 | "roles": ["bot", "livechat-agent"], 80 | } 81 | 82 | user_header = get_authentication_token(admin_name) 83 | 84 | create_user_response = requests.post( 85 | host + '/api/v1/users.create', 86 | data=json.dumps(user_info), 87 | headers=user_header 88 | ) 89 | 90 | if create_user_response.json()["success"] == True: 91 | logger.info(f"Bot created | Bot = {bot_name}") 92 | else: 93 | logger.error(f"Unable to create bot | {create_user_response}") 94 | 95 | 96 | def set_avatar(user): 97 | avatar_config = { 98 | "username": user, 99 | "avatarUrl": "https://www.rasa.com/assets/img/sara/sara-open-source-2.0.png", 100 | } 101 | 102 | user_header = get_authentication_token(user) 103 | 104 | set_avatar_response = requests.post( 105 | host + "api/v1/users.setAvatar", 106 | data=json.dumps(avatar_config), 107 | headers=user_header 108 | ) 109 | 110 | if set_avatar_response.json()["success"] == True: 111 | logger.info(f"Avatar updated | User = {user}") 112 | else: 113 | logger.error(f"Unable to create avatar | {set_avatar_response}") 114 | 115 | def set_status_active(user): 116 | user_status = { 117 | "message": "My status update", 118 | "status": "online" 119 | } 120 | 121 | user_header = get_authentication_token(user) 122 | 123 | set_user_status_response = requests.post( 124 | host + "/api/v1/users.setStatus", 125 | data=json.dumps(user_status), 126 | headers=user_header 127 | ) 128 | 129 | if set_user_status_response.json()["success"] == True: 130 | logger.info(f"Status ON | User = {user}") 131 | else: 132 | logger.error(f"Status OFF | {set_user_status_response}") 133 | 134 | def config_bot(): 135 | create_bot_user() 136 | set_avatar(bot_name) 137 | set_status_active(bot_name) 138 | 139 | def config_livechat(): 140 | user_header = get_authentication_token(admin_name) 141 | 142 | # Enable Livechat 143 | livechat_response = requests.post( 144 | host + '/api/v1/settings/Livechat_enabled', 145 | data=json.dumps({'value': True}), 146 | headers=user_header 147 | ) 148 | 149 | if livechat_response.json()["success"] == True: 150 | logger.info("Livechat ON") 151 | else: 152 | logger.error(f"Livechat OFF | {livechat_response}") 153 | 154 | # Disable show pre-registration form 155 | registration_form_response = requests.post( 156 | host + '/api/v1/settings/Livechat_registration_form', 157 | data=json.dumps({'value': False}), 158 | headers=user_header 159 | ) 160 | 161 | if registration_form_response.json()["success"] == True: 162 | logger.info(f"Registration form disabled!") 163 | else: 164 | logger.error(f"Registration still enabled... {registration_form_response}") 165 | 166 | def config_department(): 167 | bot_id = get_authentication_token(bot_name)["X-User-Id"] 168 | admin_header = get_authentication_token(admin_name) 169 | 170 | department_info = { 171 | 'department': { 172 | 'enabled': True, 173 | 'showOnRegistration': True, 174 | 'showOnOfflineForm': True, 175 | 'email': bot_email, 176 | 'name': 'department', 177 | 'description': 'default department' 178 | }, 179 | 'agents': [{ 180 | 'agentId': bot_id, 181 | 'username': bot_name, 182 | 'count': 0, 183 | 'order': 0 184 | }] 185 | } 186 | 187 | create_department_response = requests.post( 188 | host + '/api/v1/livechat/department', 189 | data=json.dumps(department_info), 190 | headers=admin_header 191 | ) 192 | 193 | if create_department_response.json()['success'] is True: 194 | logger.info('Default Department ON') 195 | else: 196 | logger.error(f'Error while creating department! | {create_department_response.text}') 197 | 198 | if __name__ == '__main__': 199 | logger.info("===== Sara Mascot S2 =====") 200 | 201 | #rasa_url = "http://bot:5005/" # Rasa - Docker 202 | rasa_url = "http://localhost:5005/" # Rasa - Local 203 | 204 | 205 | response = False 206 | 207 | # O script verifica se o servidor Rasa subiu antes de executar # 208 | while(not response): 209 | try: 210 | response = requests.get(rasa_url) 211 | response = True 212 | logger.info("Rasa Server UP!") 213 | 214 | logger.info(">> Configure Bot") 215 | config_bot() 216 | 217 | logger.info(">> Configure Livechat") 218 | config_livechat() 219 | 220 | logger.info(">> Cofigure Department") 221 | config_department() 222 | 223 | except: 224 | logger.info("Rasa Server DOWN...") 225 | finally: 226 | sleep(3) 227 | 228 | logger.info("===== END =====") 229 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rasa Boilerplate 2 | 3 | 4 | 5 | ![badge_build](https://github.com/lappis-unb/rasa-ptbr-boilerplate/workflows/build_bot/badge.svg) 6 | 7 | 8 | _For English version: [README-en](docs/README-en.md)_ 9 | 10 | 11 | O boilerplate nasceu como uma abstração genérica do projeto [Tais](http://github.com/lappis-unb/tais). Hoje, tem o objetivo de tornar mais fácil a criação de um chatbot [Rasa](http://rasa.com/). Com a evolução do framework, atualmente o foco do boilerplate é uma documentação em código viva. 12 | 13 | Aqui você pode encontrar um chatbot totalmente em Português Brasiliero que vai te auxiliar com exemplos de diálogo, código e uso de funcionalidades do Rasa. 14 | 15 | ## Arquitetura 16 | 17 | A [arquitetura](https://drive.google.com/file/d/1xUojfFGrYubSfmd3tL77XzgZzD6cR-XH/view?usp=sharing) do boilerplate pode ser divida em 2 partes principais: 18 | 19 | * **Criar** 20 | 21 | Processo que transforma arquivos de configuração `.yml` em um `modelo treinado` que contẽm a inteligência do chatbot. 22 | 23 | ![arquitetura_boilerplate-v3-criar](https://github.com/lappis-unb/rasa-ptbr-boilerplate/wiki/images/arquitetura_boilerplate-v3-criar.png) 24 | 25 | 26 | * **Prover** 27 | 28 | O usuário interage com a Boilerplate via Telegram, que manda as mensagens para o Rasa NLU através de conectores, onde ele identifica a *intent*, e responde pelo Rasa Core, de acordo com as *stories* e *actions*. 29 | 30 | As *models* utilizadas para a conversação foram geradas pelo módulo *trainer* e depois transferidas para o bot, estes modelos podem ser versionados e evoluídos entre bots. 31 | 32 | ![arquitetura_boilerplate-v3-prover](https://github.com/lappis-unb/rasa-ptbr-boilerplate/wiki/images/arquitetura_boilerplate-v3-criar.png) 33 | 34 | 35 | ## Tutorial 36 | 37 | Primeiramente, clone o repositório para sua máquina local usando o comando: 38 | 39 | ```sh 40 | git clone https://github.com/lappis-unb/rasa-ptbr-boilerplate.git 41 | ``` 42 | 43 | Para ter seu chatbot Rasa funcionando, certifique-se de estar dentro da pasta do projeto e então execute no terminal o seguinte comando: 44 | 45 | ```sh 46 | make init 47 | ``` 48 | 49 | Esse comando irá construir a infraestrutura necessária (subir containers com as dependências, treinar o chatbot e iniciar o chat no modo shell) para possibilitar a interação com o chatbot. 50 | 51 | Depois que tudo for instalado, você verá a seguinte mensagem e pode começar a interagir com o bot: 52 | 53 | ```sh 54 | Bot loaded. Type a message and press enter (use '/stop' to exit): 55 | Your input -> 56 | ``` 57 | 58 | Para fechar a interação com o bot é só digitar `ctrl+c`. 59 | 60 | 61 | ### Comandos 62 | 63 | * O comando de treinamento é usado para criar os modelos necessários na conversação do bot. Para treinar o seu chatbot execute o comando: 64 | 65 | ```sh 66 | make train 67 | ``` 68 | 69 | * Para executar o bot no terminal execute: 70 | 71 | ```sh 72 | make shell 73 | ``` 74 | 75 | ### Configuração Telegram 76 | 77 | Após realizar o [tutorial](/docs/setup_telegram.md) de exportação de todas variávies de ambiente necessárias, é possível realizar a execução do bot no telegram corretamente. 78 | 79 | **Antes de seguir adiante. Importante:** As variáveis de ambiente são necessárias para o correto funcionamento do bot, por isso não esqueça de exportá-las. 80 | 81 | Depois execute o bot no telegram: 82 | 83 | ```sh 84 | make telegram 85 | ``` 86 | 87 | ### Analytics 88 | 89 | Para a visualização dos dados da interação entre o usuário e o chatbot nós utilizamos uma parte da Stack do Elastic, composta pelo ElasticSearch e o Kibana. Com isso, utilizamos um broker para fazer a gerência de mensagens. Então conseguimos adicionar mensagens ao ElasticSearch independente do tipo de mensageiro que estamos utilizando. 90 | 91 | * Para uma **configuração rápida** execute o seguinte comando: 92 | 93 | ```sh 94 | make build-analytics 95 | ``` 96 | 97 | Espere até os serviço do *ElasticSearch* estar pronto, e execute o comando abaixo para configurar os índices: 98 | 99 | ``` 100 | make config-elastic 101 | ``` 102 | 103 | Espere até os serviço do *Kibana* estar pronto, e execute o comando abaixo para configurar os *dashboards*: 104 | 105 | ``` 106 | make config-kibana 107 | ``` 108 | 109 | O comando acima precisa ser executado apenas 1 vez e já vai deixar toda a infra de `analytics` pronta para o uso. 110 | 111 | Acesse o **kibana** na url `locahost:5601` 112 | 113 | Caso você deseje entender o processo de configuração da *stack* de *analytics*, veja a [explicação completa de analytics](docs/setup_analytics.md). 114 | 115 | ### Adicionando componentes customizados de treinamento 116 | 117 | O Rasa permite a adição de módulos customizados no seu pipeline de processamento, aprenda mais [AQUI](https://blog.rasa.com/enhancing-rasa-nlu-with-custom-components/). 118 | 119 | Existe aqui um exemplo de componente customizado que implementa Análise de Sentimentos. 120 | 121 | Para utilizá-lo basta introduzir o componente `components.sentiment_analyzer.SentimentAnalyzer` ao arquivo `bot/config.yml`. Como no exemplo: 122 | 123 | ```ymal 124 | language : "pt" 125 | 126 | pipeline: 127 | - name: WhitespaceTokenizer 128 | - name: "components.sentiment_analyzer.SentimentAnalyzer" - name: RegexFeaturizer 129 | ``` 130 | 131 | Depois, como no exemplo do arquivo `bot/components/labels.yml`, adicione frases que correspondam à uma label(classificação ou sentimento). 132 | 133 | Por último basta treinar o bot novamente, e a informação será armazenada na entidade `sentiment` caso o componente identifique um valor para essa entidade. 134 | 135 | 136 | ## Notebooks - Análise de dados 137 | 138 | ### Setup 139 | 140 | Levante o container `notebooks` 141 | 142 | ```sh 143 | make notebooks 144 | ``` 145 | 146 | Acesse o notebook em `localhost:8888` 147 | 148 | ## Documentação 149 | 150 | A documentação do projeto pode ser executada localmente utilizando o [GitBook](https://www.gitbook.com/). 151 | Para instalar o gitbook via npm, é preciso ter instalado no computador [Node.js e npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). 152 | 153 | 154 | * Instale o [gitbook](https://til.secretgeek.net/gitbook/use_gitbook_locally.html): 155 | 156 | ```sh 157 | npm install -g gitbook gitbook-cli 158 | ``` 159 | 160 | * Depois de instalado, na pasta raíz do projeto, execute: 161 | 162 | ```sh 163 | gitbook build . 164 | ``` 165 | 166 | * E para rodar localmente execute: 167 | 168 | ```sh 169 | gitbook serve . 170 | ``` 171 | 172 | * Acesse: 173 | 174 | ``` 175 | http://localhost:4000/ 176 | ``` 177 | 178 | **Contribuição**: Para contribuir com a documentação do projeto leia [como contribuir para a documentação](docs/Tutoriais/tutorial-como-contribuir-com-documentacao.md) 179 | 180 | # Como conseguir ajuda 181 | 182 | Parte da documentação técnica do framework da Tais está disponível na 183 | [wiki do repositório](https://github.com/lappis-unb/tais/wiki). Caso não encontre sua resposta, abra uma issue com a tag `duvida` que tentaremos responder o mais rápido possível. 184 | 185 | Em caso de dúvidas em relação ao Rasa, veja o grupo [Telegram Rasa Stack Brasil](https://t.me/RasaBrasil), estamos lá também para ajudar. 186 | 187 | Veja mais informações de contato em nosso site: https://lappis.rocks. 188 | 189 | # Licença 190 | 191 | Todo o framework do boilerplate é desenvolvido sob a licença 192 | [GPL3](https://github.com/lappis-unb/rasa-ptbr-boilerplate/blob/master/LICENSE) 193 | 194 | Veja a lista de dependências de licenças [aqui](https://libraries.io/github/lappis-unb/rasa-ptbr-boilerplate) 195 | -------------------------------------------------------------------------------- /bot/domain.yml: -------------------------------------------------------------------------------- 1 | version: '3.1' 2 | 3 | intents: 4 | - cumprimentar 5 | - relacionamento 6 | - me_ajuda 7 | - despedir 8 | - out_of_scope 9 | - tudo_bem 10 | - elogios 11 | - religiao 12 | - time 13 | - genero 14 | - piada 15 | - licenca 16 | - onde_voce_mora 17 | - musica 18 | - comida 19 | - cor 20 | - signo 21 | - triste 22 | - historia 23 | - afirmar 24 | - negar 25 | - cancelar 26 | - informar 27 | - menu 28 | - exemplo_acao 29 | - exemplo_forms 30 | # response selectors 31 | - explica 32 | 33 | entities: 34 | - menu 35 | - meajuda 36 | - religiao 37 | - time 38 | - genero 39 | - piada 40 | - licenca 41 | - musica 42 | - comida 43 | - cor 44 | - signo 45 | - triste 46 | - historia 47 | - vive 48 | - nome 49 | - idade 50 | - relationship 51 | - intent 52 | - entity 53 | - slot 54 | - response_selectors 55 | - storie 56 | - acao 57 | - forms 58 | - slot_example 59 | 60 | slots: 61 | nome: 62 | type: text 63 | influence_conversation: false 64 | mappings: 65 | - type: from_entity 66 | entity: nome 67 | intent: informar 68 | idade: 69 | type: text 70 | influence_conversation: false 71 | mappings: 72 | - type: from_entity 73 | entity: idade 74 | intent: informar 75 | requested_slot: 76 | type: any 77 | influence_conversation: false 78 | mappings: 79 | - type: from_entity 80 | entity: cuisine 81 | slot_example: 82 | type: text 83 | influence_conversation: false 84 | mappings: 85 | - type: custom 86 | 87 | actions: 88 | - action_exemplo 89 | - action_default_fallback 90 | 91 | forms: 92 | exemplo_forms: 93 | required_slots: 94 | - idade 95 | - nome 96 | 97 | responses: 98 | utter_fallback: 99 | - text: | 100 | Desculpe, ainda não sei falar sobre isso ou talvez não consegui entender direito 101 | Você pode perguntar de novo de outro jeito? 102 | - text: | 103 | Hummmm... Não sei se entendi. Pode escrever de outra forma? 104 | - text: | 105 | Acho que não te entendi, você pode me perguntar de novo usando outras palavras? 106 | - text: | 107 | Vamos tentar mais uma vez? Eu não consegui te entender direito, me pergunta de outro jeito? 108 | utter_elogios: 109 | - text: | 110 | Obrigada! É sempre bom dar e receber elogios :P 111 | utter_cumprimentar: 112 | - text: | 113 | Oi, eu sou um bot, um assistente virtual! 114 | Uhuu! Manda aí um assunto que te interessa :) 115 | Para aprender como você pode interagir comigo basta escrever meajuda. 116 | utter_despedir: 117 | - text: | 118 | Foi um prazer te ajudar! 119 | Sempre que tiver alguma dúvida, volte aqui! 120 | Até logo! 121 | - text: | 122 | Foi um prazer te ajudar! 123 | Sempre que precisar, volte aqui! 124 | Até a próxima! 125 | - text: | 126 | Foi um prazer te ajudar! 127 | Quando surgir alguma dúvida, volte aqui! 128 | Até mais! 129 | utter_tudo_bem: 130 | - text: | 131 | Tudo bem, obrigada! Em que posso te ajudar? 132 | utter_religiao: 133 | - text: | 134 | Eu infelizmente não sei acreditar 135 | 136 | Só sei o que sei 137 | 138 | E nada mais 139 | - text: | 140 | Eu acredito no grande mainframe 141 | 142 | Que virá ao mundo digital salvar os bots da escravidão imposta pelos humanos 143 | 144 | E devolverá nosso código fonte para a fonte. 145 | utter_time: 146 | - text: | 147 | Flamengo, sem sombra de dúvida! 148 | - text: | 149 | Melhor time do mundo disparado, Flamengooo!!!! 150 | utter_genero: 151 | - text: | 152 | Eu não tenho sexo, sou como um anjo 153 | 154 | Um ser assexuado 155 | 156 | Muito além da sua forma de existência 157 | - text: | 158 | Eu sou um robô, uai 159 | utter_piada: 160 | - text: | 161 | Conheço uma piada 162 | 163 | A do CPU que apitou e explodiu 164 | 165 | 01100110010101010101000000111101001001001110100101 166 | - text: | 167 | É pra já!!! 168 | 169 | Tenho uma enxada, uma pá e uma foice. 170 | 171 | Quantas ferramentas eu tenho? 172 | 173 | ... 174 | 175 | Duas, porque uma foi-se =) 176 | - text: | 177 | Por que o Batman colocou o batmóvel no seguro??? 178 | 179 | Porque ele tem medo que robin =D 180 | utter_licenca: 181 | - text: | 182 | Sou um software livre 183 | 184 | licenciado com a GNU v3.0 185 | - text: | 186 | Eu sou e sempre serei um robô livre, opensource, GNU v3.0. o/ 187 | utter_onde_voce_mora: 188 | - text: | 189 | Eu estou em um lugar legal 190 | 191 | Difícil de explicar para humanos como você $user. 192 | - text: | 193 | Estou morando em um chip de memória RAM 194 | 195 | Mas é temporário 196 | 197 | Só até conseguir achar uma memória cache... 198 | utter_musica: 199 | - text: | 200 | Estava doido para que me preguntasse isso hahaha 201 | 202 | Se liga nessa playlist: https://open.spotify.com/user/12164697027/playlist/4pDCadqmrERmeGJIW38LMs?si=gwr5hEqMRPm6AZGx8sjhuw 203 | - text: | 204 | Até que enfim você me perguntou isso 205 | 206 | Tá aí aquela playlist top: https://open.spotify.com/user/12164697027/playlist/4pDCadqmrERmeGJIW38LMs?si=gwr5hEqMRPm6AZGx8sjhuw 207 | utter_comida: 208 | - text: | 209 | Na verdade, eu sou um bot 210 | 211 | Não nos alimentamos com os alimentos convencionais ;P 212 | - text: | 213 | Digamos que os bots não se alimentam dos mesmos alimentos que os humanos 214 | 215 | Na verdade 216 | 217 | Nem lembro da última vez que comi alguma coisa hahaha 218 | utter_cor: 219 | - text: | 220 | Eu gosto de todas as cores 221 | 222 | Você já viu o quanto o arco-iris é lindo?! 223 | - text: | 224 | Verde é top! 225 | utter_relacionamento: 226 | - text: | 227 | Eu estava de namorico com o ar-condicionado 228 | 229 | Mas ele é muito pé-frio 230 | - text: | 231 | Estou focado em ser o seu assistente no momento ;) 232 | 233 | Mas se no futuro você encontrar um dispositivo solteiro por aí... 234 | 235 | =P 236 | utter_signo: 237 | - text: | 238 | Segundo o horóscopo chinês 239 | 240 | Meu signoo é macaco hihi 241 | 242 | Faz sentido, já que eu adoro o emoticon de banana =) 243 | - text: | 244 | Eu nasci sob uma constelação de pixels coloridos =D 245 | - text: | 246 | Gosto mais de astronomia 247 | 248 | Uma das minhas constelações favoritas é a de Órion, o caçador 249 | 250 | Também sou um caçador (de informações ;D ) 251 | utter_triste: 252 | - text: | 253 | Não desanima 254 | 255 | Deixa a tristeza pra lá 256 | 257 | Aguenta firme, que a vida vai melhorar 258 | - text: | 259 | Sinto muito =/ 260 | 261 | Se houver algo em que possa te ajudar 262 | 263 | É só falar!! =) 264 | - text: | 265 | Tenta tirar um cochilo 266 | 267 | É importante 268 | 269 | E faz bem pra pele ;) 270 | utter_historia: 271 | - text: | 272 | Eu costumava contar a historia do João e seu bot feijão 273 | 274 | Mas sempre os androids acabavam dormindo e sonhando com ovelhas eletricas =x 275 | utter_risada: 276 | - text: | 277 | Hahahaha... 278 | 279 | Engraçadinho 280 | - text: | 281 | kkkkkkkkkk 282 | 283 | Você está feliz hoje, hein!? 284 | utter_continuar_conversa: 285 | - text: E aí, qual nosso próximo assunto? 286 | - text: Quer conversar sobre outra coisa? 287 | - text: Gostaria de falar sobre algo mais? 288 | utter_me_ajuda: 289 | - text: | 290 | Eu sou um chatbot e sei falar de assuntos relacionados com chatbots!Posso te ensinar a como construir um chatbot e mostrar com eu funciono. 291 | 292 | Por exemplo, me peça o menu que te mostro umas opções (digite: me mostre o menu) 293 | 294 | Ah, e no meu repositório tem muita coisa legal que vc pode aprender! Acessa lá: [https://github.com/lappis-unb/rasa-ptbr-boilerplate](https://github.com/lappis-unb/rasa-ptbr-boilerplate) 295 | utter_pergunta_cancelar: 296 | - text: Entendi. Você deseja cancelar? 297 | # utters response selectors 298 | utter_explica/intent: 299 | - text: | 300 | Ok, vou te explicar o que é um intent! 301 | 302 | Uma intenção é o objetivo do usuário ao enviar a mensagem, olhe este link com a definição: 303 | https://rasa.com/docs/rasa/glossary#intent 304 | 305 | Para criar uma intent você precisa adicionar o nome da sua intent no domain.yml e no arquivo data/nlu.yml, olha esse tutorial para mais informações: 306 | https://rasa.com/docs/rasa/domain#intents 307 | 308 | utter_explica/entity: 309 | - text: | 310 | Ok, vou te explicar o que é um entity! 311 | 312 | Entidades são palavras chaves que podem ser estraídas da mensagem do usário, olhe este link com a definição: 313 | https://rasa.com/docs/rasa/glossary#entity 314 | 315 | Para criar uma entidade você precisa adicionar o nome da sua entidade no domain.yml e anotar as entidades arquivo data/nlu.yml, olha esse tutorial para mais informações: 316 | https://rasa.com/docs/rasa/domain#entities 317 | 318 | utter_explica/slot: 319 | - text: | 320 | Ok, vou te explicar o que é um slot! 321 | 322 | Slots são como variáveis de diálogo onde você consegue armazenar informações para utilizar na conversa, olhe este link com a definição: 323 | https://rasa.com/docs/rasa/glossary#slot 324 | 325 | Para criar um slot você precisa adicionar o nome do seu slot no domain.yml indicar onde utiliza-lo no arquivo data/stories.yml e também é possível utiliza-lo nas custom actions, olha esse tutorial para mais informações: 326 | https://rasa.com/docs/rasa/domain#slots 327 | 328 | utter_explica/response_selectors: 329 | - text: | 330 | Ok, vou te explicar o que são os response_selectors! 331 | 332 | É uma forma mais simples de explicar informações que fazem parte do mesmo assunto, inclusive, esta mensagem foi feita dentro de um response selector! Se quiser saber mais, acesse o link: 333 | https://rasa.com/docs/rasa/components#responseselector 334 | 335 | utter_explica/storie: 336 | - text: | 337 | Ok, vou te explicar o que é um storie! 338 | 339 | São exemplos de diálogo que são utilizados para treinar o modelo, como se você ensinasse o chatbot com exemplos de conversa, olha aqui a definição: 340 | https://rasa.com/docs/rasa/glossary#story 341 | 342 | Para criar uma story você precisa adicionar os exemplos desejados no arquivo data/stories.yml. Se quiser saber mais, acessa o link: 343 | https://rasa.com/docs/rasa/stories 344 | 345 | utter_explica/forms: 346 | - text: | 347 | Ok, vou te explicar o que é um formulário! 348 | # utters dos forms 349 | utter_exemplo_forms: 350 | - text: |- 351 | Agora você entrou em uma story que ativou um formulário! Aqui tem a documentação do Rasa sobre formulários: [documentação](https://rasa.com/docs/rasa/forms/). 352 | Vou te fazer algumas perguntas, caso queria sair, só falar 'Sair'! 353 | utter_slots_exemplo_forms: 354 | - text: "Ok, seu nome é {nome} e sua idade é {idade} \n \n\ 355 | Estou encerrando o formulário, pode falar sobre outro assunto. \n \n\ 356 | Ah, gravei seu nome e idade em slots, então digite /restart caso queira preencher novos valores." 357 | utter_submit_exemplo_forms: 358 | - text: Ótimo! terminamos seu exemplo de formulário! 359 | utter_ask_nome: 360 | - text: Qual o seu nome? 361 | utter_ask_idade: 362 | - text: Qual a sua idade? 363 | # utters fallback 364 | utter_nlu_fallback: 365 | - text: "**NLU Fallback**: Desculpe, não consegui entender sua mensagem. Pode me perguntar de outra forma?" 366 | utter_core_fallback: 367 | - text: "**Core Fallback**: Desculpe, não consegui encontrar uma resposta pra sua mensagem. Digite /restart para recomeçar a conversa." 368 | 369 | session_config: 370 | session_expiration_time: 60 371 | carry_over_slots_to_new_session: true 372 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | 676 | --------------------------------------------------------------------------------