rasa-pro 3.12.0.dev10__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.

Files changed (55) hide show
  1. rasa/core/actions/action.py +3 -17
  2. rasa/core/actions/forms.py +2 -4
  3. rasa/core/channels/voice_ready/audiocodes.py +23 -42
  4. rasa/core/channels/voice_stream/tts/azure.py +1 -2
  5. rasa/core/migrate.py +2 -2
  6. rasa/core/policies/flows/flow_executor.py +1 -33
  7. rasa/dialogue_understanding/commands/can_not_handle_command.py +2 -2
  8. rasa/dialogue_understanding/commands/cancel_flow_command.py +4 -62
  9. rasa/dialogue_understanding/commands/change_flow_command.py +2 -2
  10. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +2 -2
  11. rasa/dialogue_understanding/commands/clarify_command.py +2 -2
  12. rasa/dialogue_understanding/commands/correct_slots_command.py +2 -11
  13. rasa/dialogue_understanding/commands/human_handoff_command.py +2 -2
  14. rasa/dialogue_understanding/commands/knowledge_answer_command.py +2 -2
  15. rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +2 -2
  16. rasa/dialogue_understanding/commands/set_slot_command.py +15 -7
  17. rasa/dialogue_understanding/commands/skip_question_command.py +2 -2
  18. rasa/dialogue_understanding/commands/start_flow_command.py +2 -43
  19. rasa/dialogue_understanding/commands/utils.py +1 -1
  20. rasa/dialogue_understanding/constants.py +0 -1
  21. rasa/dialogue_understanding/generator/command_generator.py +76 -10
  22. rasa/dialogue_understanding/generator/command_parser.py +1 -1
  23. rasa/dialogue_understanding/generator/llm_based_command_generator.py +2 -126
  24. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +2 -10
  25. rasa/dialogue_understanding/generator/nlu_command_adapter.py +2 -4
  26. rasa/dialogue_understanding/generator/single_step/command_prompt_template.jinja2 +79 -53
  27. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +19 -11
  28. rasa/dialogue_understanding/patterns/correction.py +1 -13
  29. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +2 -62
  30. rasa/dialogue_understanding/processor/command_processor.py +28 -117
  31. rasa/dialogue_understanding/utils.py +0 -31
  32. rasa/dialogue_understanding_test/test_case_simulation/test_case_tracker_simulator.py +2 -2
  33. rasa/shared/core/constants.py +1 -22
  34. rasa/shared/core/domain.py +4 -6
  35. rasa/shared/core/events.py +2 -13
  36. rasa/shared/core/flows/flow.py +0 -17
  37. rasa/shared/core/flows/flows_yaml_schema.json +0 -38
  38. rasa/shared/core/flows/steps/collect.py +1 -18
  39. rasa/shared/core/flows/utils.py +1 -16
  40. rasa/shared/core/slot_mappings.py +6 -6
  41. rasa/shared/core/slots.py +0 -19
  42. rasa/shared/core/trackers.py +1 -3
  43. rasa/shared/nlu/constants.py +0 -1
  44. rasa/shared/utils/llm.py +1 -1
  45. rasa/shared/utils/schemas/domain.yml +1 -0
  46. rasa/validator.py +22 -172
  47. rasa/version.py +1 -1
  48. {rasa_pro-3.12.0.dev10.dist-info → rasa_pro-3.12.0.dev12.dist-info}/METADATA +1 -1
  49. {rasa_pro-3.12.0.dev10.dist-info → rasa_pro-3.12.0.dev12.dist-info}/RECORD +52 -55
  50. rasa/core/actions/action_handle_digressions.py +0 -142
  51. rasa/dialogue_understanding/commands/handle_digressions_command.py +0 -150
  52. rasa/dialogue_understanding/patterns/handle_digressions.py +0 -81
  53. {rasa_pro-3.12.0.dev10.dist-info → rasa_pro-3.12.0.dev12.dist-info}/NOTICE +0 -0
  54. {rasa_pro-3.12.0.dev10.dist-info → rasa_pro-3.12.0.dev12.dist-info}/WHEEL +0 -0
  55. {rasa_pro-3.12.0.dev10.dist-info → rasa_pro-3.12.0.dev12.dist-info}/entry_points.txt +0 -0
@@ -72,11 +72,10 @@ from rasa.shared.core.constants import (
72
72
  ACTION_UNLIKELY_INTENT_NAME,
73
73
  ACTION_VALIDATE_SLOT_MAPPINGS,
74
74
  DEFAULT_SLOT_NAMES,
75
- KEY_MAPPING_TYPE,
76
75
  KNOWLEDGE_BASE_SLOT_NAMES,
76
+ MAPPING_TYPE,
77
77
  REQUESTED_SLOT,
78
78
  USER_INTENT_OUT_OF_SCOPE,
79
- SetSlotExtractor,
80
79
  SlotMappingType,
81
80
  )
82
81
  from rasa.shared.core.domain import Domain
@@ -119,10 +118,6 @@ logger = logging.getLogger(__name__)
119
118
  def default_actions(action_endpoint: Optional[EndpointConfig] = None) -> List["Action"]:
120
119
  """List default actions."""
121
120
  from rasa.core.actions.action_clean_stack import ActionCleanStack
122
- from rasa.core.actions.action_handle_digressions import (
123
- ActionBlockDigressions,
124
- ActionContinueDigression,
125
- )
126
121
  from rasa.core.actions.action_hangup import ActionHangup
127
122
  from rasa.core.actions.action_repeat_bot_messages import ActionRepeatBotMessages
128
123
  from rasa.core.actions.action_run_slot_rejections import ActionRunSlotRejections
@@ -157,8 +152,6 @@ def default_actions(action_endpoint: Optional[EndpointConfig] = None) -> List["A
157
152
  ActionResetRouting(),
158
153
  ActionHangup(),
159
154
  ActionRepeatBotMessages(),
160
- ActionBlockDigressions(),
161
- ActionContinueDigression(),
162
155
  ]
163
156
 
164
157
 
@@ -947,14 +940,7 @@ class RemoteAction(Action):
947
940
  )
948
941
 
949
942
  events = rasa.shared.core.events.deserialise_events(events_json)
950
-
951
- processed_events = []
952
- for event in events:
953
- if isinstance(event, SlotSet) and event.filled_by is None:
954
- event.filled_by = SetSlotExtractor.CUSTOM.value
955
- processed_events.append(event)
956
-
957
- return cast(List[Event], bot_messages) + processed_events
943
+ return cast(List[Event], bot_messages) + events
958
944
 
959
945
  def name(self) -> Text:
960
946
  return self._name
@@ -1331,7 +1317,7 @@ class ActionExtractSlots(Action):
1331
1317
  slot_events.append(SlotSet(slot.name, slot_value))
1332
1318
 
1333
1319
  for mapping in slot.mappings:
1334
- mapping_type = SlotMappingType(mapping.get(KEY_MAPPING_TYPE))
1320
+ mapping_type = SlotMappingType(mapping.get(MAPPING_TYPE))
1335
1321
  should_fill_custom_slot = mapping_type == SlotMappingType.CUSTOM
1336
1322
 
1337
1323
  if should_fill_custom_slot:
@@ -16,7 +16,7 @@ from rasa.shared.constants import UTTER_PREFIX
16
16
  from rasa.shared.core.constants import (
17
17
  ACTION_EXTRACT_SLOTS,
18
18
  ACTION_LISTEN_NAME,
19
- KEY_MAPPING_TYPE,
19
+ MAPPING_TYPE,
20
20
  REQUESTED_SLOT,
21
21
  SLOT_MAPPINGS,
22
22
  SlotMappingType,
@@ -158,9 +158,7 @@ class FormAction(LoopAction):
158
158
  domain_slots = domain.as_dict().get(KEY_SLOTS, {})
159
159
  for slot in domain.required_slots_for_form(self.name()):
160
160
  for slot_mapping in domain_slots.get(slot, {}).get(SLOT_MAPPINGS, []):
161
- if slot_mapping.get(KEY_MAPPING_TYPE) == str(
162
- SlotMappingType.FROM_ENTITY
163
- ):
161
+ if slot_mapping.get(MAPPING_TYPE) == str(SlotMappingType.FROM_ENTITY):
164
162
  mapping_as_string = json.dumps(slot_mapping, sort_keys=True)
165
163
  if mapping_as_string in unique_entity_slot_mappings:
166
164
  unique_entity_slot_mappings.remove(mapping_as_string)
@@ -1,11 +1,9 @@
1
- import asyncio
2
1
  import copy
3
2
  import json
4
3
  import uuid
5
- from collections import defaultdict
6
4
  from dataclasses import asdict
7
5
  from datetime import datetime, timedelta, timezone
8
- from typing import Any, Awaitable, Callable, Dict, List, Optional, Set, Text, Union
6
+ from typing import Any, Awaitable, Callable, Dict, List, Optional, Text, Union
9
7
 
10
8
  import structlog
11
9
  from jsonschema import ValidationError, validate
@@ -225,16 +223,6 @@ class AudiocodesInput(InputChannel):
225
223
  self.scheduler_job = None
226
224
  self.keep_alive = keep_alive
227
225
  self.keep_alive_expiration_factor = keep_alive_expiration_factor
228
- self.background_tasks: Dict[Text, Set[asyncio.Task]] = defaultdict(set)
229
-
230
- def _create_task(self, conversation_id: Text, coro: Awaitable[Any]) -> asyncio.Task:
231
- """Create and track an asyncio task for a conversation."""
232
- task: asyncio.Task = asyncio.create_task(coro)
233
- self.background_tasks[conversation_id].add(task)
234
- task.add_done_callback(
235
- lambda t: self.background_tasks[conversation_id].discard(t)
236
- )
237
- return task
238
226
 
239
227
  async def _set_scheduler_job(self) -> None:
240
228
  if self.scheduler_job:
@@ -263,20 +251,11 @@ class AudiocodesInput(InputChannel):
263
251
  )
264
252
  now = datetime.now(timezone.utc)
265
253
  delta = timedelta(seconds=self.keep_alive * self.keep_alive_expiration_factor)
266
-
267
- # clean up conversations
268
- inactive = [
269
- conv_id
270
- for conv_id, conv in self.conversations.items()
271
- if not conv.is_active_conversation(now, delta)
272
- ]
273
-
274
- # cancel tasks and remove conversations
275
- for conv_id in inactive:
276
- for task in self.background_tasks[conv_id]:
277
- task.cancel()
278
- self.background_tasks.pop(conv_id, None)
279
- self.conversations.pop(conv_id, None)
254
+ self.conversations = {
255
+ k: v
256
+ for k, v in self.conversations.items()
257
+ if v.is_active_conversation(now, delta)
258
+ }
280
259
 
281
260
  def handle_start_conversation(self, body: Dict[Text, Any]) -> Dict[Text, Any]:
282
261
  conversation_id = body["conversation"]
@@ -368,29 +347,31 @@ class AudiocodesInput(InputChannel):
368
347
  structlogger.debug("audiocodes.on_activities", conversation=conversation_id)
369
348
  conversation = self._get_conversation(request.token, conversation_id)
370
349
  if conversation is None:
371
- structlogger.warning(
372
- "audiocodes.on_activities.no_conversation", request=request.json
373
- )
374
350
  return response.json({})
375
351
  elif conversation.ws:
376
352
  ac_output: Union[WebsocketOutput, AudiocodesOutput] = WebsocketOutput(
377
353
  conversation.ws, conversation_id
378
354
  )
379
- response_json = {}
355
+ await conversation.handle_activities(
356
+ request.json,
357
+ output_channel=ac_output,
358
+ on_new_message=on_new_message,
359
+ )
360
+ return response.json({})
380
361
  else:
381
362
  # handle non websocket case where messages get returned in json
382
363
  ac_output = AudiocodesOutput()
383
- response_json = {
384
- "conversation": conversation_id,
385
- "activities": ac_output.messages,
386
- }
387
-
388
- # start a background task to handle activities
389
- self._create_task(
390
- conversation_id,
391
- conversation.handle_activities(request.json, ac_output, on_new_message),
392
- )
393
- return response.json(response_json)
364
+ await conversation.handle_activities(
365
+ request.json,
366
+ output_channel=ac_output,
367
+ on_new_message=on_new_message,
368
+ )
369
+ return response.json(
370
+ {
371
+ "conversation": conversation_id,
372
+ "activities": ac_output.messages,
373
+ }
374
+ )
394
375
 
395
376
  @ac_webhook.route(
396
377
  "/conversation/<conversation_id>/disconnect", methods=["POST"]
@@ -81,8 +81,7 @@ class AzureTTS(TTSEngine[AzureTTSConfig]):
81
81
  @staticmethod
82
82
  def create_request_body(text: str, conf: AzureTTSConfig) -> str:
83
83
  return f"""
84
- <speak version='1.0' xml:lang='{conf.language}' xmlns:mstts='http://www.w3.org/2001/mstts'
85
- xmlns='http://www.w3.org/2001/10/synthesis'>
84
+ <speak version='1.0' xml:lang='{conf.language}'>
86
85
  <voice xml:lang='{conf.language}' name='{conf.voice}'>
87
86
  {text}
88
87
  </voice>
rasa/core/migrate.py CHANGED
@@ -14,7 +14,7 @@ from rasa.shared.constants import (
14
14
  )
15
15
  from rasa.shared.core.constants import (
16
16
  ACTIVE_LOOP,
17
- KEY_MAPPING_TYPE,
17
+ MAPPING_TYPE,
18
18
  REQUESTED_SLOT,
19
19
  SLOT_MAPPINGS,
20
20
  SlotMappingType,
@@ -43,7 +43,7 @@ def _create_back_up(domain_file: Path, backup_location: Path) -> Dict[Text, Any]
43
43
  def _get_updated_mapping_condition(
44
44
  condition: Dict[Text, Text], mapping: Dict[Text, Any], slot_name: Text
45
45
  ) -> Dict[Text, Text]:
46
- if mapping.get(KEY_MAPPING_TYPE) not in [
46
+ if mapping.get(MAPPING_TYPE) not in [
47
47
  str(SlotMappingType.FROM_ENTITY),
48
48
  str(SlotMappingType.FROM_TRIGGER_INTENT),
49
49
  ]:
@@ -23,7 +23,6 @@ from rasa.core.policies.flows.flow_step_result import (
23
23
  )
24
24
  from rasa.dialogue_understanding.commands import CancelFlowCommand
25
25
  from rasa.dialogue_understanding.patterns.cancel import CancelPatternFlowStackFrame
26
- from rasa.dialogue_understanding.patterns.clarify import ClarifyPatternFlowStackFrame
27
26
  from rasa.dialogue_understanding.patterns.collect_information import (
28
27
  CollectInformationPatternFlowStackFrame,
29
28
  )
@@ -51,7 +50,6 @@ from rasa.dialogue_understanding.stack.frames.flow_stack_frame import (
51
50
  )
52
51
  from rasa.dialogue_understanding.stack.utils import (
53
52
  top_user_flow_frame,
54
- user_flows_on_the_stack,
55
53
  )
56
54
  from rasa.shared.constants import RASA_PATTERN_HUMAN_HANDOFF
57
55
  from rasa.shared.core.constants import ACTION_LISTEN_NAME, SlotMappingType
@@ -274,28 +272,6 @@ def trigger_pattern_continue_interrupted(
274
272
  return events
275
273
 
276
274
 
277
- def trigger_pattern_clarification(
278
- current_frame: DialogueStackFrame, stack: DialogueStack, flows: FlowsList
279
- ) -> None:
280
- """Trigger the pattern to clarify which topic to continue if needed."""
281
- if not isinstance(current_frame, UserFlowStackFrame):
282
- return None
283
-
284
- if current_frame.frame_type == FlowStackFrameType.CALL:
285
- # we want to return to the flow that called the current flow
286
- return None
287
-
288
- pending_flows = [
289
- flows.flow_by_id(frame.flow_id)
290
- for frame in stack.frames
291
- if isinstance(frame, UserFlowStackFrame)
292
- and frame.flow_id != current_frame.flow_id
293
- ]
294
-
295
- flow_names = [flow.readable_name() for flow in pending_flows if flow is not None]
296
- stack.push(ClarifyPatternFlowStackFrame(names=flow_names))
297
-
298
-
299
275
  def trigger_pattern_completed(
300
276
  current_frame: DialogueStackFrame, stack: DialogueStack, flows: FlowsList
301
277
  ) -> None:
@@ -693,15 +669,7 @@ def _run_end_step(
693
669
  structlogger.debug("flow.step.run.flow_end")
694
670
  current_frame = stack.pop()
695
671
  trigger_pattern_completed(current_frame, stack, flows)
696
- resumed_events = []
697
- if len(user_flows_on_the_stack(stack)) > 1:
698
- # if there are more user flows on the stack,
699
- # we need to trigger the pattern clarify
700
- trigger_pattern_clarification(current_frame, stack, flows)
701
- else:
702
- resumed_events = trigger_pattern_continue_interrupted(
703
- current_frame, stack, flows
704
- )
672
+ resumed_events = trigger_pattern_continue_interrupted(current_frame, stack, flows)
705
673
  reset_events: List[Event] = reset_scoped_slots(current_frame, flow, tracker)
706
674
  return ContinueFlowWithNextStep(
707
675
  events=initial_events + reset_events + resumed_events, has_flow_ended=True
@@ -74,7 +74,7 @@ class CannotHandleCommand(Command):
74
74
 
75
75
  def to_dsl(self) -> str:
76
76
  """Converts the command to a DSL string."""
77
- return "CannotHandle()"
77
+ return "cannot handle"
78
78
 
79
79
  @classmethod
80
80
  def from_dsl(cls, match: re.Match, **kwargs: Any) -> CannotHandleCommand:
@@ -86,4 +86,4 @@ class CannotHandleCommand(Command):
86
86
 
87
87
  @staticmethod
88
88
  def regex_pattern() -> str:
89
- return r"CannotHandle\(\)"
89
+ return r"^cannot handle$"
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import copy
4
3
  import re
5
4
  from dataclasses import dataclass
6
5
  from typing import Any, Dict, List
@@ -9,11 +8,8 @@ import structlog
9
8
 
10
9
  from rasa.dialogue_understanding.commands.command import Command
11
10
  from rasa.dialogue_understanding.patterns.cancel import CancelPatternFlowStackFrame
12
- from rasa.dialogue_understanding.patterns.clarify import ClarifyPatternFlowStackFrame
13
11
  from rasa.dialogue_understanding.stack.dialogue_stack import DialogueStack
14
- from rasa.dialogue_understanding.stack.frames import (
15
- UserFlowStackFrame,
16
- )
12
+ from rasa.dialogue_understanding.stack.frames import UserFlowStackFrame
17
13
  from rasa.dialogue_understanding.stack.frames.flow_stack_frame import FlowStackFrameType
18
14
  from rasa.dialogue_understanding.stack.utils import top_user_flow_frame
19
15
  from rasa.shared.core.events import Event, FlowCancelled
@@ -93,8 +89,7 @@ class CancelFlowCommand(Command):
93
89
  original_stack = original_tracker.stack
94
90
 
95
91
  applied_events: List[Event] = []
96
- # capture the top frame before we push new frames onto the stack
97
- initial_top_frame = stack.top()
92
+
98
93
  user_frame = top_user_flow_frame(original_stack)
99
94
  current_flow = user_frame.flow(all_flows) if user_frame else None
100
95
 
@@ -119,21 +114,6 @@ class CancelFlowCommand(Command):
119
114
  if user_frame:
120
115
  applied_events.append(FlowCancelled(user_frame.flow_id, user_frame.step_id))
121
116
 
122
- if initial_top_frame and isinstance(
123
- initial_top_frame, ClarifyPatternFlowStackFrame
124
- ):
125
- structlogger.debug(
126
- "command_executor.cancel_flow.cancel_clarification_options",
127
- clarification_options=initial_top_frame.clarification_options,
128
- )
129
- applied_events += cancel_all_pending_clarification_options(
130
- initial_top_frame,
131
- original_stack,
132
- canceled_frames,
133
- all_flows,
134
- stack,
135
- )
136
-
137
117
  return applied_events + tracker.create_stack_updated_events(stack)
138
118
 
139
119
  def __hash__(self) -> int:
@@ -144,7 +124,7 @@ class CancelFlowCommand(Command):
144
124
 
145
125
  def to_dsl(self) -> str:
146
126
  """Converts the command to a DSL string."""
147
- return "CancelFlow()"
127
+ return "cancel flow"
148
128
 
149
129
  @classmethod
150
130
  def from_dsl(cls, match: re.Match, **kwargs: Any) -> CancelFlowCommand:
@@ -153,42 +133,4 @@ class CancelFlowCommand(Command):
153
133
 
154
134
  @staticmethod
155
135
  def regex_pattern() -> str:
156
- return r"CancelFlow\(\)"
157
-
158
-
159
- def cancel_all_pending_clarification_options(
160
- initial_top_frame: ClarifyPatternFlowStackFrame,
161
- original_stack: DialogueStack,
162
- canceled_frames: List[str],
163
- all_flows: FlowsList,
164
- stack: DialogueStack,
165
- ) -> List[FlowCancelled]:
166
- """Cancel all pending clarification options.
167
-
168
- This is a special case when the assistant asks the user to clarify
169
- which pending digression flow to start after the completion of an active flow.
170
- If the user chooses to cancel all options, this function takes care of
171
- updating the stack by removing all pending flow stack frames
172
- listed as clarification options.
173
- """
174
- clarification_names = set(initial_top_frame.names)
175
- to_be_canceled_frames = []
176
- applied_events = []
177
- for frame in reversed(original_stack.frames):
178
- if frame.frame_id in canceled_frames:
179
- continue
180
-
181
- to_be_canceled_frames.append(frame.frame_id)
182
- if isinstance(frame, UserFlowStackFrame):
183
- readable_flow_name = frame.flow(all_flows).readable_name()
184
- if readable_flow_name in clarification_names:
185
- stack.push(
186
- CancelPatternFlowStackFrame(
187
- canceled_name=readable_flow_name,
188
- canceled_frames=copy.deepcopy(to_be_canceled_frames),
189
- )
190
- )
191
- applied_events.append(FlowCancelled(frame.flow_id, frame.step_id))
192
- to_be_canceled_frames.clear()
193
-
194
- return applied_events
136
+ return r"^cancel flow$"
@@ -48,7 +48,7 @@ class ChangeFlowCommand(Command):
48
48
 
49
49
  def to_dsl(self) -> str:
50
50
  """Converts the command to a DSL string."""
51
- return "ChangeFlow()"
51
+ return "change"
52
52
 
53
53
  @staticmethod
54
54
  def from_dsl(match: re.Match, **kwargs: Any) -> ChangeFlowCommand:
@@ -57,4 +57,4 @@ class ChangeFlowCommand(Command):
57
57
 
58
58
  @staticmethod
59
59
  def regex_pattern() -> str:
60
- return r"ChangeFlow\(\)"
60
+ return r"^change"
@@ -59,7 +59,7 @@ class ChitChatAnswerCommand(FreeFormAnswerCommand):
59
59
 
60
60
  def to_dsl(self) -> str:
61
61
  """Converts the command to a DSL string."""
62
- return "ChitChat()"
62
+ return "offtopic reply"
63
63
 
64
64
  @classmethod
65
65
  def from_dsl(cls, match: re.Match, **kwargs: Any) -> ChitChatAnswerCommand:
@@ -68,4 +68,4 @@ class ChitChatAnswerCommand(FreeFormAnswerCommand):
68
68
 
69
69
  @staticmethod
70
70
  def regex_pattern() -> str:
71
- return r"ChitChat\(\)"
71
+ return r"^offtopic reply$"
@@ -89,7 +89,7 @@ class ClarifyCommand(Command):
89
89
 
90
90
  def to_dsl(self) -> str:
91
91
  """Converts the command to a DSL string."""
92
- return f"Clarify({', '.join(self.options)})"
92
+ return f"disambiguate flows {' '.join(self.options)}"
93
93
 
94
94
  @classmethod
95
95
  def from_dsl(cls, match: re.Match, **kwargs: Any) -> Optional[ClarifyCommand]:
@@ -99,4 +99,4 @@ class ClarifyCommand(Command):
99
99
 
100
100
  @staticmethod
101
101
  def regex_pattern() -> str:
102
- return r"Clarify\(([\"\'a-zA-Z0-9_, ]*)\)"
102
+ return r"^disambiguate flows([\"\'a-zA-Z0-9_, ]*)$"
@@ -31,7 +31,6 @@ class CorrectedSlot:
31
31
 
32
32
  name: str
33
33
  value: Any
34
- filled_by: Optional[str] = None
35
34
 
36
35
 
37
36
  @dataclass
@@ -55,9 +54,7 @@ class CorrectSlotsCommand(Command):
55
54
  try:
56
55
  return CorrectSlotsCommand(
57
56
  corrected_slots=[
58
- CorrectedSlot(
59
- s["name"], value=s["value"], filled_by=s.get("filled_by", None)
60
- )
57
+ CorrectedSlot(s["name"], value=s["value"])
61
58
  for s in data["corrected_slots"]
62
59
  ]
63
60
  )
@@ -138,10 +135,7 @@ class CorrectSlotsCommand(Command):
138
135
  proposed_slots = {}
139
136
  for corrected_slot in self.corrected_slots:
140
137
  if tracker.get_slot(corrected_slot.name) != corrected_slot.value:
141
- proposed_slots[corrected_slot.name] = {
142
- "value": corrected_slot.value,
143
- "filled_by": corrected_slot.filled_by,
144
- }
138
+ proposed_slots[corrected_slot.name] = corrected_slot.value
145
139
  else:
146
140
  structlogger.debug(
147
141
  "command_executor.skip_correction.slot_already_set", command=self
@@ -246,9 +240,6 @@ class CorrectSlotsCommand(Command):
246
240
  corrected_slots=proposed_slots,
247
241
  reset_flow_id=earliest_collect.flow_id if earliest_collect else None,
248
242
  reset_step_id=earliest_collect.step.id if earliest_collect else None,
249
- new_slot_values=[
250
- value.get("value") for slot, value in proposed_slots.items()
251
- ],
252
243
  )
253
244
 
254
245
  def run_command_on_tracker(
@@ -66,7 +66,7 @@ class HumanHandoffCommand(Command):
66
66
 
67
67
  def to_dsl(self) -> str:
68
68
  """Converts the command to a DSL string."""
69
- return "HumanHandoff()"
69
+ return "hand over"
70
70
 
71
71
  @classmethod
72
72
  def from_dsl(cls, match: re.Match, **kwargs: Any) -> HumanHandoffCommand:
@@ -75,4 +75,4 @@ class HumanHandoffCommand(Command):
75
75
 
76
76
  @staticmethod
77
77
  def regex_pattern() -> str:
78
- return r"HumanHandoff\(\)"
78
+ return r"^hand over$"
@@ -59,7 +59,7 @@ class KnowledgeAnswerCommand(FreeFormAnswerCommand):
59
59
 
60
60
  def to_dsl(self) -> str:
61
61
  """Converts the command to a DSL string."""
62
- return "SearchAndReply()"
62
+ return "provide info"
63
63
 
64
64
  @classmethod
65
65
  def from_dsl(cls, match: re.Match, **kwargs: Any) -> KnowledgeAnswerCommand:
@@ -68,4 +68,4 @@ class KnowledgeAnswerCommand(FreeFormAnswerCommand):
68
68
 
69
69
  @staticmethod
70
70
  def regex_pattern() -> str:
71
- return r"SearchAndReply\(\)"
71
+ return r"^provide info$"
@@ -60,7 +60,7 @@ class RepeatBotMessagesCommand(Command):
60
60
 
61
61
  def to_dsl(self) -> str:
62
62
  """Converts the command to a DSL string."""
63
- return "RepeatLastBotMessages()"
63
+ return "repeat message"
64
64
 
65
65
  @classmethod
66
66
  def from_dsl(cls, match: re.Match, **kwargs: Any) -> RepeatBotMessagesCommand:
@@ -69,4 +69,4 @@ class RepeatBotMessagesCommand(Command):
69
69
 
70
70
  @staticmethod
71
71
  def regex_pattern() -> str:
72
- return r"RepeatLastBotMessages\(\)"
72
+ return r"^repeat message$"
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import re
4
4
  from dataclasses import dataclass
5
+ from enum import Enum
5
6
  from typing import Any, Dict, List
6
7
 
7
8
  import structlog
@@ -18,7 +19,6 @@ from rasa.dialogue_understanding.stack.utils import (
18
19
  get_collect_steps_excluding_ask_before_filling_for_active_flow,
19
20
  )
20
21
  from rasa.shared.constants import ROUTE_TO_CALM_SLOT
21
- from rasa.shared.core.constants import SetSlotExtractor
22
22
  from rasa.shared.core.events import Event, SlotSet
23
23
  from rasa.shared.core.flows import FlowsList
24
24
  from rasa.shared.core.trackers import DialogueStateTracker
@@ -27,6 +27,17 @@ from rasa.shared.nlu.constants import SET_SLOT_COMMAND
27
27
  structlogger = structlog.get_logger()
28
28
 
29
29
 
30
+ class SetSlotExtractor(Enum):
31
+ """The extractors that can set a slot."""
32
+
33
+ LLM = "LLM"
34
+ COMMAND_PAYLOAD_READER = "CommandPayloadReader"
35
+ NLU = "NLU"
36
+
37
+ def __str__(self) -> str:
38
+ return self.value
39
+
40
+
30
41
  def get_flows_predicted_to_start_from_tracker(
31
42
  tracker: DialogueStateTracker,
32
43
  ) -> List[str]:
@@ -126,7 +137,6 @@ class SetSlotCommand(Command):
126
137
  in {
127
138
  SetSlotExtractor.LLM.value,
128
139
  SetSlotExtractor.COMMAND_PAYLOAD_READER.value,
129
- SetSlotExtractor.NLU.value,
130
140
  }
131
141
  ):
132
142
  # Get the other predicted flows from the most recent message on the tracker.
@@ -144,9 +154,7 @@ class SetSlotCommand(Command):
144
154
  return []
145
155
 
146
156
  structlogger.debug("command_executor.set_slot", command=self)
147
- return [
148
- SlotSet(self.name, slot.coerce_value(self.value), filled_by=self.extractor)
149
- ]
157
+ return [SlotSet(self.name, slot.coerce_value(self.value))]
150
158
 
151
159
  def __hash__(self) -> int:
152
160
  return hash(self.value) + hash(self.name)
@@ -162,7 +170,7 @@ class SetSlotCommand(Command):
162
170
 
163
171
  def to_dsl(self) -> str:
164
172
  """Converts the command to a DSL string."""
165
- return f"SetSlot({self.name}, {self.value})"
173
+ return f"set slot {self.name} {self.value}"
166
174
 
167
175
  @classmethod
168
176
  def from_dsl(cls, match: re.Match, **kwargs: Any) -> SetSlotCommand:
@@ -173,4 +181,4 @@ class SetSlotCommand(Command):
173
181
 
174
182
  @staticmethod
175
183
  def regex_pattern() -> str:
176
- return r"""SetSlot\(['"]?([a-zA-Z_][a-zA-Z0-9_-]*)['"]?, ?['"]?(.*)['"]?\)"""
184
+ return r"""^set slot ['"]?([a-zA-Z_][a-zA-Z0-9_-]*)['"]? ['"]?(.+?)['"]?$"""
@@ -75,7 +75,7 @@ class SkipQuestionCommand(Command):
75
75
 
76
76
  def to_dsl(self) -> str:
77
77
  """Converts the command to a DSL string."""
78
- return "SkipQuestion()"
78
+ return "skip"
79
79
 
80
80
  @classmethod
81
81
  def from_dsl(cls, match: re.Match, **kwargs: Any) -> SkipQuestionCommand:
@@ -84,4 +84,4 @@ class SkipQuestionCommand(Command):
84
84
 
85
85
  @staticmethod
86
86
  def regex_pattern() -> str:
87
- return r"SkipQuestion\(\)"
87
+ return r"^skip$"