rasa-pro 3.12.0.dev12__py3-none-any.whl → 3.12.0rc1__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/anonymization/anonymization_rule_executor.py +16 -10
- rasa/cli/data.py +16 -0
- rasa/cli/inspect.py +20 -1
- rasa/cli/project_templates/calm/config.yml +2 -2
- rasa/cli/project_templates/calm/endpoints.yml +2 -2
- rasa/cli/shell.py +3 -3
- rasa/cli/utils.py +12 -0
- rasa/core/actions/action.py +99 -193
- rasa/core/actions/action_handle_digressions.py +142 -0
- rasa/core/actions/action_run_slot_rejections.py +16 -4
- rasa/core/actions/forms.py +10 -5
- rasa/core/channels/__init__.py +4 -0
- rasa/core/channels/studio_chat.py +19 -0
- rasa/core/channels/telegram.py +42 -24
- rasa/core/channels/voice_ready/audiocodes.py +42 -23
- rasa/core/channels/voice_ready/utils.py +1 -1
- rasa/core/channels/voice_stream/asr/asr_engine.py +10 -4
- rasa/core/channels/voice_stream/asr/azure.py +14 -1
- rasa/core/channels/voice_stream/asr/deepgram.py +20 -4
- rasa/core/channels/voice_stream/audiocodes.py +264 -0
- rasa/core/channels/voice_stream/browser_audio.py +5 -1
- rasa/core/channels/voice_stream/call_state.py +10 -1
- rasa/core/channels/voice_stream/genesys.py +335 -0
- rasa/core/channels/voice_stream/tts/azure.py +11 -2
- rasa/core/channels/voice_stream/tts/cartesia.py +29 -10
- rasa/core/channels/voice_stream/twilio_media_streams.py +2 -1
- rasa/core/channels/voice_stream/voice_channel.py +25 -3
- rasa/core/constants.py +2 -0
- rasa/core/migrate.py +2 -2
- rasa/core/nlg/contextual_response_rephraser.py +18 -1
- rasa/core/nlg/generator.py +83 -15
- rasa/core/nlg/response.py +6 -3
- rasa/core/nlg/translate.py +55 -0
- rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +1 -1
- rasa/core/policies/flows/flow_executor.py +47 -46
- rasa/core/processor.py +72 -9
- rasa/core/run.py +4 -3
- rasa/dialogue_understanding/commands/can_not_handle_command.py +20 -2
- rasa/dialogue_understanding/commands/cancel_flow_command.py +80 -4
- rasa/dialogue_understanding/commands/change_flow_command.py +20 -2
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +20 -2
- rasa/dialogue_understanding/commands/clarify_command.py +29 -3
- rasa/dialogue_understanding/commands/command.py +1 -16
- rasa/dialogue_understanding/commands/command_syntax_manager.py +55 -0
- rasa/dialogue_understanding/commands/correct_slots_command.py +11 -2
- rasa/dialogue_understanding/commands/handle_digressions_command.py +150 -0
- rasa/dialogue_understanding/commands/human_handoff_command.py +20 -2
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +20 -2
- rasa/dialogue_understanding/commands/prompt_command.py +94 -0
- rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +20 -2
- rasa/dialogue_understanding/commands/set_slot_command.py +29 -15
- rasa/dialogue_understanding/commands/skip_question_command.py +20 -2
- rasa/dialogue_understanding/commands/start_flow_command.py +61 -2
- rasa/dialogue_understanding/commands/utils.py +98 -4
- rasa/dialogue_understanding/constants.py +1 -0
- rasa/dialogue_understanding/generator/__init__.py +2 -0
- rasa/dialogue_understanding/generator/command_generator.py +110 -73
- rasa/dialogue_understanding/generator/command_parser.py +16 -13
- rasa/dialogue_understanding/generator/constants.py +3 -0
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +170 -5
- rasa/dialogue_understanding/generator/llm_command_generator.py +5 -3
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +26 -4
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +44 -3
- rasa/dialogue_understanding/generator/prompt_templates/__init__.py +0 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_template.jinja2 +60 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +77 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_default.jinja2 +68 -0
- rasa/dialogue_understanding/generator/{single_step/command_prompt_template.jinja2 → prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2} +1 -1
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +460 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +12 -318
- rasa/dialogue_understanding/generator/utils.py +32 -1
- rasa/dialogue_understanding/patterns/collect_information.py +1 -1
- rasa/dialogue_understanding/patterns/correction.py +13 -1
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +78 -2
- rasa/dialogue_understanding/patterns/handle_digressions.py +81 -0
- rasa/dialogue_understanding/patterns/validate_slot.py +65 -0
- rasa/dialogue_understanding/processor/command_processor.py +154 -28
- rasa/dialogue_understanding/utils.py +31 -0
- rasa/dialogue_understanding_test/README.md +50 -0
- rasa/dialogue_understanding_test/du_test_case.py +28 -8
- rasa/dialogue_understanding_test/du_test_result.py +13 -9
- rasa/dialogue_understanding_test/io.py +14 -0
- rasa/dialogue_understanding_test/test_case_simulation/test_case_tracker_simulator.py +3 -3
- rasa/e2e_test/utils/io.py +0 -37
- rasa/engine/graph.py +1 -0
- rasa/engine/language.py +140 -0
- rasa/engine/recipes/config_files/default_config.yml +4 -0
- rasa/engine/recipes/default_recipe.py +2 -0
- rasa/engine/recipes/graph_recipe.py +2 -0
- rasa/engine/storage/local_model_storage.py +1 -0
- rasa/engine/storage/storage.py +4 -1
- rasa/model_manager/runner_service.py +7 -4
- rasa/model_manager/socket_bridge.py +7 -6
- rasa/model_manager/warm_rasa_process.py +0 -1
- rasa/model_training.py +24 -27
- rasa/shared/constants.py +15 -13
- rasa/shared/core/constants.py +30 -3
- rasa/shared/core/domain.py +13 -20
- rasa/shared/core/events.py +13 -2
- rasa/shared/core/flows/constants.py +11 -0
- rasa/shared/core/flows/flow.py +100 -19
- rasa/shared/core/flows/flows_yaml_schema.json +69 -3
- rasa/shared/core/flows/steps/collect.py +19 -37
- rasa/shared/core/flows/utils.py +43 -4
- rasa/shared/core/flows/validation.py +1 -1
- rasa/shared/core/slot_mappings.py +350 -111
- rasa/shared/core/slots.py +154 -3
- rasa/shared/core/trackers.py +77 -2
- rasa/shared/importers/importer.py +50 -2
- rasa/shared/nlu/constants.py +1 -0
- rasa/shared/nlu/training_data/schemas/responses.yml +19 -12
- rasa/shared/providers/_configs/azure_entra_id_config.py +541 -0
- rasa/shared/providers/_configs/azure_openai_client_config.py +138 -3
- rasa/shared/providers/_configs/client_config.py +3 -1
- rasa/shared/providers/_configs/default_litellm_client_config.py +3 -1
- rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +3 -1
- rasa/shared/providers/_configs/litellm_router_client_config.py +3 -1
- rasa/shared/providers/_configs/model_group_config.py +4 -2
- rasa/shared/providers/_configs/oauth_config.py +33 -0
- rasa/shared/providers/_configs/openai_client_config.py +3 -1
- rasa/shared/providers/_configs/rasa_llm_client_config.py +3 -1
- rasa/shared/providers/_configs/self_hosted_llm_client_config.py +3 -1
- rasa/shared/providers/constants.py +6 -0
- rasa/shared/providers/embedding/azure_openai_embedding_client.py +28 -3
- rasa/shared/providers/embedding/litellm_router_embedding_client.py +3 -1
- rasa/shared/providers/llm/_base_litellm_client.py +42 -17
- rasa/shared/providers/llm/azure_openai_llm_client.py +81 -25
- rasa/shared/providers/llm/default_litellm_llm_client.py +3 -1
- rasa/shared/providers/llm/litellm_router_llm_client.py +29 -8
- rasa/shared/providers/llm/llm_client.py +23 -7
- rasa/shared/providers/llm/openai_llm_client.py +9 -3
- rasa/shared/providers/llm/rasa_llm_client.py +11 -2
- rasa/shared/providers/llm/self_hosted_llm_client.py +30 -11
- rasa/shared/providers/router/_base_litellm_router_client.py +3 -1
- rasa/shared/providers/router/router_client.py +3 -1
- rasa/shared/utils/constants.py +3 -0
- rasa/shared/utils/llm.py +31 -8
- rasa/shared/utils/pykwalify_extensions.py +24 -0
- rasa/shared/utils/schemas/domain.yml +26 -1
- rasa/telemetry.py +45 -14
- rasa/tracing/config.py +2 -0
- rasa/tracing/constants.py +12 -0
- rasa/tracing/instrumentation/instrumentation.py +36 -0
- rasa/tracing/instrumentation/metrics.py +41 -0
- rasa/tracing/metric_instrument_provider.py +40 -0
- rasa/utils/common.py +0 -1
- rasa/validator.py +561 -89
- rasa/version.py +1 -1
- {rasa_pro-3.12.0.dev12.dist-info → rasa_pro-3.12.0rc1.dist-info}/METADATA +2 -1
- {rasa_pro-3.12.0.dev12.dist-info → rasa_pro-3.12.0rc1.dist-info}/RECORD +153 -134
- {rasa_pro-3.12.0.dev12.dist-info → rasa_pro-3.12.0rc1.dist-info}/NOTICE +0 -0
- {rasa_pro-3.12.0.dev12.dist-info → rasa_pro-3.12.0rc1.dist-info}/WHEEL +0 -0
- {rasa_pro-3.12.0.dev12.dist-info → rasa_pro-3.12.0rc1.dist-info}/entry_points.txt +0 -0
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING, List, Optional, Union
|
|
1
|
+
from typing import TYPE_CHECKING, Any, List, Optional, Tuple, Union
|
|
2
2
|
|
|
3
3
|
import structlog
|
|
4
4
|
|
|
5
|
+
from rasa.dialogue_understanding.patterns.validate_slot import (
|
|
6
|
+
ValidateSlotPatternFlowStackFrame,
|
|
7
|
+
)
|
|
8
|
+
from rasa.shared.constants import (
|
|
9
|
+
ACTION_ASK_PREFIX,
|
|
10
|
+
UTTER_ASK_PREFIX,
|
|
11
|
+
)
|
|
12
|
+
from rasa.shared.core.events import Event, SlotSet
|
|
13
|
+
from rasa.shared.core.slots import Slot
|
|
14
|
+
from rasa.shared.core.trackers import DialogueStateTracker
|
|
15
|
+
|
|
5
16
|
if TYPE_CHECKING:
|
|
6
17
|
from rasa.dialogue_understanding.commands import StartFlowCommand
|
|
7
18
|
from rasa.shared.core.flows import FlowsList
|
|
@@ -25,10 +36,13 @@ def start_flow_by_name(
|
|
|
25
36
|
|
|
26
37
|
def extract_cleaned_options(options_str: str) -> List[str]:
|
|
27
38
|
"""Extract and clean options from a string."""
|
|
39
|
+
delimiters = [",", " "]
|
|
40
|
+
|
|
41
|
+
for delimiter in delimiters:
|
|
42
|
+
options_str = options_str.replace(delimiter, " ")
|
|
43
|
+
|
|
28
44
|
return sorted(
|
|
29
|
-
opt.strip().strip('"').strip("'")
|
|
30
|
-
for opt in options_str.split(" ")
|
|
31
|
-
if opt.strip()
|
|
45
|
+
opt.strip().strip('"').strip("'") for opt in options_str.split() if opt.strip()
|
|
32
46
|
)
|
|
33
47
|
|
|
34
48
|
|
|
@@ -62,3 +76,83 @@ def get_nullable_slot_value(slot_value: str) -> Union[str, None]:
|
|
|
62
76
|
The slot value or None if the value is a none value.
|
|
63
77
|
"""
|
|
64
78
|
return slot_value if not is_none_value(slot_value) else None
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def initialize_pattern_validate_slot(
|
|
82
|
+
slot: Slot,
|
|
83
|
+
) -> Optional[ValidateSlotPatternFlowStackFrame]:
|
|
84
|
+
"""Initialize the pattern to validate a slot value."""
|
|
85
|
+
if not slot.requires_validation():
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
validation = slot.validation
|
|
89
|
+
slot_name = slot.name
|
|
90
|
+
return ValidateSlotPatternFlowStackFrame(
|
|
91
|
+
validate=slot_name,
|
|
92
|
+
refill_utter=validation.refill_utter or f"{UTTER_ASK_PREFIX}{slot_name}", # type: ignore[union-attr]
|
|
93
|
+
refill_action=f"{ACTION_ASK_PREFIX}{slot_name}",
|
|
94
|
+
rejections=validation.rejections, # type: ignore[union-attr]
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def create_validate_frames_from_slot_set_events(
|
|
99
|
+
tracker: DialogueStateTracker,
|
|
100
|
+
events: List[Event],
|
|
101
|
+
validate_frames: List[ValidateSlotPatternFlowStackFrame] = [],
|
|
102
|
+
should_break: bool = False,
|
|
103
|
+
update_corrected_slots: bool = False,
|
|
104
|
+
) -> Tuple[DialogueStateTracker, List[ValidateSlotPatternFlowStackFrame]]:
|
|
105
|
+
"""Process SlotSet events and create validation frames.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
tracker: The dialogue state tracker.
|
|
109
|
+
events: List of events to process.
|
|
110
|
+
should_break: whether or not to break after the first non-SlotSet event.
|
|
111
|
+
if True, break out of the event loop as soon as the first non-SlotSet
|
|
112
|
+
event is encountered.
|
|
113
|
+
if False, continue processing the events until the end.
|
|
114
|
+
update_corrected_slots: whether or not corrected slots in the last
|
|
115
|
+
correction frame need to be updated.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
Tuple of (updated tracker, list of validation frames).
|
|
119
|
+
"""
|
|
120
|
+
for event in events:
|
|
121
|
+
if not isinstance(event, SlotSet):
|
|
122
|
+
if should_break:
|
|
123
|
+
# we want to only process the most recent SlotSet events
|
|
124
|
+
# so we break once we encounter a different event
|
|
125
|
+
break
|
|
126
|
+
continue
|
|
127
|
+
|
|
128
|
+
slot = tracker.slots.get(event.key)
|
|
129
|
+
frame = initialize_pattern_validate_slot(slot)
|
|
130
|
+
|
|
131
|
+
if frame:
|
|
132
|
+
validate_frames.append(frame)
|
|
133
|
+
if update_corrected_slots:
|
|
134
|
+
tracker = update_corrected_slots_in_correction_frame(
|
|
135
|
+
tracker, event.key, event.value
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
return tracker, validate_frames
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def update_corrected_slots_in_correction_frame(
|
|
142
|
+
tracker: DialogueStateTracker, slot_name: str, slot_value: Any
|
|
143
|
+
) -> DialogueStateTracker:
|
|
144
|
+
"""Update the corrected_slots and new_slot_values of the
|
|
145
|
+
CorrectionPatternFlowStackFrame with only valid values.
|
|
146
|
+
"""
|
|
147
|
+
stack = tracker.stack
|
|
148
|
+
top_frame = stack.top()
|
|
149
|
+
del top_frame.corrected_slots[slot_name] # type: ignore[union-attr]
|
|
150
|
+
top_frame.new_slot_values.remove(slot_value) # type: ignore[union-attr]
|
|
151
|
+
|
|
152
|
+
# since we can't directly modify a stack we have to pop first
|
|
153
|
+
# and then push back the updated frame
|
|
154
|
+
stack.pop()
|
|
155
|
+
stack.push(top_frame)
|
|
156
|
+
new_events = tracker.create_stack_updated_events(stack)
|
|
157
|
+
tracker.update_with_events(new_events)
|
|
158
|
+
return tracker
|
|
@@ -9,6 +9,7 @@ from rasa.dialogue_understanding.generator.multi_step.multi_step_llm_command_gen
|
|
|
9
9
|
MultiStepLLMCommandGenerator,
|
|
10
10
|
)
|
|
11
11
|
from rasa.dialogue_understanding.generator.single_step.single_step_llm_command_generator import ( # noqa: E501
|
|
12
|
+
CompactLLMCommandGenerator,
|
|
12
13
|
SingleStepLLMCommandGenerator,
|
|
13
14
|
)
|
|
14
15
|
|
|
@@ -18,4 +19,5 @@ __all__ = [
|
|
|
18
19
|
"LLMCommandGenerator",
|
|
19
20
|
"MultiStepLLMCommandGenerator",
|
|
20
21
|
"SingleStepLLMCommandGenerator",
|
|
22
|
+
"CompactLLMCommandGenerator",
|
|
21
23
|
]
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
-
from typing import Any, Dict, List, Optional, Text
|
|
2
|
+
from typing import Any, Dict, List, Optional, Set, Text, Tuple
|
|
3
3
|
|
|
4
4
|
import structlog
|
|
5
5
|
|
|
6
6
|
from rasa.dialogue_understanding.commands import (
|
|
7
7
|
Command,
|
|
8
|
+
CorrectSlotsCommand,
|
|
8
9
|
ErrorCommand,
|
|
9
10
|
SetSlotCommand,
|
|
10
11
|
StartFlowCommand,
|
|
11
12
|
)
|
|
12
|
-
from rasa.dialogue_understanding.
|
|
13
|
+
from rasa.dialogue_understanding.utils import (
|
|
14
|
+
_handle_via_nlu_in_coexistence,
|
|
15
|
+
)
|
|
13
16
|
from rasa.shared.constants import (
|
|
14
17
|
RASA_PATTERN_INTERNAL_ERROR_USER_INPUT_EMPTY,
|
|
15
18
|
RASA_PATTERN_INTERNAL_ERROR_USER_INPUT_TOO_LONG,
|
|
16
19
|
)
|
|
17
|
-
from rasa.shared.core.constants import SlotMappingType
|
|
18
20
|
from rasa.shared.core.domain import Domain
|
|
19
21
|
from rasa.shared.core.flows import FlowsList
|
|
20
|
-
from rasa.shared.core.slot_mappings import SlotFillingManager
|
|
21
22
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
22
23
|
from rasa.shared.nlu.constants import (
|
|
23
24
|
COMMANDS,
|
|
@@ -92,9 +93,9 @@ class CommandGenerator:
|
|
|
92
93
|
)
|
|
93
94
|
|
|
94
95
|
for message in messages:
|
|
95
|
-
if message
|
|
96
|
-
#
|
|
97
|
-
#
|
|
96
|
+
if _handle_via_nlu_in_coexistence(tracker, message):
|
|
97
|
+
# Skip running the CALM pipeline if the message should
|
|
98
|
+
# be handled by the NLU-based system in a coexistence mode.
|
|
98
99
|
continue
|
|
99
100
|
|
|
100
101
|
commands = await self._evaluate_and_predict(
|
|
@@ -106,9 +107,6 @@ class CommandGenerator:
|
|
|
106
107
|
commands = self._check_commands_against_startable_flows(
|
|
107
108
|
commands, startable_flows
|
|
108
109
|
)
|
|
109
|
-
commands = self._check_commands_against_slot_mappings(
|
|
110
|
-
commands, tracker, domain
|
|
111
|
-
)
|
|
112
110
|
commands_dicts = [command.as_dict() for command in commands]
|
|
113
111
|
message.set(COMMANDS, commands_dicts, add_to_output=True)
|
|
114
112
|
|
|
@@ -202,6 +200,94 @@ class CommandGenerator:
|
|
|
202
200
|
"""
|
|
203
201
|
raise NotImplementedError()
|
|
204
202
|
|
|
203
|
+
def _check_commands_overlap(
|
|
204
|
+
self, prior_commands: List[Command], commands: List[Command]
|
|
205
|
+
) -> List[Command]:
|
|
206
|
+
"""Check if there is overlap between the prior commands and the current ones.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
prior_commands: The prior commands.
|
|
210
|
+
commands: The commands to check.
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
The final commands.
|
|
214
|
+
"""
|
|
215
|
+
if not prior_commands:
|
|
216
|
+
return commands
|
|
217
|
+
|
|
218
|
+
prior_commands, commands = self._check_slot_command_overlap(
|
|
219
|
+
prior_commands, commands
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
prior_start_flow_names = {
|
|
223
|
+
command.flow
|
|
224
|
+
for command in prior_commands
|
|
225
|
+
if isinstance(command, StartFlowCommand)
|
|
226
|
+
}
|
|
227
|
+
current_start_flow_names = {
|
|
228
|
+
command.flow
|
|
229
|
+
for command in commands
|
|
230
|
+
if isinstance(command, StartFlowCommand)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return self._check_start_flow_command_overlap(
|
|
234
|
+
prior_commands,
|
|
235
|
+
commands,
|
|
236
|
+
prior_start_flow_names,
|
|
237
|
+
current_start_flow_names,
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
def _check_start_flow_command_overlap(
|
|
241
|
+
self,
|
|
242
|
+
prior_commands: List[Command],
|
|
243
|
+
commands: List[Command],
|
|
244
|
+
prior_start_flow_names: Set[str],
|
|
245
|
+
current_start_flow_names: Set[str],
|
|
246
|
+
) -> List[Command]:
|
|
247
|
+
"""Get the final commands.
|
|
248
|
+
|
|
249
|
+
Args:
|
|
250
|
+
prior_commands: The prior commands.
|
|
251
|
+
commands: The currently predicted commands to check.
|
|
252
|
+
prior_start_flow_names: The names of the flows from the prior commands.
|
|
253
|
+
current_start_flow_names: The names of the flows from the current commands.
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
The final commands.
|
|
257
|
+
"""
|
|
258
|
+
raise NotImplementedError()
|
|
259
|
+
|
|
260
|
+
def _check_slot_command_overlap(
|
|
261
|
+
self,
|
|
262
|
+
prior_commands: List[Command],
|
|
263
|
+
commands: List[Command],
|
|
264
|
+
) -> Tuple[List[Command], List[Command]]:
|
|
265
|
+
"""Check if the current commands overlap with the prior commands."""
|
|
266
|
+
prior_slot_names = gather_slot_names(prior_commands)
|
|
267
|
+
current_slot_names = gather_slot_names(commands)
|
|
268
|
+
overlapping_slot_names = prior_slot_names.intersection(current_slot_names)
|
|
269
|
+
|
|
270
|
+
structlogger.debug(
|
|
271
|
+
"command_generator.check_slot_command_overlap",
|
|
272
|
+
overlapping_slot_names=overlapping_slot_names,
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
if not overlapping_slot_names:
|
|
276
|
+
return prior_commands, commands
|
|
277
|
+
|
|
278
|
+
return self._filter_slot_commands(
|
|
279
|
+
prior_commands, commands, overlapping_slot_names
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
def _filter_slot_commands(
|
|
283
|
+
self,
|
|
284
|
+
prior_commands: List[Command],
|
|
285
|
+
commands: List[Command],
|
|
286
|
+
overlapping_slot_names: Set[str],
|
|
287
|
+
) -> Tuple[List[Command], List[Command]]:
|
|
288
|
+
"""Filter out the overlapping slot commands."""
|
|
289
|
+
raise NotImplementedError()
|
|
290
|
+
|
|
205
291
|
def _check_commands_against_startable_flows(
|
|
206
292
|
self, commands: List[Command], startable_flows: FlowsList
|
|
207
293
|
) -> List[Command]:
|
|
@@ -278,70 +364,21 @@ class CommandGenerator:
|
|
|
278
364
|
return len(message.get(TEXT, "").strip()) == 0
|
|
279
365
|
|
|
280
366
|
@staticmethod
|
|
281
|
-
def
|
|
282
|
-
commands
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
) -> List[Command]:
|
|
286
|
-
"""Check if the LLM-issued slot commands are fillable.
|
|
287
|
-
|
|
288
|
-
The LLM-issued slot commands are fillable if the slot
|
|
289
|
-
mappings are satisfied.
|
|
290
|
-
"""
|
|
291
|
-
if not domain:
|
|
292
|
-
return commands
|
|
293
|
-
|
|
294
|
-
llm_fillable_slot_names = [
|
|
295
|
-
command.name
|
|
296
|
-
for command in commands
|
|
297
|
-
if isinstance(command, SetSlotCommand)
|
|
298
|
-
and command.extractor == SetSlotExtractor.LLM.value
|
|
299
|
-
]
|
|
300
|
-
|
|
301
|
-
if not llm_fillable_slot_names:
|
|
302
|
-
return commands
|
|
303
|
-
|
|
304
|
-
llm_fillable_slots = [
|
|
305
|
-
slot for slot in domain.slots if slot.name in llm_fillable_slot_names
|
|
367
|
+
def _get_prior_commands(message: Message) -> List[Command]:
|
|
368
|
+
"""Get the prior commands from the tracker."""
|
|
369
|
+
return [
|
|
370
|
+
Command.command_from_json(command) for command in message.get(COMMANDS, [])
|
|
306
371
|
]
|
|
307
372
|
|
|
308
|
-
slot_filling_manager = SlotFillingManager(domain, tracker)
|
|
309
|
-
slots_to_be_removed = []
|
|
310
373
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
for
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
should_fill_slot = slot_filling_manager.should_fill_slot(
|
|
322
|
-
slot.name, mapping_type, mapping
|
|
323
|
-
)
|
|
324
|
-
|
|
325
|
-
if should_fill_slot:
|
|
326
|
-
break
|
|
327
|
-
|
|
328
|
-
if not should_fill_slot:
|
|
329
|
-
structlogger.debug(
|
|
330
|
-
"command_processor.check_commands_against_slot_mappings.slot_not_fillable",
|
|
331
|
-
slot_name=slot.name,
|
|
332
|
-
)
|
|
333
|
-
slots_to_be_removed.append(slot.name)
|
|
334
|
-
|
|
335
|
-
if not slots_to_be_removed:
|
|
336
|
-
return commands
|
|
337
|
-
|
|
338
|
-
filtered_commands = [
|
|
339
|
-
command
|
|
340
|
-
for command in commands
|
|
341
|
-
if not (
|
|
342
|
-
isinstance(command, SetSlotCommand)
|
|
343
|
-
and command.name in slots_to_be_removed
|
|
344
|
-
)
|
|
345
|
-
]
|
|
374
|
+
def gather_slot_names(commands: List[Command]) -> Set[str]:
|
|
375
|
+
"""Gather all slot names from the commands."""
|
|
376
|
+
slot_names = set()
|
|
377
|
+
for command in commands:
|
|
378
|
+
if isinstance(command, SetSlotCommand):
|
|
379
|
+
slot_names.add(command.name)
|
|
380
|
+
if isinstance(command, CorrectSlotsCommand):
|
|
381
|
+
for slot in command.corrected_slots:
|
|
382
|
+
slot_names.add(slot.name)
|
|
346
383
|
|
|
347
|
-
|
|
384
|
+
return slot_names
|
|
@@ -16,6 +16,7 @@ from rasa.dialogue_understanding.commands import (
|
|
|
16
16
|
SkipQuestionCommand,
|
|
17
17
|
StartFlowCommand,
|
|
18
18
|
)
|
|
19
|
+
from rasa.dialogue_understanding.commands.prompt_command import PromptCommand
|
|
19
20
|
from rasa.dialogue_understanding.commands.utils import start_flow_by_name
|
|
20
21
|
from rasa.shared.core.flows import FlowsList
|
|
21
22
|
|
|
@@ -41,8 +42,8 @@ def _get_compiled_pattern(pattern_str: str) -> re.Pattern:
|
|
|
41
42
|
|
|
42
43
|
|
|
43
44
|
def _create_default_commands(
|
|
44
|
-
default_commands_to_remove: Union[List[Type[
|
|
45
|
-
) -> List[Type[
|
|
45
|
+
default_commands_to_remove: Union[List[Type[PromptCommand]], List[str]],
|
|
46
|
+
) -> List[Type[PromptCommand]]:
|
|
46
47
|
"""Return an updated list of default commands after removing the provided commands.
|
|
47
48
|
|
|
48
49
|
Args:
|
|
@@ -64,11 +65,11 @@ def _create_default_commands(
|
|
|
64
65
|
|
|
65
66
|
|
|
66
67
|
def _get_additional_parsing_logic(
|
|
67
|
-
command_clz: Type[
|
|
68
|
-
) -> Optional[Callable[[
|
|
68
|
+
command_clz: Type[PromptCommand],
|
|
69
|
+
) -> Optional[Callable[[PromptCommand, FlowsList], Optional[PromptCommand]]]:
|
|
69
70
|
"""Get additional parsing logic for a command."""
|
|
70
71
|
command_to_parsing_fn_mapper: Dict[
|
|
71
|
-
Type[
|
|
72
|
+
Type[PromptCommand], Callable[..., Optional[PromptCommand]]
|
|
72
73
|
] = {
|
|
73
74
|
ClarifyCommand: _parse_clarify_command,
|
|
74
75
|
SetSlotCommand: _parse_set_slot_command,
|
|
@@ -81,8 +82,10 @@ def parse_commands(
|
|
|
81
82
|
actions: Optional[str],
|
|
82
83
|
flows: FlowsList,
|
|
83
84
|
is_handle_flows_prompt: bool = False,
|
|
84
|
-
additional_commands: Optional[List[Type[
|
|
85
|
-
default_commands_to_remove: Optional[
|
|
85
|
+
additional_commands: Optional[List[Type[PromptCommand]]] = None,
|
|
86
|
+
default_commands_to_remove: Optional[
|
|
87
|
+
Union[List[Type[PromptCommand]], List[str]]
|
|
88
|
+
] = None,
|
|
86
89
|
**kwargs: Any,
|
|
87
90
|
) -> List[Command]:
|
|
88
91
|
"""Parse a list of action commands."""
|
|
@@ -116,7 +119,7 @@ def parse_commands(
|
|
|
116
119
|
|
|
117
120
|
|
|
118
121
|
def _parse_standard_commands(
|
|
119
|
-
standard_commands: List[Type[
|
|
122
|
+
standard_commands: List[Type[PromptCommand]],
|
|
120
123
|
action: str,
|
|
121
124
|
flows: FlowsList,
|
|
122
125
|
**kwargs: Any,
|
|
@@ -125,7 +128,7 @@ def _parse_standard_commands(
|
|
|
125
128
|
commands: List[Command] = []
|
|
126
129
|
for command_clz in standard_commands:
|
|
127
130
|
pattern = _get_compiled_pattern(command_clz.regex_pattern())
|
|
128
|
-
if match := pattern.search(action
|
|
131
|
+
if match := pattern.search(action):
|
|
129
132
|
parsed_command = command_clz.from_dsl(match, **kwargs)
|
|
130
133
|
if _additional_parsing_fn := _get_additional_parsing_logic(command_clz):
|
|
131
134
|
parsed_command = _additional_parsing_fn(parsed_command, flows, **kwargs)
|
|
@@ -135,7 +138,7 @@ def _parse_standard_commands(
|
|
|
135
138
|
|
|
136
139
|
|
|
137
140
|
def _parse_custom_commands(
|
|
138
|
-
custom_commands: List[Type[
|
|
141
|
+
custom_commands: List[Type[PromptCommand]],
|
|
139
142
|
action: str,
|
|
140
143
|
flows: FlowsList,
|
|
141
144
|
**kwargs: Any,
|
|
@@ -152,7 +155,7 @@ def _parse_custom_commands(
|
|
|
152
155
|
|
|
153
156
|
def _parse_set_slot_command(
|
|
154
157
|
parsed_command: Optional[SetSlotCommand], flows: FlowsList, **kwargs: Any
|
|
155
|
-
) -> Optional[
|
|
158
|
+
) -> Optional[PromptCommand]:
|
|
156
159
|
"""Additional parsing logic for the SetSlotCommand."""
|
|
157
160
|
if not parsed_command:
|
|
158
161
|
return None
|
|
@@ -164,7 +167,7 @@ def _parse_set_slot_command(
|
|
|
164
167
|
|
|
165
168
|
def _parse_clarify_command(
|
|
166
169
|
parsed_command: Optional[ClarifyCommand], flows: FlowsList, **kwargs: Any
|
|
167
|
-
) -> Optional[
|
|
170
|
+
) -> Optional[PromptCommand]:
|
|
168
171
|
"""Additional parsing logic for the ClarifyCommand."""
|
|
169
172
|
if not parsed_command:
|
|
170
173
|
return None
|
|
@@ -194,7 +197,7 @@ def _parse_clarify_command(
|
|
|
194
197
|
|
|
195
198
|
def _parse_start_flow_command(
|
|
196
199
|
parsed_command: Optional[StartFlowCommand], flows: FlowsList, **kwargs: Any
|
|
197
|
-
) -> Optional[
|
|
200
|
+
) -> Optional[PromptCommand]:
|
|
198
201
|
"""Additional parsing logic for the StartFlowCommand."""
|
|
199
202
|
if not parsed_command:
|
|
200
203
|
return None
|