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.

Files changed (71) hide show
  1. rasa/cli/inspect.py +1 -20
  2. rasa/cli/shell.py +3 -3
  3. rasa/core/actions/action.py +7 -20
  4. rasa/core/actions/forms.py +5 -10
  5. rasa/core/channels/__init__.py +0 -2
  6. rasa/core/channels/voice_ready/audiocodes.py +23 -42
  7. rasa/core/channels/voice_stream/browser_audio.py +0 -1
  8. rasa/core/channels/voice_stream/call_state.py +1 -7
  9. rasa/core/channels/voice_stream/tts/azure.py +1 -2
  10. rasa/core/channels/voice_stream/tts/cartesia.py +3 -16
  11. rasa/core/channels/voice_stream/twilio_media_streams.py +1 -2
  12. rasa/core/channels/voice_stream/voice_channel.py +1 -2
  13. rasa/core/migrate.py +2 -2
  14. rasa/core/policies/flows/flow_executor.py +42 -36
  15. rasa/core/run.py +3 -4
  16. rasa/dialogue_understanding/commands/can_not_handle_command.py +2 -2
  17. rasa/dialogue_understanding/commands/cancel_flow_command.py +4 -62
  18. rasa/dialogue_understanding/commands/change_flow_command.py +2 -2
  19. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +2 -2
  20. rasa/dialogue_understanding/commands/clarify_command.py +2 -2
  21. rasa/dialogue_understanding/commands/correct_slots_command.py +2 -11
  22. rasa/dialogue_understanding/commands/human_handoff_command.py +2 -2
  23. rasa/dialogue_understanding/commands/knowledge_answer_command.py +2 -2
  24. rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +2 -2
  25. rasa/dialogue_understanding/commands/set_slot_command.py +15 -7
  26. rasa/dialogue_understanding/commands/skip_question_command.py +2 -2
  27. rasa/dialogue_understanding/commands/start_flow_command.py +2 -43
  28. rasa/dialogue_understanding/commands/utils.py +1 -1
  29. rasa/dialogue_understanding/constants.py +0 -1
  30. rasa/dialogue_understanding/generator/command_generator.py +73 -110
  31. rasa/dialogue_understanding/generator/command_parser.py +1 -1
  32. rasa/dialogue_understanding/generator/llm_based_command_generator.py +3 -161
  33. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +2 -10
  34. rasa/dialogue_understanding/generator/nlu_command_adapter.py +3 -44
  35. rasa/dialogue_understanding/generator/single_step/command_prompt_template.jinja2 +79 -53
  36. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +19 -11
  37. rasa/dialogue_understanding/generator/utils.py +1 -32
  38. rasa/dialogue_understanding/patterns/correction.py +1 -13
  39. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +2 -62
  40. rasa/dialogue_understanding/processor/command_processor.py +28 -115
  41. rasa/dialogue_understanding/utils.py +0 -31
  42. rasa/dialogue_understanding_test/README.md +0 -50
  43. rasa/dialogue_understanding_test/test_case_simulation/test_case_tracker_simulator.py +3 -3
  44. rasa/model_service.py +0 -4
  45. rasa/model_training.py +27 -24
  46. rasa/shared/core/constants.py +3 -28
  47. rasa/shared/core/domain.py +20 -13
  48. rasa/shared/core/events.py +2 -13
  49. rasa/shared/core/flows/flow.py +0 -17
  50. rasa/shared/core/flows/flows_yaml_schema.json +0 -38
  51. rasa/shared/core/flows/steps/collect.py +1 -18
  52. rasa/shared/core/flows/utils.py +1 -16
  53. rasa/shared/core/slot_mappings.py +108 -144
  54. rasa/shared/core/slots.py +2 -23
  55. rasa/shared/core/trackers.py +1 -3
  56. rasa/shared/nlu/constants.py +0 -1
  57. rasa/shared/utils/llm.py +1 -1
  58. rasa/shared/utils/schemas/domain.yml +1 -0
  59. rasa/telemetry.py +13 -43
  60. rasa/utils/common.py +1 -0
  61. rasa/validator.py +82 -189
  62. rasa/version.py +1 -1
  63. {rasa_pro-3.12.0.dev11.dist-info → rasa_pro-3.12.0.dev12.dist-info}/METADATA +1 -1
  64. {rasa_pro-3.12.0.dev11.dist-info → rasa_pro-3.12.0.dev12.dist-info}/RECORD +67 -71
  65. rasa/core/actions/action_handle_digressions.py +0 -142
  66. rasa/core/channels/voice_stream/genesys.py +0 -331
  67. rasa/dialogue_understanding/commands/handle_digressions_command.py +0 -150
  68. rasa/dialogue_understanding/patterns/handle_digressions.py +0 -81
  69. {rasa_pro-3.12.0.dev11.dist-info → rasa_pro-3.12.0.dev12.dist-info}/NOTICE +0 -0
  70. {rasa_pro-3.12.0.dev11.dist-info → rasa_pro-3.12.0.dev12.dist-info}/WHEEL +0 -0
  71. {rasa_pro-3.12.0.dev11.dist-info → rasa_pro-3.12.0.dev12.dist-info}/entry_points.txt +0 -0
@@ -1,20 +1,15 @@
1
- from __future__ import annotations
2
-
3
- import copy
4
1
  import logging
5
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, Text, Tuple, Union, cast
6
-
7
- from pydantic import BaseModel, Field
2
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Text, Tuple, cast
8
3
 
9
4
  import rasa.shared.utils.io
10
5
  from rasa.shared.constants import DOCS_URL_NLU_BASED_SLOTS, IGNORED_INTENTS
11
6
  from rasa.shared.core.constants import (
7
+ ACTIVE_FLOW,
12
8
  ACTIVE_LOOP,
13
- KEY_ACTION,
14
- KEY_MAPPING_TYPE,
15
- KEY_RUN_ACTION_EVERY_TURN,
16
9
  MAPPING_CONDITIONS,
10
+ MAPPING_TYPE,
17
11
  REQUESTED_SLOT,
12
+ SLOT_MAPPINGS,
18
13
  SlotMappingType,
19
14
  )
20
15
  from rasa.shared.core.slots import ListSlot, Slot
@@ -26,6 +21,7 @@ from rasa.shared.nlu.constants import (
26
21
  ENTITY_ATTRIBUTE_VALUE,
27
22
  INTENT,
28
23
  INTENT_NAME_KEY,
24
+ NOT_INTENT,
29
25
  TEXT,
30
26
  )
31
27
 
@@ -39,81 +35,11 @@ if TYPE_CHECKING:
39
35
  logger = logging.getLogger(__name__)
40
36
 
41
37
 
42
- class SlotMappingCondition(BaseModel):
43
- """Defines a condition for a slot mapping."""
44
-
45
- active_loop: Optional[str]
46
- requested_slot: Optional[str] = None
47
- active_flow: Optional[str] = None
48
-
49
- @staticmethod
50
- def from_dict(data: Dict[str, Any]) -> SlotMappingCondition:
51
- # we allow None as a valid value for active_loop
52
- # therefore we need to set a different default value
53
- active_loop = data.pop(ACTIVE_LOOP, "")
54
-
55
- return SlotMappingCondition(active_loop=active_loop, **data)
56
-
57
- def as_dict(self) -> Dict[str, Any]:
58
- return self.model_dump(exclude_none=True)
59
-
60
-
61
- class SlotMapping(BaseModel):
38
+ class SlotMapping:
62
39
  """Defines functionality for the available slot mappings."""
63
40
 
64
- type: SlotMappingType
65
- conditions: List[SlotMappingCondition] = Field(default_factory=list)
66
- entity: Optional[str] = None
67
- intent: Optional[Union[str, List[str]]] = None
68
- role: Optional[str] = None
69
- group: Optional[str] = None
70
- not_intent: Optional[Union[str, List[str]]] = None
71
- value: Optional[Any] = None
72
- allow_nlu_correction: Optional[bool] = None
73
- run_action_every_turn: Optional[str] = None
74
-
75
- @staticmethod
76
- def from_dict(data: Dict[str, Any], slot_name: str) -> SlotMapping:
77
- data_copy = copy.deepcopy(data)
78
- mapping_type = SlotMapping.validate_mapping(data_copy, slot_name)
79
- conditions = [
80
- SlotMappingCondition.from_dict(condition)
81
- for condition in data_copy.pop(MAPPING_CONDITIONS, [])
82
- ]
83
-
84
- deprecated_action = data_copy.pop(KEY_ACTION, None)
85
- if deprecated_action:
86
- rasa.shared.utils.io.raise_deprecation_warning(
87
- f"The `{KEY_ACTION}` key in slot mappings is deprecated and "
88
- f"will be removed in Rasa Pro 4.0.0. "
89
- f"Please use the `{KEY_RUN_ACTION_EVERY_TURN}` key instead.",
90
- )
91
- data_copy[KEY_RUN_ACTION_EVERY_TURN] = deprecated_action
92
-
93
- run_action_every_turn = data_copy.pop(KEY_RUN_ACTION_EVERY_TURN, None)
94
-
95
- return SlotMapping(
96
- type=mapping_type,
97
- conditions=conditions,
98
- run_action_every_turn=run_action_every_turn,
99
- **data_copy,
100
- )
101
-
102
- def as_dict(self) -> Dict[str, Any]:
103
- data = self.model_dump(mode="json", exclude_none=True)
104
- data[KEY_MAPPING_TYPE] = self.type.value
105
-
106
- if self.conditions:
107
- data[MAPPING_CONDITIONS] = [
108
- condition.as_dict() for condition in self.conditions
109
- ]
110
- else:
111
- data.pop(MAPPING_CONDITIONS, None)
112
-
113
- return data
114
-
115
41
  @staticmethod
116
- def validate_mapping(mapping: Dict[str, Any], slot_name: str) -> SlotMappingType:
42
+ def validate(mapping: Dict[Text, Any], slot_name: Text) -> None:
117
43
  """Validates a slot mapping.
118
44
 
119
45
  Args:
@@ -132,22 +58,12 @@ class SlotMapping(BaseModel):
132
58
  f"{DOCS_URL_NLU_BASED_SLOTS} for more information."
133
59
  )
134
60
 
135
- mapping_raw = mapping.pop(KEY_MAPPING_TYPE, SlotMappingType.FROM_LLM.value)
136
-
137
- if mapping_raw == "custom":
138
- rasa.shared.utils.io.raise_deprecation_warning(
139
- "The `custom` slot mapping type is deprecated and "
140
- "will be removed in Rasa Pro 4.0.0. "
141
- "Please use the `controlled` slot mapping type instead.",
142
- )
143
- mapping_raw = "controlled"
144
-
145
61
  try:
146
- mapping_type = SlotMappingType(mapping_raw)
62
+ mapping_type = SlotMappingType(mapping.get(MAPPING_TYPE))
147
63
  except ValueError:
148
64
  raise InvalidDomain(
149
65
  f"Your domain uses an invalid slot mapping of type "
150
- f"'{mapping_raw}' for slot '{slot_name}'. Please see "
66
+ f"'{mapping.get(MAPPING_TYPE)}' for slot '{slot_name}'. Please see "
151
67
  f"{DOCS_URL_NLU_BASED_SLOTS} for more information."
152
68
  )
153
69
 
@@ -156,7 +72,7 @@ class SlotMapping(BaseModel):
156
72
  SlotMappingType.FROM_INTENT: ["value"],
157
73
  SlotMappingType.FROM_TRIGGER_INTENT: ["value"],
158
74
  SlotMappingType.FROM_TEXT: [],
159
- SlotMappingType.CONTROLLED: [],
75
+ SlotMappingType.CUSTOM: [],
160
76
  SlotMappingType.FROM_LLM: [],
161
77
  }
162
78
 
@@ -170,18 +86,19 @@ class SlotMapping(BaseModel):
170
86
  f"{DOCS_URL_NLU_BASED_SLOTS} for more information."
171
87
  )
172
88
 
173
- return mapping_type
174
-
89
+ @staticmethod
175
90
  def _get_active_loop_ignored_intents(
176
- self, domain: "Domain", active_loop_name: Text
91
+ mapping: Dict[Text, Any], domain: "Domain", active_loop_name: Text
177
92
  ) -> List[Text]:
178
- mapping_conditions = self.conditions
93
+ from rasa.shared.core.constants import ACTIVE_LOOP
94
+
95
+ mapping_conditions = mapping.get(MAPPING_CONDITIONS)
179
96
  active_loop_match = True
180
97
  ignored_intents = []
181
98
 
182
99
  if mapping_conditions:
183
100
  match_list = [
184
- condition.active_loop == active_loop_name
101
+ condition.get(ACTIVE_LOOP) == active_loop_name
185
102
  for condition in mapping_conditions
186
103
  ]
187
104
  active_loop_match = any(match_list)
@@ -194,21 +111,24 @@ class SlotMapping(BaseModel):
194
111
 
195
112
  return ignored_intents
196
113
 
114
+ @staticmethod
197
115
  def intent_is_desired(
198
- self,
116
+ mapping: Dict[Text, Any],
199
117
  tracker: "DialogueStateTracker",
200
118
  domain: "Domain",
201
119
  message: Optional["Message"] = None,
202
120
  ) -> bool:
203
121
  """Checks whether user intent matches slot mapping intent specifications."""
204
- mapping_intents = SlotMapping.to_list(self.intent)
205
- mapping_not_intents = SlotMapping.to_list(self.not_intent)
122
+ mapping_intents = SlotMapping.to_list(mapping.get(INTENT, []))
123
+ mapping_not_intents = SlotMapping.to_list(mapping.get(NOT_INTENT, []))
206
124
 
207
125
  active_loop_name = tracker.active_loop_name
208
126
  if active_loop_name:
209
127
  mapping_not_intents = (
210
128
  mapping_not_intents
211
- + self._get_active_loop_ignored_intents(domain, active_loop_name)
129
+ + SlotMapping._get_active_loop_ignored_intents(
130
+ mapping, domain, active_loop_name
131
+ )
212
132
  )
213
133
 
214
134
  if message is not None:
@@ -235,14 +155,16 @@ class SlotMapping(BaseModel):
235
155
 
236
156
  return x
237
157
 
158
+ @staticmethod
238
159
  def entity_is_desired(
239
- self,
160
+ mapping: Dict[Text, Any],
240
161
  tracker: "DialogueStateTracker",
241
162
  message: Optional["Message"] = None,
242
163
  ) -> List[str]:
243
164
  """Checks whether slot should be filled by an entity in the input or not.
244
165
 
245
166
  Args:
167
+ mapping: Slot mapping.
246
168
  tracker: The tracker.
247
169
  message: The message being processed.
248
170
 
@@ -254,16 +176,19 @@ class SlotMapping(BaseModel):
254
176
  matching_values = [
255
177
  cast(Text, entity[ENTITY_ATTRIBUTE_VALUE])
256
178
  for entity in extracted_entities
257
- if entity.get(ENTITY_ATTRIBUTE_TYPE) == self.entity
258
- and entity.get(ENTITY_ATTRIBUTE_GROUP) == self.group
259
- and entity.get(ENTITY_ATTRIBUTE_ROLE) == self.role
179
+ if entity.get(ENTITY_ATTRIBUTE_TYPE)
180
+ == mapping.get(ENTITY_ATTRIBUTE_TYPE)
181
+ and entity.get(ENTITY_ATTRIBUTE_GROUP)
182
+ == mapping.get(ENTITY_ATTRIBUTE_GROUP)
183
+ and entity.get(ENTITY_ATTRIBUTE_ROLE)
184
+ == mapping.get(ENTITY_ATTRIBUTE_ROLE)
260
185
  ]
261
186
  elif tracker.latest_message and tracker.latest_message.text is not None:
262
187
  matching_values = list(
263
188
  tracker.get_latest_entity_values(
264
- self.entity,
265
- self.role,
266
- self.group,
189
+ mapping.get(ENTITY_ATTRIBUTE_TYPE),
190
+ mapping.get(ENTITY_ATTRIBUTE_ROLE),
191
+ mapping.get(ENTITY_ATTRIBUTE_GROUP),
267
192
  )
268
193
  )
269
194
  else:
@@ -271,38 +196,45 @@ class SlotMapping(BaseModel):
271
196
 
272
197
  return matching_values
273
198
 
199
+ @staticmethod
274
200
  def check_mapping_validity(
275
- self,
276
201
  slot_name: Text,
202
+ mapping_type: SlotMappingType,
203
+ mapping: Dict[Text, Any],
277
204
  domain: "Domain",
278
205
  ) -> bool:
279
206
  """Checks the mapping for validity.
280
207
 
281
208
  Args:
282
209
  slot_name: The name of the slot to be validated.
210
+ mapping_type: The type of the slot mapping.
211
+ mapping: Slot mapping.
283
212
  domain: The domain to check against.
284
213
 
285
214
  Returns:
286
215
  True, if intent and entity specified in a mapping exist in domain.
287
216
  """
288
217
  if (
289
- self.type == SlotMappingType.FROM_ENTITY
290
- and self.entity not in domain.entities
218
+ mapping_type == SlotMappingType.FROM_ENTITY
219
+ and mapping.get(ENTITY_ATTRIBUTE_TYPE) not in domain.entities
291
220
  ):
292
221
  rasa.shared.utils.io.raise_warning(
293
222
  f"Slot '{slot_name}' uses a 'from_entity' mapping "
294
- f"for a non-existent entity '{self.entity}'. "
223
+ f"for a non-existent entity '{mapping.get(ENTITY_ATTRIBUTE_TYPE)}'. "
295
224
  f"Skipping slot extraction because of invalid mapping."
296
225
  )
297
226
  return False
298
227
 
299
- if self.type == SlotMappingType.FROM_INTENT and self.intent is not None:
300
- intent_list = SlotMapping.to_list(self.intent)
228
+ if (
229
+ mapping_type == SlotMappingType.FROM_INTENT
230
+ and mapping.get(INTENT) is not None
231
+ ):
232
+ intent_list = SlotMapping.to_list(mapping.get(INTENT))
301
233
  for intent in intent_list:
302
234
  if intent and intent not in domain.intents:
303
235
  rasa.shared.utils.io.raise_warning(
304
236
  f"Slot '{slot_name}' uses a 'from_intent' mapping for "
305
- f"a non-existent intent '{intent}'. "
237
+ f"a non-existent intent '{mapping.get('intent')}'. "
306
238
  f"Skipping slot extraction because of invalid mapping."
307
239
  )
308
240
  return False
@@ -310,6 +242,22 @@ class SlotMapping(BaseModel):
310
242
  return True
311
243
 
312
244
 
245
+ def validate_slot_mappings(domain_slots: Dict[Text, Any]) -> None:
246
+ """Raises InvalidDomain exception if slot mappings are invalid."""
247
+ rasa.shared.utils.io.raise_warning(
248
+ f"Slot auto-fill has been removed in 3.0 and replaced with a "
249
+ f"new explicit mechanism to set slots. "
250
+ f"Please refer to {DOCS_URL_NLU_BASED_SLOTS} to learn more.",
251
+ UserWarning,
252
+ )
253
+
254
+ for slot_name, properties in domain_slots.items():
255
+ mappings = properties.get(SLOT_MAPPINGS, [])
256
+
257
+ for slot_mapping in mappings:
258
+ SlotMapping.validate(slot_mapping, slot_name)
259
+
260
+
313
261
  class SlotFillingManager:
314
262
  """Manages slot filling based on conversation context."""
315
263
 
@@ -328,34 +276,41 @@ class SlotFillingManager:
328
276
  def is_slot_mapping_valid(
329
277
  self,
330
278
  slot_name: str,
331
- mapping: SlotMapping,
279
+ mapping_type: SlotMappingType,
280
+ mapping: Dict[str, Any],
332
281
  ) -> bool:
333
282
  """Check if a slot mapping is valid."""
334
- return mapping.check_mapping_validity(
283
+ return SlotMapping.check_mapping_validity(
335
284
  slot_name=slot_name,
285
+ mapping_type=mapping_type,
286
+ mapping=mapping,
336
287
  domain=self.domain,
337
288
  )
338
289
 
339
- def is_intent_desired(self, mapping: SlotMapping) -> bool:
290
+ def is_intent_desired(self, mapping: Dict[str, Any]) -> bool:
340
291
  """Check if the intent matches the one indicated in the slot mapping."""
341
- return mapping.intent_is_desired(
292
+ return SlotMapping.intent_is_desired(
293
+ mapping=mapping,
342
294
  tracker=self.tracker,
343
295
  domain=self.domain,
344
296
  message=self.message,
345
297
  )
346
298
 
347
- def _verify_mapping_conditions(self, mapping: SlotMapping, slot_name: Text) -> bool:
348
- if mapping.conditions and mapping.type != str(
299
+ def _verify_mapping_conditions(
300
+ self, mapping: Dict[Text, Any], slot_name: Text
301
+ ) -> bool:
302
+ if mapping.get(MAPPING_CONDITIONS) and mapping[MAPPING_TYPE] != str(
349
303
  SlotMappingType.FROM_TRIGGER_INTENT
350
304
  ):
351
- return self._matches_mapping_conditions(mapping, slot_name)
305
+ if not self._matches_mapping_conditions(mapping, slot_name):
306
+ return False
352
307
 
353
308
  return True
354
309
 
355
310
  def _matches_mapping_conditions(
356
- self, mapping: SlotMapping, slot_name: Text
311
+ self, mapping: Dict[Text, Any], slot_name: Text
357
312
  ) -> bool:
358
- slot_mapping_conditions = mapping.conditions
313
+ slot_mapping_conditions = mapping.get(MAPPING_CONDITIONS)
359
314
 
360
315
  if not slot_mapping_conditions:
361
316
  return True
@@ -373,20 +328,20 @@ class SlotFillingManager:
373
328
  @staticmethod
374
329
  def _mapping_conditions_match_flow(
375
330
  active_flow: str,
376
- slot_mapping_conditions: List[SlotMappingCondition],
331
+ slot_mapping_conditions: List[Dict[str, str]],
377
332
  ) -> bool:
378
333
  active_flow_conditions = list(
379
- filter(lambda x: x.active_flow is not None, slot_mapping_conditions)
334
+ filter(lambda x: x.get(ACTIVE_FLOW) is not None, slot_mapping_conditions)
380
335
  )
381
336
  return any(
382
337
  [
383
- condition.active_flow == active_flow
338
+ condition.get(ACTIVE_FLOW) == active_flow
384
339
  for condition in active_flow_conditions
385
340
  ]
386
341
  )
387
342
 
388
343
  def _mapping_conditions_match_form(
389
- self, slot_name: str, slot_mapping_conditions: List[SlotMappingCondition]
344
+ self, slot_name: str, slot_mapping_conditions: List[Dict[str, str]]
390
345
  ) -> bool:
391
346
  if (
392
347
  self.tracker.is_active_loop_rejected
@@ -396,10 +351,12 @@ class SlotFillingManager:
396
351
 
397
352
  # check if found mapping conditions matches form
398
353
  for condition in slot_mapping_conditions:
399
- active_loop = condition.active_loop
354
+ # we allow None as a valid value for active_loop
355
+ # therefore we need to set a different default value
356
+ active_loop = condition.get(ACTIVE_LOOP, "")
400
357
 
401
358
  if active_loop and active_loop == self.tracker.active_loop_name:
402
- condition_requested_slot = condition.requested_slot
359
+ condition_requested_slot = condition.get(REQUESTED_SLOT)
403
360
  if not condition_requested_slot:
404
361
  return True
405
362
  if condition_requested_slot == self.tracker.get_slot(REQUESTED_SLOT):
@@ -413,11 +370,11 @@ class SlotFillingManager:
413
370
  def _fails_unique_entity_mapping_check(
414
371
  self,
415
372
  slot_name: Text,
416
- mapping: SlotMapping,
373
+ mapping: Dict[Text, Any],
417
374
  ) -> bool:
418
375
  from rasa.core.actions.forms import FormAction
419
376
 
420
- if mapping.type != SlotMappingType.FROM_ENTITY:
377
+ if mapping[MAPPING_TYPE] != str(SlotMappingType.FROM_ENTITY):
421
378
  return False
422
379
 
423
380
  form_name = self.tracker.active_loop_name
@@ -438,9 +395,12 @@ class SlotFillingManager:
438
395
 
439
396
  return True
440
397
 
441
- def _is_trigger_intent_mapping_condition_met(self, mapping: SlotMapping) -> bool:
398
+ def _is_trigger_intent_mapping_condition_met(
399
+ self, mapping: Dict[Text, Any]
400
+ ) -> bool:
442
401
  active_loops_in_mapping_conditions = [
443
- condition.active_loop for condition in mapping.conditions
402
+ condition.get(ACTIVE_LOOP)
403
+ for condition in mapping.get(MAPPING_CONDITIONS, [])
444
404
  ]
445
405
 
446
406
  trigger_mapping_condition_met = True
@@ -461,7 +421,7 @@ class SlotFillingManager:
461
421
  def extract_slot_value_from_predefined_mapping(
462
422
  self,
463
423
  mapping_type: SlotMappingType,
464
- mapping: SlotMapping,
424
+ mapping: Dict[Text, Any],
465
425
  ) -> List[Any]:
466
426
  """Extracts slot value if slot has an applicable predefined mapping."""
467
427
  if (
@@ -494,9 +454,9 @@ class SlotFillingManager:
494
454
  value: List[Any] = []
495
455
 
496
456
  if should_fill_entity_slot:
497
- value = mapping.entity_is_desired(self.tracker, self.message)
457
+ value = SlotMapping.entity_is_desired(mapping, self.tracker, self.message)
498
458
  elif should_fill_intent_slot or should_fill_trigger_slot:
499
- value = [mapping.value]
459
+ value = [mapping.get("value")]
500
460
  elif should_fill_text_slot:
501
461
  value = [self.message.get(TEXT)] if self.message is not None else []
502
462
  if not value:
@@ -508,9 +468,11 @@ class SlotFillingManager:
508
468
 
509
469
  return value
510
470
 
511
- def should_fill_slot(self, slot_name: str, mapping: SlotMapping) -> bool:
471
+ def should_fill_slot(
472
+ self, slot_name: str, mapping_type: SlotMappingType, mapping: Dict[Text, Any]
473
+ ) -> bool:
512
474
  """Checks if a slot should be filled based on the conversation context."""
513
- if not self.is_slot_mapping_valid(slot_name, mapping):
475
+ if not self.is_slot_mapping_valid(slot_name, mapping_type, mapping):
514
476
  return False
515
477
 
516
478
  if not self.is_intent_desired(mapping):
@@ -532,12 +494,14 @@ def extract_slot_value(
532
494
  is_extracted = False
533
495
 
534
496
  for mapping in slot.mappings:
535
- mapping_type = mapping.type
497
+ mapping_type = SlotMappingType(
498
+ mapping.get(MAPPING_TYPE, SlotMappingType.FROM_LLM.value)
499
+ )
536
500
 
537
- if mapping_type in [SlotMappingType.FROM_LLM, SlotMappingType.CONTROLLED]:
501
+ if mapping_type in [SlotMappingType.FROM_LLM, SlotMappingType.CUSTOM]:
538
502
  continue
539
503
 
540
- if not slot_filling_manager.should_fill_slot(slot.name, mapping):
504
+ if not slot_filling_manager.should_fill_slot(slot.name, mapping_type, mapping):
541
505
  continue
542
506
 
543
507
  value: List[Any] = (
rasa/shared/core/slots.py CHANGED
@@ -41,7 +41,6 @@ class Slot(ABC):
41
41
  influence_conversation: bool = True,
42
42
  is_builtin: bool = False,
43
43
  shared_for_coexistence: bool = False,
44
- filled_by: Optional[str] = None,
45
44
  ) -> None:
46
45
  """Create a Slot.
47
46
 
@@ -58,12 +57,9 @@ class Slot(ABC):
58
57
  such as `return_value`.
59
58
  shared_for_coexistence: If `True` the slot is not forgotten after either
60
59
  dm1 or CALM finishes.
61
- filled_by: The name of the extractor that fills the slot.
62
60
  """
63
- from rasa.shared.core.slot_mappings import SlotMapping
64
-
65
61
  self.name = name
66
- self.mappings = [SlotMapping.from_dict(mapping, name) for mapping in mappings]
62
+ self.mappings = mappings
67
63
  self._value = initial_value
68
64
  self.initial_value = initial_value
69
65
  self._value_reset_delay = value_reset_delay
@@ -71,7 +67,6 @@ class Slot(ABC):
71
67
  self._has_been_set = False
72
68
  self.is_builtin = is_builtin
73
69
  self.shared_for_coexistence = shared_for_coexistence
74
- self._filled_by = filled_by
75
70
 
76
71
  def feature_dimensionality(self) -> int:
77
72
  """How many features this single slot creates.
@@ -137,16 +132,6 @@ class Slot(ABC):
137
132
  self._value = value
138
133
  self._has_been_set = True
139
134
 
140
- @property
141
- def filled_by(self) -> Optional[str]:
142
- """Gets the slot's latest value extractor."""
143
- return self._filled_by
144
-
145
- @filled_by.setter
146
- def filled_by(self, extractor: str) -> None:
147
- """Sets the slot's latest value extractor."""
148
- self._filled_by = extractor
149
-
150
135
  def has_same_coerced_value(self, other_value: Any) -> bool:
151
136
  """Checks if the coerced value of is the same as the slot value.
152
137
 
@@ -195,7 +180,7 @@ class Slot(ABC):
195
180
  "type": rasa.shared.utils.common.module_path_from_instance(self),
196
181
  "initial_value": self.initial_value,
197
182
  "influence_conversation": self.influence_conversation,
198
- "mappings": [mapping.as_dict() for mapping in self.mappings],
183
+ "mappings": self.mappings,
199
184
  }
200
185
 
201
186
  def fingerprint(self) -> Text:
@@ -230,7 +215,6 @@ class FloatSlot(Slot):
230
215
  influence_conversation: bool = True,
231
216
  is_builtin: bool = False,
232
217
  shared_for_coexistence: bool = False,
233
- filled_by: Optional[str] = None,
234
218
  ) -> None:
235
219
  """Creates a FloatSlot.
236
220
 
@@ -246,7 +230,6 @@ class FloatSlot(Slot):
246
230
  influence_conversation,
247
231
  is_builtin,
248
232
  shared_for_coexistence,
249
- filled_by=filled_by,
250
233
  )
251
234
  self.max_value = max_value
252
235
  self.min_value = min_value
@@ -404,7 +387,6 @@ class CategoricalSlot(Slot):
404
387
  influence_conversation: bool = True,
405
388
  is_builtin: bool = False,
406
389
  shared_for_coexistence: bool = False,
407
- filled_by: Optional[str] = None,
408
390
  ) -> None:
409
391
  """Creates a `Categorical Slot` (see parent class for detailed docstring)."""
410
392
  super().__init__(
@@ -415,7 +397,6 @@ class CategoricalSlot(Slot):
415
397
  influence_conversation,
416
398
  is_builtin,
417
399
  shared_for_coexistence,
418
- filled_by=filled_by,
419
400
  )
420
401
  if values and None in values:
421
402
  rasa.shared.utils.io.raise_warning(
@@ -626,7 +607,6 @@ class AnySlot(Slot):
626
607
  influence_conversation: bool = False,
627
608
  is_builtin: bool = False,
628
609
  shared_for_coexistence: bool = False,
629
- filled_by: Optional[str] = None,
630
610
  ) -> None:
631
611
  """Creates an `Any Slot` (see parent class for detailed docstring).
632
612
 
@@ -650,7 +630,6 @@ class AnySlot(Slot):
650
630
  influence_conversation,
651
631
  is_builtin,
652
632
  shared_for_coexistence,
653
- filled_by=filled_by,
654
633
  )
655
634
 
656
635
  def __eq__(self, other: Any) -> bool:
@@ -916,13 +916,11 @@ class DialogueStateTracker:
916
916
  continue
917
917
  slot.reset()
918
918
 
919
- def _set_slot(self, key: Text, value: Any, filled_by: Optional[str] = None) -> None:
919
+ def _set_slot(self, key: Text, value: Any) -> None:
920
920
  """Sets the value of a slot if that slot exists."""
921
921
  if key in self.slots:
922
922
  slot = self.slots[key]
923
923
  slot.value = value
924
- if filled_by is not None:
925
- slot.filled_by = filled_by
926
924
  else:
927
925
  logger.error(
928
926
  f"Tried to set non existent slot '{key}'. Make sure you "
@@ -55,4 +55,3 @@ SPLIT_ENTITIES_BY_COMMA_DEFAULT_VALUE = True
55
55
  SINGLE_ENTITY_ALLOWED_INTERLEAVING_CHARSET = {".", ",", " ", ";"}
56
56
 
57
57
  SET_SLOT_COMMAND = "set slot"
58
- HANDLE_DIGRESSIONS_COMMAND = "handle digressions"
rasa/shared/utils/llm.py CHANGED
@@ -680,7 +680,7 @@ def allowed_values_for_slot(slot: Slot) -> Union[str, None]:
680
680
  if isinstance(slot, BooleanSlot):
681
681
  return str([True, False])
682
682
  if isinstance(slot, CategoricalSlot):
683
- return str([v for v in slot.values if v != "__other__"])
683
+ return str([v for v in slot.values if v != "__other__"] + ["other"])
684
684
  else:
685
685
  return None
686
686
 
@@ -78,6 +78,7 @@ mapping:
78
78
  mappings:
79
79
  type: "seq"
80
80
  required: False
81
+ allowempty: False
81
82
  sequence:
82
83
  - type: "map"
83
84
  allowempty: True