rasa-pro 3.12.4__py3-none-any.whl → 3.12.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rasa-pro might be problematic. Click here for more details.
- rasa/core/actions/action.py +0 -6
- rasa/core/channels/voice_ready/audiocodes.py +52 -17
- rasa/core/channels/voice_stream/audiocodes.py +53 -9
- rasa/core/channels/voice_stream/genesys.py +146 -16
- rasa/core/policies/flows/flow_executor.py +3 -38
- rasa/core/policies/intentless_policy.py +6 -59
- rasa/core/processor.py +19 -5
- rasa/core/utils.py +53 -0
- rasa/dialogue_understanding/commands/cancel_flow_command.py +4 -59
- rasa/dialogue_understanding/commands/start_flow_command.py +0 -41
- rasa/dialogue_understanding/generator/_jinja_filters.py +9 -0
- rasa/dialogue_understanding/generator/command_generator.py +67 -0
- rasa/dialogue_understanding/generator/constants.py +4 -0
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +22 -16
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +1 -1
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +2 -2
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +2 -2
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +0 -61
- rasa/dialogue_understanding/processor/command_processor.py +27 -70
- rasa/dialogue_understanding/processor/command_processor_component.py +5 -2
- rasa/dialogue_understanding/stack/utils.py +0 -38
- rasa/e2e_test/llm_judge_prompts/answer_relevance_prompt_template.jinja2 +1 -1
- rasa/engine/validation.py +36 -1
- rasa/model_training.py +2 -1
- rasa/shared/constants.py +2 -0
- rasa/shared/core/constants.py +0 -8
- rasa/shared/core/domain.py +12 -3
- rasa/shared/core/flows/flow.py +0 -17
- rasa/shared/core/flows/flows_yaml_schema.json +3 -38
- rasa/shared/core/flows/steps/collect.py +5 -18
- rasa/shared/core/flows/utils.py +1 -16
- rasa/shared/core/policies/__init__.py +0 -0
- rasa/shared/core/policies/utils.py +87 -0
- rasa/shared/core/slot_mappings.py +23 -5
- rasa/shared/nlu/constants.py +0 -1
- rasa/shared/utils/common.py +11 -1
- rasa/tracing/instrumentation/attribute_extractors.py +2 -0
- rasa/validator.py +1 -123
- rasa/version.py +1 -1
- {rasa_pro-3.12.4.dist-info → rasa_pro-3.12.6.dist-info}/METADATA +4 -5
- {rasa_pro-3.12.4.dist-info → rasa_pro-3.12.6.dist-info}/RECORD +44 -46
- {rasa_pro-3.12.4.dist-info → rasa_pro-3.12.6.dist-info}/WHEEL +1 -1
- README.md +0 -38
- rasa/core/actions/action_handle_digressions.py +0 -164
- rasa/dialogue_understanding/commands/handle_digressions_command.py +0 -144
- rasa/dialogue_understanding/patterns/handle_digressions.py +0 -81
- rasa/keys +0 -1
- {rasa_pro-3.12.4.dist-info → rasa_pro-3.12.6.dist-info}/NOTICE +0 -0
- {rasa_pro-3.12.4.dist-info → rasa_pro-3.12.6.dist-info}/entry_points.txt +0 -0
|
@@ -18,9 +18,6 @@ from rasa.dialogue_understanding.commands import (
|
|
|
18
18
|
from rasa.dialogue_understanding.commands.handle_code_change_command import (
|
|
19
19
|
HandleCodeChangeCommand,
|
|
20
20
|
)
|
|
21
|
-
from rasa.dialogue_understanding.commands.handle_digressions_command import (
|
|
22
|
-
HandleDigressionsCommand,
|
|
23
|
-
)
|
|
24
21
|
from rasa.dialogue_understanding.commands.set_slot_command import SetSlotExtractor
|
|
25
22
|
from rasa.dialogue_understanding.commands.utils import (
|
|
26
23
|
create_validate_frames_from_slot_set_events,
|
|
@@ -54,9 +51,11 @@ from rasa.shared.core.constants import (
|
|
|
54
51
|
FLOW_HASHES_SLOT,
|
|
55
52
|
SlotMappingType,
|
|
56
53
|
)
|
|
54
|
+
from rasa.shared.core.domain import Domain
|
|
57
55
|
from rasa.shared.core.events import Event, SlotSet
|
|
58
56
|
from rasa.shared.core.flows import FlowsList
|
|
59
57
|
from rasa.shared.core.flows.steps.collect import CollectInformationFlowStep
|
|
58
|
+
from rasa.shared.core.policies.utils import contains_intentless_policy_responses
|
|
60
59
|
from rasa.shared.core.slot_mappings import SlotMapping
|
|
61
60
|
from rasa.shared.core.slots import Slot
|
|
62
61
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
@@ -197,6 +196,7 @@ def execute_commands(
|
|
|
197
196
|
all_flows: FlowsList,
|
|
198
197
|
execution_context: ExecutionContext,
|
|
199
198
|
story_graph: Optional[StoryGraph] = None,
|
|
199
|
+
domain: Optional[Domain] = None,
|
|
200
200
|
) -> List[Event]:
|
|
201
201
|
"""Executes a list of commands.
|
|
202
202
|
|
|
@@ -206,6 +206,7 @@ def execute_commands(
|
|
|
206
206
|
all_flows: All flows.
|
|
207
207
|
execution_context: Information about the single graph run.
|
|
208
208
|
story_graph: StoryGraph object with stories available for training.
|
|
209
|
+
domain: The domain of the bot.
|
|
209
210
|
|
|
210
211
|
Returns:
|
|
211
212
|
A list of the events that were created.
|
|
@@ -214,7 +215,7 @@ def execute_commands(
|
|
|
214
215
|
original_tracker = tracker.copy()
|
|
215
216
|
|
|
216
217
|
commands = clean_up_commands(
|
|
217
|
-
commands, tracker, all_flows, execution_context, story_graph
|
|
218
|
+
commands, tracker, all_flows, execution_context, story_graph, domain
|
|
218
219
|
)
|
|
219
220
|
|
|
220
221
|
updated_flows = find_updated_flows(tracker, all_flows)
|
|
@@ -381,6 +382,7 @@ def clean_up_commands(
|
|
|
381
382
|
all_flows: FlowsList,
|
|
382
383
|
execution_context: ExecutionContext,
|
|
383
384
|
story_graph: Optional[StoryGraph] = None,
|
|
385
|
+
domain: Optional[Domain] = None,
|
|
384
386
|
) -> List[Command]:
|
|
385
387
|
"""Clean up a list of commands.
|
|
386
388
|
|
|
@@ -396,10 +398,13 @@ def clean_up_commands(
|
|
|
396
398
|
all_flows: All flows.
|
|
397
399
|
execution_context: Information about a single graph run.
|
|
398
400
|
story_graph: StoryGraph object with stories available for training.
|
|
401
|
+
domain: The domain of the bot.
|
|
399
402
|
|
|
400
403
|
Returns:
|
|
401
404
|
The cleaned up commands.
|
|
402
405
|
"""
|
|
406
|
+
domain = domain if domain else Domain.empty()
|
|
407
|
+
|
|
403
408
|
slots_so_far, active_flow = filled_slots_for_active_flow(tracker, all_flows)
|
|
404
409
|
|
|
405
410
|
clean_commands: List[Command] = []
|
|
@@ -446,26 +451,17 @@ def clean_up_commands(
|
|
|
446
451
|
)
|
|
447
452
|
continue
|
|
448
453
|
|
|
449
|
-
|
|
450
|
-
handle_digression_command = HandleDigressionsCommand(flow=command.flow)
|
|
451
|
-
if handle_digression_command in clean_commands:
|
|
452
|
-
structlogger.debug(
|
|
453
|
-
"command_processor.clean_up_commands.skip_handle_digressions.command_already_present",
|
|
454
|
-
command=handle_digression_command,
|
|
455
|
-
)
|
|
456
|
-
continue
|
|
457
|
-
clean_commands.append(handle_digression_command)
|
|
458
|
-
structlogger.debug(
|
|
459
|
-
"command_processor.clean_up_commands.push_handle_digressions",
|
|
460
|
-
command=command,
|
|
461
|
-
)
|
|
462
|
-
else:
|
|
463
|
-
clean_commands.append(command)
|
|
454
|
+
clean_commands.append(command)
|
|
464
455
|
|
|
465
456
|
# handle chitchat command differently from other free-form answer commands
|
|
466
457
|
elif isinstance(command, ChitChatAnswerCommand):
|
|
467
458
|
clean_commands = clean_up_chitchat_command(
|
|
468
|
-
clean_commands,
|
|
459
|
+
clean_commands,
|
|
460
|
+
command,
|
|
461
|
+
all_flows,
|
|
462
|
+
execution_context,
|
|
463
|
+
domain,
|
|
464
|
+
story_graph,
|
|
469
465
|
)
|
|
470
466
|
|
|
471
467
|
elif isinstance(command, FreeFormAnswerCommand):
|
|
@@ -490,21 +486,9 @@ def clean_up_commands(
|
|
|
490
486
|
# when coexistence is enabled, by default there will be a SetSlotCommand
|
|
491
487
|
# for the ROUTE_TO_CALM_SLOT slot.
|
|
492
488
|
if tracker.has_coexistence_routing_slot and len(clean_commands) > 2:
|
|
493
|
-
clean_commands =
|
|
489
|
+
clean_commands = filter_cannot_handle_command(clean_commands)
|
|
494
490
|
elif not tracker.has_coexistence_routing_slot and len(clean_commands) > 1:
|
|
495
|
-
clean_commands =
|
|
496
|
-
|
|
497
|
-
# remove cancel flow when there is a handle digression command
|
|
498
|
-
# otherwise the cancel command will cancel the active flow which defined a specific
|
|
499
|
-
# behavior for the digression
|
|
500
|
-
if contains_command(clean_commands, HandleDigressionsCommand) and contains_command(
|
|
501
|
-
clean_commands, CancelFlowCommand
|
|
502
|
-
):
|
|
503
|
-
clean_commands = [
|
|
504
|
-
command
|
|
505
|
-
for command in clean_commands
|
|
506
|
-
if not isinstance(command, CancelFlowCommand)
|
|
507
|
-
]
|
|
491
|
+
clean_commands = filter_cannot_handle_command(clean_commands)
|
|
508
492
|
|
|
509
493
|
clean_commands = ensure_max_number_of_command_type(
|
|
510
494
|
clean_commands, RepeatBotMessagesCommand, 1
|
|
@@ -708,6 +692,7 @@ def clean_up_chitchat_command(
|
|
|
708
692
|
command: ChitChatAnswerCommand,
|
|
709
693
|
flows: FlowsList,
|
|
710
694
|
execution_context: ExecutionContext,
|
|
695
|
+
domain: Domain,
|
|
711
696
|
story_graph: Optional[StoryGraph] = None,
|
|
712
697
|
) -> List[Command]:
|
|
713
698
|
"""Clean up a chitchat answer command.
|
|
@@ -721,6 +706,8 @@ def clean_up_chitchat_command(
|
|
|
721
706
|
flows: All flows.
|
|
722
707
|
execution_context: Information about a single graph run.
|
|
723
708
|
story_graph: StoryGraph object with stories available for training.
|
|
709
|
+
domain: The domain of the bot.
|
|
710
|
+
|
|
724
711
|
Returns:
|
|
725
712
|
The cleaned up commands.
|
|
726
713
|
"""
|
|
@@ -746,10 +733,9 @@ def clean_up_chitchat_command(
|
|
|
746
733
|
)
|
|
747
734
|
defines_intentless_policy = execution_context.has_node(IntentlessPolicy)
|
|
748
735
|
|
|
749
|
-
has_e2e_stories = True if (story_graph and story_graph.has_e2e_stories()) else False
|
|
750
|
-
|
|
751
736
|
if (has_action_trigger_chitchat and not defines_intentless_policy) or (
|
|
752
|
-
defines_intentless_policy
|
|
737
|
+
defines_intentless_policy
|
|
738
|
+
and not contains_intentless_policy_responses(flows, domain, story_graph)
|
|
753
739
|
):
|
|
754
740
|
resulting_commands.insert(
|
|
755
741
|
0, CannotHandleCommand(RASA_PATTERN_CANNOT_HANDLE_CHITCHAT)
|
|
@@ -842,12 +828,12 @@ def should_slot_be_set(
|
|
|
842
828
|
return True
|
|
843
829
|
|
|
844
830
|
|
|
845
|
-
def
|
|
831
|
+
def filter_cannot_handle_command(
|
|
846
832
|
clean_commands: List[Command],
|
|
847
833
|
) -> List[Command]:
|
|
848
|
-
"""Filter out a 'cannot handle' command
|
|
834
|
+
"""Filter out a 'cannot handle' command.
|
|
849
835
|
|
|
850
|
-
This is used to filter out a 'cannot handle' command
|
|
836
|
+
This is used to filter out a 'cannot handle' command
|
|
851
837
|
in case other commands are present.
|
|
852
838
|
|
|
853
839
|
Returns:
|
|
@@ -856,34 +842,5 @@ def filter_cannot_handle_command_for_skipped_slots(
|
|
|
856
842
|
return [
|
|
857
843
|
command
|
|
858
844
|
for command in clean_commands
|
|
859
|
-
if not (
|
|
860
|
-
isinstance(command, CannotHandleCommand)
|
|
861
|
-
and command.reason
|
|
862
|
-
and CANNOT_HANDLE_REASON == command.reason
|
|
863
|
-
)
|
|
845
|
+
if not isinstance(command, CannotHandleCommand)
|
|
864
846
|
]
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
def should_add_handle_digressions_command(
|
|
868
|
-
tracker: DialogueStateTracker, all_flows: FlowsList, top_flow_id: str
|
|
869
|
-
) -> bool:
|
|
870
|
-
"""Check if a handle digressions command should be added to the commands.
|
|
871
|
-
|
|
872
|
-
The command should replace a StartFlow command only if we are at a collect step of
|
|
873
|
-
a flow and a new flow is predicted by the command generator to start.
|
|
874
|
-
"""
|
|
875
|
-
current_flow = all_flows.flow_by_id(top_flow_id)
|
|
876
|
-
current_flow_condition = current_flow and (
|
|
877
|
-
current_flow.ask_confirm_digressions or current_flow.block_digressions
|
|
878
|
-
)
|
|
879
|
-
|
|
880
|
-
collect_info = get_current_collect_step(tracker.stack, all_flows)
|
|
881
|
-
|
|
882
|
-
if collect_info and (
|
|
883
|
-
collect_info.ask_confirm_digressions
|
|
884
|
-
or collect_info.block_digressions
|
|
885
|
-
or current_flow_condition
|
|
886
|
-
):
|
|
887
|
-
return True
|
|
888
|
-
|
|
889
|
-
return False
|
|
@@ -6,6 +6,7 @@ import rasa.dialogue_understanding.processor.command_processor
|
|
|
6
6
|
from rasa.engine.graph import ExecutionContext, GraphComponent
|
|
7
7
|
from rasa.engine.storage.resource import Resource
|
|
8
8
|
from rasa.engine.storage.storage import ModelStorage
|
|
9
|
+
from rasa.shared.core.domain import Domain
|
|
9
10
|
from rasa.shared.core.events import Event
|
|
10
11
|
from rasa.shared.core.flows import FlowsList
|
|
11
12
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
@@ -15,7 +16,8 @@ from rasa.shared.core.training_data.structures import StoryGraph
|
|
|
15
16
|
class CommandProcessorComponent(GraphComponent):
|
|
16
17
|
"""Processes commands by issuing events to modify a tracker.
|
|
17
18
|
|
|
18
|
-
Minimal component that applies commands to a tracker.
|
|
19
|
+
Minimal component that applies commands to a tracker.
|
|
20
|
+
"""
|
|
19
21
|
|
|
20
22
|
def __init__(self, execution_context: ExecutionContext):
|
|
21
23
|
self._execution_context = execution_context
|
|
@@ -36,8 +38,9 @@ class CommandProcessorComponent(GraphComponent):
|
|
|
36
38
|
tracker: DialogueStateTracker,
|
|
37
39
|
flows: FlowsList,
|
|
38
40
|
story_graph: StoryGraph,
|
|
41
|
+
domain: Domain,
|
|
39
42
|
) -> List[Event]:
|
|
40
43
|
"""Execute commands to update tracker state."""
|
|
41
44
|
return rasa.dialogue_understanding.processor.command_processor.execute_commands(
|
|
42
|
-
tracker, flows, self._execution_context, story_graph
|
|
45
|
+
tracker, flows, self._execution_context, story_graph, domain
|
|
43
46
|
)
|
|
@@ -4,9 +4,6 @@ from typing import List, Optional, Set, Tuple
|
|
|
4
4
|
from rasa.dialogue_understanding.patterns.collect_information import (
|
|
5
5
|
CollectInformationPatternFlowStackFrame,
|
|
6
6
|
)
|
|
7
|
-
from rasa.dialogue_understanding.patterns.continue_interrupted import (
|
|
8
|
-
ContinueInterruptedPatternFlowStackFrame,
|
|
9
|
-
)
|
|
10
7
|
from rasa.dialogue_understanding.stack.dialogue_stack import DialogueStack
|
|
11
8
|
from rasa.dialogue_understanding.stack.frames import (
|
|
12
9
|
BaseFlowStackFrame,
|
|
@@ -221,38 +218,3 @@ def get_collect_steps_excluding_ask_before_filling_for_active_flow(
|
|
|
221
218
|
for step in active_flow.get_collect_steps()
|
|
222
219
|
if not step.ask_before_filling
|
|
223
220
|
)
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
def remove_digression_from_stack(stack: DialogueStack, flow_id: str) -> DialogueStack:
|
|
227
|
-
"""Remove a specific flow frame from the stack and other frames that reference it.
|
|
228
|
-
|
|
229
|
-
The main use-case is to prevent duplicate digressions from being added to the stack.
|
|
230
|
-
|
|
231
|
-
Args:
|
|
232
|
-
stack: The dialogue stack.
|
|
233
|
-
flow_id: The flow to remove.
|
|
234
|
-
|
|
235
|
-
Returns:
|
|
236
|
-
The updated dialogue stack.
|
|
237
|
-
"""
|
|
238
|
-
updated_stack = stack.copy()
|
|
239
|
-
original_frames = updated_stack.frames[:]
|
|
240
|
-
found_digression_index = -1
|
|
241
|
-
for index, frame in enumerate(original_frames):
|
|
242
|
-
if isinstance(frame, BaseFlowStackFrame) and frame.flow_id == flow_id:
|
|
243
|
-
updated_stack.frames.pop(index)
|
|
244
|
-
found_digression_index = index
|
|
245
|
-
|
|
246
|
-
# we also need to remove the `ContinueInterruptedPatternFlowStackFrame`
|
|
247
|
-
elif (
|
|
248
|
-
isinstance(frame, ContinueInterruptedPatternFlowStackFrame)
|
|
249
|
-
and frame.previous_flow_name == flow_id
|
|
250
|
-
and found_digression_index + 1 == index
|
|
251
|
-
):
|
|
252
|
-
# we know that this frame is always added after the digressing flow frame
|
|
253
|
-
# that was blocked previously by action_block_digressions,
|
|
254
|
-
# so this check would occur after the digressing flow was popped.
|
|
255
|
-
# Therefore, we need to update the index dynamically before popping.
|
|
256
|
-
updated_stack.frames.pop(index - 1)
|
|
257
|
-
|
|
258
|
-
return updated_stack
|
|
@@ -6,7 +6,7 @@ Each question variation should be a question that the input answer is attempting
|
|
|
6
6
|
Follow these steps to complete the task:
|
|
7
7
|
|
|
8
8
|
1. Generate {{ num_variations }} question variations that the input answer is attempting to answer.
|
|
9
|
-
|
|
9
|
+
2. Compile all the question variations into a JSON object.
|
|
10
10
|
|
|
11
11
|
### JSON Output
|
|
12
12
|
|
rasa/engine/validation.py
CHANGED
|
@@ -86,7 +86,9 @@ from rasa.shared.constants import (
|
|
|
86
86
|
from rasa.shared.core.constants import ACTION_RESET_ROUTING, ACTION_TRIGGER_CHITCHAT
|
|
87
87
|
from rasa.shared.core.domain import Domain
|
|
88
88
|
from rasa.shared.core.flows import Flow, FlowsList
|
|
89
|
+
from rasa.shared.core.policies.utils import contains_intentless_policy_responses
|
|
89
90
|
from rasa.shared.core.slots import Slot
|
|
91
|
+
from rasa.shared.core.training_data.structures import StoryGraph
|
|
90
92
|
from rasa.shared.exceptions import RasaException
|
|
91
93
|
from rasa.shared.nlu.training_data.message import Message
|
|
92
94
|
from rasa.shared.utils.common import display_research_study_prompt
|
|
@@ -642,11 +644,18 @@ def _recursively_check_required_components(
|
|
|
642
644
|
|
|
643
645
|
|
|
644
646
|
def validate_flow_component_dependencies(
|
|
645
|
-
flows: FlowsList,
|
|
647
|
+
flows: FlowsList,
|
|
648
|
+
domain: Domain,
|
|
649
|
+
story_graph: StoryGraph,
|
|
650
|
+
model_configuration: GraphModelConfiguration,
|
|
646
651
|
) -> None:
|
|
647
652
|
if (pattern_chitchat := flows.flow_by_id(FLOW_PATTERN_CHITCHAT)) is not None:
|
|
648
653
|
_validate_chitchat_dependencies(pattern_chitchat, model_configuration)
|
|
649
654
|
|
|
655
|
+
_validate_intentless_policy_responses(
|
|
656
|
+
flows, domain, story_graph, model_configuration
|
|
657
|
+
)
|
|
658
|
+
|
|
650
659
|
|
|
651
660
|
def _validate_chitchat_dependencies(
|
|
652
661
|
pattern_chitchat: Flow, model_configuration: GraphModelConfiguration
|
|
@@ -674,6 +683,32 @@ def _validate_chitchat_dependencies(
|
|
|
674
683
|
)
|
|
675
684
|
|
|
676
685
|
|
|
686
|
+
def _validate_intentless_policy_responses(
|
|
687
|
+
flows: FlowsList,
|
|
688
|
+
domain: Domain,
|
|
689
|
+
story_graph: StoryGraph,
|
|
690
|
+
model_configuration: GraphModelConfiguration,
|
|
691
|
+
) -> None:
|
|
692
|
+
"""If IntentlessPolicy is configured, validate that it has responses to use:
|
|
693
|
+
either responses from the domain that are not part of any flow, or from
|
|
694
|
+
end-to-end stories.
|
|
695
|
+
"""
|
|
696
|
+
if not model_configuration.predict_schema.has_node(IntentlessPolicy):
|
|
697
|
+
return
|
|
698
|
+
|
|
699
|
+
if not contains_intentless_policy_responses(flows, domain, story_graph):
|
|
700
|
+
structlogger.error(
|
|
701
|
+
"validation.intentless_policy.no_applicable_responses_found",
|
|
702
|
+
event_info=(
|
|
703
|
+
"IntentlessPolicy is configured, but no applicable responses are "
|
|
704
|
+
"found. Please make sure that there are responses defined in the "
|
|
705
|
+
"domain that are not part of any flow, or that there are "
|
|
706
|
+
"end-to-end stories in the training data."
|
|
707
|
+
),
|
|
708
|
+
)
|
|
709
|
+
sys.exit(1)
|
|
710
|
+
|
|
711
|
+
|
|
677
712
|
def get_component_index(schema: GraphSchema, component_class: Type) -> Optional[int]:
|
|
678
713
|
"""Extracts the index of a component of the given class in the schema.
|
|
679
714
|
This function assumes that each component's node name is stored in a way
|
rasa/model_training.py
CHANGED
|
@@ -315,6 +315,7 @@ async def _train_graph(
|
|
|
315
315
|
)
|
|
316
316
|
flows = file_importer.get_flows()
|
|
317
317
|
domain = file_importer.get_domain()
|
|
318
|
+
story_graph = file_importer.get_stories()
|
|
318
319
|
model_configuration = recipe.graph_config_for_recipe(
|
|
319
320
|
config,
|
|
320
321
|
kwargs,
|
|
@@ -330,7 +331,7 @@ async def _train_graph(
|
|
|
330
331
|
config
|
|
331
332
|
)
|
|
332
333
|
rasa.engine.validation.validate_flow_component_dependencies(
|
|
333
|
-
flows, model_configuration
|
|
334
|
+
flows, domain, story_graph, model_configuration
|
|
334
335
|
)
|
|
335
336
|
rasa.engine.validation.validate_command_generator_setup(model_configuration)
|
|
336
337
|
|
rasa/shared/constants.py
CHANGED
|
@@ -99,6 +99,8 @@ UTTER_ASK_PREFIX = "utter_ask_"
|
|
|
99
99
|
ACTION_ASK_PREFIX = "action_ask_"
|
|
100
100
|
FLOW_PREFIX = "flow_"
|
|
101
101
|
|
|
102
|
+
UTTER_FREE_CHITCHAT_RESPONSE = "utter_free_chitchat_response"
|
|
103
|
+
|
|
102
104
|
ASSISTANT_ID_KEY = "assistant_id"
|
|
103
105
|
ASSISTANT_ID_DEFAULT_VALUE = "placeholder_default"
|
|
104
106
|
|
rasa/shared/core/constants.py
CHANGED
|
@@ -52,8 +52,6 @@ ACTION_TRIGGER_CHITCHAT = "action_trigger_chitchat"
|
|
|
52
52
|
ACTION_RESET_ROUTING = "action_reset_routing"
|
|
53
53
|
ACTION_HANGUP = "action_hangup"
|
|
54
54
|
ACTION_REPEAT_BOT_MESSAGES = "action_repeat_bot_messages"
|
|
55
|
-
ACTION_BLOCK_DIGRESSION = "action_block_digression"
|
|
56
|
-
ACTION_CONTINUE_DIGRESSION = "action_continue_digression"
|
|
57
55
|
|
|
58
56
|
ACTION_METADATA_EXECUTION_SUCCESS = "execution_success"
|
|
59
57
|
ACTION_METADATA_EXECUTION_ERROR_MESSAGE = "execution_error_message"
|
|
@@ -84,8 +82,6 @@ DEFAULT_ACTION_NAMES = [
|
|
|
84
82
|
ACTION_RESET_ROUTING,
|
|
85
83
|
ACTION_HANGUP,
|
|
86
84
|
ACTION_REPEAT_BOT_MESSAGES,
|
|
87
|
-
ACTION_BLOCK_DIGRESSION,
|
|
88
|
-
ACTION_CONTINUE_DIGRESSION,
|
|
89
85
|
]
|
|
90
86
|
|
|
91
87
|
ACTION_SHOULD_SEND_DOMAIN = "send_domain"
|
|
@@ -205,8 +201,4 @@ CLASSIFIER_NAME_FALLBACK = "FallbackClassifier"
|
|
|
205
201
|
|
|
206
202
|
POLICIES_THAT_EXTRACT_ENTITIES = {"TEDPolicy"}
|
|
207
203
|
|
|
208
|
-
# digression constants
|
|
209
|
-
KEY_ASK_CONFIRM_DIGRESSIONS = "ask_confirm_digressions"
|
|
210
|
-
KEY_BLOCK_DIGRESSIONS = "block_digressions"
|
|
211
|
-
|
|
212
204
|
ERROR_CODE_KEY = "error_code"
|
rasa/shared/core/domain.py
CHANGED
|
@@ -1678,6 +1678,14 @@ class Domain:
|
|
|
1678
1678
|
"""Write domain to a file."""
|
|
1679
1679
|
as_yaml = self.as_yaml()
|
|
1680
1680
|
rasa.shared.utils.io.write_text_file(as_yaml, filename)
|
|
1681
|
+
# run the check again on the written domain to catch any errors
|
|
1682
|
+
# that may have been missed in the user defined domain files
|
|
1683
|
+
structlogger.info(
|
|
1684
|
+
"domain.persist.domain_written_to_file",
|
|
1685
|
+
event_info="The entire domain content has been written to file.",
|
|
1686
|
+
filename=filename,
|
|
1687
|
+
)
|
|
1688
|
+
Domain.is_domain_file(filename)
|
|
1681
1689
|
|
|
1682
1690
|
def as_yaml(self) -> Text:
|
|
1683
1691
|
"""Dump the `Domain` object as a YAML string.
|
|
@@ -1972,17 +1980,18 @@ class Domain:
|
|
|
1972
1980
|
|
|
1973
1981
|
try:
|
|
1974
1982
|
content = read_yaml_file(filename, expand_env_vars=cls.expand_env_vars)
|
|
1975
|
-
except (RasaException, YamlSyntaxException):
|
|
1976
|
-
structlogger.
|
|
1983
|
+
except (RasaException, YamlSyntaxException) as error:
|
|
1984
|
+
structlogger.error(
|
|
1977
1985
|
"domain.cannot_load_domain_file",
|
|
1978
1986
|
file=filename,
|
|
1987
|
+
error=error,
|
|
1979
1988
|
event_info=(
|
|
1980
1989
|
f"The file {filename} could not be loaded as domain file. "
|
|
1981
1990
|
f"You can use https://yamlchecker.com/ to validate "
|
|
1982
1991
|
f"the YAML syntax of your file."
|
|
1983
1992
|
),
|
|
1984
1993
|
)
|
|
1985
|
-
|
|
1994
|
+
raise RasaException(f"Domain could not be loaded: {error}")
|
|
1986
1995
|
|
|
1987
1996
|
return any(key in content for key in ALL_DOMAIN_KEYS)
|
|
1988
1997
|
|
rasa/shared/core/flows/flow.py
CHANGED
|
@@ -13,10 +13,6 @@ from pypred import Predicate
|
|
|
13
13
|
import rasa.shared.utils.io
|
|
14
14
|
from rasa.engine.language import Language
|
|
15
15
|
from rasa.shared.constants import RASA_DEFAULT_FLOW_PATTERN_PREFIX
|
|
16
|
-
from rasa.shared.core.constants import (
|
|
17
|
-
KEY_ASK_CONFIRM_DIGRESSIONS,
|
|
18
|
-
KEY_BLOCK_DIGRESSIONS,
|
|
19
|
-
)
|
|
20
16
|
from rasa.shared.core.flows.constants import (
|
|
21
17
|
KEY_ALWAYS_INCLUDE_IN_PROMPT,
|
|
22
18
|
KEY_DESCRIPTION,
|
|
@@ -52,7 +48,6 @@ from rasa.shared.core.flows.steps.constants import (
|
|
|
52
48
|
START_STEP,
|
|
53
49
|
)
|
|
54
50
|
from rasa.shared.core.flows.steps.continuation import ContinueFlowStep
|
|
55
|
-
from rasa.shared.core.flows.utils import extract_digression_prop
|
|
56
51
|
from rasa.shared.core.slots import Slot
|
|
57
52
|
|
|
58
53
|
structlogger = structlog.get_logger()
|
|
@@ -94,10 +89,6 @@ class Flow:
|
|
|
94
89
|
"""The path to the file where the flow is stored."""
|
|
95
90
|
persisted_slots: List[str] = field(default_factory=list)
|
|
96
91
|
"""The list of slots that should be persisted after the flow ends."""
|
|
97
|
-
ask_confirm_digressions: List[str] = field(default_factory=list)
|
|
98
|
-
"""The flow ids for which the assistant should ask for confirmation."""
|
|
99
|
-
block_digressions: List[str] = field(default_factory=list)
|
|
100
|
-
"""The flow ids that the assistant should block from digressing to."""
|
|
101
92
|
run_pattern_completed: bool = True
|
|
102
93
|
"""Whether the pattern_completed flow should be run after the flow ends."""
|
|
103
94
|
|
|
@@ -138,10 +129,6 @@ class Flow:
|
|
|
138
129
|
# data. When the model is trained, take the provided file_path.
|
|
139
130
|
file_path=data.get(KEY_FILE_PATH) if KEY_FILE_PATH in data else file_path,
|
|
140
131
|
persisted_slots=data.get(KEY_PERSISTED_SLOTS, []),
|
|
141
|
-
ask_confirm_digressions=extract_digression_prop(
|
|
142
|
-
KEY_ASK_CONFIRM_DIGRESSIONS, data
|
|
143
|
-
),
|
|
144
|
-
block_digressions=extract_digression_prop(KEY_BLOCK_DIGRESSIONS, data),
|
|
145
132
|
run_pattern_completed=data.get(KEY_RUN_PATTERN_COMPLETED, True),
|
|
146
133
|
translation=extract_translations(
|
|
147
134
|
translation_data=data.get(KEY_TRANSLATION, {})
|
|
@@ -220,10 +207,6 @@ class Flow:
|
|
|
220
207
|
data[KEY_FILE_PATH] = self.file_path
|
|
221
208
|
if self.persisted_slots:
|
|
222
209
|
data[KEY_PERSISTED_SLOTS] = self.persisted_slots
|
|
223
|
-
if self.ask_confirm_digressions:
|
|
224
|
-
data[KEY_ASK_CONFIRM_DIGRESSIONS] = self.ask_confirm_digressions
|
|
225
|
-
if self.block_digressions:
|
|
226
|
-
data[KEY_BLOCK_DIGRESSIONS] = self.block_digressions
|
|
227
210
|
if self.run_pattern_completed is not None:
|
|
228
211
|
data["run_pattern_completed"] = self.run_pattern_completed
|
|
229
212
|
if self.translation:
|
|
@@ -217,15 +217,12 @@
|
|
|
217
217
|
"reset_after_flow_ends": {
|
|
218
218
|
"type": "boolean"
|
|
219
219
|
},
|
|
220
|
-
"ask_confirm_digressions": {
|
|
221
|
-
"$ref": "#/$defs/ask_confirm_digressions"
|
|
222
|
-
},
|
|
223
|
-
"block_digressions": {
|
|
224
|
-
"$ref": "#/$defs/block_digressions"
|
|
225
|
-
},
|
|
226
220
|
"utter": {
|
|
227
221
|
"type": "string"
|
|
228
222
|
},
|
|
223
|
+
"force_slot_filling": {
|
|
224
|
+
"type": "boolean"
|
|
225
|
+
},
|
|
229
226
|
"rejections": {
|
|
230
227
|
"type": "array",
|
|
231
228
|
"schema_name": "list of rejections",
|
|
@@ -253,32 +250,6 @@
|
|
|
253
250
|
}
|
|
254
251
|
}
|
|
255
252
|
},
|
|
256
|
-
"ask_confirm_digressions": {
|
|
257
|
-
"oneOf": [
|
|
258
|
-
{
|
|
259
|
-
"type": "boolean"
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
"type": "array",
|
|
263
|
-
"items": {
|
|
264
|
-
"type": "string"
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
]
|
|
268
|
-
},
|
|
269
|
-
"block_digressions": {
|
|
270
|
-
"oneOf": [
|
|
271
|
-
{
|
|
272
|
-
"type": "boolean"
|
|
273
|
-
},
|
|
274
|
-
{
|
|
275
|
-
"type": "array",
|
|
276
|
-
"items": {
|
|
277
|
-
"type": "string"
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
]
|
|
281
|
-
},
|
|
282
253
|
"flow": {
|
|
283
254
|
"required": [
|
|
284
255
|
"steps",
|
|
@@ -340,12 +311,6 @@
|
|
|
340
311
|
"persisted_slots": {
|
|
341
312
|
"$ref": "#/$defs/persisted_slots"
|
|
342
313
|
},
|
|
343
|
-
"ask_confirm_digressions": {
|
|
344
|
-
"$ref": "#/$defs/ask_confirm_digressions"
|
|
345
|
-
},
|
|
346
|
-
"block_digressions": {
|
|
347
|
-
"$ref": "#/$defs/block_digressions"
|
|
348
|
-
},
|
|
349
314
|
"run_pattern_completed": {
|
|
350
315
|
"type": "boolean"
|
|
351
316
|
}
|
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from dataclasses import dataclass
|
|
3
|
+
from dataclasses import dataclass
|
|
4
4
|
from typing import Any, Dict, List, Set, Text
|
|
5
5
|
|
|
6
6
|
from rasa.shared.constants import ACTION_ASK_PREFIX, UTTER_ASK_PREFIX
|
|
7
|
-
from rasa.shared.core.constants import (
|
|
8
|
-
KEY_ASK_CONFIRM_DIGRESSIONS,
|
|
9
|
-
KEY_BLOCK_DIGRESSIONS,
|
|
10
|
-
)
|
|
11
7
|
from rasa.shared.core.flows.flow_step import FlowStep
|
|
12
|
-
from rasa.shared.core.flows.utils import extract_digression_prop
|
|
13
8
|
from rasa.shared.core.slots import SlotRejection
|
|
14
9
|
|
|
15
10
|
|
|
@@ -29,10 +24,8 @@ class CollectInformationFlowStep(FlowStep):
|
|
|
29
24
|
"""Whether to always ask the question even if the slot is already filled."""
|
|
30
25
|
reset_after_flow_ends: bool = True
|
|
31
26
|
"""Whether to reset the slot value at the end of the flow."""
|
|
32
|
-
|
|
33
|
-
"""
|
|
34
|
-
block_digressions: List[str] = field(default_factory=list)
|
|
35
|
-
"""The flow id digressions that should be blocked during the flow step."""
|
|
27
|
+
force_slot_filling: bool = False
|
|
28
|
+
"""Whether to keep only the SetSlot command for the collected slot."""
|
|
36
29
|
|
|
37
30
|
@classmethod
|
|
38
31
|
def from_json(
|
|
@@ -60,10 +53,7 @@ class CollectInformationFlowStep(FlowStep):
|
|
|
60
53
|
SlotRejection.from_dict(rejection)
|
|
61
54
|
for rejection in data.get("rejections", [])
|
|
62
55
|
],
|
|
63
|
-
|
|
64
|
-
KEY_ASK_CONFIRM_DIGRESSIONS, data
|
|
65
|
-
),
|
|
66
|
-
block_digressions=extract_digression_prop(KEY_BLOCK_DIGRESSIONS, data),
|
|
56
|
+
force_slot_filling=data.get("force_slot_filling", False),
|
|
67
57
|
**base.__dict__,
|
|
68
58
|
)
|
|
69
59
|
|
|
@@ -79,10 +69,7 @@ class CollectInformationFlowStep(FlowStep):
|
|
|
79
69
|
data["ask_before_filling"] = self.ask_before_filling
|
|
80
70
|
data["reset_after_flow_ends"] = self.reset_after_flow_ends
|
|
81
71
|
data["rejections"] = [rejection.as_dict() for rejection in self.rejections]
|
|
82
|
-
data["
|
|
83
|
-
data["block_digressions"] = (
|
|
84
|
-
self.block_digressions if self.block_digressions else False
|
|
85
|
-
)
|
|
72
|
+
data["force_slot_filling"] = self.force_slot_filling
|
|
86
73
|
|
|
87
74
|
return data
|
|
88
75
|
|
rasa/shared/core/flows/utils.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING, Any, Dict,
|
|
1
|
+
from typing import TYPE_CHECKING, Any, Dict, Set, Text
|
|
2
2
|
|
|
3
3
|
from rasa.shared.utils.io import raise_deprecation_warning
|
|
4
4
|
|
|
@@ -8,7 +8,6 @@ if TYPE_CHECKING:
|
|
|
8
8
|
|
|
9
9
|
RESET_PROPERTY_NAME = "reset_after_flow_ends"
|
|
10
10
|
PERSIST_PROPERTY_NAME = "persisted_slots"
|
|
11
|
-
ALL_LABEL = "ALL"
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
def warn_deprecated_collect_step_config() -> None:
|
|
@@ -45,20 +44,6 @@ def get_invalid_slot_persistence_config_error_message(
|
|
|
45
44
|
)
|
|
46
45
|
|
|
47
46
|
|
|
48
|
-
def extract_digression_prop(prop: str, data: Dict[str, Any]) -> List[str]:
|
|
49
|
-
"""Extracts the digression property from the data.
|
|
50
|
-
|
|
51
|
-
There can be two types of properties: ask_confirm_digressions and
|
|
52
|
-
block_digressions.
|
|
53
|
-
"""
|
|
54
|
-
digression_property = data.get(prop, [])
|
|
55
|
-
|
|
56
|
-
if isinstance(digression_property, bool):
|
|
57
|
-
digression_property = [ALL_LABEL] if digression_property else []
|
|
58
|
-
|
|
59
|
-
return digression_property
|
|
60
|
-
|
|
61
|
-
|
|
62
47
|
def extract_translations(
|
|
63
48
|
translation_data: Dict[Text, Any],
|
|
64
49
|
) -> Dict[Text, "FlowLanguageTranslation"]:
|
|
File without changes
|