rasa-pro 3.13.0.dev1__py3-none-any.whl → 3.13.0.dev2__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 (58) hide show
  1. rasa/core/actions/action.py +0 -6
  2. rasa/core/channels/voice_ready/audiocodes.py +52 -17
  3. rasa/core/channels/voice_stream/audiocodes.py +53 -9
  4. rasa/core/channels/voice_stream/genesys.py +146 -16
  5. rasa/core/information_retrieval/faiss.py +6 -1
  6. rasa/core/information_retrieval/information_retrieval.py +40 -2
  7. rasa/core/information_retrieval/milvus.py +7 -2
  8. rasa/core/information_retrieval/qdrant.py +7 -2
  9. rasa/core/policies/enterprise_search_policy.py +61 -301
  10. rasa/core/policies/flows/flow_executor.py +3 -38
  11. rasa/core/processor.py +27 -6
  12. rasa/core/utils.py +53 -0
  13. rasa/dialogue_understanding/commands/cancel_flow_command.py +4 -59
  14. rasa/dialogue_understanding/commands/start_flow_command.py +0 -41
  15. rasa/dialogue_understanding/generator/command_generator.py +67 -0
  16. rasa/dialogue_understanding/generator/command_parser.py +1 -1
  17. rasa/dialogue_understanding/generator/llm_based_command_generator.py +4 -13
  18. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_template.jinja2 +1 -1
  19. rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +20 -1
  20. rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +7 -0
  21. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +0 -61
  22. rasa/dialogue_understanding/processor/command_processor.py +7 -65
  23. rasa/dialogue_understanding/stack/utils.py +0 -38
  24. rasa/dialogue_understanding_test/io.py +13 -8
  25. rasa/document_retrieval/__init__.py +0 -0
  26. rasa/document_retrieval/constants.py +32 -0
  27. rasa/document_retrieval/document_post_processor.py +351 -0
  28. rasa/document_retrieval/document_post_processor_prompt_template.jinja2 +0 -0
  29. rasa/document_retrieval/document_retriever.py +333 -0
  30. rasa/document_retrieval/knowledge_base_connectors/__init__.py +0 -0
  31. rasa/document_retrieval/knowledge_base_connectors/api_connector.py +39 -0
  32. rasa/document_retrieval/knowledge_base_connectors/knowledge_base_connector.py +34 -0
  33. rasa/document_retrieval/knowledge_base_connectors/vector_store_connector.py +226 -0
  34. rasa/document_retrieval/query_rewriter.py +234 -0
  35. rasa/document_retrieval/query_rewriter_prompt_template.jinja2 +8 -0
  36. rasa/engine/recipes/default_components.py +2 -0
  37. rasa/shared/core/constants.py +0 -8
  38. rasa/shared/core/domain.py +12 -3
  39. rasa/shared/core/flows/flow.py +0 -17
  40. rasa/shared/core/flows/flows_yaml_schema.json +3 -38
  41. rasa/shared/core/flows/steps/collect.py +5 -18
  42. rasa/shared/core/flows/utils.py +1 -16
  43. rasa/shared/core/slot_mappings.py +11 -5
  44. rasa/shared/nlu/constants.py +0 -1
  45. rasa/shared/utils/common.py +11 -1
  46. rasa/shared/utils/llm.py +1 -1
  47. rasa/tracing/instrumentation/attribute_extractors.py +10 -7
  48. rasa/tracing/instrumentation/instrumentation.py +12 -12
  49. rasa/validator.py +1 -123
  50. rasa/version.py +1 -1
  51. {rasa_pro-3.13.0.dev1.dist-info → rasa_pro-3.13.0.dev2.dist-info}/METADATA +1 -1
  52. {rasa_pro-3.13.0.dev1.dist-info → rasa_pro-3.13.0.dev2.dist-info}/RECORD +55 -47
  53. rasa/core/actions/action_handle_digressions.py +0 -164
  54. rasa/dialogue_understanding/commands/handle_digressions_command.py +0 -144
  55. rasa/dialogue_understanding/patterns/handle_digressions.py +0 -81
  56. {rasa_pro-3.13.0.dev1.dist-info → rasa_pro-3.13.0.dev2.dist-info}/NOTICE +0 -0
  57. {rasa_pro-3.13.0.dev1.dist-info → rasa_pro-3.13.0.dev2.dist-info}/WHEEL +0 -0
  58. {rasa_pro-3.13.0.dev1.dist-info → rasa_pro-3.13.0.dev2.dist-info}/entry_points.txt +0 -0
rasa/core/utils.py CHANGED
@@ -19,6 +19,7 @@ from rasa.core.constants import (
19
19
  )
20
20
  from rasa.core.lock_store import InMemoryLockStore, LockStore, RedisLockStore
21
21
  from rasa.shared.constants import DEFAULT_ENDPOINTS_PATH, TCP_PROTOCOL
22
+ from rasa.shared.core.constants import SlotMappingType
22
23
  from rasa.shared.core.trackers import DialogueStateTracker
23
24
  from rasa.utils.endpoints import (
24
25
  EndpointConfig,
@@ -30,6 +31,7 @@ from rasa.utils.io import write_yaml
30
31
  if TYPE_CHECKING:
31
32
  from rasa.core.nlg import NaturalLanguageGenerator
32
33
  from rasa.shared.core.domain import Domain
34
+ from rasa.shared.core.flows.flows_list import FlowsList
33
35
 
34
36
  structlogger = structlog.get_logger()
35
37
 
@@ -364,3 +366,54 @@ def add_bot_utterance_metadata(
364
366
  ]
365
367
 
366
368
  return message
369
+
370
+
371
+ def should_force_slot_filling(
372
+ tracker: Optional[DialogueStateTracker], flows: "FlowsList"
373
+ ) -> Tuple[bool, Optional[str]]:
374
+ """Check if the flow should force slot filling.
375
+
376
+ This is only valid when the flow is at a collect information step which
377
+ has set `force_slot_filling` to true and the slot has a valid `from_text` mapping.
378
+
379
+ Args:
380
+ tracker: The dialogue state tracker.
381
+ flows: The list of flows.
382
+
383
+ Returns:
384
+ A tuple of a boolean indicating if the flow should force slot filling
385
+ and the name of the slot if applicable.
386
+ """
387
+ from rasa.dialogue_understanding.processor.command_processor import (
388
+ get_current_collect_step,
389
+ )
390
+
391
+ if tracker is None:
392
+ structlogger.error(
393
+ "slot.force_slot_filling.error",
394
+ event_info="Tracker is None. Cannot force slot filling.",
395
+ )
396
+ return False, None
397
+
398
+ stack = tracker.stack
399
+ step = get_current_collect_step(stack, flows)
400
+ if step is None or not step.force_slot_filling:
401
+ return False, None
402
+
403
+ slot_name = step.collect
404
+ slot = tracker.slots.get(slot_name)
405
+
406
+ if not slot:
407
+ structlogger.debug(
408
+ "slot.force_slot_filling.error",
409
+ event_info=f"Slot '{slot_name}' not found in tracker. "
410
+ f"Cannot force slot filling. "
411
+ f"Please check if the slot is defined in the domain.",
412
+ )
413
+ return False, None
414
+
415
+ for slot_mapping in slot.mappings:
416
+ if slot_mapping.type == SlotMappingType.FROM_TEXT:
417
+ return True, slot_name
418
+
419
+ return False, None
@@ -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
@@ -13,10 +12,11 @@ from rasa.dialogue_understanding.commands.command_syntax_manager import (
13
12
  CommandSyntaxVersion,
14
13
  )
15
14
  from rasa.dialogue_understanding.patterns.cancel import CancelPatternFlowStackFrame
16
- from rasa.dialogue_understanding.patterns.clarify import ClarifyPatternFlowStackFrame
17
15
  from rasa.dialogue_understanding.stack.dialogue_stack import DialogueStack
18
- from rasa.dialogue_understanding.stack.frames import UserFlowStackFrame
19
- from rasa.dialogue_understanding.stack.frames.flow_stack_frame import FlowStackFrameType
16
+ from rasa.dialogue_understanding.stack.frames.flow_stack_frame import (
17
+ FlowStackFrameType,
18
+ UserFlowStackFrame,
19
+ )
20
20
  from rasa.dialogue_understanding.stack.utils import top_user_flow_frame
21
21
  from rasa.shared.core.events import Event, FlowCancelled
22
22
  from rasa.shared.core.flows import FlowsList
@@ -95,8 +95,6 @@ class CancelFlowCommand(Command):
95
95
  original_stack = original_tracker.stack
96
96
 
97
97
  applied_events: List[Event] = []
98
- # capture the top frame before we push new frames onto the stack
99
- initial_top_frame = stack.top()
100
98
  user_frame = top_user_flow_frame(original_stack)
101
99
  current_flow = user_frame.flow(all_flows) if user_frame else None
102
100
 
@@ -123,21 +121,6 @@ class CancelFlowCommand(Command):
123
121
  if user_frame:
124
122
  applied_events.append(FlowCancelled(user_frame.flow_id, user_frame.step_id))
125
123
 
126
- if initial_top_frame and isinstance(
127
- initial_top_frame, ClarifyPatternFlowStackFrame
128
- ):
129
- structlogger.debug(
130
- "command_executor.cancel_flow.cancel_clarification_options",
131
- clarification_options=initial_top_frame.clarification_options,
132
- )
133
- applied_events += cancel_all_pending_clarification_options(
134
- initial_top_frame,
135
- original_stack,
136
- canceled_frames,
137
- all_flows,
138
- stack,
139
- )
140
-
141
124
  return applied_events + tracker.create_stack_updated_events(stack)
142
125
 
143
126
  def __hash__(self) -> int:
@@ -172,41 +155,3 @@ class CancelFlowCommand(Command):
172
155
  CommandSyntaxManager.get_syntax_version(),
173
156
  mapper[CommandSyntaxManager.get_default_syntax_version()],
174
157
  )
175
-
176
-
177
- def cancel_all_pending_clarification_options(
178
- initial_top_frame: ClarifyPatternFlowStackFrame,
179
- original_stack: DialogueStack,
180
- canceled_frames: List[str],
181
- all_flows: FlowsList,
182
- stack: DialogueStack,
183
- ) -> List[FlowCancelled]:
184
- """Cancel all pending clarification options.
185
-
186
- This is a special case when the assistant asks the user to clarify
187
- which pending digression flow to start after the completion of an active flow.
188
- If the user chooses to cancel all options, this function takes care of
189
- updating the stack by removing all pending flow stack frames
190
- listed as clarification options.
191
- """
192
- clarification_names = set(initial_top_frame.names)
193
- to_be_canceled_frames = []
194
- applied_events = []
195
- for frame in reversed(original_stack.frames):
196
- if frame.frame_id in canceled_frames:
197
- continue
198
-
199
- to_be_canceled_frames.append(frame.frame_id)
200
- if isinstance(frame, UserFlowStackFrame):
201
- readable_flow_name = frame.flow(all_flows).readable_name()
202
- if readable_flow_name in clarification_names:
203
- stack.push(
204
- CancelPatternFlowStackFrame(
205
- canceled_name=readable_flow_name,
206
- canceled_frames=copy.deepcopy(to_be_canceled_frames),
207
- )
208
- )
209
- applied_events.append(FlowCancelled(frame.flow_id, frame.step_id))
210
- to_be_canceled_frames.clear()
211
-
212
- return applied_events
@@ -11,11 +11,6 @@ from rasa.dialogue_understanding.commands.command_syntax_manager import (
11
11
  CommandSyntaxManager,
12
12
  CommandSyntaxVersion,
13
13
  )
14
- from rasa.dialogue_understanding.patterns.clarify import FLOW_PATTERN_CLARIFICATION
15
- from rasa.dialogue_understanding.patterns.continue_interrupted import (
16
- ContinueInterruptedPatternFlowStackFrame,
17
- )
18
- from rasa.dialogue_understanding.stack.dialogue_stack import DialogueStack
19
14
  from rasa.dialogue_understanding.stack.frames.flow_stack_frame import (
20
15
  FlowStackFrameType,
21
16
  UserFlowStackFrame,
@@ -77,10 +72,6 @@ class StartFlowCommand(Command):
77
72
  applied_events: List[Event] = []
78
73
 
79
74
  if self.flow in user_flows_on_the_stack(stack):
80
- top_frame = stack.top()
81
- if top_frame is not None and top_frame.type() == FLOW_PATTERN_CLARIFICATION:
82
- return self.change_flow_frame_position_in_the_stack(stack, tracker)
83
-
84
75
  structlogger.debug(
85
76
  "command_executor.skip_command.already_started_flow", command=self
86
77
  )
@@ -149,35 +140,3 @@ class StartFlowCommand(Command):
149
140
  CommandSyntaxManager.get_syntax_version(),
150
141
  mapper[CommandSyntaxManager.get_default_syntax_version()],
151
142
  )
152
-
153
- def change_flow_frame_position_in_the_stack(
154
- self, stack: DialogueStack, tracker: DialogueStateTracker
155
- ) -> List[Event]:
156
- """Changes the position of the flow frame in the stack.
157
-
158
- This is a special case when pattern clarification is the active flow and
159
- the same flow is selected to start. In this case, the existing flow frame
160
- should be moved up in the stack.
161
- """
162
- frames = stack.frames[:]
163
-
164
- for idx, frame in enumerate(frames):
165
- if isinstance(frame, UserFlowStackFrame) and frame.flow_id == self.flow:
166
- structlogger.debug(
167
- "command_executor.change_flow_position_during_clarification",
168
- command=self,
169
- index=idx,
170
- )
171
- # pop the continue interrupted flow frame if it exists
172
- next_frame = frames[idx + 1] if idx + 1 < len(frames) else None
173
- if (
174
- isinstance(next_frame, ContinueInterruptedPatternFlowStackFrame)
175
- and next_frame.previous_flow_name == self.flow
176
- ):
177
- stack.frames.pop(idx + 1)
178
- # move up the existing flow from the stack
179
- stack.frames.pop(idx)
180
- stack.push(frame)
181
- return tracker.create_stack_updated_events(stack)
182
-
183
- return []
@@ -4,6 +4,7 @@ from typing import Any, Dict, List, Optional, Set, Text, Tuple
4
4
  import structlog
5
5
 
6
6
  from rasa.dialogue_understanding.commands import (
7
+ CannotHandleCommand,
7
8
  Command,
8
9
  CorrectSlotsCommand,
9
10
  ErrorCommand,
@@ -107,6 +108,14 @@ class CommandGenerator:
107
108
  commands = self._check_commands_against_startable_flows(
108
109
  commands, startable_flows
109
110
  )
111
+
112
+ # During force slot filling, keep only the command that sets the
113
+ # slot asked by the active collect step.
114
+ # Or return a CannotHandleCommand if no matching command is found.
115
+ commands = self._filter_commands_during_force_slot_filling(
116
+ commands, available_flows, tracker
117
+ )
118
+
110
119
  commands_dicts = [command.as_dict() for command in commands]
111
120
  message.set(COMMANDS, commands_dicts, add_to_output=True)
112
121
 
@@ -370,6 +379,64 @@ class CommandGenerator:
370
379
  Command.command_from_json(command) for command in message.get(COMMANDS, [])
371
380
  ]
372
381
 
382
+ @staticmethod
383
+ def _filter_commands_during_force_slot_filling(
384
+ commands: List[Command],
385
+ available_flows: FlowsList,
386
+ tracker: Optional[DialogueStateTracker] = None,
387
+ ) -> List[Command]:
388
+ """Filter commands during a collect step that has set `force_slot_filling`.
389
+
390
+ Args:
391
+ commands: The commands to filter.
392
+ available_flows: The available flows.
393
+ tracker: The tracker.
394
+
395
+ Returns:
396
+ The filtered commands.
397
+ """
398
+ from rasa.dialogue_understanding.processor.command_processor import (
399
+ get_current_collect_step,
400
+ )
401
+
402
+ if tracker is None:
403
+ structlogger.error(
404
+ "command_generator.filter_commands_during_force_slot_filling.tracker_not_found",
405
+ )
406
+ return commands
407
+
408
+ stack = tracker.stack
409
+ step = get_current_collect_step(stack, available_flows)
410
+
411
+ if step is None or not step.force_slot_filling:
412
+ return commands
413
+
414
+ # Retain only the command that sets the slot asked by
415
+ # the active collect step
416
+ filtered_commands: List[Command] = [
417
+ command
418
+ for command in commands
419
+ if (isinstance(command, SetSlotCommand) and command.name == step.collect)
420
+ ]
421
+
422
+ if not filtered_commands:
423
+ # If no commands were predicted, we need to return a CannotHandleCommand
424
+ structlogger.debug(
425
+ "command_generator.filter_commands_during_force_slot_filling.no_commands",
426
+ event_info=f"The command generator did not find any SetSlot "
427
+ f"command at the collect step for the slot '{step.collect}'. "
428
+ f"Returning a CannotHandleCommand instead.",
429
+ )
430
+ return [CannotHandleCommand()]
431
+
432
+ structlogger.debug(
433
+ "command_generator.filter_commands_during_force_slot_filling.filtered_commands",
434
+ slot_name=step.collect,
435
+ filtered_commands=filtered_commands,
436
+ )
437
+
438
+ return filtered_commands
439
+
373
440
 
374
441
  def gather_slot_names(commands: List[Command]) -> Set[str]:
375
442
  """Gather all slot names from the commands."""
@@ -169,7 +169,7 @@ def _parse_standard_commands(
169
169
  commands: List[Command] = []
170
170
  for command_clz in standard_commands:
171
171
  pattern = _get_compiled_pattern(command_clz.regex_pattern())
172
- if match := pattern.search(action):
172
+ if match := pattern.search(action.strip()):
173
173
  parsed_command = command_clz.from_dsl(match, **kwargs)
174
174
  if _additional_parsing_fn := _get_additional_parsing_logic(command_clz):
175
175
  parsed_command = _additional_parsing_fn(parsed_command, flows, **kwargs)
@@ -12,9 +12,6 @@ from rasa.dialogue_understanding.commands import (
12
12
  SetSlotCommand,
13
13
  StartFlowCommand,
14
14
  )
15
- from rasa.dialogue_understanding.commands.handle_digressions_command import (
16
- HandleDigressionsCommand,
17
- )
18
15
  from rasa.dialogue_understanding.constants import KEY_MINIMIZE_NUM_CALLS
19
16
  from rasa.dialogue_understanding.generator import CommandGenerator
20
17
  from rasa.dialogue_understanding.generator._jinja_filters import to_json_escaped_string
@@ -393,7 +390,8 @@ class LLMBasedCommandGenerator(
393
390
  "slots": slots_with_info,
394
391
  }
395
392
  )
396
- return result
393
+
394
+ return sorted(result, key=lambda x: x["name"])
397
395
 
398
396
  @staticmethod
399
397
  def is_extractable(
@@ -609,16 +607,9 @@ class LLMBasedCommandGenerator(
609
607
  ) -> bool:
610
608
  """Check if the LLM current commands should be merged with the prior commands.
611
609
 
612
- This can be done if there are no prior start flow commands and
613
- no prior handle digressions commands.
610
+ This can be done if there are no prior start flow commands.
614
611
  """
615
- prior_handle_digressions = [
616
- command
617
- for command in prior_commands
618
- if isinstance(command, HandleDigressionsCommand)
619
- ]
620
-
621
- return not prior_start_flow_names and not prior_handle_digressions
612
+ return not prior_start_flow_names
622
613
 
623
614
  def _check_start_flow_command_overlap(
624
615
  self,
@@ -57,4 +57,4 @@ Strictly adhere to the provided action types listed above.
57
57
  Focus on the last message and take it one step at a time.
58
58
  Use the previous conversation steps only to aid understanding.
59
59
 
60
- Your action list:
60
+ Your action list:
@@ -16,7 +16,9 @@ Use the following structured data:
16
16
  * `set slot slot_name slot_value`: Slot setting. For example, `set slot transfer_money_recipient Freddy`. Can be used to correct and change previously set values.
17
17
  * `cancel flow`: Cancelling the current flow.
18
18
  * `disambiguate flows flow_name1 flow_name2 ... flow_name_n`: Disambiguate which flow should be started when user input is ambiguous by listing the potential flows as options. For example, `disambiguate flows list_contacts add_contact remove_contact ...` if the user just wrote "contacts".
19
- * `search and reply`: Responding to the user's message by accessing and supplying relevant information from the knowledge base to address their inquiry effectively.
19
+ {%- if relevant_documents.results %}
20
+ * `search and reply`: Responding to the user's message by using the relevant FAQs (included in this prompt) retrieved from the knowledge base.
21
+ {%- endif %}
20
22
  * `offtopic reply`: Responding to casual or social user messages that are unrelated to any flows, engaging in friendly conversation and addressing off-topic remarks.
21
23
  * `hand over`: Handing over to a human, in case the user seems frustrated or explicitly asks to speak to one.
22
24
 
@@ -29,8 +31,10 @@ Use the following structured data:
29
31
  * Extract text slot values exactly as provided by the user. Avoid assumptions, format changes, or partial extractions.
30
32
  * Use clarification in ambiguous cases.
31
33
  * Use `disambiguate flows` only when multiple flows could fit the same message (e.g., "card" could mean `block_card` or `replace_card`).
34
+ {%- if relevant_documents.results %}
32
35
  * A user asking a question does not automatically imply that they want `search and reply`. The objective is to help them complete a business process if its possible to do so via a flow.
33
36
  * **Flow Priority**: If a user message can be addressed by starting a flow (even if it looks like a general question), ALWAYS start the flow first. Example: If the user says "How do I activate my card?", use `start flow activate_card` instead of `search and reply`. Only use `search and reply` if no flow matches the request.
37
+ {%- endif %}
34
38
  * Only use information provided by the user.
35
39
  * Multiple flows can be started. If a user wants to digress into a second flow, you do not need to cancel the current flow.
36
40
  * Do not cancel the flow unless the user explicitly requests it.
@@ -38,8 +42,23 @@ Use the following structured data:
38
42
  * Focus on the last message and take it one step at a time.
39
43
  * Use the previous conversation steps only to aid understanding.
40
44
 
45
+ {%- if relevant_documents.results %}
46
+
47
+ ---
48
+
49
+ ## Relevant FAQs from the knowledge base
50
+ ```json
51
+ {"documents":[{% for document in relevant_documents.results %}{"Q":"{{ document.text }}","A":"{{ document.metadata.answer }}"},{% endfor %}]}
52
+ ```
53
+
41
54
  ---
42
55
 
56
+ {% else %}
57
+
58
+ ---
59
+
60
+ {% endif -%}
61
+
43
62
  ## Current State
44
63
  {% if current_flow != None %}Use the following structured data:
45
64
  ```json
@@ -4,6 +4,7 @@ from typing import Any, Dict, List, Optional, Text
4
4
  import structlog
5
5
 
6
6
  import rasa.shared.utils.io
7
+ from rasa.core.information_retrieval import SearchResultList
7
8
  from rasa.dialogue_understanding.commands import (
8
9
  CannotHandleCommand,
9
10
  Command,
@@ -38,6 +39,7 @@ from rasa.dialogue_understanding.utils import (
38
39
  add_commands_to_message_parse_data,
39
40
  add_prompt_to_message_parse_data,
40
41
  )
42
+ from rasa.document_retrieval.constants import POST_PROCESSED_DOCUMENTS_KEY
41
43
  from rasa.engine.graph import ExecutionContext
42
44
  from rasa.engine.recipes.default_recipe import DefaultV1Recipe
43
45
  from rasa.engine.storage.resource import Resource
@@ -493,6 +495,10 @@ class CompactLLMCommandGenerator(LLMBasedCommandGenerator):
493
495
  latest_user_message = sanitize_message_for_prompt(message.get(TEXT))
494
496
  current_conversation += f"\nUSER: {latest_user_message}"
495
497
 
498
+ relevant_documents = SearchResultList.from_dict(
499
+ message.get(POST_PROCESSED_DOCUMENTS_KEY, [])
500
+ )
501
+
496
502
  inputs = {
497
503
  "available_flows": self.prepare_flows_for_template(
498
504
  startable_flows, tracker
@@ -506,6 +512,7 @@ class CompactLLMCommandGenerator(LLMBasedCommandGenerator):
506
512
  "current_slot_allowed_values": current_slot_allowed_values,
507
513
  "user_message": latest_user_message,
508
514
  "is_repeat_command_enabled": self.repeat_command_enabled,
515
+ "relevant_documents": relevant_documents,
509
516
  }
510
517
 
511
518
  return self.compile_template(self.prompt_template).render(**inputs)
@@ -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,12 +35,6 @@ 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
39
  - text: "Ok, I am updating {{ context.corrected_slots.keys()|join(', ') }} to {{ context.new_slot_values | join(', ') }} respectively."
71
40
  metadata:
@@ -150,10 +119,6 @@ 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
157
122
 
158
123
  flows:
159
124
  pattern_cancel_flow:
@@ -197,7 +162,6 @@ flows:
197
162
  steps:
198
163
  - action: action_clarify_flows
199
164
  - action: utter_clarification_options_rasa
200
- - action: action_listen
201
165
 
202
166
  pattern_code_change:
203
167
  description: Conversation repair flow for cleaning the stack after an assistant update
@@ -247,31 +211,6 @@ flows:
247
211
  next: END
248
212
  - else: END
249
213
 
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
214
  pattern_human_handoff:
276
215
  description: Conversation repair flow for switching users to a human agent if their request can't be handled
277
216
  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.commands.utils import (
26
23
  create_validate_frames_from_slot_set_events,
@@ -454,21 +451,7 @@ def clean_up_commands(
454
451
  )
455
452
  continue
456
453
 
457
- if should_add_handle_digressions_command(tracker, all_flows, top_flow_id):
458
- handle_digression_command = HandleDigressionsCommand(flow=command.flow)
459
- if handle_digression_command in clean_commands:
460
- structlogger.debug(
461
- "command_processor.clean_up_commands.skip_handle_digressions.command_already_present",
462
- command=handle_digression_command,
463
- )
464
- continue
465
- clean_commands.append(handle_digression_command)
466
- structlogger.debug(
467
- "command_processor.clean_up_commands.push_handle_digressions",
468
- command=command,
469
- )
470
- else:
471
- clean_commands.append(command)
454
+ clean_commands.append(command)
472
455
 
473
456
  # handle chitchat command differently from other free-form answer commands
474
457
  elif isinstance(command, ChitChatAnswerCommand):
@@ -503,21 +486,9 @@ def clean_up_commands(
503
486
  # when coexistence is enabled, by default there will be a SetSlotCommand
504
487
  # for the ROUTE_TO_CALM_SLOT slot.
505
488
  if tracker.has_coexistence_routing_slot and len(clean_commands) > 2:
506
- clean_commands = filter_cannot_handle_command_for_skipped_slots(clean_commands)
489
+ clean_commands = filter_cannot_handle_command(clean_commands)
507
490
  elif not tracker.has_coexistence_routing_slot and len(clean_commands) > 1:
508
- clean_commands = filter_cannot_handle_command_for_skipped_slots(clean_commands)
509
-
510
- # remove cancel flow when there is a handle digression command
511
- # otherwise the cancel command will cancel the active flow which defined a specific
512
- # behavior for the digression
513
- if contains_command(clean_commands, HandleDigressionsCommand) and contains_command(
514
- clean_commands, CancelFlowCommand
515
- ):
516
- clean_commands = [
517
- command
518
- for command in clean_commands
519
- if not isinstance(command, CancelFlowCommand)
520
- ]
491
+ clean_commands = filter_cannot_handle_command(clean_commands)
521
492
 
522
493
  clean_commands = ensure_max_number_of_command_type(
523
494
  clean_commands, RepeatBotMessagesCommand, 1
@@ -857,12 +828,12 @@ def should_slot_be_set(
857
828
  return True
858
829
 
859
830
 
860
- def filter_cannot_handle_command_for_skipped_slots(
831
+ def filter_cannot_handle_command(
861
832
  clean_commands: List[Command],
862
833
  ) -> List[Command]:
863
- """Filter out a 'cannot handle' command for skipped slots.
834
+ """Filter out a 'cannot handle' command.
864
835
 
865
- This is used to filter out a 'cannot handle' command for skipped slots
836
+ This is used to filter out a 'cannot handle' command
866
837
  in case other commands are present.
867
838
 
868
839
  Returns:
@@ -871,34 +842,5 @@ def filter_cannot_handle_command_for_skipped_slots(
871
842
  return [
872
843
  command
873
844
  for command in clean_commands
874
- if not (
875
- isinstance(command, CannotHandleCommand)
876
- and command.reason
877
- and CANNOT_HANDLE_REASON == command.reason
878
- )
845
+ if not isinstance(command, CannotHandleCommand)
879
846
  ]
880
-
881
-
882
- def should_add_handle_digressions_command(
883
- tracker: DialogueStateTracker, all_flows: FlowsList, top_flow_id: str
884
- ) -> bool:
885
- """Check if a handle digressions command should be added to the commands.
886
-
887
- The command should replace a StartFlow command only if we are at a collect step of
888
- a flow and a new flow is predicted by the command generator to start.
889
- """
890
- current_flow = all_flows.flow_by_id(top_flow_id)
891
- current_flow_condition = current_flow and (
892
- current_flow.ask_confirm_digressions or current_flow.block_digressions
893
- )
894
-
895
- collect_info = get_current_collect_step(tracker.stack, all_flows)
896
-
897
- if collect_info and (
898
- collect_info.ask_confirm_digressions
899
- or collect_info.block_digressions
900
- or current_flow_condition
901
- ):
902
- return True
903
-
904
- return False