Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

290 general activity #61

Merged
merged 40 commits into from
Nov 29, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
98f844c
#290 added code for discussion
Wouter1 Oct 3, 2022
aa68590
fdas
Wouter1 Oct 4, 2022
686dbc7
gfd
Wouter1 Oct 4, 2022
7dd845d
asdf
Wouter1 Oct 4, 2022
d10ee85
fixes to get this working again
Wouter1 Oct 4, 2022
3f7c72a
ignore generated
Wouter1 Oct 4, 2022
5ca8107
discussion
Wouter1 Oct 5, 2022
c78cdcd
sync'ed with Bouke's code. Yet validate action not triggering
Wouter1 Oct 5, 2022
5215c16
validate action must differ from form name
Wouter1 Oct 5, 2022
97ceca7
minor changes
Wouter1 Oct 5, 2022
423c50e
Added texts
Wouter1 Oct 6, 2022
555c3d0
added proper dialog flow graph as graphml object (use free yed program
Wouter1 Oct 6, 2022
4eac0bc
Added stories for the 'learned from' phase
Wouter1 Oct 6, 2022
1f25465
added next-activity dialog
Wouter1 Oct 6, 2022
43d3eab
added the XLS sheet on which the general activity dialog was based.
Wouter1 Oct 6, 2022
5a197aa
review dialog first functional layer
wbaccinelli Oct 19, 2022
fae022c
more branches implemented
wbaccinelli Oct 21, 2022
3d503c1
next activity choice
wbaccinelli Oct 21, 2022
b0763c5
functional dialog structure
wbaccinelli Oct 24, 2022
4a0dd1b
refine branches
wbaccinelli Oct 24, 2022
616678f
accounting for none last utterance
wbaccinelli Oct 28, 2022
fcf1f90
connected to rescheduling dialog
wbaccinelli Oct 28, 2022
f0d25f0
get last perfromed activity
wbaccinelli Nov 10, 2022
ab33b40
check activity ranking
wbaccinelli Nov 10, 2022
36b4965
Merge branch 'main' into 290-general-activity
wbaccinelli Nov 10, 2022
26f5a89
implemented some decision logics
wbaccinelli Nov 14, 2022
0f008f0
random activity choice
wbaccinelli Nov 14, 2022
595fd5e
increase max number of predictions
wbaccinelli Nov 16, 2022
517a2e0
selected activity
wbaccinelli Nov 16, 2022
f2b60c7
get activity chosen slot fixed
wbaccinelli Nov 16, 2022
58db8e1
Merge remote-tracking branch 'origin/main' into 290-general-activity
wbaccinelli Nov 16, 2022
411ac3f
correct logic for updating fak
wbaccinelli Nov 16, 2022
f7dc334
managing first execution
wbaccinelli Nov 16, 2022
7783147
fix user input query
wbaccinelli Nov 16, 2022
ea751e8
model added
wbaccinelli Nov 16, 2022
36d1253
cleaning
wbaccinelli Nov 16, 2022
176b036
type fix
wbaccinelli Nov 16, 2022
82759db
fix check first activity
wbaccinelli Nov 16, 2022
388c32d
different random selection method
wbaccinelli Nov 23, 2022
7754759
lynting
wbaccinelli Nov 23, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Merge branch 'main' into 290-general-activity
# Conflicts:
#	Rasa_Bot/actions/helper.py
#	Rasa_Bot/data/nlu.yml
#	Rasa_Bot/models/20221014-151911-hot-dodecagon.tar.gz
  • Loading branch information
wbaccinelli committed Nov 10, 2022
commit 36b49656ff4ac613b6eefa93719d8ca195f2cfd1
1 change: 1 addition & 0 deletions Rasa_Bot/actions/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ WORKDIR /app
# Copy actions requirements
COPY requirements-actions.txt ./

COPY tst.PNG ./
# Change to root user to install dependencies
USER root

Expand Down
63 changes: 60 additions & 3 deletions Rasa_Bot/actions/actions_common.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import logging

from celery import Celery
from niceday_client import NicedayClient
from rasa_sdk import Action
from rasa_sdk.events import FollowupAction
from .definitions import REDIS_URL

from rasa_sdk.events import FollowupAction, SlotSet
from .definitions import REDIS_URL, NICEDAY_API_ENDPOINT

celery = Celery(broker=REDIS_URL)

Expand Down Expand Up @@ -37,3 +37,60 @@ async def run(self, dispatcher, tracker, domain):
logging.info("no celery error")

return []


class SendMetadata(Action):
def name(self):
return "action_send_metadata"

async def run(self, dispatcher, tracker, domain):
"""
Sends the text message specified in the 'text' value of the json_message,
and sends the image identified by the id_file under the 'attachmentIds' key.

The id_file is obtained in the action_upload_file as a result of
a file uploaded to the NiceDay server. The id is stored in the
uploaded_file_id slot.

The uploaded file is a local one, and is uses the file indicated
by the action_set_file_path
"""
id_file = tracker.get_slot("uploaded_file_id")
dispatcher.utter_message(
json_message={"text": "image",
"attachmentIds": [id_file]},
)
return[]


class UploadFile(Action):
def name(self):
return "action_upload_file"

async def run(self, dispatcher, tracker, domain):
client = NicedayClient(NICEDAY_API_ENDPOINT)
user_id = int(tracker.current_state()['sender_id'])

filepath = tracker.get_slot('upload_file_path')
with open(filepath, 'rb') as content:
file = content.read()

response = client.upload_file(user_id, filepath, file)
file_id = response['id']
logging.info(response)
logging.info(file_id)

return[SlotSet("uploaded_file_id", file_id)]


class SetFilePath(Action):
def name(self):
return "action_set_file_path"

async def run(self, dispatcher, tracker, domain):

# TODO: This is hardcoded for testing. Needs to be set according to the use case

filepath = '/app/tst.PNG'

return[SlotSet("upload_file_path", filepath)]
38 changes: 37 additions & 1 deletion Rasa_Bot/actions/actions_minimum_functional_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
"""
import datetime
import logging
from typing import Text, Dict, Any

from dateutil.relativedelta import relativedelta
from dateutil.rrule import rrule, DAILY
from niceday_client import NicedayClient, definitions
from paalgorithms import weekly_kilometers
from rasa_sdk import Action
from rasa_sdk import Action, Tracker
from rasa_sdk.events import SlotSet
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.forms import FormValidationAction
from virtual_coach_db.dbschema.models import Users
from virtual_coach_db.helper.helper_functions import get_db_session

Expand Down Expand Up @@ -175,3 +178,36 @@ async def run(self, dispatcher, tracker, domain):
"This is a tracker",
recursive_rule)
return[]


class ValidateActivityGetFileForm(FormValidationAction):
def name(self) -> Text:
return 'validate_activity_get_file_form'

def validate_received_file_text(
self, slot_value: Text, dispatcher: CollectingDispatcher,
tracker: Tracker, domain: Dict[Text, Any]) -> Dict[Text, Any]:
# pylint: disable=unused-argument
"""Validate the presence of an attached file"""

# here the message metadata are retrieved
events = tracker.current_state()['events']

user_events = [e for e in events if e['event'] == 'user']
# we defined the metadata key name 'attachmentIds' is defined in the broker
received_file_ids_list = user_events[-1]['metadata']['attachmentIds']

if not self._is_valid_input(received_file_ids_list):
dispatcher.utter_message(response="utter_no_attachment")
return {"received_file_text": None}

# At this point the file ID should be saved in the DB for
# re-accessing the shared file

return {"received_file_text": slot_value}

@staticmethod
def _is_valid_input(value):
if len(value) == 0:
return False
return True
117 changes: 116 additions & 1 deletion Rasa_Bot/actions/actions_preparation_dialogs.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
"""
Contains custom actions related to the preparation dialogs
"""
from typing import Text, Any, Dict
from datetime import datetime

from rasa_sdk import Action
from rasa_sdk import Tracker, FormValidationAction, Action
from rasa_sdk.events import SlotSet
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.types import DomainDict
from virtual_coach_db.helper.definitions import PreparationInterventionComponents

from .helper import (store_user_preferences_to_db, get_intervention_component_id,
week_day_to_numerical_form)

YES_OR_NO = ["yes", "no"]
ALLOWED_WEEK_DAYS = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]

### Slot-setting methods called for rasa to store current intervention component
class SetSlotProfileCreation(Action):
Expand Down Expand Up @@ -60,3 +69,109 @@ def name(self):
async def run(self, dispatcher, tracker, domain):
return [SlotSet("current_intervention_component",
PreparationInterventionComponents.GOAL_SETTING)]

class ValidateUserPreferencesForm(FormValidationAction):
def name(self) -> Text:
return "validate_user_preferences_form"

def validate_recursive_reminder(
self,
slot_value: Any,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: DomainDict,
) -> Dict[Text, Any]:
# pylint: disable=unused-argument
"""Validate recursive_reminder` value."""
if slot_value.lower() not in YES_OR_NO:
dispatcher.utter_message(text="We only accept 'yes' or 'no' as answers")
return {"recursive_reminder": None}
dispatcher.utter_message(text=f"OK! You have answered {slot_value}.")
return {"recursive_reminder": slot_value}

def validate_week_days(
self,
slot_value: Any,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: DomainDict,
) -> Dict[Text, Any]:
# pylint: disable=unused-argument
"""Validate `week_days` value."""

week_days_string = slot_value
week_days_list = week_days_string.split(", ")
invalidinput = False

for weekday in week_days_list:
if weekday.lower() not in ALLOWED_WEEK_DAYS:
invalidinput = True

if invalidinput:
dispatcher.utter_message(text="Please submit the days of the week as" +
" a comma separated list!")
return {"week_days": None}
dispatcher.utter_message(text="OK! You want to receive reminders on these" +
f" days of the week: {slot_value}.")
return {"week_days": slot_value}

def validate_time_stamp(
self,
slot_value: Any,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: DomainDict,
) -> Dict[Text, Any]:
# pylint: disable=unused-argument
"""Validate `time_stamp` value."""

timestring = slot_value
timeformat = "%H:%M:%S"
res = False

# using try-except to check for truth value
try:
res = bool(datetime.strptime(timestring, timeformat))
except ValueError:
res = False

if not res:
dispatcher.utter_message(text="Please submit an answer as given by the example:" +
" 20:34:20")
return {"time_stamp": None}
dispatcher.utter_message(text=f"OK! You want to receive reminders at {slot_value}.")
return {"time_stamp": slot_value}

class StoreUserPreferencesToDb(Action):
def name(self) -> Text:
return "action_store_user_preferences_to_db"

async def run(self, dispatcher, tracker, domain):
user_id = tracker.current_state()['sender_id']

recursive = tracker.get_slot("recursive_reminder")
week_days = tracker.get_slot("week_days")
preferred_time_string = tracker.get_slot("time_stamp")

recursive_bool = False
if recursive in ('yes', 'Yes'):
recursive_bool = True

week_days_numbers = ""
week_days_list = week_days.split(", ")
for weekday in week_days_list:
week_days_numbers += str(week_day_to_numerical_form(weekday))
week_days_numbers += ","

##TODO Set the slot in rasa
# When calling this in the right context, the intervention component slot should have
# a value.Uncomment the next two lines and remove the one under those two to switch
# from a hardcoded intervention component to the one decided by the slot.
##intervention_component_string = tracker.get_slot("current_intervention_component")
##intervention_component = get_intervention_component_id(intervention_component_string)
intervention_component = get_intervention_component_id("profile_creation")

datetime_format = datetime.strptime(preferred_time_string, '%H:%M:%S')

store_user_preferences_to_db(user_id, intervention_component, recursive_bool,
week_days_numbers.rstrip(week_days_numbers[-1]), datetime_format)
35 changes: 33 additions & 2 deletions Rasa_Bot/actions/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import datetime

from .definitions import DialogQuestions, DATABASE_URL, TIMEZONE
from virtual_coach_db.dbschema.models import (Users, DialogAnswers, InterventionComponents)
from virtual_coach_db.dbschema.models import (Users, DialogAnswers, InterventionComponents,
UserPreferences)
from virtual_coach_db.helper.helper_functions import get_db_session


Expand All @@ -15,10 +16,22 @@ def store_dialog_answer_to_db(user_id, answer, question: DialogQuestions):
entry = DialogAnswers(answer=answer,
question_id=question.value,
datetime=datetime.datetime.now().astimezone(TIMEZONE))

selected.dialog_answers.append(entry)
session.commit() # Update database

def store_user_preferences_to_db(user_id, intervention_component, recursive, week_days,
preferred_time):
session = get_db_session(db_url=DATABASE_URL) # Create session object to connect db
selected = session.query(Users).filter_by(nicedayuid=user_id).one()

entry = UserPreferences(users_nicedayuid=user_id,
intervention_component_id=intervention_component,
recursive=recursive,
week_days=week_days,
preferred_time=preferred_time)
selected.user_preferences.append(entry)
session.commit() # Update database


def get_intervention_component_id(intervention_component_name: str) -> int:
"""
Expand Down Expand Up @@ -55,3 +68,21 @@ def get_latest_bot_utterance(events) -> str:
last_utterance = None

return last_utterance


def week_day_to_numerical_form(week_day):
if week_day.lower() == "monday":
return 1
if week_day.lower() == "tuesday":
return 2
if week_day.lower() == "wednesday":
return 3
if week_day.lower() == "thursday":
return 4
if week_day.lower() == "friday":
return 5
if week_day.lower() == "saturday":
return 6
if week_day.lower() == "sunday":
return 7
return -1
Binary file added Rasa_Bot/actions/tst.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
You are viewing a condensed version of this merge commit. You can view the full changes here.