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

Create UserModel class #184

Merged
merged 16 commits into from
Oct 16, 2023
53 changes: 45 additions & 8 deletions moviebot/nlg/nlg.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
from moviebot.nlu.annotation.operator import Operator
from moviebot.nlu.annotation.slots import Slots
from moviebot.nlu.annotation.values import Values
from moviebot.nlu.user_intents_checker import (
RecommendationChoices,
convert_choice_to_preference,
)

ButtonOptions = Dict[DialogueAct, List[str]]
CINType = Dict[str, Union[str, List[str]]]
Expand Down Expand Up @@ -141,7 +145,9 @@ def __init__(self, args=None) -> None:

self.slot_not_found = {
Slots.GENRES.value: ["I could not find the genres __replace__."],
Slots.KEYWORDS.value: ["I couldn't find the keywords __replace__."],
Slots.KEYWORDS.value: [
"I couldn't find the keywords __replace__."
],
Slots.DIRECTORS.value: [
"I could not find the the director name __replace__."
],
Expand Down Expand Up @@ -514,7 +520,9 @@ def _clarify_CIN( # noqa: C901
)
else:
response = (
response + " named similar to " + CIN[Slots.TITLE.value]
response
+ " named similar to "
+ CIN[Slots.TITLE.value]
)
if (
CIN[Slots.DIRECTORS.value]
Expand Down Expand Up @@ -572,7 +580,9 @@ def _user_options_continue(self, agent_dact: DialogueAct) -> ButtonOptions:
DialogueAct(UserIntents.RESTART, []): [
"I want to restart for a new movie."
],
DialogueAct(UserIntents.BYE, []): ["I would like to quit now."],
DialogueAct(UserIntents.BYE, []): [
"I would like to quit now."
],
}
return options

Expand All @@ -585,19 +595,46 @@ def _user_options_recommend(self) -> ButtonOptions:
options = {
DialogueAct(
UserIntents.REJECT,
[ItemConstraint("reason", Operator.EQ, "watched")],
[
ItemConstraint("reason", Operator.EQ, "watched"),
ItemConstraint(
"preference",
Operator.EQ,
convert_choice_to_preference(
RecommendationChoices.WATCHED
),
),
],
): ["I have already watched it."],
# [random.choice(['I have already watched it.',
# 'I have seen this already.'])],
DialogueAct(
UserIntents.REJECT,
[ItemConstraint("reason", Operator.EQ, "dont_like")],
[
ItemConstraint("reason", Operator.EQ, "dont_like"),
ItemConstraint(
"preference",
Operator.EQ,
convert_choice_to_preference(
RecommendationChoices.DONT_LIKE
),
),
],
): ["Recommend me something else please."],
# [random.choice(['I don\'t like this recommendation.',
# 'Recommend me something else please.'])],
DialogueAct(UserIntents.ACCEPT, []): [
"I like this recommendation."
],
DialogueAct(
UserIntents.ACCEPT,
[
ItemConstraint(
"preference",
Operator.EQ,
convert_choice_to_preference(
RecommendationChoices.ACCEPT
),
),
],
): ["I like this recommendation."],
DialogueAct(
UserIntents.INQUIRE,
[ItemConstraint(Slots.MORE_INFO.value, Operator.EQ, "")],
Expand Down
38 changes: 38 additions & 0 deletions moviebot/nlu/recommendation_decision_processing.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine, but why not just have the enum values as the preferences?
https://stackoverflow.com/questions/69716107/can-i-use-an-enum-with-floating-point-values-and-comparators-in-python-3-9-and-s

Not sure it needs Python 3.9, but also there is probably no reason for us not to use 3.9 for MovieBot.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up issue #226

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""This module is used to process the user's decision on a movie recommendation.
"""

from enum import Enum


class RecommendationChoices(Enum):
"""Enum class for recommendation choices."""

ACCEPT = "accept"
REJECT = "reject"
DONT_LIKE = "dont_like"
WATCHED = "watched"


def convert_choice_to_preference(choice: RecommendationChoices) -> float:
"""Converts a choice to a preference within the range [-1,1].

Dislike is represented by a preference below 0, while like is
represented by a preference above 0. If the choice does not express a
preference (e.g., inquire), then the preference is neutral, i.e., 0.
Possible choices are: accept, reject, dont_like, inquire, and watched.

Args:
choice: Choice.

Returns:
Preference within the range [-1,1].
"""
if choice == RecommendationChoices.ACCEPT:
return 1.0
elif choice in [
RecommendationChoices.REJECT,
RecommendationChoices.DONT_LIKE,
]:
return -1.0

return 0.0
20 changes: 18 additions & 2 deletions moviebot/nlu/user_intents_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
from moviebot.nlu.annotation.slots import Slots
from moviebot.nlu.annotation.values import Values
from moviebot.nlu.data_loader import DataLoader
from moviebot.nlu.recommendation_decision_processing import (
RecommendationChoices,
convert_choice_to_preference,
)

PATTERN_BASIC = {
UserIntents.ACKNOWLEDGE: ["yes", "okay", "fine", "sure"],
Expand Down Expand Up @@ -334,15 +338,27 @@ def check_reject_intent(
]
):
dact.intent = UserIntents.REJECT
dact.params = [ItemConstraint("reason", Operator.EQ, "dont_like")]
preference = convert_choice_to_preference(
RecommendationChoices.DONT_LIKE
)
dact.params = [
ItemConstraint("reason", Operator.EQ, "dont_like"),
ItemConstraint("preference", Operator.EQ, preference),
]
elif any(
[
re.search(r"\b{0}\b".format(pattern), utterance)
for pattern in PATTERN_WATCHED
]
):
dact.intent = UserIntents.REJECT
dact.params = [ItemConstraint("reason", Operator.EQ, "watched")]
preference = convert_choice_to_preference(
RecommendationChoices.WATCHED
)
dact.params = [
ItemConstraint("reason", Operator.EQ, "watched"),
ItemConstraint("preference", Operator.EQ, preference),
Comment on lines +361 to +362
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please create an issue for creating enums for the possible contraints that can be expressed ("reason", "perference", etc.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up issue #225

]
if dact.intent != UserIntents.UNK:
user_dacts.append(dact)
return user_dacts
Expand Down
Empty file.
Loading
Loading