rasa-pro 3.12.28__py3-none-any.whl → 3.12.29__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.

@@ -115,7 +115,6 @@ class CorrectSlotsCommand(Command):
115
115
  The earliest collect information step that fills one of the slots and
116
116
  the flow id of that step.
117
117
  """
118
-
119
118
  collect_steps = utils.previous_collect_steps_for_active_flow(tracker, all_flows)
120
119
 
121
120
  for collect_step, flow_id in collect_steps:
@@ -269,7 +268,21 @@ class CorrectSlotsCommand(Command):
269
268
  )
270
269
  return []
271
270
 
272
- structlogger.debug("command_executor.correct_slots", command=self)
271
+ structlogger.debug("correct_slots_command", command=self)
272
+
273
+ # check if the correct slot is referring to a slot of a flow on the stack
274
+ # the slot also needs to be part of a collect step in any of those flows
275
+ # if this is not the case, we don't want to correct the slot
276
+ for slot in self.corrected_slots:
277
+ if not self.should_correct_slot(slot, tracker, all_flows):
278
+ structlogger.warning(
279
+ "correct_slots_command.skip_correct_slot",
280
+ correct_slot=slot,
281
+ reason="The slot is not part of a collect step in any of the flows "
282
+ "on the stack. Skipping correction.",
283
+ )
284
+ return []
285
+
273
286
  proposed_slots = self.corrected_slots_dict(tracker)
274
287
 
275
288
  correction_frame = self.create_correction_frame(
@@ -294,3 +307,27 @@ class CorrectSlotsCommand(Command):
294
307
  return False
295
308
 
296
309
  return True
310
+
311
+ def should_correct_slot(
312
+ self, slot: CorrectedSlot, tracker: DialogueStateTracker, all_flows: FlowsList
313
+ ) -> bool:
314
+ """Checks if the slot should be corrected.
315
+
316
+ Args:
317
+ slot: The slot to check.
318
+ tracker: The tracker.
319
+ all_flows: All flows in the assistant.
320
+ """
321
+ # get all flows on the stack
322
+ flows_on_stack = utils.user_flows_on_the_stack(tracker.stack)
323
+
324
+ # check if the slot is part of a collect step in any of the flows on the stack
325
+ for flow_id in flows_on_stack:
326
+ flow = all_flows.flow_by_id(flow_id)
327
+ if flow is None:
328
+ continue
329
+ for collect_step in flow.get_collect_steps():
330
+ if collect_step.collect == slot.name:
331
+ return True
332
+
333
+ return False
@@ -37,7 +37,6 @@ from rasa.dialogue_understanding.stack.frames import (
37
37
  BaseFlowStackFrame,
38
38
  )
39
39
  from rasa.dialogue_understanding.stack.utils import (
40
- filled_slots_for_active_flow,
41
40
  top_flow_frame,
42
41
  top_user_flow_frame,
43
42
  )
@@ -125,8 +124,9 @@ def validate_state_of_commands(commands: List[Command]) -> None:
125
124
  # check that there is only at max one cancel flow command
126
125
  if sum(isinstance(c, CancelFlowCommand) for c in commands) > 1:
127
126
  structlogger.error(
128
- "command_processor.validate_state_of_commands.multiple_cancel_flow_commands",
129
- commands=commands,
127
+ "command_processor.validate_state_of_commands."
128
+ "multiple_cancel_flow_commands",
129
+ commands=[command.__class__.__name__ for command in commands],
130
130
  )
131
131
  raise ValueError("There can only be one cancel flow command.")
132
132
 
@@ -136,8 +136,9 @@ def validate_state_of_commands(commands: List[Command]) -> None:
136
136
  ]
137
137
  if free_form_answer_commands != commands[: len(free_form_answer_commands)]:
138
138
  structlogger.error(
139
- "command_processor.validate_state_of_commands.free_form_answer_commands_not_at_beginning",
140
- commands=commands,
139
+ "command_processor.validate_state_of_commands."
140
+ "free_form_answer_commands_not_at_beginning",
141
+ commands=[command.__class__.__name__ for command in commands],
141
142
  )
142
143
  raise ValueError(
143
144
  "Free form answer commands must be at start of the predicted command list."
@@ -146,8 +147,9 @@ def validate_state_of_commands(commands: List[Command]) -> None:
146
147
  # check that there is at max only one correctslots command
147
148
  if sum(isinstance(c, CorrectSlotsCommand) for c in commands) > 1:
148
149
  structlogger.error(
149
- "command_processor.validate_state_of_commands.multiple_correct_slots_commands",
150
- commands=commands,
150
+ "command_processor.validate_state_of_commands."
151
+ "multiple_correct_slots_commands",
152
+ commands=[command.__class__.__name__ for command in commands],
151
153
  )
152
154
  raise ValueError("There can only be one correct slots command.")
153
155
 
@@ -230,11 +232,9 @@ def execute_commands(
230
232
 
231
233
  events: List[Event] = flow_hash_events
232
234
 
233
- # commands need to be reversed to make sure they end up in the right order
234
- # on the stack. e.g. if there multiple start flow commands, the first one
235
- # should be on top of the stack. this is achieved by reversing the list
236
- # and then pushing the commands onto the stack in the reversed order.
237
- reversed_commands = list(reversed(commands))
235
+ # reorder commands: in case there is no active flow, we want to make sure to
236
+ # run the start flow commands first.
237
+ final_commands = reorder_commands(commands, tracker)
238
238
 
239
239
  # we need to keep track of the ValidateSlotPatternFlowStackFrame that
240
240
  # should be pushed onto the stack before executing the StartFlowCommands.
@@ -245,7 +245,7 @@ def execute_commands(
245
245
 
246
246
  validate_state_of_commands(commands)
247
247
 
248
- for command in reversed_commands:
248
+ for command in final_commands:
249
249
  new_events = command.run_command_on_tracker(
250
250
  tracker, all_flows, original_tracker
251
251
  )
@@ -399,11 +399,11 @@ def clean_up_commands(
399
399
  """
400
400
  domain = domain if domain else Domain.empty()
401
401
 
402
- slots_so_far, _ = filled_slots_for_active_flow(tracker, all_flows)
403
-
404
- # update the slots so far with the slots that were set in the tracker
405
- slots_so_far.update(
406
- {event.key for event in tracker.events if isinstance(event, SlotSet)}
402
+ # we consider all slots that were set in the tracker for potential corrections
403
+ # in the correct_slot_command we will check if a slot should actually be
404
+ # corrected
405
+ slots_so_far = set(
406
+ [event.key for event in tracker.events if isinstance(event, SlotSet)]
407
407
  )
408
408
 
409
409
  clean_commands: List[Command] = []
@@ -445,7 +445,8 @@ def clean_up_commands(
445
445
  # drop a start flow command if the starting flow is equal
446
446
  # to the currently active flow
447
447
  structlogger.debug(
448
- "command_processor.clean_up_commands.skip_command_flow_already_active",
448
+ "command_processor.clean_up_commands."
449
+ "skip_command_flow_already_active",
449
450
  command=command,
450
451
  )
451
452
  continue
@@ -476,7 +477,8 @@ def clean_up_commands(
476
477
  clean_commands = clean_up_clarify_command(clean_commands, commands, command)
477
478
  if command not in clean_commands:
478
479
  structlogger.debug(
479
- "command_processor.clean_up_commands.drop_clarify_given_other_commands",
480
+ "command_processor.clean_up_commands."
481
+ "drop_clarify_given_other_commands",
480
482
  command=command,
481
483
  )
482
484
  else:
@@ -578,10 +580,10 @@ def clean_up_slot_command(
578
580
  The cleaned up commands.
579
581
  """
580
582
  stack = tracker.stack
581
-
582
583
  resulting_commands = commands_so_far[:]
583
-
584
584
  slot = tracker.slots.get(command.name)
585
+
586
+ # if the slot is not in the domain, we cannot set it
585
587
  if slot is None:
586
588
  structlogger.debug(
587
589
  "command_processor.clean_up_slot_command.skip_command_slot_not_in_domain",
@@ -594,6 +596,7 @@ def clean_up_slot_command(
594
596
  )
595
597
  return resulting_commands
596
598
 
599
+ # check if the slot should be set by the command
597
600
  if not should_slot_be_set(slot, command, resulting_commands):
598
601
  structlogger.debug(
599
602
  "command_processor.clean_up_slot_command.skip_command.extractor_"
@@ -619,6 +622,7 @@ def clean_up_slot_command(
619
622
 
620
623
  return resulting_commands
621
624
 
625
+ # check if the slot can be corrected by the LLM
622
626
  if (
623
627
  slot.filled_by == SetSlotExtractor.NLU.value
624
628
  and command.extractor == SetSlotExtractor.LLM.value
@@ -647,49 +651,71 @@ def clean_up_slot_command(
647
651
  resulting_commands.append(command)
648
652
  return resulting_commands
649
653
 
650
- if (slot := tracker.slots.get(command.name)) is not None and str(
651
- slot.value
652
- ) == str(command.value):
653
- # the slot is already set, we don't need to set it again
654
- structlogger.debug(
655
- "command_processor.clean_up_slot_command.skip_command_slot_already_set",
656
- command=command,
657
- )
654
+ if should_slot_be_corrected(command, tracker, stack, all_flows):
655
+ # if the slot was already set before, we need to convert it into
656
+ # a correction
657
+ return convert_set_slot_to_correction(command, resulting_commands)
658
+ else:
658
659
  return resulting_commands
659
660
 
660
- top = top_flow_frame(stack)
661
- if isinstance(top, CorrectionPatternFlowStackFrame):
662
- already_corrected_slots = top.corrected_slots
663
- else:
664
- already_corrected_slots = {}
661
+ resulting_commands.append(command)
662
+ return resulting_commands
665
663
 
666
- if command.name in already_corrected_slots and str(
667
- already_corrected_slots[command.name]
668
- ) == str(command.value):
669
- structlogger.debug(
670
- "command_processor.clean_up_slot_command"
671
- ".skip_command_slot_already_corrected",
672
- command=command,
673
- )
674
- return resulting_commands
675
664
 
665
+ def should_slot_be_corrected(
666
+ command: SetSlotCommand,
667
+ tracker: DialogueStateTracker,
668
+ stack: DialogueStack,
669
+ all_flows: FlowsList,
670
+ ) -> bool:
671
+ """Check if a slot should be corrected."""
672
+ if (slot := tracker.slots.get(command.name)) is not None and str(slot.value) == str(
673
+ command.value
674
+ ):
675
+ # the slot is already set to the same value, we don't need to set it again
676
676
  structlogger.debug(
677
- "command_processor.clean_up_slot_command.convert_command_to_correction",
677
+ "command_processor.clean_up_slot_command.skip_command_slot_already_set",
678
678
  command=command,
679
679
  )
680
+ return False
680
681
 
681
- # Group all corrections into one command
682
- corrected_slot = CorrectedSlot(command.name, command.value, command.extractor)
683
- for c in resulting_commands:
684
- if isinstance(c, CorrectSlotsCommand):
685
- c.corrected_slots.append(corrected_slot)
686
- break
687
- else:
688
- resulting_commands.append(
689
- CorrectSlotsCommand(corrected_slots=[corrected_slot])
690
- )
682
+ top = top_flow_frame(stack)
683
+ if isinstance(top, CorrectionPatternFlowStackFrame):
684
+ already_corrected_slots = top.corrected_slots
691
685
  else:
692
- resulting_commands.append(command)
686
+ already_corrected_slots = {}
687
+
688
+ if command.name in already_corrected_slots and str(
689
+ already_corrected_slots[command.name]
690
+ ) == str(command.value):
691
+ structlogger.debug(
692
+ "command_processor.clean_up_slot_command"
693
+ ".skip_command_slot_already_corrected",
694
+ command=command,
695
+ )
696
+ return False
697
+
698
+ return True
699
+
700
+
701
+ def convert_set_slot_to_correction(
702
+ command: SetSlotCommand,
703
+ resulting_commands: List[Command],
704
+ ) -> List[Command]:
705
+ """Convert a set slot command to a correction command."""
706
+ structlogger.debug(
707
+ "command_processor.convert_set_slot_to_correction",
708
+ command=command,
709
+ )
710
+
711
+ # Group all corrections into one command
712
+ corrected_slot = CorrectedSlot(command.name, command.value, command.extractor)
713
+ for c in resulting_commands:
714
+ if isinstance(c, CorrectSlotsCommand):
715
+ c.corrected_slots.append(corrected_slot)
716
+ break
717
+ else:
718
+ resulting_commands.append(CorrectSlotsCommand(corrected_slots=[corrected_slot]))
693
719
 
694
720
  return resulting_commands
695
721
 
@@ -748,8 +774,9 @@ def clean_up_chitchat_command(
748
774
  0, CannotHandleCommand(RASA_PATTERN_CANNOT_HANDLE_CHITCHAT)
749
775
  )
750
776
  structlogger.warn(
751
- "command_processor.clean_up_chitchat_command.replace_chitchat_answer_with_cannot_handle",
752
- command=resulting_commands[0],
777
+ "command_processor.clean_up_chitchat_command."
778
+ "replace_chitchat_answer_with_cannot_handle",
779
+ command=resulting_commands[0], # no PII
753
780
  pattern_chitchat_uses_action_trigger_chitchat=has_action_trigger_chitchat,
754
781
  defined_intentless_policy_in_config=defines_intentless_policy,
755
782
  )
@@ -851,3 +878,49 @@ def filter_cannot_handle_command(
851
878
  for command in clean_commands
852
879
  if not isinstance(command, CannotHandleCommand)
853
880
  ]
881
+
882
+
883
+ def reorder_commands(
884
+ commands: List[Command], tracker: DialogueStateTracker
885
+ ) -> List[Command]:
886
+ """Reorder commands.
887
+
888
+ In case there is no active flow, we want to make sure to run the start flow
889
+ commands first.
890
+ """
891
+ reordered_commands = commands
892
+
893
+ top_flow_frame = top_user_flow_frame(tracker.stack)
894
+
895
+ if top_flow_frame is None:
896
+ # no active flow, we want to make sure to run the start flow commands first
897
+ start_flow_commands: List[Command] = [
898
+ command for command in commands if isinstance(command, StartFlowCommand)
899
+ ]
900
+
901
+ # if there are no start flow commands, we can return the commands as they are
902
+ if not start_flow_commands:
903
+ reordered_commands = commands
904
+
905
+ # if there is just one start flow command, we want to run it first
906
+ # as the order of commands is reserved later,
907
+ # we need to add it to the end of the list
908
+ elif len(start_flow_commands) == 1:
909
+ reordered_commands = [
910
+ command for command in commands if command not in start_flow_commands
911
+ ] + start_flow_commands
912
+
913
+ # if there are multiple start flow commands,
914
+ # we just make sure to move the first start flow command to the end of the list
915
+ # (due to the reverse execution order of commands) and keep the other commands
916
+ # as they are.
917
+ else:
918
+ reordered_commands = [
919
+ command for command in commands if command != start_flow_commands[-1]
920
+ ] + [start_flow_commands[-1]]
921
+
922
+ # commands need to be reversed to make sure they end up in the right order
923
+ # on the stack. e.g. if there multiple start flow commands, the first one
924
+ # should be on top of the stack. this is achieved by reversing the list
925
+ # and then pushing the commands onto the stack in the reversed order.
926
+ return list(reversed(reordered_commands))
rasa/version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  # this file will automatically be changed,
2
2
  # do not add anything but the version number here!
3
- __version__ = "3.12.28"
3
+ __version__ = "3.12.29"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rasa-pro
3
- Version: 3.12.28
3
+ Version: 3.12.29
4
4
  Summary: State-of-the-art open-core Conversational AI framework for Enterprises that natively leverages generative AI for effortless assistant development.
5
5
  Keywords: nlp,machine-learning,machine-learning-library,bot,bots,botkit,rasa conversational-agents,conversational-ai,chatbot,chatbot-framework,bot-framework
6
6
  Author: Rasa Technologies GmbH
@@ -375,7 +375,7 @@ rasa/dialogue_understanding/commands/chit_chat_answer_command.py,sha256=PtwNuAHJ
375
375
  rasa/dialogue_understanding/commands/clarify_command.py,sha256=mxdHWdyaQwA4uYdhVUjwAUPfl0HvqtDHU2DWKEeZal4,4290
376
376
  rasa/dialogue_understanding/commands/command.py,sha256=rhxHmllTMwvb4Uq-pDqmUdlKtu-87y8nqN5DRO-KDwE,2529
377
377
  rasa/dialogue_understanding/commands/command_syntax_manager.py,sha256=vO6sOak0g9GucEtiNximJ9bQFbHQwWJ-M5XNF1gGxz4,1893
378
- rasa/dialogue_understanding/commands/correct_slots_command.py,sha256=bIApo1i-RbF7JojHb4WiiKkZwRV6GBaUIGkdsn9Scog,10396
378
+ rasa/dialogue_understanding/commands/correct_slots_command.py,sha256=2oRix75ciUWMM4vs5bQt_BP8e4VMklepqTAoqGvUP4k,11899
379
379
  rasa/dialogue_understanding/commands/error_command.py,sha256=LTEsxkGGGZR6wEEGuTtQ4K4EK_u2UFhNK4eAKyPfyME,2436
380
380
  rasa/dialogue_understanding/commands/free_form_answer_command.py,sha256=XlQrHXrcOemzu1LHZiDhBAluiSlnUQ2V7ET5Z-aG7gc,224
381
381
  rasa/dialogue_understanding/commands/handle_code_change_command.py,sha256=Cp2e1iD0zacXmljJ8vDXHJu9Fp6BwB7cGx8NF748akw,2192
@@ -436,7 +436,7 @@ rasa/dialogue_understanding/patterns/skip_question.py,sha256=fJ1MC0WEEtS-BpnGJEf
436
436
  rasa/dialogue_understanding/patterns/user_silence.py,sha256=xP-QMnd-MsybH5z4g01hBv4OLOHcw6m3rc26LQfe2zo,1140
437
437
  rasa/dialogue_understanding/patterns/validate_slot.py,sha256=hqd5AEGT3M3HLNhMwuI9W9kZNCvgU6GyI-2xc2b4kz8,2085
438
438
  rasa/dialogue_understanding/processor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
439
- rasa/dialogue_understanding/processor/command_processor.py,sha256=BRpT28JKwNhKo5i8FwJ785KmmM6jJhln7BuUX087vf0,30343
439
+ rasa/dialogue_understanding/processor/command_processor.py,sha256=BJNtJEd-Rvk1BNo8jZ51mcshay3SqrPdDbS3VMCQScs,33019
440
440
  rasa/dialogue_understanding/processor/command_processor_component.py,sha256=rkErI_Uo7s3LsEojUSGSRbWGyGaX7GtGOYSJn0V-TI4,1650
441
441
  rasa/dialogue_understanding/stack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
442
442
  rasa/dialogue_understanding/stack/dialogue_stack.py,sha256=cYV6aQeh0EuOJHODDqK3biqXozYTX8baPgLwHhPxFqs,5244
@@ -822,9 +822,9 @@ rasa/utils/train_utils.py,sha256=ClJx-6x3-h3Vt6mskacgkcCUJTMXjFPe3zAcy_DfmaU,212
822
822
  rasa/utils/url_tools.py,sha256=dZ1HGkVdWTJB7zYEdwoDIrEuyX9HE5WsxKKFVsXBLE0,1218
823
823
  rasa/utils/yaml.py,sha256=KjbZq5C94ZP7Jdsw8bYYF7HASI6K4-C_kdHfrnPLpSI,2000
824
824
  rasa/validator.py,sha256=524VlFTYK0B3iXYveVD6BDC3K0j1QfpzJ9O-TAWczmc,83166
825
- rasa/version.py,sha256=aC6Pou7VXpWxwawa48upNJvkusxhNBoc_GAG_QsLZ-Y,118
826
- rasa_pro-3.12.28.dist-info/METADATA,sha256=z6d0ful_P2-MrVxrxMuuIauM7g9cLCLftJd-zPq_fqo,10609
827
- rasa_pro-3.12.28.dist-info/NOTICE,sha256=7HlBoMHJY9CL2GlYSfTQ-PZsVmLmVkYmMiPlTjhuCqA,218
828
- rasa_pro-3.12.28.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
829
- rasa_pro-3.12.28.dist-info/entry_points.txt,sha256=ckJ2SfEyTPgBqj_I6vm_tqY9dZF_LAPJZA335Xp0Q9U,43
830
- rasa_pro-3.12.28.dist-info/RECORD,,
825
+ rasa/version.py,sha256=T_XkU0ivAlg_G8z81que2BHbFXN7f32bBBK5LW2Np-Q,118
826
+ rasa_pro-3.12.29.dist-info/METADATA,sha256=Fau5T-JWA5BClkNV9o61pS4t-Hf1En0GHfDyPhloJXE,10609
827
+ rasa_pro-3.12.29.dist-info/NOTICE,sha256=7HlBoMHJY9CL2GlYSfTQ-PZsVmLmVkYmMiPlTjhuCqA,218
828
+ rasa_pro-3.12.29.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
829
+ rasa_pro-3.12.29.dist-info/entry_points.txt,sha256=ckJ2SfEyTPgBqj_I6vm_tqY9dZF_LAPJZA335Xp0Q9U,43
830
+ rasa_pro-3.12.29.dist-info/RECORD,,