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,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.new_slot_values | join(', ') }} respectively."
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
- continue_previous_flow:
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, resulting_commands):
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 not slot_command_exists_already and cannot_handle not in resulting_commands:
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, command.extractor)
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 slot.mappings:
744
- slot_mappings = [SlotMapping(type=SlotMappingType.FROM_LLM)]
671
+ if not slot_mappings:
672
+ slot_mappings = [{"type": SlotMappingType.FROM_LLM.value}]
745
673
 
746
- mapping_types = [mapping.type for mapping in slot_mappings]
747
-
748
- slot_has_nlu_mapping = any(
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
- if (
771
- slot_has_nlu_mapping
772
- and command.extractor == SetSlotExtractor.LLM.value
773
- and not slot_has_llm_mapping
774
- ):
775
- return False
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
- if (
778
- slot_has_llm_mapping
779
- and command.extractor == SetSlotExtractor.NLU.value
780
- and not slot_has_nlu_mapping
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
- if slot_has_controlled_mapping and not (
785
- slot_has_nlu_mapping or slot_has_llm_mapping
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.type for mapping in slot_definition.mappings
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
- await trainer.train(
356
- model_configuration,
357
- file_importer,
358
- full_model_path,
359
- force_retraining=force_full_training,
360
- is_finetuning=is_finetuning,
361
- )
362
- if remote_storage:
363
- push_model_to_remote_storage(full_model_path, remote_storage)
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
 
@@ -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
- KEY_MAPPING_TYPE = "type"
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
- CONTROLLED = "controlled"
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"
@@ -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
- KEY_MAPPING_TYPE,
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
- {KEY_MAPPING_TYPE: SlotMappingType.FROM_LLM.value}
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.conditions
1569
- if mapping.type != SlotMappingType.FROM_ENTITY or (
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].active_loop is not None
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) == mapping.entity
1578
- and entity.get(ENTITY_ATTRIBUTE_ROLE) == mapping.role
1579
- and entity.get(ENTITY_ATTRIBUTE_GROUP) == mapping.group
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
- controlled_mappings = 0
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.type == SlotMappingType.CONTROLLED:
2018
- controlled_mappings += 1
2024
+ if mapping[MAPPING_TYPE] == str(SlotMappingType.CUSTOM):
2025
+ custom_mappings += 1
2019
2026
 
2020
- if mapping.conditions:
2027
+ if MAPPING_CONDITIONS in mapping:
2021
2028
  conditional_mappings += 1
2022
2029
 
2023
- return total_mappings, controlled_mappings, conditional_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.