diff --git a/.gitignore b/.gitignore index e5c2e6d5..b21ce3d6 100644 --- a/.gitignore +++ b/.gitignore @@ -122,3 +122,5 @@ harmoni_actuators/harmoni_tts/content/* doc/_build harmoni_actuators/harmoni_tts/scale_stats.npy harmoni_actuators/harmoni_tts/temp_data/tts.wav + +harmoni_actuators/harmoni_tts/TTS/ diff --git a/dockerfiles/harmoni/kinetic/base/dockerfile b/dockerfiles/harmoni/kinetic/base/dockerfile index 3d4bf170..df8ebaa4 100644 --- a/dockerfiles/harmoni/kinetic/base/dockerfile +++ b/dockerfiles/harmoni/kinetic/base/dockerfile @@ -89,6 +89,8 @@ RUN \ google-cloud-speech==1.3.2 \ dialogflow \ google-api-python-client \ + # Rasa + rasa==2.7.1 \ # Local STT deepspeech \ # Testing diff --git a/dockerfiles/harmoni/noetic/base/dockerfile b/dockerfiles/harmoni/noetic/base/dockerfile index b315e02c..e3f1f773 100644 --- a/dockerfiles/harmoni/noetic/base/dockerfile +++ b/dockerfiles/harmoni/noetic/base/dockerfile @@ -66,6 +66,8 @@ RUN \ google-cloud-speech==1.3.2 \ dialogflow \ google-api-python-client \ + # Rasa + rasa==2.7.1 \ # Local STT deepspeech \ # Testing diff --git a/harmoni_core/harmoni_pattern/config/configuration.yaml b/harmoni_core/harmoni_pattern/config/configuration.yaml index 52b6069a..24b79f02 100644 --- a/harmoni_core/harmoni_pattern/config/configuration.yaml +++ b/harmoni_core/harmoni_pattern/config/configuration.yaml @@ -23,6 +23,11 @@ mic_test: trigger_intent: "Hey" pattern_scripting: $(find harmoni_pattern)/pattern_scripting/mic_test.json +chatbot: + default_param: + trigger_intent: "Hey" + pattern_scripting: $(find harmoni_pattern)/pattern_scripting/chatbot.json + speak_test: default_param: diff --git a/harmoni_core/harmoni_pattern/pattern_scripting/chatbot.json b/harmoni_core/harmoni_pattern/pattern_scripting/chatbot.json new file mode 100644 index 00000000..f9d4e0c5 --- /dev/null +++ b/harmoni_core/harmoni_pattern/pattern_scripting/chatbot.json @@ -0,0 +1,55 @@ +[ + { + "set": "setup", + "steps": [ + { + "microphone_default": { + "action_goal": "ON", + "resource_type": "sensor", + "wait_for": "" + } + }, + { + "stt_default": { + "action_goal": "ON", + "resource_type": "detector", + "wait_for": "" + } + } + ] + }, + { + "set": "loop", + "steps": [ + { + "stt_default": { + "resource_type": "detector", + "wait_for": "new" + } + }, + { + "bot_default": { + "action_goal": "REQUEST", + "resource_type": "service", + "wait_for": "new" + } + }, + { + "tts_default": { + "action_goal": "REQUEST", + "resource_type": "service", + "wait_for": "new" + } + }, + [ + { + "speaker_default": { + "action_goal": "DO", + "resource_type": "actuator", + "wait_for": "new" + } + } + ] + ] + } +] diff --git a/harmoni_dialogues/harmoni_bot/README.md b/harmoni_dialogues/harmoni_bot/README.md index 00d242fe..cac46d65 100644 --- a/harmoni_dialogues/harmoni_bot/README.md +++ b/harmoni_dialogues/harmoni_bot/README.md @@ -1,6 +1,16 @@ # HARMONI Bot -This package wraps different chatbot services that can be used with HARMONI. Currently we support AWS Lex and Goodle Dialogflow. Rasa is a high priority on our roadmap for local chatbot functionality. +This package wraps different chatbot services that can be used with HARMONI. Currently we support AWS Lex, Google Dialogflow, and Rasa. + +### Using the Rasa service +The default Rasa assistant is `rasa_example`. The Rasa workspace for this assistant is located in `harmoni_models/bot`, +and the assistant name can be set in `configuration.yaml` by changing the rasa_assistant parameter value to the name of the corresponding workspace. + +The start_rasa_server.sh script is called before the service is launched and gets the correct path to train and run the Rasa server through rosparam. +The model is only trained and run if it is a valid bot within `harmoni_models/bot`. + +### Adding Rasa assistants +Custom Rasa bots must also be placed in `harmoni_models/bot` for the start_server script to find the workspace path. ## Usage ## Parameters @@ -14,6 +24,14 @@ Parameters input for the aws lex service: |bot_alias | | | |region_name | | | +Parameters input for the Rasa service: + +| Parameters | Definition | Values | +|----------------------|------------|--------| +|rasa_assistant | | | +|host | | | +|post | | | + ## Testing ## References [Documentation](https://harmoni.readthedocs.io/en/latest/packages/harmoni_bot.html) \ No newline at end of file diff --git a/harmoni_dialogues/harmoni_bot/config/configuration.yaml b/harmoni_dialogues/harmoni_bot/config/configuration.yaml index 2c31bd18..cca383ab 100644 --- a/harmoni_dialogues/harmoni_bot/config/configuration.yaml +++ b/harmoni_dialogues/harmoni_bot/config/configuration.yaml @@ -22,3 +22,9 @@ google: language: "en" session_id: "testing" credential_path: "$(find harmoni_bot)/config/private-keys_en.json" + +rasa: + default_param: + rasa_assistant: "rasa_example" + host: "localhost" + port: 5005 diff --git a/harmoni_dialogues/harmoni_bot/launch/bot_service.launch b/harmoni_dialogues/harmoni_bot/launch/bot_service.launch index 5ea5c4de..17bec0b4 100644 --- a/harmoni_dialogues/harmoni_bot/launch/bot_service.launch +++ b/harmoni_dialogues/harmoni_bot/launch/bot_service.launch @@ -1,8 +1,9 @@ - + + @@ -14,4 +15,11 @@ + + + + + + + diff --git a/harmoni_dialogues/harmoni_bot/nodes/rasa_service.py b/harmoni_dialogues/harmoni_bot/nodes/rasa_service.py new file mode 100755 index 00000000..0576069d --- /dev/null +++ b/harmoni_dialogues/harmoni_bot/nodes/rasa_service.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 + +# Common Imports +import rospy +import roslib + +from harmoni_common_lib.constants import State +from harmoni_common_lib.service_server import HarmoniServiceServer +from harmoni_common_lib.service_manager import HarmoniServiceManager + +# Specific Imports +import argparse +import os +import rasa +import threading +from harmoni_common_lib.constants import DialogueNameSpace +from harmoni_bot.rasa_client import RasaClient + + +class RasaService(HarmoniServiceManager): + """Rasa chatbot service""" + + def __init__(self, name, param): + """Constructor method: Initialization of variables and lex parameters + setting up""" + super().__init__(name) + """ Initialization of variables and parameters """ + self.host = param["host"] + self.port = param["port"] + + self.rasa_client = RasaClient( + self.host, + self.port + ) + + self.state = State.INIT + return + + def request(self, input_text): + """[summary] + + Args: + input_text (str): User request (or input text) for triggering Rasa Intent + + Returns: + object: It contains information about the response received (bool) and response message (str) + response: bool + message: str + """ + rospy.loginfo("Start the %s request" % self.name) + self.state = State.REQUEST + + try: + rasa_response = self.rasa_client.get_rasa_response(input_text) + rospy.loginfo(f"The Rasa response is {rasa_response}") + self.state = State.SUCCESS + except Exception as e: + rospy.loginfo(f"Exception occurred: {e}") + self.state = State.FAILED + rasa_response = "" + self.response_received = True + self.result_msg = rasa_response + return {"response": self.state, "message": rasa_response} + + +def main(): + """[summary] + Main function for starting HarmoniRasa service + """ + service_name = DialogueNameSpace.bot.name + instance_id = rospy.get_param("instance_id") # "default" + service_id = f"{service_name}_{instance_id}" + try: + rospy.init_node(service_name, log_level=rospy.INFO) + params = rospy.get_param("rasa" + "/" + instance_id + "_param/") + s = RasaService(service_id, params) + service_server = HarmoniServiceServer(service_id, s) + service_server.start_sending_feedback() + rospy.spin() + except rospy.ROSInterruptException: + pass + + +if __name__ == "__main__": + main() diff --git a/harmoni_dialogues/harmoni_bot/requirements.txt b/harmoni_dialogues/harmoni_bot/requirements.txt new file mode 100644 index 00000000..72d22dd5 --- /dev/null +++ b/harmoni_dialogues/harmoni_bot/requirements.txt @@ -0,0 +1 @@ +rasa==2.7.1 diff --git a/harmoni_dialogues/harmoni_bot/scripts/start_rasa_server.sh b/harmoni_dialogues/harmoni_bot/scripts/start_rasa_server.sh new file mode 100755 index 00000000..83a067a3 --- /dev/null +++ b/harmoni_dialogues/harmoni_bot/scripts/start_rasa_server.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +shopt -s dotglob +shopt -s nullglob + +RASA_ASSISTANT=$(rosparam get /rasa/default_param/rasa_assistant) +RASA_MODEL_DIR=$(rosparam get /bot_model_dir) +RASA_BOTS=("$RASA_MODEL_DIR/bot/"*) + +found=0 +for dir in "${RASA_BOTS[@]}" ; do + dir=$(basename "$dir") + [[ $dir = "$RASA_ASSISTANT" ]] && found=1 +done + +if [ $found == 1 ]; then + cd "$RASA_MODEL_DIR"/bot/"$RASA_ASSISTANT" || exit + rasa train && rasa run +else + echo "Not a valid Rasa bot" +fi \ No newline at end of file diff --git a/harmoni_dialogues/harmoni_bot/setup.py b/harmoni_dialogues/harmoni_bot/setup.py index 25781ac2..92c6dbea 100644 --- a/harmoni_dialogues/harmoni_bot/setup.py +++ b/harmoni_dialogues/harmoni_bot/setup.py @@ -1,4 +1,5 @@ # ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD +import os from distutils.core import setup from catkin_pkg.python_setup import generate_distutils_setup @@ -6,7 +7,10 @@ # fetch values from package.xml setup_args = generate_distutils_setup( packages=['harmoni_bot'], - package_dir={'': 'src'}, + package_dir={ + '': 'src', + 'harmoni_bot': os.path.join('src', 'harmoni_bot') + }, ) setup(**setup_args) diff --git a/harmoni_dialogues/harmoni_bot/src/harmoni_bot/rasa_client.py b/harmoni_dialogues/harmoni_bot/src/harmoni_bot/rasa_client.py new file mode 100644 index 00000000..818ac4ea --- /dev/null +++ b/harmoni_dialogues/harmoni_bot/src/harmoni_bot/rasa_client.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +import logging +import requests + +logging.basicConfig(level=logging.INFO) + + +class RasaClient: + + def __init__( + self, + host="localhost", + port=5005 + ): + self._host = host + self._port = port + + def get_rasa_response(self, input_text): + headers = { + 'Content-Type': 'application/json', + } + data = '{ "sender": "test_user", "message": "' + input_text + '", "metadata": {} }' + response = requests.post(f"http://{self._host}:{self._port}/webhooks/myio/webhook", headers=headers, data=data) + logging.info(f"Bot response: \n{response.text}\n") + try: + text = response.json()[0]["text"] + except IndexError: + logging.error("Warning: Bad index") + text = "I didn't catch that" + return text + + +if __name__ == "__main__": + rasa_client = RasaClient() + r = "Let's start a conversation with the rasa bot. What would you like to say?\n->" + while True: + i = input(r) + r = rasa_client.get_rasa_response(i) + "\n->" diff --git a/harmoni_dialogues/harmoni_bot/test/rasa.test b/harmoni_dialogues/harmoni_bot/test/rasa.test new file mode 100644 index 00000000..b9a62ad0 --- /dev/null +++ b/harmoni_dialogues/harmoni_bot/test/rasa.test @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/harmoni_dialogues/harmoni_bot/test/rostest_rasa.py b/harmoni_dialogues/harmoni_bot/test/rostest_rasa.py new file mode 100755 index 00000000..83766cb2 --- /dev/null +++ b/harmoni_dialogues/harmoni_bot/test/rostest_rasa.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 + +# Common Imports +import rospy +import sys +import unittest +from collections import deque + +# Specific Imports +import requests +from actionlib_msgs.msg import GoalStatus +from harmoni_common_lib.action_client import HarmoniActionClient +from harmoni_common_lib.constants import DialogueNameSpace, ActionType +from harmoni_common_msgs.msg import harmoniFeedback, harmoniResult + +PKG = "test_harmoni_bot" + + +class TestRasa(unittest.TestCase): + + def setUp(self): + """ + Set up the client for requesting to harmoni_bot + """ + rospy.init_node("test_rasa", log_level=rospy.INFO) + self.text = rospy.get_param("test_rasa_input") + self.instance_id = rospy.get_param("instance_id") + self.host = rospy.get_param("rasa/default_param/host") + self.port = rospy.get_param("rasa/default_param/port") + self.result = False + self.name = DialogueNameSpace.bot.name + "_" + self.instance_id + self.service_client = HarmoniActionClient(self.name) + self.client_result = deque() + self.service_client.setup_client(self.name, self.result_cb, self.feedback_cb) + # NOTE currently no feedback, status, or result is received. + rospy.Subscriber( + "/harmoni_bot_default/feedback", harmoniFeedback, self.feedback_cb + ) + rospy.Subscriber("/harmoni_bot_default/status", GoalStatus, self.status_cb) + rospy.Subscriber("/harmoni_bot_default/result", harmoniResult, self.result_cb) + rospy.loginfo("TestRasa: Started up; waiting for Rasa startup") + + # Wait until Rasa server is running before running any test methods + connected = False + while not connected: + try: + headers = { + 'Content-Type': 'application/json', + } + data = '{ "sender": "test_user", "message": "", "metadata": {} }' + response = requests.post( + f"http://{self.host}:{self.port}/webhooks/myio/webhook", headers=headers, data=data + ) + connected = response.ok + except Exception: + rospy.loginfo("Retrying server connection...") + rospy.sleep(1) + + rospy.loginfo("TestRasa: Started") + + def feedback_cb(self, data): + rospy.loginfo(f"Feedback: {data}") + self.result = False + + def status_cb(self, data): + rospy.loginfo(f"Status: {data}") + self.result = False + + def result_cb(self, data): + rospy.loginfo(f"Result: {data}") + self.result = True + + def test_request_response(self): + rospy.loginfo(f"The input text is {self.text}") + # expected response from the rasa_example bot when the input text is "Hello" + text = "Hey! How are you?" + self.service_client.send_goal( + action_goal=ActionType.REQUEST.value, + optional_data=self.text, + wait=True, + ) + rasa_response = self.service_client.get_result() + rospy.loginfo("HarmoniResult:" + rasa_response.message) + assert rasa_response.message == text + + +def main(): + # TODO convert to a test suite so that setup doesn't have to run over and over. + import rostest + + rospy.loginfo("test_rasa started") + rospy.loginfo("TestRasa: sys.argv: %s" % str(sys.argv)) + rostest.rosrun(PKG, "test_rasa", TestRasa, sys.argv) + + +if __name__ == "__main__": + main() diff --git a/harmoni_dialogues/harmoni_bot/test/test_rasa_client.py b/harmoni_dialogues/harmoni_bot/test/test_rasa_client.py new file mode 100755 index 00000000..26126cd4 --- /dev/null +++ b/harmoni_dialogues/harmoni_bot/test/test_rasa_client.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +import mock +import requests +import unittest + +from harmoni_bot.rasa_client import RasaClient + + +class TestRasaClient(unittest.TestCase): + + def setUp(self): + self.client = RasaClient("localhost", 5005) + + @mock.patch("harmoni_bot.rasa_client.requests.post") + def test_get_rasa_response(self, mock_post): + recipient_id = "test_user" + text = "Welcome to the Interaction Lab!" + mock_post.return_value.json.return_value = [ + {"recipient_id": recipient_id, "text": text} + ] + rasa_response = self.client.get_rasa_response("Hello world!") + assert rasa_response == text + + +if __name__ == "__main__": + unittest.main() diff --git a/harmoni_models/bot/rasa_example/actions/__init__.py b/harmoni_models/bot/rasa_example/actions/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/harmoni_models/bot/rasa_example/actions/actions.py b/harmoni_models/bot/rasa_example/actions/actions.py new file mode 100644 index 00000000..040c2bc0 --- /dev/null +++ b/harmoni_models/bot/rasa_example/actions/actions.py @@ -0,0 +1,23 @@ +# This files contains your custom actions which can be used to run +# custom Python code. +# +# See this guide on how to implement these action: +# https://rasa.com/docs/rasa/custom-actions + + +# This is a simple example for a custom action which utters "Hello World!" + +# from typing import Any, Text, Dict, List +# +# from rasa_sdk import Action, Tracker +# from rasa_sdk.executor import CollectingDispatcher +# +# +# class ActionHelloWorld(Action): +# +# def name(self) -> Text: +# return "action_hello_world" +# +# def run(self, dispatcher: CollectingDispatcher, +# tracker: Tracker, +# domain: Dict[Text, Any]) -> List[Dict[Text, Any]]: diff --git a/harmoni_models/bot/rasa_example/addons/__init__.py b/harmoni_models/bot/rasa_example/addons/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/harmoni_models/bot/rasa_example/addons/custom_channel.py b/harmoni_models/bot/rasa_example/addons/custom_channel.py new file mode 100644 index 00000000..85416140 --- /dev/null +++ b/harmoni_models/bot/rasa_example/addons/custom_channel.py @@ -0,0 +1,57 @@ +import asyncio +import inspect +from sanic import Sanic, Blueprint, response +from sanic.request import Request +from sanic.response import HTTPResponse +from typing import Text, Dict, Any, Optional, Callable, Awaitable, NoReturn + +import rasa.utils.endpoints +from rasa.core.channels.channel import ( + InputChannel, + CollectingOutputChannel, + UserMessage, +) + + +class MyIO(InputChannel): + def name(self) -> Text: + """Name of your custom channel.""" + return "myio" + + def blueprint( + self, on_new_message: Callable[[UserMessage], Awaitable[None]] + ) -> Blueprint: + + custom_webhook = Blueprint( + "custom_webhook_{}".format(type(self).__name__), + inspect.getmodule(self).__name__, + ) + + @custom_webhook.route("/", methods=["GET"]) + async def health(request: Request) -> HTTPResponse: + return response.json({"status": "ok"}) + + @custom_webhook.route("/webhook", methods=["POST"]) + async def receive(request: Request) -> HTTPResponse: + sender_id = request.json.get("sender") # method to get sender_id + text = request.json.get("message") # method to fetch text + input_channel = self.name() # method to fetch input channel + metadata = self.get_metadata(request) # method to get metadata + + collector = CollectingOutputChannel() + + # include exception handling + + await on_new_message( + UserMessage( + text, + collector, + sender_id, + input_channel=input_channel, + metadata=metadata, + ) + ) + + return response.json(collector.messages) + + return custom_webhook diff --git a/harmoni_models/bot/rasa_example/config.yml b/harmoni_models/bot/rasa_example/config.yml new file mode 100644 index 00000000..c6c2f39b --- /dev/null +++ b/harmoni_models/bot/rasa_example/config.yml @@ -0,0 +1,39 @@ +# Configuration for Rasa NLU. +# https://rasa.com/docs/rasa/nlu/components/ +language: en + +pipeline: +# # No configuration for the NLU pipeline was provided. The following default pipeline was used to train your model. +# # If you'd like to customize it, uncomment and adjust the pipeline. +# # See https://rasa.com/docs/rasa/tuning-your-model for more information. +# - name: WhitespaceTokenizer +# - name: RegexFeaturizer +# - name: LexicalSyntacticFeaturizer +# - name: CountVectorsFeaturizer +# - name: CountVectorsFeaturizer +# analyzer: char_wb +# min_ngram: 1 +# max_ngram: 4 +# - name: DIETClassifier +# epochs: 100 +# constrain_similarities: true +# - name: EntitySynonymMapper +# - name: ResponseSelector +# epochs: 100 +# constrain_similarities: true +# - name: FallbackClassifier +# threshold: 0.3 +# ambiguity_threshold: 0.1 + +# Configuration for Rasa Core. +# https://rasa.com/docs/rasa/core/policies/ +policies: +# # No configuration for policies was provided. The following default policies were used to train your model. +# # If you'd like to customize them, uncomment and adjust the policies. +# # See https://rasa.com/docs/rasa/policies for more information. +# - name: MemoizationPolicy +# - name: RulePolicy +# - name: TEDPolicy +# max_history: 5 +# epochs: 100 +# constrain_similarities: true diff --git a/harmoni_models/bot/rasa_example/credentials.yml b/harmoni_models/bot/rasa_example/credentials.yml new file mode 100644 index 00000000..b9318e86 --- /dev/null +++ b/harmoni_models/bot/rasa_example/credentials.yml @@ -0,0 +1,36 @@ +# This file contains the credentials for the voice & chat platforms +# which your bot is using. +# https://rasa.com/docs/rasa/messaging-and-voice-channels + +rest: +# # you don't need to provide anything here - this channel doesn't +# # require any credentials + +addons.custom_channel.MyIO: + username: "user_name" + another_parameter: "some value" + +#facebook: +# verify: "" +# secret: "" +# page-access-token: "" + +#slack: +# slack_token: "" +# slack_channel: "" +# slack_signing_secret: "" + +#socketio: +# user_message_evt: +# bot_message_evt: +# session_persistence: + +#mattermost: +# url: "https:///api/v4" +# token: "" +# webhook_url: "" + +# This entry is needed if you are using Rasa X. The entry represents credentials +# for the Rasa X "channel", i.e. Talk to your bot and Share with guest testers. +rasa: + url: "http://localhost:5002/api" diff --git a/harmoni_models/bot/rasa_example/data/nlu.yml b/harmoni_models/bot/rasa_example/data/nlu.yml new file mode 100644 index 00000000..dedbedbf --- /dev/null +++ b/harmoni_models/bot/rasa_example/data/nlu.yml @@ -0,0 +1,92 @@ +version: "2.0" + +nlu: +- intent: greet + examples: | + - hey + - hello + - hi + - hello there + - good morning + - good evening + - moin + - hey there + - let's go + - hey dude + - goodmorning + - goodevening + - good afternoon + +- intent: goodbye + examples: | + - good afternoon + - cu + - good by + - cee you later + - good night + - bye + - goodbye + - have a nice day + - see you around + - bye bye + - see you later + +- intent: affirm + examples: | + - yes + - y + - indeed + - of course + - that sounds good + - correct + +- intent: deny + examples: | + - no + - n + - never + - I don't think so + - don't like that + - no way + - not really + +- intent: mood_great + examples: | + - perfect + - great + - amazing + - feeling like a king + - wonderful + - I am feeling very good + - I am great + - I am amazing + - I am going to save the world + - super stoked + - extremely good + - so so perfect + - so good + - so perfect + +- intent: mood_unhappy + examples: | + - my day was horrible + - I am sad + - I don't feel very well + - I am disappointed + - super sad + - I'm so sad + - sad + - very sad + - unhappy + - not good + - not very good + - extremly sad + - so saad + - so sad + +- intent: bot_challenge + examples: | + - are you a bot? + - are you a human? + - am I talking to a bot? + - am I talking to a human? diff --git a/harmoni_models/bot/rasa_example/data/rules.yml b/harmoni_models/bot/rasa_example/data/rules.yml new file mode 100644 index 00000000..51f030d0 --- /dev/null +++ b/harmoni_models/bot/rasa_example/data/rules.yml @@ -0,0 +1,13 @@ +version: "2.0" + +rules: + +- rule: Say goodbye anytime the user says goodbye + steps: + - intent: goodbye + - action: utter_goodbye + +- rule: Say 'I am a bot' anytime the user challenges + steps: + - intent: bot_challenge + - action: utter_iamabot diff --git a/harmoni_models/bot/rasa_example/data/stories.yml b/harmoni_models/bot/rasa_example/data/stories.yml new file mode 100644 index 00000000..360348ea --- /dev/null +++ b/harmoni_models/bot/rasa_example/data/stories.yml @@ -0,0 +1,29 @@ +version: "2.0" + +stories: +- story: happy path + steps: + - intent: greet + - action: utter_greet + - intent: mood_great + - action: utter_happy + +- story: sad path 1 + steps: + - intent: greet + - action: utter_greet + - intent: mood_unhappy + - action: utter_cheer_up + - action: utter_did_that_help + - intent: affirm + - action: utter_happy + +- story: sad path 2 + steps: + - intent: greet + - action: utter_greet + - intent: mood_unhappy + - action: utter_cheer_up + - action: utter_did_that_help + - intent: deny + - action: utter_goodbye diff --git a/harmoni_models/bot/rasa_example/domain.yml b/harmoni_models/bot/rasa_example/domain.yml new file mode 100644 index 00000000..b5225577 --- /dev/null +++ b/harmoni_models/bot/rasa_example/domain.yml @@ -0,0 +1,34 @@ +version: "2.0" + +intents: + - greet + - goodbye + - affirm + - deny + - mood_great + - mood_unhappy + - bot_challenge + +responses: + utter_greet: + - text: "Hey! How are you?" + + utter_cheer_up: + - text: "Here is something to cheer you up:" + image: "https://i.imgur.com/nGF1K8f.jpg" + + utter_did_that_help: + - text: "Did that help you?" + + utter_happy: + - text: "Great, carry on!" + + utter_goodbye: + - text: "Bye" + + utter_iamabot: + - text: "I am a bot, powered by Rasa." + +session_config: + session_expiration_time: 60 + carry_over_slots_to_new_session: true diff --git a/harmoni_models/bot/rasa_example/endpoints.yml b/harmoni_models/bot/rasa_example/endpoints.yml new file mode 100644 index 00000000..1128e1d5 --- /dev/null +++ b/harmoni_models/bot/rasa_example/endpoints.yml @@ -0,0 +1,42 @@ +# This file contains the different endpoints your bot can use. + +# Server where the models are pulled from. +# https://rasa.com/docs/rasa/model-storage#fetching-models-from-a-server + +#models: +# url: http://my-server.com/models/default_core@latest +# wait_time_between_pulls: 10 # [optional](default: 100) + +# Server which runs your custom actions. +# https://rasa.com/docs/rasa/custom-actions + +#action_endpoint: +# url: "http://localhost:5055/webhook" + +# Tracker store which is used to store the conversations. +# By default the conversations are stored in memory. +# https://rasa.com/docs/rasa/tracker-stores + +#tracker_store: +# type: redis +# url: +# port: +# db: +# password: +# use_ssl: + +#tracker_store: +# type: mongod +# url: +# db: +# username: +# password: + +# Event broker which all conversation events should be streamed to. +# https://rasa.com/docs/rasa/event-brokers + +#event_broker: +# url: localhost +# username: username +# password: password +# queue: queue diff --git a/harmoni_models/bot/rasa_example/tests/test_stories.yml b/harmoni_models/bot/rasa_example/tests/test_stories.yml new file mode 100644 index 00000000..d46e39b3 --- /dev/null +++ b/harmoni_models/bot/rasa_example/tests/test_stories.yml @@ -0,0 +1,91 @@ +#### This file contains tests to evaluate that your bot behaves as expected. +#### If you want to learn more, please see the docs: https://rasa.com/docs/rasa/testing-your-assistant + +stories: +- story: happy path 1 + steps: + - user: | + hello there! + intent: greet + - action: utter_greet + - user: | + amazing + intent: mood_great + - action: utter_happy + +- story: happy path 2 + steps: + - user: | + hello there! + intent: greet + - action: utter_greet + - user: | + amazing + intent: mood_great + - action: utter_happy + - user: | + bye-bye! + intent: goodbye + - action: utter_goodbye + +- story: sad path 1 + steps: + - user: | + hello + intent: greet + - action: utter_greet + - user: | + not good + intent: mood_unhappy + - action: utter_cheer_up + - action: utter_did_that_help + - user: | + yes + intent: affirm + - action: utter_happy + +- story: sad path 2 + steps: + - user: | + hello + intent: greet + - action: utter_greet + - user: | + not good + intent: mood_unhappy + - action: utter_cheer_up + - action: utter_did_that_help + - user: | + not really + intent: deny + - action: utter_goodbye + +- story: sad path 3 + steps: + - user: | + hi + intent: greet + - action: utter_greet + - user: | + very terrible + intent: mood_unhappy + - action: utter_cheer_up + - action: utter_did_that_help + - user: | + no + intent: deny + - action: utter_goodbye + +- story: say goodbye + steps: + - user: | + bye-bye! + intent: goodbye + - action: utter_goodbye + +- story: bot challenge + steps: + - user: | + are you a bot? + intent: bot_challenge + - action: utter_iamabot