rasa-pro 3.12.0.dev11__py3-none-any.whl → 3.12.0.dev12__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/cli/inspect.py +1 -20
- rasa/cli/shell.py +3 -3
- rasa/core/actions/action.py +7 -20
- rasa/core/actions/forms.py +5 -10
- rasa/core/channels/__init__.py +0 -2
- rasa/core/channels/voice_ready/audiocodes.py +23 -42
- rasa/core/channels/voice_stream/browser_audio.py +0 -1
- rasa/core/channels/voice_stream/call_state.py +1 -7
- rasa/core/channels/voice_stream/tts/azure.py +1 -2
- rasa/core/channels/voice_stream/tts/cartesia.py +3 -16
- rasa/core/channels/voice_stream/twilio_media_streams.py +1 -2
- rasa/core/channels/voice_stream/voice_channel.py +1 -2
- rasa/core/migrate.py +2 -2
- rasa/core/policies/flows/flow_executor.py +42 -36
- rasa/core/run.py +3 -4
- rasa/dialogue_understanding/commands/can_not_handle_command.py +2 -2
- rasa/dialogue_understanding/commands/cancel_flow_command.py +4 -62
- rasa/dialogue_understanding/commands/change_flow_command.py +2 -2
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +2 -2
- rasa/dialogue_understanding/commands/clarify_command.py +2 -2
- rasa/dialogue_understanding/commands/correct_slots_command.py +2 -11
- rasa/dialogue_understanding/commands/human_handoff_command.py +2 -2
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +2 -2
- rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +2 -2
- rasa/dialogue_understanding/commands/set_slot_command.py +15 -7
- rasa/dialogue_understanding/commands/skip_question_command.py +2 -2
- rasa/dialogue_understanding/commands/start_flow_command.py +2 -43
- rasa/dialogue_understanding/commands/utils.py +1 -1
- rasa/dialogue_understanding/constants.py +0 -1
- rasa/dialogue_understanding/generator/command_generator.py +73 -110
- rasa/dialogue_understanding/generator/command_parser.py +1 -1
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +3 -161
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +2 -10
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +3 -44
- rasa/dialogue_understanding/generator/single_step/command_prompt_template.jinja2 +79 -53
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +19 -11
- rasa/dialogue_understanding/generator/utils.py +1 -32
- rasa/dialogue_understanding/patterns/correction.py +1 -13
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +2 -62
- rasa/dialogue_understanding/processor/command_processor.py +28 -115
- rasa/dialogue_understanding/utils.py +0 -31
- rasa/dialogue_understanding_test/README.md +0 -50
- rasa/dialogue_understanding_test/test_case_simulation/test_case_tracker_simulator.py +3 -3
- rasa/model_service.py +0 -4
- rasa/model_training.py +27 -24
- rasa/shared/core/constants.py +3 -28
- rasa/shared/core/domain.py +20 -13
- rasa/shared/core/events.py +2 -13
- rasa/shared/core/flows/flow.py +0 -17
- rasa/shared/core/flows/flows_yaml_schema.json +0 -38
- rasa/shared/core/flows/steps/collect.py +1 -18
- rasa/shared/core/flows/utils.py +1 -16
- rasa/shared/core/slot_mappings.py +108 -144
- rasa/shared/core/slots.py +2 -23
- rasa/shared/core/trackers.py +1 -3
- rasa/shared/nlu/constants.py +0 -1
- rasa/shared/utils/llm.py +1 -1
- rasa/shared/utils/schemas/domain.yml +1 -0
- rasa/telemetry.py +13 -43
- rasa/utils/common.py +1 -0
- rasa/validator.py +82 -189
- rasa/version.py +1 -1
- {rasa_pro-3.12.0.dev11.dist-info → rasa_pro-3.12.0.dev12.dist-info}/METADATA +1 -1
- {rasa_pro-3.12.0.dev11.dist-info → rasa_pro-3.12.0.dev12.dist-info}/RECORD +67 -71
- rasa/core/actions/action_handle_digressions.py +0 -142
- rasa/core/channels/voice_stream/genesys.py +0 -331
- rasa/dialogue_understanding/commands/handle_digressions_command.py +0 -150
- rasa/dialogue_understanding/patterns/handle_digressions.py +0 -81
- {rasa_pro-3.12.0.dev11.dist-info → rasa_pro-3.12.0.dev12.dist-info}/NOTICE +0 -0
- {rasa_pro-3.12.0.dev11.dist-info → rasa_pro-3.12.0.dev12.dist-info}/WHEEL +0 -0
- {rasa_pro-3.12.0.dev11.dist-info → rasa_pro-3.12.0.dev12.dist-info}/entry_points.txt +0 -0
|
@@ -1,17 +1,6 @@
|
|
|
1
1
|
version: "3.1"
|
|
2
2
|
responses:
|
|
3
3
|
|
|
4
|
-
utter_ask_continue_previous_flow:
|
|
5
|
-
- text: "Confirm if you would like to continue with the initial topic: {{context.interrupted_flow_id}}?"
|
|
6
|
-
metadata:
|
|
7
|
-
rephrase: True
|
|
8
|
-
template: jinja
|
|
9
|
-
buttons:
|
|
10
|
-
- title: Continue with the previous topic.
|
|
11
|
-
payload: /SetSlots(continue_previous_flow=True)
|
|
12
|
-
- title: Switch to new topic.
|
|
13
|
-
payload: /SetSlots(continue_previous_flow=False)
|
|
14
|
-
|
|
15
4
|
utter_ask_rephrase:
|
|
16
5
|
- text: I’m sorry I am unable to understand you, could you please rephrase?
|
|
17
6
|
|
|
@@ -20,20 +9,6 @@ responses:
|
|
|
20
9
|
metadata:
|
|
21
10
|
rephrase: True
|
|
22
11
|
|
|
23
|
-
utter_block_digressions:
|
|
24
|
-
- text: "We can look into {{ context.interrupting_flow_id }} later. Let's focus on the current topic: {{ context.interrupted_flow_id }}."
|
|
25
|
-
metadata:
|
|
26
|
-
rephrase: True
|
|
27
|
-
template: jinja
|
|
28
|
-
- text: "Let's continue with the current topic: {{ context.interrupted_flow_id }}."
|
|
29
|
-
condition:
|
|
30
|
-
- type: slot
|
|
31
|
-
name: continue_previous_flow
|
|
32
|
-
value: True
|
|
33
|
-
metadata:
|
|
34
|
-
rephrase: True
|
|
35
|
-
template: jinja
|
|
36
|
-
|
|
37
12
|
utter_boolean_slot_rejection:
|
|
38
13
|
- text: "Sorry, the value you provided, `{{value}}`, is not valid. Please respond with a valid value."
|
|
39
14
|
metadata:
|
|
@@ -60,14 +35,8 @@ responses:
|
|
|
60
35
|
rephrase: True
|
|
61
36
|
template: jinja
|
|
62
37
|
|
|
63
|
-
utter_continue_interruption:
|
|
64
|
-
- text: "Let's continue with the chosen topic instead: {{ context.interrupting_flow_id }}."
|
|
65
|
-
metadata:
|
|
66
|
-
rephrase: True
|
|
67
|
-
template: jinja
|
|
68
|
-
|
|
69
38
|
utter_corrected_previous_input:
|
|
70
|
-
- text: "Ok, I am updating {{ context.corrected_slots.keys()|join(', ') }} to {{ context.
|
|
39
|
+
- text: "Ok, I am updating {{ context.corrected_slots.keys()|join(', ') }} to {{ context.corrected_slots.values()|join(', ') }} respectively."
|
|
71
40
|
metadata:
|
|
72
41
|
rephrase: True
|
|
73
42
|
template: jinja
|
|
@@ -150,10 +119,7 @@ slots:
|
|
|
150
119
|
type: float
|
|
151
120
|
initial_value: 0.0
|
|
152
121
|
max_value: 1000000
|
|
153
|
-
|
|
154
|
-
type: bool
|
|
155
|
-
mappings:
|
|
156
|
-
- type: from_llm
|
|
122
|
+
|
|
157
123
|
|
|
158
124
|
flows:
|
|
159
125
|
pattern_cancel_flow:
|
|
@@ -197,7 +163,6 @@ flows:
|
|
|
197
163
|
steps:
|
|
198
164
|
- action: action_clarify_flows
|
|
199
165
|
- action: utter_clarification_options_rasa
|
|
200
|
-
- action: action_listen
|
|
201
166
|
|
|
202
167
|
pattern_code_change:
|
|
203
168
|
description: Conversation repair flow for cleaning the stack after an assistant update
|
|
@@ -247,31 +212,6 @@ flows:
|
|
|
247
212
|
next: END
|
|
248
213
|
- else: END
|
|
249
214
|
|
|
250
|
-
pattern_handle_digressions:
|
|
251
|
-
description: Conversation repair flow for handling digressions
|
|
252
|
-
name: pattern handle digressions
|
|
253
|
-
steps:
|
|
254
|
-
- noop: true
|
|
255
|
-
id: branching
|
|
256
|
-
next:
|
|
257
|
-
- if: context.ask_confirm_digressions contains context.interrupting_flow_id
|
|
258
|
-
then: continue_previous_flow
|
|
259
|
-
- if: context.block_digressions contains context.interrupting_flow_id
|
|
260
|
-
then: block_digression
|
|
261
|
-
- else: continue_digression
|
|
262
|
-
- id: continue_previous_flow
|
|
263
|
-
collect: continue_previous_flow
|
|
264
|
-
next:
|
|
265
|
-
- if: slots.continue_previous_flow
|
|
266
|
-
then: block_digression
|
|
267
|
-
- else: continue_digression
|
|
268
|
-
- id: block_digression
|
|
269
|
-
action: action_block_digression
|
|
270
|
-
next: END
|
|
271
|
-
- id: continue_digression
|
|
272
|
-
action: action_continue_digression
|
|
273
|
-
next: END
|
|
274
|
-
|
|
275
215
|
pattern_human_handoff:
|
|
276
216
|
description: Conversation repair flow for switching users to a human agent if their request can't be handled
|
|
277
217
|
name: pattern human handoff
|
|
@@ -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.patterns.chitchat import FLOW_PATTERN_CHITCHAT
|
|
26
23
|
from rasa.dialogue_understanding.patterns.collect_information import (
|
|
@@ -50,7 +47,6 @@ from rasa.shared.core.constants import (
|
|
|
50
47
|
from rasa.shared.core.events import Event, SlotSet
|
|
51
48
|
from rasa.shared.core.flows import FlowsList
|
|
52
49
|
from rasa.shared.core.flows.steps.collect import CollectInformationFlowStep
|
|
53
|
-
from rasa.shared.core.slot_mappings import SlotMapping
|
|
54
50
|
from rasa.shared.core.slots import Slot
|
|
55
51
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
56
52
|
from rasa.shared.core.training_data.structures import StoryGraph
|
|
@@ -399,28 +395,6 @@ def clean_up_commands(
|
|
|
399
395
|
command=command,
|
|
400
396
|
)
|
|
401
397
|
|
|
402
|
-
elif isinstance(command, StartFlowCommand) and active_flow is not None:
|
|
403
|
-
# push handle digressions command if we are at a collect step of
|
|
404
|
-
# a flow and a new flow is started
|
|
405
|
-
collect_info = get_current_collect_step(tracker.stack, all_flows)
|
|
406
|
-
current_flow = all_flows.flow_by_id(active_flow)
|
|
407
|
-
current_flow_condition = current_flow and (
|
|
408
|
-
current_flow.ask_confirm_digressions or current_flow.block_digressions
|
|
409
|
-
)
|
|
410
|
-
|
|
411
|
-
if collect_info and (
|
|
412
|
-
collect_info.ask_confirm_digressions
|
|
413
|
-
or collect_info.block_digressions
|
|
414
|
-
or current_flow_condition
|
|
415
|
-
):
|
|
416
|
-
clean_commands.append(HandleDigressionsCommand(flow=command.flow))
|
|
417
|
-
structlogger.debug(
|
|
418
|
-
"command_processor.clean_up_commands.push_handle_digressions",
|
|
419
|
-
command=command,
|
|
420
|
-
)
|
|
421
|
-
else:
|
|
422
|
-
clean_commands.append(command)
|
|
423
|
-
|
|
424
398
|
# handle chitchat command differently from other free-form answer commands
|
|
425
399
|
elif isinstance(command, ChitChatAnswerCommand):
|
|
426
400
|
clean_commands = clean_up_chitchat_command(
|
|
@@ -553,48 +527,13 @@ def clean_up_slot_command(
|
|
|
553
527
|
)
|
|
554
528
|
return resulting_commands
|
|
555
529
|
|
|
556
|
-
if not should_slot_be_set(slot, command
|
|
557
|
-
structlogger.debug(
|
|
558
|
-
"command_processor.clean_up_slot_command.skip_command.extractor_"
|
|
559
|
-
"does_not_match_slot_mapping",
|
|
560
|
-
extractor=command.extractor,
|
|
561
|
-
slot_name=slot.name,
|
|
562
|
-
)
|
|
563
|
-
|
|
564
|
-
# prevent adding a cannot handle command in case commands_so_far already
|
|
565
|
-
# contains a valid prior set slot command for the same slot whose current
|
|
566
|
-
# slot command was rejected by should_slot_be_set
|
|
567
|
-
slot_command_exists_already = any(
|
|
568
|
-
isinstance(command, SetSlotCommand) and command.name == slot.name
|
|
569
|
-
for command in resulting_commands
|
|
570
|
-
)
|
|
571
|
-
|
|
530
|
+
if not should_slot_be_set(slot, command):
|
|
572
531
|
cannot_handle = CannotHandleCommand(reason=CANNOT_HANDLE_REASON)
|
|
573
|
-
if
|
|
532
|
+
if cannot_handle not in resulting_commands:
|
|
574
533
|
resulting_commands.append(cannot_handle)
|
|
575
534
|
|
|
576
535
|
return resulting_commands
|
|
577
536
|
|
|
578
|
-
if (
|
|
579
|
-
slot.filled_by == SetSlotExtractor.NLU.value
|
|
580
|
-
and command.extractor == SetSlotExtractor.LLM.value
|
|
581
|
-
):
|
|
582
|
-
allow_nlu_correction = any(
|
|
583
|
-
[
|
|
584
|
-
mapping.allow_nlu_correction is True
|
|
585
|
-
for mapping in slot.mappings
|
|
586
|
-
if mapping.type == SlotMappingType.FROM_LLM
|
|
587
|
-
]
|
|
588
|
-
)
|
|
589
|
-
|
|
590
|
-
if not allow_nlu_correction:
|
|
591
|
-
structlogger.debug(
|
|
592
|
-
"command_processor.clean_up_slot_command"
|
|
593
|
-
".skip_command.disallow_llm_correction_of_nlu_set_value",
|
|
594
|
-
command=command,
|
|
595
|
-
)
|
|
596
|
-
return resulting_commands
|
|
597
|
-
|
|
598
537
|
if command.name in slots_so_far and command.name != ROUTE_TO_CALM_SLOT:
|
|
599
538
|
current_collect_info = get_current_collect_step(stack, all_flows)
|
|
600
539
|
|
|
@@ -635,7 +574,7 @@ def clean_up_slot_command(
|
|
|
635
574
|
)
|
|
636
575
|
|
|
637
576
|
# Group all corrections into one command
|
|
638
|
-
corrected_slot = CorrectedSlot(command.name, command.value
|
|
577
|
+
corrected_slot = CorrectedSlot(command.name, command.value)
|
|
639
578
|
for c in resulting_commands:
|
|
640
579
|
if isinstance(c, CorrectSlotsCommand):
|
|
641
580
|
c.corrected_slots.append(corrected_slot)
|
|
@@ -719,9 +658,7 @@ def clean_up_chitchat_command(
|
|
|
719
658
|
return resulting_commands
|
|
720
659
|
|
|
721
660
|
|
|
722
|
-
def should_slot_be_set(
|
|
723
|
-
slot: Slot, command: SetSlotCommand, commands_so_far: Optional[List[Command]] = None
|
|
724
|
-
) -> bool:
|
|
661
|
+
def should_slot_be_set(slot: Slot, command: SetSlotCommand) -> bool:
|
|
725
662
|
"""Check if a slot should be set by a command."""
|
|
726
663
|
if command.extractor == SetSlotExtractor.COMMAND_PAYLOAD_READER.value:
|
|
727
664
|
# if the command is issued by the command payload reader, it means the slot
|
|
@@ -729,61 +666,37 @@ def should_slot_be_set(
|
|
|
729
666
|
# we can always set it
|
|
730
667
|
return True
|
|
731
668
|
|
|
732
|
-
if commands_so_far is None:
|
|
733
|
-
commands_so_far = []
|
|
734
|
-
|
|
735
|
-
set_slot_commands_so_far = [
|
|
736
|
-
command
|
|
737
|
-
for command in commands_so_far
|
|
738
|
-
if isinstance(command, SetSlotCommand) and command.name == slot.name
|
|
739
|
-
]
|
|
740
|
-
|
|
741
669
|
slot_mappings = slot.mappings
|
|
742
670
|
|
|
743
|
-
if not
|
|
744
|
-
slot_mappings = [
|
|
671
|
+
if not slot_mappings:
|
|
672
|
+
slot_mappings = [{"type": SlotMappingType.FROM_LLM.value}]
|
|
745
673
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
[mapping_type.is_predefined_type() for mapping_type in mapping_types]
|
|
750
|
-
)
|
|
751
|
-
slot_has_llm_mapping = any(
|
|
752
|
-
[mapping_type == SlotMappingType.FROM_LLM for mapping_type in mapping_types]
|
|
753
|
-
)
|
|
754
|
-
slot_has_controlled_mapping = any(
|
|
755
|
-
[mapping_type == SlotMappingType.CONTROLLED for mapping_type in mapping_types]
|
|
756
|
-
)
|
|
757
|
-
|
|
758
|
-
if set_slot_commands_so_far and command.extractor == SetSlotExtractor.LLM.value:
|
|
759
|
-
# covers the following scenarios:
|
|
760
|
-
# scenario 1: NLU mapping extracts a value for slot_a → If LLM extracts a value for slot_a, it is discarded. # noqa: E501
|
|
761
|
-
# scenario 2: NLU mapping is unable to extract a value for slot_a → If LLM extracts a value for slot_a, it is accepted. # noqa: E501
|
|
762
|
-
command_has_nlu_extractor = any(
|
|
763
|
-
[
|
|
764
|
-
command.extractor == SetSlotExtractor.NLU.value
|
|
765
|
-
for command in set_slot_commands_so_far
|
|
766
|
-
]
|
|
674
|
+
for mapping in slot_mappings:
|
|
675
|
+
mapping_type = SlotMappingType(
|
|
676
|
+
mapping.get("type", SlotMappingType.FROM_LLM.value)
|
|
767
677
|
)
|
|
768
|
-
return not command_has_nlu_extractor and slot_has_llm_mapping
|
|
769
678
|
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
679
|
+
should_be_set_by_llm = (
|
|
680
|
+
command.extractor == SetSlotExtractor.LLM.value
|
|
681
|
+
and mapping_type == SlotMappingType.FROM_LLM
|
|
682
|
+
)
|
|
683
|
+
should_be_set_by_nlu = (
|
|
684
|
+
command.extractor == SetSlotExtractor.NLU.value
|
|
685
|
+
and mapping_type.is_predefined_type()
|
|
686
|
+
)
|
|
776
687
|
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
):
|
|
782
|
-
return False
|
|
688
|
+
if should_be_set_by_llm or should_be_set_by_nlu:
|
|
689
|
+
# if the extractor matches the mapping type, we can continue
|
|
690
|
+
# setting the slot
|
|
691
|
+
break
|
|
783
692
|
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
693
|
+
structlogger.debug(
|
|
694
|
+
"command_processor.clean_up_slot_command.skip_command.extractor_"
|
|
695
|
+
"does_not_match_slot_mapping",
|
|
696
|
+
extractor=command.extractor,
|
|
697
|
+
slot_name=slot.name,
|
|
698
|
+
mapping_type=mapping_type.value,
|
|
699
|
+
)
|
|
787
700
|
return False
|
|
788
701
|
|
|
789
702
|
return True
|
|
@@ -5,10 +5,7 @@ from rasa.dialogue_understanding.commands import Command
|
|
|
5
5
|
from rasa.dialogue_understanding.constants import (
|
|
6
6
|
RASA_RECORD_COMMANDS_AND_PROMPTS_ENV_VAR_NAME,
|
|
7
7
|
)
|
|
8
|
-
from rasa.shared.constants import ROUTE_TO_CALM_SLOT
|
|
9
|
-
from rasa.shared.core.trackers import DialogueStateTracker
|
|
10
8
|
from rasa.shared.nlu.constants import (
|
|
11
|
-
COMMANDS,
|
|
12
9
|
KEY_COMPONENT_NAME,
|
|
13
10
|
KEY_LLM_RESPONSE_METADATA,
|
|
14
11
|
KEY_PROMPT_NAME,
|
|
@@ -16,7 +13,6 @@ from rasa.shared.nlu.constants import (
|
|
|
16
13
|
KEY_USER_PROMPT,
|
|
17
14
|
PREDICTED_COMMANDS,
|
|
18
15
|
PROMPTS,
|
|
19
|
-
SET_SLOT_COMMAND,
|
|
20
16
|
)
|
|
21
17
|
from rasa.shared.nlu.training_data.message import Message
|
|
22
18
|
from rasa.shared.providers.llm.llm_response import LLMResponse
|
|
@@ -135,30 +131,3 @@ def add_prompt_to_message_parse_data(
|
|
|
135
131
|
|
|
136
132
|
# Update the message with the new prompts list.
|
|
137
133
|
message.set(PROMPTS, prompts, add_to_output=True)
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
def _handle_via_nlu_in_coexistence(
|
|
141
|
-
tracker: Optional[DialogueStateTracker], message: Message
|
|
142
|
-
) -> bool:
|
|
143
|
-
"""Check if the message should be handled by the NLU subsystem in coexistence mode.""" # noqa: E501
|
|
144
|
-
if not tracker:
|
|
145
|
-
return False
|
|
146
|
-
|
|
147
|
-
if not tracker.has_coexistence_routing_slot:
|
|
148
|
-
return False
|
|
149
|
-
|
|
150
|
-
value = tracker.get_slot(ROUTE_TO_CALM_SLOT)
|
|
151
|
-
if value is not None:
|
|
152
|
-
return not value
|
|
153
|
-
|
|
154
|
-
# routing slot has been reset so we need to check
|
|
155
|
-
# the command issued by the Router component
|
|
156
|
-
if message.get(COMMANDS):
|
|
157
|
-
for command in message.get(COMMANDS):
|
|
158
|
-
if (
|
|
159
|
-
command.get("command") == SET_SLOT_COMMAND
|
|
160
|
-
and command.get("name") == ROUTE_TO_CALM_SLOT
|
|
161
|
-
):
|
|
162
|
-
return not command.get("value")
|
|
163
|
-
|
|
164
|
-
return False
|
|
@@ -377,53 +377,3 @@ Test cases in **to_review** may require manual intervention because the E2E test
|
|
|
377
377
|
Review these cases to ensure that the converted test cases are correct and the list of commands and
|
|
378
378
|
bot responses is complete.
|
|
379
379
|
|
|
380
|
-
|
|
381
|
-
## Converting DUT test from one DSL to a another DSL
|
|
382
|
-
|
|
383
|
-
If you need to transform your commands from one DSL format to another
|
|
384
|
-
(for instance, updating `StartFlow(flow_name)` to `start flow_name` or `SetSlot(slot_name, slot_value)` to `set slot_name slot_value`),
|
|
385
|
-
you can use a standalone Python script:
|
|
386
|
-
|
|
387
|
-
```bash
|
|
388
|
-
python convert_dut_dsl.py --dut-tests-dir <path> --output-dir <path> --dsl-mappings <path>
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
The script has the following required parameters:
|
|
392
|
-
|
|
393
|
-
- `--dut-tests-dir <path>`: The directory (relative or absolute) containing your
|
|
394
|
-
existing Dialogue Understanding Tests (DUT). The script will look for `.yaml` or
|
|
395
|
-
`.yml` files within this folder (and subfolders).
|
|
396
|
-
- `--output-dir <path>`: The directory where transformed files will be saved. The folder
|
|
397
|
-
structure from your `dut-tests-dir` is preserved.
|
|
398
|
-
- `--dsl-mappings <path>`: The YAML file defining your DSL mapping rules.
|
|
399
|
-
|
|
400
|
-
The YAML file containing the mappings must adhere to the following format:
|
|
401
|
-
```yaml
|
|
402
|
-
mappings:
|
|
403
|
-
|
|
404
|
-
- from_dsl_regex: "^StartFlow\\(([^)]*)\\)$"
|
|
405
|
-
to_dsl_pattern: "start {1}"
|
|
406
|
-
|
|
407
|
-
- from_dsl_regex: "^SetSlot\\(([^,]+),\\s*(.*)\\)$"
|
|
408
|
-
to_dsl_pattern: "set {1} {2}"
|
|
409
|
-
|
|
410
|
-
- from_dsl_regex: "Clarify\(([\"\'a-zA-Z0-9_, ]*)\)"
|
|
411
|
-
to_dsl_pattern: "clarify {1}"
|
|
412
|
-
input_separators:
|
|
413
|
-
- ","
|
|
414
|
-
- " "
|
|
415
|
-
output_separator: " "
|
|
416
|
-
|
|
417
|
-
# ... add more mappings here
|
|
418
|
-
|
|
419
|
-
```
|
|
420
|
-
|
|
421
|
-
- `from_dsl_regex`: A regular expression (string) used to match the old DSL command.
|
|
422
|
-
Must include any necessary anchors (like ^ and $) and capturing groups ( ... ) for
|
|
423
|
-
dynamic parts.
|
|
424
|
-
- `to_dsl_pattern`: A string that contains placeholders like `{1}`, `{2}`, etc. Each
|
|
425
|
-
placeholder corresponds to a capturing group in from_dsl_regex, in order of
|
|
426
|
-
appearance.
|
|
427
|
-
- `input_separators`: Optional list of separators of the captured groups that can be replaced
|
|
428
|
-
with the `output_separator`
|
|
429
|
-
- `output_separator`: Output separator to replace separators from the list of `input_separators` in the captured group.
|
|
@@ -20,7 +20,7 @@ from rasa.dialogue_understanding_test.test_case_simulation.exception import (
|
|
|
20
20
|
)
|
|
21
21
|
from rasa.dialogue_understanding_test.utils import filter_metadata
|
|
22
22
|
from rasa.e2e_test.e2e_test_case import Fixture, Metadata
|
|
23
|
-
from rasa.shared.core.constants import SlotMappingType
|
|
23
|
+
from rasa.shared.core.constants import MAPPING_TYPE, SlotMappingType
|
|
24
24
|
from rasa.shared.core.events import BotUttered, SlotSet, UserUttered
|
|
25
25
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
26
26
|
from rasa.shared.nlu.constants import COMMANDS, ENTITIES, INTENT
|
|
@@ -328,8 +328,8 @@ class TestCaseTrackerSimulator:
|
|
|
328
328
|
command.extractor = SetSlotExtractor.COMMAND_PAYLOAD_READER.value
|
|
329
329
|
# Use the SetSlotExtractor.NLU extractor if the slot mapping type is
|
|
330
330
|
# not FROM_LLM.
|
|
331
|
-
elif SlotMappingType.FROM_LLM not in [
|
|
332
|
-
mapping
|
|
331
|
+
elif SlotMappingType.FROM_LLM.value not in [
|
|
332
|
+
mapping[MAPPING_TYPE] for mapping in slot_definition.mappings
|
|
333
333
|
]:
|
|
334
334
|
command.extractor = SetSlotExtractor.NLU.value
|
|
335
335
|
|
rasa/model_service.py
CHANGED
|
@@ -61,7 +61,6 @@ def main() -> None:
|
|
|
61
61
|
The API server can receive requests to train models, run bots, and manage
|
|
62
62
|
the lifecycle of models and bots.
|
|
63
63
|
"""
|
|
64
|
-
import rasa.telemetry
|
|
65
64
|
import rasa.utils.licensing
|
|
66
65
|
|
|
67
66
|
log_level = logging.DEBUG
|
|
@@ -75,9 +74,6 @@ def main() -> None:
|
|
|
75
74
|
|
|
76
75
|
rasa.utils.licensing.validate_license_from_env()
|
|
77
76
|
|
|
78
|
-
rasa.telemetry.initialize_telemetry()
|
|
79
|
-
rasa.telemetry.initialize_error_reporting()
|
|
80
|
-
|
|
81
77
|
try:
|
|
82
78
|
model_api.prepare_working_directories()
|
|
83
79
|
except Exception as e:
|
rasa/model_training.py
CHANGED
|
@@ -352,31 +352,34 @@ async def _train_graph(
|
|
|
352
352
|
model_name = determine_model_name(fixed_model_name, training_type)
|
|
353
353
|
full_model_path = Path(output_path, model_name)
|
|
354
354
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
if not keep_local_model_copy:
|
|
365
|
-
full_model_path.unlink()
|
|
366
|
-
structlogger.info(
|
|
367
|
-
"model_training.train.finished_training",
|
|
368
|
-
event_info=(
|
|
369
|
-
f"Your Rasa model {model_name} is trained "
|
|
370
|
-
f"and saved at remote storage provider '{remote_storage}'."
|
|
371
|
-
),
|
|
372
|
-
)
|
|
373
|
-
else:
|
|
374
|
-
structlogger.info(
|
|
375
|
-
"model_training.train.finished_training",
|
|
376
|
-
event_info=(
|
|
377
|
-
f"Your Rasa model is trained and saved at '{full_model_path}'."
|
|
378
|
-
),
|
|
355
|
+
with telemetry.track_model_training(
|
|
356
|
+
file_importer, model_type=training_type.model_type
|
|
357
|
+
):
|
|
358
|
+
await trainer.train(
|
|
359
|
+
model_configuration,
|
|
360
|
+
file_importer,
|
|
361
|
+
full_model_path,
|
|
362
|
+
force_retraining=force_full_training,
|
|
363
|
+
is_finetuning=is_finetuning,
|
|
379
364
|
)
|
|
365
|
+
if remote_storage:
|
|
366
|
+
push_model_to_remote_storage(full_model_path, remote_storage)
|
|
367
|
+
if not keep_local_model_copy:
|
|
368
|
+
full_model_path.unlink()
|
|
369
|
+
structlogger.info(
|
|
370
|
+
"model_training.train.finished_training",
|
|
371
|
+
event_info=(
|
|
372
|
+
f"Your Rasa model {model_name} is trained "
|
|
373
|
+
f"and saved at remote storage provider '{remote_storage}'."
|
|
374
|
+
),
|
|
375
|
+
)
|
|
376
|
+
else:
|
|
377
|
+
structlogger.info(
|
|
378
|
+
"model_training.train.finished_training",
|
|
379
|
+
event_info=(
|
|
380
|
+
f"Your Rasa model is trained and saved at '{full_model_path}'."
|
|
381
|
+
),
|
|
382
|
+
)
|
|
380
383
|
|
|
381
384
|
return TrainingResult(str(full_model_path), 0)
|
|
382
385
|
|
rasa/shared/core/constants.py
CHANGED
|
@@ -51,8 +51,6 @@ ACTION_TRIGGER_CHITCHAT = "action_trigger_chitchat"
|
|
|
51
51
|
ACTION_RESET_ROUTING = "action_reset_routing"
|
|
52
52
|
ACTION_HANGUP = "action_hangup"
|
|
53
53
|
ACTION_REPEAT_BOT_MESSAGES = "action_repeat_bot_messages"
|
|
54
|
-
ACTION_BLOCK_DIGRESSION = "action_block_digression"
|
|
55
|
-
ACTION_CONTINUE_DIGRESSION = "action_continue_digression"
|
|
56
54
|
|
|
57
55
|
ACTION_METADATA_EXECUTION_SUCCESS = "execution_success"
|
|
58
56
|
ACTION_METADATA_EXECUTION_ERROR_MESSAGE = "execution_error_message"
|
|
@@ -83,8 +81,6 @@ DEFAULT_ACTION_NAMES = [
|
|
|
83
81
|
ACTION_RESET_ROUTING,
|
|
84
82
|
ACTION_HANGUP,
|
|
85
83
|
ACTION_REPEAT_BOT_MESSAGES,
|
|
86
|
-
ACTION_BLOCK_DIGRESSION,
|
|
87
|
-
ACTION_CONTINUE_DIGRESSION,
|
|
88
84
|
]
|
|
89
85
|
|
|
90
86
|
ACTION_SHOULD_SEND_DOMAIN = "send_domain"
|
|
@@ -141,10 +137,7 @@ DEFAULT_SLOT_NAMES = {
|
|
|
141
137
|
|
|
142
138
|
SLOT_MAPPINGS = "mappings"
|
|
143
139
|
MAPPING_CONDITIONS = "conditions"
|
|
144
|
-
|
|
145
|
-
KEY_ALLOW_NLU_CORRECTION = "allow_nlu_correction"
|
|
146
|
-
KEY_ACTION = "action"
|
|
147
|
-
KEY_RUN_ACTION_EVERY_TURN = "run_action_every_turn"
|
|
140
|
+
MAPPING_TYPE = "type"
|
|
148
141
|
|
|
149
142
|
|
|
150
143
|
class SlotMappingType(Enum):
|
|
@@ -155,7 +148,7 @@ class SlotMappingType(Enum):
|
|
|
155
148
|
FROM_TRIGGER_INTENT = "from_trigger_intent"
|
|
156
149
|
FROM_TEXT = "from_text"
|
|
157
150
|
FROM_LLM = "from_llm"
|
|
158
|
-
|
|
151
|
+
CUSTOM = "custom"
|
|
159
152
|
|
|
160
153
|
def __str__(self) -> str:
|
|
161
154
|
"""Returns the string representation that should be used in config files."""
|
|
@@ -163,21 +156,7 @@ class SlotMappingType(Enum):
|
|
|
163
156
|
|
|
164
157
|
def is_predefined_type(self) -> bool:
|
|
165
158
|
"""Returns True if the mapping type is NLU-predefined."""
|
|
166
|
-
return not (
|
|
167
|
-
self == SlotMappingType.CONTROLLED or self == SlotMappingType.FROM_LLM
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
class SetSlotExtractor(Enum):
|
|
172
|
-
"""The extractors that can set a slot."""
|
|
173
|
-
|
|
174
|
-
LLM = "LLM"
|
|
175
|
-
COMMAND_PAYLOAD_READER = "CommandPayloadReader"
|
|
176
|
-
NLU = "NLU"
|
|
177
|
-
CUSTOM = "CUSTOM"
|
|
178
|
-
|
|
179
|
-
def __str__(self) -> str:
|
|
180
|
-
return self.value
|
|
159
|
+
return not (self == SlotMappingType.CUSTOM or self == SlotMappingType.FROM_LLM)
|
|
181
160
|
|
|
182
161
|
|
|
183
162
|
# the keys for `State` (USER, PREVIOUS_ACTION, SLOTS, ACTIVE_LOOP)
|
|
@@ -202,7 +181,3 @@ POLICY_NAME_RULE = "RulePolicy"
|
|
|
202
181
|
CLASSIFIER_NAME_FALLBACK = "FallbackClassifier"
|
|
203
182
|
|
|
204
183
|
POLICIES_THAT_EXTRACT_ENTITIES = {"TEDPolicy"}
|
|
205
|
-
|
|
206
|
-
# digression constants
|
|
207
|
-
KEY_ASK_CONFIRM_DIGRESSIONS = "ask_confirm_digressions"
|
|
208
|
-
KEY_BLOCK_DIGRESSIONS = "block_digressions"
|
rasa/shared/core/domain.py
CHANGED
|
@@ -46,8 +46,10 @@ from rasa.shared.constants import (
|
|
|
46
46
|
)
|
|
47
47
|
from rasa.shared.core.constants import (
|
|
48
48
|
ACTION_SHOULD_SEND_DOMAIN,
|
|
49
|
-
|
|
49
|
+
ACTIVE_LOOP,
|
|
50
50
|
KNOWLEDGE_BASE_SLOT_NAMES,
|
|
51
|
+
MAPPING_CONDITIONS,
|
|
52
|
+
MAPPING_TYPE,
|
|
51
53
|
SLOT_MAPPINGS,
|
|
52
54
|
SlotMappingType,
|
|
53
55
|
)
|
|
@@ -288,6 +290,8 @@ class Domain:
|
|
|
288
290
|
responses = data.get(KEY_RESPONSES, {})
|
|
289
291
|
|
|
290
292
|
domain_slots = data.get(KEY_SLOTS, {})
|
|
293
|
+
if domain_slots:
|
|
294
|
+
rasa.shared.core.slot_mappings.validate_slot_mappings(domain_slots)
|
|
291
295
|
slots = cls.collect_slots(domain_slots)
|
|
292
296
|
domain_actions = data.get(KEY_ACTIONS, [])
|
|
293
297
|
actions = cls._collect_action_names(domain_actions)
|
|
@@ -592,7 +596,7 @@ class Domain:
|
|
|
592
596
|
),
|
|
593
597
|
)
|
|
594
598
|
slot_dict[slot_name][SLOT_MAPPINGS] = [
|
|
595
|
-
{
|
|
599
|
+
{MAPPING_TYPE: SlotMappingType.FROM_LLM.value}
|
|
596
600
|
]
|
|
597
601
|
|
|
598
602
|
slot = slot_class(slot_name, **slot_dict[slot_name])
|
|
@@ -1565,18 +1569,21 @@ class Domain:
|
|
|
1565
1569
|
matching_entities = []
|
|
1566
1570
|
|
|
1567
1571
|
for mapping in slot.mappings:
|
|
1568
|
-
mapping_conditions = mapping.
|
|
1569
|
-
if mapping
|
|
1572
|
+
mapping_conditions = mapping.get(MAPPING_CONDITIONS)
|
|
1573
|
+
if mapping[MAPPING_TYPE] != str(SlotMappingType.FROM_ENTITY) or (
|
|
1570
1574
|
mapping_conditions
|
|
1571
|
-
and mapping_conditions[0].
|
|
1575
|
+
and mapping_conditions[0].get(ACTIVE_LOOP) is not None
|
|
1572
1576
|
):
|
|
1573
1577
|
continue
|
|
1574
1578
|
|
|
1575
1579
|
for entity in entities:
|
|
1576
1580
|
if (
|
|
1577
|
-
entity.get(ENTITY_ATTRIBUTE_TYPE)
|
|
1578
|
-
|
|
1579
|
-
and entity.get(
|
|
1581
|
+
entity.get(ENTITY_ATTRIBUTE_TYPE)
|
|
1582
|
+
== mapping.get(ENTITY_ATTRIBUTE_TYPE)
|
|
1583
|
+
and entity.get(ENTITY_ATTRIBUTE_ROLE)
|
|
1584
|
+
== mapping.get(ENTITY_ATTRIBUTE_ROLE)
|
|
1585
|
+
and entity.get(ENTITY_ATTRIBUTE_GROUP)
|
|
1586
|
+
== mapping.get(ENTITY_ATTRIBUTE_GROUP)
|
|
1580
1587
|
):
|
|
1581
1588
|
matching_entities.append(entity.get("value"))
|
|
1582
1589
|
|
|
@@ -2008,19 +2015,19 @@ class Domain:
|
|
|
2008
2015
|
is the total number of mappings which have conditions attached.
|
|
2009
2016
|
"""
|
|
2010
2017
|
total_mappings = 0
|
|
2011
|
-
|
|
2018
|
+
custom_mappings = 0
|
|
2012
2019
|
conditional_mappings = 0
|
|
2013
2020
|
|
|
2014
2021
|
for slot in self.slots:
|
|
2015
2022
|
total_mappings += len(slot.mappings)
|
|
2016
2023
|
for mapping in slot.mappings:
|
|
2017
|
-
if mapping
|
|
2018
|
-
|
|
2024
|
+
if mapping[MAPPING_TYPE] == str(SlotMappingType.CUSTOM):
|
|
2025
|
+
custom_mappings += 1
|
|
2019
2026
|
|
|
2020
|
-
if mapping
|
|
2027
|
+
if MAPPING_CONDITIONS in mapping:
|
|
2021
2028
|
conditional_mappings += 1
|
|
2022
2029
|
|
|
2023
|
-
return total_mappings,
|
|
2030
|
+
return (total_mappings, custom_mappings, conditional_mappings)
|
|
2024
2031
|
|
|
2025
2032
|
def does_custom_action_explicitly_need_domain(self, action_name: Text) -> bool:
|
|
2026
2033
|
"""Assert if action has explicitly stated that it needs domain.
|