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

Eng 545 stack cleaning #12834

Merged
merged 21 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
837eaac
improved typing of FlowLink
twerkmeister Sep 20, 2023
c7c9947
consistently using kwargs
twerkmeister Sep 20, 2023
f87bf7e
implemented stack cleaning and test
twerkmeister Sep 21, 2023
f7a4391
Revert "improved typing of FlowLink"
twerkmeister Sep 22, 2023
a0b95b3
improved and fixed tests relying on strict number indices
twerkmeister Sep 25, 2023
cba9791
Only update flow hashes when they changed, added slot to tests
twerkmeister Sep 25, 2023
75bad36
Code quality, moved fixtures to conftest
twerkmeister Sep 25, 2023
2cf529a
removed unused imports
twerkmeister Sep 25, 2023
416be84
Added explicit typing
twerkmeister Sep 25, 2023
68af0a3
improved tests
twerkmeister Sep 25, 2023
cc7e1a0
removed unused imports
twerkmeister Sep 25, 2023
64de8f1
Merge branch 'dm2' into ENG-545-stack-cleaning
tmbo Sep 27, 2023
b03c781
Update rasa/dialogue_understanding/patterns/default_flows_for_pattern…
twerkmeister Sep 28, 2023
17d9ff6
Update rasa/dialogue_understanding/patterns/clean_stack.py
twerkmeister Sep 28, 2023
c9fff34
applying and returning flow hash events
twerkmeister Sep 28, 2023
e17c603
added logging call for when flows were updated
twerkmeister Sep 28, 2023
d7857d0
made fingerprint of flows a cached property
twerkmeister Sep 28, 2023
7a629f9
restructured command, pattern, and action to be more modular
twerkmeister Sep 28, 2023
586e1c7
adjusted flow texts to reflect conversation designer preferences
twerkmeister Sep 28, 2023
a46c520
fixes for code quality, tests
twerkmeister Sep 28, 2023
ff6c1fb
fixed default flow syntax
twerkmeister Sep 29, 2023
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
1 change: 1 addition & 0 deletions data/test_trackers/tracker_moodbot.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"followup_action": null,
"slots": {
"dialogue_stack": null,
"flow_hashes": null,
"name": null,
"requested_slot": null,
"return_value": null,
Expand Down
5 changes: 4 additions & 1 deletion rasa/core/actions/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
ACTION_VALIDATE_SLOT_MAPPINGS,
MAPPING_TYPE,
SlotMappingType,
KNOWLEDGE_BASE_SLOT_NAMES,
)
from rasa.shared.core.domain import Domain
from rasa.shared.core.events import (
Expand Down Expand Up @@ -1292,7 +1293,9 @@ async def run(
executed_custom_actions: Set[Text] = set()

user_slots = [
slot for slot in domain.slots if slot.name not in DEFAULT_SLOT_NAMES
slot
for slot in domain.slots
if slot.name not in DEFAULT_SLOT_NAMES | KNOWLEDGE_BASE_SLOT_NAMES
]

for slot in user_slots:
Expand Down
50 changes: 50 additions & 0 deletions rasa/core/actions/action_clean_stack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from __future__ import annotations

from typing import Optional, Dict, Any, List

from rasa.core.actions import action
from rasa.core.channels import OutputChannel
from rasa.core.nlg import NaturalLanguageGenerator
from rasa.dialogue_understanding.stack.dialogue_stack import DialogueStack
from rasa.dialogue_understanding.stack.frames import (
BaseFlowStackFrame,
UserFlowStackFrame,
)
from rasa.dialogue_understanding.stack.frames.flow_stack_frame import FlowStackFrameType
from rasa.shared.core.constants import ACTION_CLEAN_STACK, DIALOGUE_STACK_SLOT
from rasa.shared.core.domain import Domain
from rasa.shared.core.events import Event, SlotSet
from rasa.shared.core.flows.flow import ContinueFlowStep, END_STEP
from rasa.shared.core.trackers import DialogueStateTracker


class ActionCleanStack(action.Action):
"""Action which cancels a flow from the stack."""

def name(self) -> str:
"""Return the flow name."""
return ACTION_CLEAN_STACK

async def run(
self,
output_channel: OutputChannel,
nlg: NaturalLanguageGenerator,
tracker: DialogueStateTracker,
domain: Domain,
metadata: Optional[Dict[str, Any]] = None,
) -> List[Event]:
"""Clean the stack."""
stack = DialogueStack.from_tracker(tracker)

new_frames = []
# Set all frames to their end step, filter out any non-BaseFlowStackFrames
for frame in stack.frames:
if isinstance(frame, BaseFlowStackFrame):
frame.step_id = ContinueFlowStep.continue_step_for_id(END_STEP)
if isinstance(frame, UserFlowStackFrame):
# Making sure there are no "continue interrupts" triggered
frame.frame_type = FlowStackFrameType.REGULAR
new_frames.append(frame)
new_stack = DialogueStack.from_dict([frame.as_dict() for frame in new_frames])

return [SlotSet(DIALOGUE_STACK_SLOT, new_stack.as_dict())]
4 changes: 2 additions & 2 deletions rasa/dialogue_understanding/commands/cancel_flow_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ def select_canceled_frames(stack: DialogueStack) -> List[str]:
The frames that were canceled."""
canceled_frames = []
# we need to go through the original stack dump in reverse order
# to find the frames that were canceled. we cancel everthing from
# to find the frames that were canceled. we cancel everything from
# the top of the stack until we hit the user flow that was canceled.
# this will also cancel any patterns put ontop of that user flow,
# this will also cancel any patterns put on top of that user flow,
# e.g. corrections.
for frame in reversed(stack.frames):
canceled_frames.append(frame.frame_id)
Expand Down
67 changes: 67 additions & 0 deletions rasa/dialogue_understanding/commands/handle_code_change_command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from __future__ import annotations

from dataclasses import dataclass
from typing import Any, Dict, List

import structlog

from rasa.dialogue_understanding.commands import Command
from rasa.dialogue_understanding.patterns.code_change import CodeChangeFlowStackFrame
from rasa.dialogue_understanding.stack.dialogue_stack import DialogueStack
from rasa.shared.core.constants import DIALOGUE_STACK_SLOT
from rasa.shared.core.events import Event, SlotSet
from rasa.shared.core.flows.flow import FlowsList
from rasa.shared.core.trackers import DialogueStateTracker
from rasa.dialogue_understanding.stack.utils import top_user_flow_frame

structlogger = structlog.get_logger()


@dataclass
class HandleCodeChangeCommand(Command):
"""A that is executed when the flows have changed."""

@classmethod
def command(cls) -> str:
"""Returns the command type."""
return "handle code change"

@classmethod
def from_dict(cls, data: Dict[str, Any]) -> HandleCodeChangeCommand:
"""Converts the dictionary to a command.

Returns:
The converted dictionary.
"""
return HandleCodeChangeCommand()

def run_command_on_tracker(
self,
tracker: DialogueStateTracker,
all_flows: FlowsList,
original_tracker: DialogueStateTracker,
) -> List[Event]:
"""Runs the command on the tracker.

Args:
tracker: The tracker to run the command on.
all_flows: All flows in the assistant.
original_tracker: The tracker before any command was executed.

Returns:
The events to apply to the tracker.
"""

stack = DialogueStack.from_tracker(tracker)
original_stack = DialogueStack.from_tracker(original_tracker)
user_frame = top_user_flow_frame(original_stack)
current_flow = user_frame.flow(all_flows) if user_frame else None

if not current_flow:
structlogger.debug(
"handle_code_change_command.skip.no_active_flow", command=self
)
return []

stack.push(CodeChangeFlowStackFrame())
return [SlotSet(DIALOGUE_STACK_SLOT, stack.as_dict())]
2 changes: 1 addition & 1 deletion rasa/dialogue_understanding/patterns/cancel.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def from_dict(data: Dict[str, Any]) -> CancelPatternFlowStackFrame:
The created `DialogueStackFrame`.
"""
return CancelPatternFlowStackFrame(
data["frame_id"],
frame_id=data["frame_id"],
step_id=data["step_id"],
canceled_name=data["canceled_name"],
canceled_frames=data["canceled_frames"],
Expand Down
2 changes: 1 addition & 1 deletion rasa/dialogue_understanding/patterns/clarify.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def from_dict(data: Dict[str, Any]) -> ClarifyPatternFlowStackFrame:
The created `DialogueStackFrame`.
"""
return ClarifyPatternFlowStackFrame(
data["frame_id"],
frame_id=data["frame_id"],
step_id=data["step_id"],
names=data["names"],
clarification_options=data["clarification_options"],
Expand Down
42 changes: 42 additions & 0 deletions rasa/dialogue_understanding/patterns/code_change.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from __future__ import annotations

from dataclasses import dataclass
from typing import Any, Dict

import structlog
from rasa.dialogue_understanding.stack.frames import (
PatternFlowStackFrame,
)
from rasa.shared.constants import RASA_DEFAULT_FLOW_PATTERN_PREFIX

structlogger = structlog.get_logger()

FLOW_PATTERN_CODE_CHANGE_ID = RASA_DEFAULT_FLOW_PATTERN_PREFIX + "code_change"


@dataclass
class CodeChangeFlowStackFrame(PatternFlowStackFrame):
"""A pattern flow stack frame which cleans the stack after a bot update."""

flow_id: str = FLOW_PATTERN_CODE_CHANGE_ID
"""The ID of the flow."""

@classmethod
def type(cls) -> str:
"""Returns the type of the frame."""
return FLOW_PATTERN_CODE_CHANGE_ID

@staticmethod
def from_dict(data: Dict[str, Any]) -> CodeChangeFlowStackFrame:
"""Creates a `DialogueStackFrame` from a dictionary.

Args:
data: The dictionary to create the `DialogueStackFrame` from.

Returns:
The created `DialogueStackFrame`.
"""
return CodeChangeFlowStackFrame(
frame_id=data["frame_id"],
step_id=data["step_id"],
)
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def from_dict(data: Dict[str, Any]) -> CollectInformationPatternFlowStackFrame:
]

return CollectInformationPatternFlowStackFrame(
data["frame_id"],
frame_id=data["frame_id"],
step_id=data["step_id"],
collect=data["collect"],
utter=data["utter"],
Expand Down
2 changes: 1 addition & 1 deletion rasa/dialogue_understanding/patterns/completed.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def from_dict(data: Dict[str, Any]) -> CompletedPatternFlowStackFrame:
The created `DialogueStackFrame`.
"""
return CompletedPatternFlowStackFrame(
data["frame_id"],
frame_id=data["frame_id"],
step_id=data["step_id"],
previous_flow_name=data["previous_flow_name"],
)
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def from_dict(data: Dict[str, Any]) -> ContinueInterruptedPatternFlowStackFrame:
The created `DialogueStackFrame`.
"""
return ContinueInterruptedPatternFlowStackFrame(
data["frame_id"],
frame_id=data["frame_id"],
step_id=data["step_id"],
previous_flow_name=data["previous_flow_name"],
)
2 changes: 1 addition & 1 deletion rasa/dialogue_understanding/patterns/correction.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def from_dict(data: Dict[Text, Any]) -> CorrectionPatternFlowStackFrame:
The created `DialogueStackFrame`.
"""
return CorrectionPatternFlowStackFrame(
data["frame_id"],
frame_id=data["frame_id"],
step_id=data["step_id"],
is_reset_only=data["is_reset_only"],
corrected_slots=data["corrected_slots"],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
version: "3.1"
responses:
utter_flow_continue_interrupted:
- text: Let's continue with the topic {{ context.previous_flow_name }}.
- text: "Let's continue with {{ context.previous_flow_name }}."
metadata:
rephrase: True
template: jinja

utter_corrected_previous_input:
- text: "Ok, I corrected the {{ context.corrected_slots.keys()|join(', ') }}."
- text: "Ok, I am updating {{ context.corrected_slots.keys()|join(', ') }} to {{ context.corrected_slots.values()|join(', ') }} respectively."
metadata:
rephrase: True
template: jinja

utter_flow_cancelled_rasa:
- text: Okay, stopping the flow {{ context.canceled_name }}.
- text: "Okay, stopping {{ context.canceled_name }}."
metadata:
rephrase: True
template: jinja

utter_can_do_something_else:
- text: "Is there anything else I can help you with?"
- text: "What else I can help you with?"
metadata:
rephrase: True

utter_internal_error_rasa:
- text: Sorry, I'm having trouble understanding you right now. Please try again later.
- text: Sorry, I am having trouble with that. Please try again in a few minutes.

utter_clarification_options_rasa:
- text: I'm not sure what you'd like to achieve. Do you want to {{context.clarification_options}}?
- text: "I can help, but I need more information. Which of these would you like to do: {{context.clarification_options}}?"
metadata:
rephrase: True
template: jinja

utter_inform_code_change:
- text: There has been an update to my code. I need to wrap up our running dialogue and start from scratch.
metadata:
rephrase: True

slots:
confirm_correction:
Expand Down Expand Up @@ -125,3 +129,12 @@ flows:
action: action_listen
next: "start"
- id: "done"

pattern_code_change:
description: flow used to clean the stack after a bot update
steps:
- id: "inform_user"
action: utter_inform_code_change
next: "run_cleanup"
- id: "run_cleanup"
action: action_clean_stack
Loading
Loading