rasa-pro 3.12.0.dev13__py3-none-any.whl → 3.12.0rc2__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.
- README.md +10 -13
- rasa/anonymization/anonymization_rule_executor.py +16 -10
- rasa/cli/data.py +16 -0
- rasa/cli/project_templates/calm/config.yml +2 -2
- rasa/cli/project_templates/calm/domain/list_contacts.yml +1 -2
- rasa/cli/project_templates/calm/domain/remove_contact.yml +1 -2
- rasa/cli/project_templates/calm/domain/shared.yml +1 -4
- rasa/cli/project_templates/calm/endpoints.yml +2 -2
- rasa/cli/utils.py +12 -0
- rasa/core/actions/action.py +84 -191
- rasa/core/actions/action_handle_digressions.py +35 -13
- rasa/core/actions/action_run_slot_rejections.py +16 -4
- rasa/core/channels/__init__.py +2 -0
- rasa/core/channels/studio_chat.py +19 -0
- rasa/core/channels/telegram.py +42 -24
- rasa/core/channels/voice_ready/utils.py +1 -1
- rasa/core/channels/voice_stream/asr/asr_engine.py +10 -4
- rasa/core/channels/voice_stream/asr/azure.py +14 -1
- rasa/core/channels/voice_stream/asr/deepgram.py +20 -4
- rasa/core/channels/voice_stream/audiocodes.py +264 -0
- rasa/core/channels/voice_stream/browser_audio.py +4 -1
- rasa/core/channels/voice_stream/call_state.py +3 -0
- rasa/core/channels/voice_stream/genesys.py +6 -2
- rasa/core/channels/voice_stream/tts/azure.py +9 -1
- rasa/core/channels/voice_stream/tts/cartesia.py +14 -8
- rasa/core/channels/voice_stream/voice_channel.py +23 -2
- rasa/core/constants.py +2 -0
- rasa/core/nlg/contextual_response_rephraser.py +18 -1
- rasa/core/nlg/generator.py +83 -15
- rasa/core/nlg/response.py +6 -3
- rasa/core/nlg/translate.py +55 -0
- rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +1 -1
- rasa/core/policies/flows/flow_executor.py +19 -7
- rasa/core/processor.py +71 -9
- rasa/dialogue_understanding/commands/can_not_handle_command.py +20 -2
- rasa/dialogue_understanding/commands/cancel_flow_command.py +24 -6
- rasa/dialogue_understanding/commands/change_flow_command.py +20 -2
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +20 -2
- rasa/dialogue_understanding/commands/clarify_command.py +29 -3
- rasa/dialogue_understanding/commands/command.py +1 -16
- rasa/dialogue_understanding/commands/command_syntax_manager.py +55 -0
- rasa/dialogue_understanding/commands/handle_digressions_command.py +1 -7
- rasa/dialogue_understanding/commands/human_handoff_command.py +20 -2
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +20 -2
- rasa/dialogue_understanding/commands/prompt_command.py +94 -0
- rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +20 -2
- rasa/dialogue_understanding/commands/set_slot_command.py +24 -2
- rasa/dialogue_understanding/commands/skip_question_command.py +20 -2
- rasa/dialogue_understanding/commands/start_flow_command.py +22 -2
- rasa/dialogue_understanding/commands/utils.py +71 -4
- rasa/dialogue_understanding/generator/__init__.py +2 -0
- rasa/dialogue_understanding/generator/command_parser.py +15 -12
- rasa/dialogue_understanding/generator/constants.py +3 -0
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +12 -5
- rasa/dialogue_understanding/generator/llm_command_generator.py +5 -3
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +17 -3
- rasa/dialogue_understanding/generator/prompt_templates/__init__.py +0 -0
- rasa/dialogue_understanding/generator/{single_step → prompt_templates}/command_prompt_template.jinja2 +2 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +77 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_default.jinja2 +68 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +84 -0
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +522 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +12 -310
- rasa/dialogue_understanding/patterns/collect_information.py +1 -1
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +16 -0
- rasa/dialogue_understanding/patterns/validate_slot.py +65 -0
- rasa/dialogue_understanding/processor/command_processor.py +39 -0
- rasa/dialogue_understanding/stack/utils.py +38 -0
- rasa/dialogue_understanding_test/du_test_case.py +58 -18
- rasa/dialogue_understanding_test/du_test_result.py +14 -10
- rasa/dialogue_understanding_test/io.py +14 -0
- rasa/e2e_test/assertions.py +6 -8
- rasa/e2e_test/llm_judge_prompts/answer_relevance_prompt_template.jinja2 +5 -1
- rasa/e2e_test/llm_judge_prompts/groundedness_prompt_template.jinja2 +4 -0
- rasa/e2e_test/utils/io.py +0 -37
- rasa/engine/graph.py +1 -0
- rasa/engine/language.py +140 -0
- rasa/engine/recipes/config_files/default_config.yml +4 -0
- rasa/engine/recipes/default_recipe.py +2 -0
- rasa/engine/recipes/graph_recipe.py +2 -0
- rasa/engine/storage/local_model_storage.py +1 -0
- rasa/engine/storage/storage.py +4 -1
- rasa/llm_fine_tuning/conversations.py +1 -1
- rasa/model_manager/runner_service.py +7 -4
- rasa/model_manager/socket_bridge.py +7 -6
- rasa/shared/constants.py +15 -13
- rasa/shared/core/constants.py +2 -0
- rasa/shared/core/flows/constants.py +11 -0
- rasa/shared/core/flows/flow.py +83 -19
- rasa/shared/core/flows/flows_yaml_schema.json +31 -3
- rasa/shared/core/flows/steps/collect.py +1 -36
- rasa/shared/core/flows/utils.py +28 -4
- rasa/shared/core/flows/validation.py +1 -1
- rasa/shared/core/slot_mappings.py +208 -5
- rasa/shared/core/slots.py +137 -1
- rasa/shared/core/trackers.py +74 -1
- rasa/shared/importers/importer.py +50 -2
- rasa/shared/nlu/training_data/schemas/responses.yml +19 -12
- rasa/shared/providers/_configs/azure_entra_id_config.py +541 -0
- rasa/shared/providers/_configs/azure_openai_client_config.py +138 -3
- rasa/shared/providers/_configs/client_config.py +3 -1
- rasa/shared/providers/_configs/default_litellm_client_config.py +3 -1
- rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +3 -1
- rasa/shared/providers/_configs/litellm_router_client_config.py +3 -1
- rasa/shared/providers/_configs/model_group_config.py +4 -2
- rasa/shared/providers/_configs/oauth_config.py +33 -0
- rasa/shared/providers/_configs/openai_client_config.py +3 -1
- rasa/shared/providers/_configs/rasa_llm_client_config.py +3 -1
- rasa/shared/providers/_configs/self_hosted_llm_client_config.py +3 -1
- rasa/shared/providers/constants.py +6 -0
- rasa/shared/providers/embedding/azure_openai_embedding_client.py +28 -3
- rasa/shared/providers/embedding/litellm_router_embedding_client.py +3 -1
- rasa/shared/providers/llm/_base_litellm_client.py +42 -17
- rasa/shared/providers/llm/azure_openai_llm_client.py +81 -25
- rasa/shared/providers/llm/default_litellm_llm_client.py +3 -1
- rasa/shared/providers/llm/litellm_router_llm_client.py +29 -8
- rasa/shared/providers/llm/llm_client.py +23 -7
- rasa/shared/providers/llm/openai_llm_client.py +9 -3
- rasa/shared/providers/llm/rasa_llm_client.py +11 -2
- rasa/shared/providers/llm/self_hosted_llm_client.py +30 -11
- rasa/shared/providers/router/_base_litellm_router_client.py +3 -1
- rasa/shared/providers/router/router_client.py +3 -1
- rasa/shared/utils/constants.py +3 -0
- rasa/shared/utils/llm.py +33 -7
- rasa/shared/utils/pykwalify_extensions.py +24 -0
- rasa/shared/utils/schemas/domain.yml +26 -0
- rasa/telemetry.py +2 -1
- rasa/tracing/config.py +2 -0
- rasa/tracing/constants.py +12 -0
- rasa/tracing/instrumentation/instrumentation.py +36 -0
- rasa/tracing/instrumentation/metrics.py +41 -0
- rasa/tracing/metric_instrument_provider.py +40 -0
- rasa/validator.py +372 -7
- rasa/version.py +1 -1
- {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc2.dist-info}/METADATA +13 -14
- {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc2.dist-info}/RECORD +139 -124
- {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc2.dist-info}/NOTICE +0 -0
- {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc2.dist-info}/WHEEL +0 -0
- {rasa_pro-3.12.0.dev13.dist-info → rasa_pro-3.12.0rc2.dist-info}/entry_points.txt +0 -0
|
@@ -4,6 +4,10 @@ import re
|
|
|
4
4
|
from dataclasses import dataclass
|
|
5
5
|
from typing import Any, Dict, List
|
|
6
6
|
|
|
7
|
+
from rasa.dialogue_understanding.commands.command_syntax_manager import (
|
|
8
|
+
CommandSyntaxManager,
|
|
9
|
+
CommandSyntaxVersion,
|
|
10
|
+
)
|
|
7
11
|
from rasa.dialogue_understanding.commands.free_form_answer_command import (
|
|
8
12
|
FreeFormAnswerCommand,
|
|
9
13
|
)
|
|
@@ -59,7 +63,14 @@ class KnowledgeAnswerCommand(FreeFormAnswerCommand):
|
|
|
59
63
|
|
|
60
64
|
def to_dsl(self) -> str:
|
|
61
65
|
"""Converts the command to a DSL string."""
|
|
62
|
-
|
|
66
|
+
mapper = {
|
|
67
|
+
CommandSyntaxVersion.v1: "SearchAndReply()",
|
|
68
|
+
CommandSyntaxVersion.v2: "provide info",
|
|
69
|
+
}
|
|
70
|
+
return mapper.get(
|
|
71
|
+
CommandSyntaxManager.get_syntax_version(),
|
|
72
|
+
mapper[CommandSyntaxManager.get_default_syntax_version()],
|
|
73
|
+
)
|
|
63
74
|
|
|
64
75
|
@classmethod
|
|
65
76
|
def from_dsl(cls, match: re.Match, **kwargs: Any) -> KnowledgeAnswerCommand:
|
|
@@ -68,4 +79,11 @@ class KnowledgeAnswerCommand(FreeFormAnswerCommand):
|
|
|
68
79
|
|
|
69
80
|
@staticmethod
|
|
70
81
|
def regex_pattern() -> str:
|
|
71
|
-
|
|
82
|
+
mapper = {
|
|
83
|
+
CommandSyntaxVersion.v1: r"SearchAndReply\(\)",
|
|
84
|
+
CommandSyntaxVersion.v2: r"""^[\s\W\d]*provide info['"`]*$""",
|
|
85
|
+
}
|
|
86
|
+
return mapper.get(
|
|
87
|
+
CommandSyntaxManager.get_syntax_version(),
|
|
88
|
+
mapper[CommandSyntaxManager.get_default_syntax_version()],
|
|
89
|
+
)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from typing import Any, Dict, List, Optional, Protocol, runtime_checkable
|
|
5
|
+
|
|
6
|
+
from rasa.shared.core.events import Event
|
|
7
|
+
from rasa.shared.core.flows import FlowsList
|
|
8
|
+
from rasa.shared.core.trackers import DialogueStateTracker
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@runtime_checkable
|
|
12
|
+
class PromptCommand(Protocol):
|
|
13
|
+
"""
|
|
14
|
+
A protocol for commands predicted by the LLM model and incorporated into the prompt.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
@classmethod
|
|
18
|
+
def command(cls) -> str:
|
|
19
|
+
"""
|
|
20
|
+
Returns the command name.
|
|
21
|
+
|
|
22
|
+
This class method should be implemented to return the name of the command.
|
|
23
|
+
"""
|
|
24
|
+
...
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
def from_dict(cls, data: Dict[str, Any]) -> PromptCommand:
|
|
28
|
+
"""
|
|
29
|
+
Converts the dictionary to a command.
|
|
30
|
+
|
|
31
|
+
This class method should be implemented to create a command instance from the
|
|
32
|
+
given dictionary.
|
|
33
|
+
"""
|
|
34
|
+
...
|
|
35
|
+
|
|
36
|
+
def run_command_on_tracker(
|
|
37
|
+
self,
|
|
38
|
+
tracker: DialogueStateTracker,
|
|
39
|
+
all_flows: FlowsList,
|
|
40
|
+
original_tracker: DialogueStateTracker,
|
|
41
|
+
) -> List[Event]:
|
|
42
|
+
"""
|
|
43
|
+
Runs the command on the tracker.
|
|
44
|
+
|
|
45
|
+
This method should be implemented to execute the command on the given tracker.
|
|
46
|
+
"""
|
|
47
|
+
...
|
|
48
|
+
|
|
49
|
+
def __hash__(self) -> int:
|
|
50
|
+
"""
|
|
51
|
+
Returns the hash of the command.
|
|
52
|
+
|
|
53
|
+
This method should be implemented to return the hash of the command.
|
|
54
|
+
Useful for comparing commands and storing them in sets.
|
|
55
|
+
"""
|
|
56
|
+
...
|
|
57
|
+
|
|
58
|
+
def __eq__(self, other: object) -> bool:
|
|
59
|
+
"""
|
|
60
|
+
Compares the command with another object.
|
|
61
|
+
|
|
62
|
+
This method should be implemented to compare the command with another object.
|
|
63
|
+
"""
|
|
64
|
+
...
|
|
65
|
+
|
|
66
|
+
def to_dsl(self) -> str:
|
|
67
|
+
"""
|
|
68
|
+
Converts the command to a DSL string.
|
|
69
|
+
|
|
70
|
+
This method should be implemented to convert the command to a DSL string.
|
|
71
|
+
A DSL string is a string representation of the command that is used in the
|
|
72
|
+
prompt.
|
|
73
|
+
"""
|
|
74
|
+
...
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def from_dsl(cls, match: re.Match, **kwargs: Any) -> Optional[PromptCommand]:
|
|
78
|
+
"""
|
|
79
|
+
Converts the regex match to a command.
|
|
80
|
+
|
|
81
|
+
This class method should be implemented to create a command instance from the
|
|
82
|
+
given DSL string.
|
|
83
|
+
"""
|
|
84
|
+
...
|
|
85
|
+
|
|
86
|
+
@staticmethod
|
|
87
|
+
def regex_pattern() -> str:
|
|
88
|
+
"""
|
|
89
|
+
Returns the regex pattern for the command.
|
|
90
|
+
|
|
91
|
+
This method should be implemented to return the regex pattern that matches the
|
|
92
|
+
command in the prompt.
|
|
93
|
+
"""
|
|
94
|
+
...
|
|
@@ -5,6 +5,10 @@ from dataclasses import dataclass
|
|
|
5
5
|
from typing import Any, Dict, List
|
|
6
6
|
|
|
7
7
|
from rasa.dialogue_understanding.commands.command import Command
|
|
8
|
+
from rasa.dialogue_understanding.commands.command_syntax_manager import (
|
|
9
|
+
CommandSyntaxManager,
|
|
10
|
+
CommandSyntaxVersion,
|
|
11
|
+
)
|
|
8
12
|
from rasa.dialogue_understanding.patterns.repeat import (
|
|
9
13
|
RepeatBotMessagesPatternFlowStackFrame,
|
|
10
14
|
)
|
|
@@ -60,7 +64,14 @@ class RepeatBotMessagesCommand(Command):
|
|
|
60
64
|
|
|
61
65
|
def to_dsl(self) -> str:
|
|
62
66
|
"""Converts the command to a DSL string."""
|
|
63
|
-
|
|
67
|
+
mapper = {
|
|
68
|
+
CommandSyntaxVersion.v1: "RepeatLastBotMessages()",
|
|
69
|
+
CommandSyntaxVersion.v2: "repeat message",
|
|
70
|
+
}
|
|
71
|
+
return mapper.get(
|
|
72
|
+
CommandSyntaxManager.get_syntax_version(),
|
|
73
|
+
mapper[CommandSyntaxManager.get_default_syntax_version()],
|
|
74
|
+
)
|
|
64
75
|
|
|
65
76
|
@classmethod
|
|
66
77
|
def from_dsl(cls, match: re.Match, **kwargs: Any) -> RepeatBotMessagesCommand:
|
|
@@ -69,4 +80,11 @@ class RepeatBotMessagesCommand(Command):
|
|
|
69
80
|
|
|
70
81
|
@staticmethod
|
|
71
82
|
def regex_pattern() -> str:
|
|
72
|
-
|
|
83
|
+
mapper = {
|
|
84
|
+
CommandSyntaxVersion.v1: r"RepeatLastBotMessages\(\)",
|
|
85
|
+
CommandSyntaxVersion.v2: r"""^[\s\W\d]*repeat message['"`]*$""",
|
|
86
|
+
}
|
|
87
|
+
return mapper.get(
|
|
88
|
+
CommandSyntaxManager.get_syntax_version(),
|
|
89
|
+
mapper[CommandSyntaxManager.get_default_syntax_version()],
|
|
90
|
+
)
|
|
@@ -7,6 +7,10 @@ from typing import Any, Dict, List
|
|
|
7
7
|
import structlog
|
|
8
8
|
|
|
9
9
|
from rasa.dialogue_understanding.commands.command import Command
|
|
10
|
+
from rasa.dialogue_understanding.commands.command_syntax_manager import (
|
|
11
|
+
CommandSyntaxManager,
|
|
12
|
+
CommandSyntaxVersion,
|
|
13
|
+
)
|
|
10
14
|
from rasa.dialogue_understanding.commands.utils import (
|
|
11
15
|
clean_extracted_value,
|
|
12
16
|
get_nullable_slot_value,
|
|
@@ -162,7 +166,14 @@ class SetSlotCommand(Command):
|
|
|
162
166
|
|
|
163
167
|
def to_dsl(self) -> str:
|
|
164
168
|
"""Converts the command to a DSL string."""
|
|
165
|
-
|
|
169
|
+
mapper = {
|
|
170
|
+
CommandSyntaxVersion.v1: f"SetSlot({self.name}, {self.value})",
|
|
171
|
+
CommandSyntaxVersion.v2: f"set slot {self.name} {self.value}",
|
|
172
|
+
}
|
|
173
|
+
return mapper.get(
|
|
174
|
+
CommandSyntaxManager.get_syntax_version(),
|
|
175
|
+
mapper[CommandSyntaxManager.get_default_syntax_version()],
|
|
176
|
+
)
|
|
166
177
|
|
|
167
178
|
@classmethod
|
|
168
179
|
def from_dsl(cls, match: re.Match, **kwargs: Any) -> SetSlotCommand:
|
|
@@ -173,4 +184,15 @@ class SetSlotCommand(Command):
|
|
|
173
184
|
|
|
174
185
|
@staticmethod
|
|
175
186
|
def regex_pattern() -> str:
|
|
176
|
-
|
|
187
|
+
mapper = {
|
|
188
|
+
CommandSyntaxVersion.v1: (
|
|
189
|
+
r"""SetSlot\(['"]?([a-zA-Z_][a-zA-Z0-9_-]*)['"]?, ?['"]?(.*)['"]?\)"""
|
|
190
|
+
),
|
|
191
|
+
CommandSyntaxVersion.v2: (
|
|
192
|
+
r"""^[\s\W\d]*set slot ['"`]?([a-zA-Z_][a-zA-Z0-9_-]*)['"`]? ['"`]?(.+?)['"`]*$""" # noqa: E501
|
|
193
|
+
),
|
|
194
|
+
}
|
|
195
|
+
return mapper.get(
|
|
196
|
+
CommandSyntaxManager.get_syntax_version(),
|
|
197
|
+
mapper[CommandSyntaxManager.get_default_syntax_version()],
|
|
198
|
+
)
|
|
@@ -7,6 +7,10 @@ from typing import Any, Dict, List
|
|
|
7
7
|
import structlog
|
|
8
8
|
|
|
9
9
|
from rasa.dialogue_understanding.commands.command import Command
|
|
10
|
+
from rasa.dialogue_understanding.commands.command_syntax_manager import (
|
|
11
|
+
CommandSyntaxManager,
|
|
12
|
+
CommandSyntaxVersion,
|
|
13
|
+
)
|
|
10
14
|
from rasa.dialogue_understanding.patterns.skip_question import (
|
|
11
15
|
SkipQuestionPatternFlowStackFrame,
|
|
12
16
|
)
|
|
@@ -75,7 +79,14 @@ class SkipQuestionCommand(Command):
|
|
|
75
79
|
|
|
76
80
|
def to_dsl(self) -> str:
|
|
77
81
|
"""Converts the command to a DSL string."""
|
|
78
|
-
|
|
82
|
+
mapper = {
|
|
83
|
+
CommandSyntaxVersion.v1: "SkipQuestion()",
|
|
84
|
+
CommandSyntaxVersion.v2: "skip question",
|
|
85
|
+
}
|
|
86
|
+
return mapper.get(
|
|
87
|
+
CommandSyntaxManager.get_syntax_version(),
|
|
88
|
+
mapper[CommandSyntaxManager.get_default_syntax_version()],
|
|
89
|
+
)
|
|
79
90
|
|
|
80
91
|
@classmethod
|
|
81
92
|
def from_dsl(cls, match: re.Match, **kwargs: Any) -> SkipQuestionCommand:
|
|
@@ -84,4 +95,11 @@ class SkipQuestionCommand(Command):
|
|
|
84
95
|
|
|
85
96
|
@staticmethod
|
|
86
97
|
def regex_pattern() -> str:
|
|
87
|
-
|
|
98
|
+
mapper = {
|
|
99
|
+
CommandSyntaxVersion.v1: r"SkipQuestion\(\)",
|
|
100
|
+
CommandSyntaxVersion.v2: r"""^[\s\W\d]*skip question['"`]*$""",
|
|
101
|
+
}
|
|
102
|
+
return mapper.get(
|
|
103
|
+
CommandSyntaxManager.get_syntax_version(),
|
|
104
|
+
mapper[CommandSyntaxManager.get_default_syntax_version()],
|
|
105
|
+
)
|
|
@@ -7,6 +7,10 @@ from typing import Any, Dict, List, Optional
|
|
|
7
7
|
import structlog
|
|
8
8
|
|
|
9
9
|
from rasa.dialogue_understanding.commands.command import Command
|
|
10
|
+
from rasa.dialogue_understanding.commands.command_syntax_manager import (
|
|
11
|
+
CommandSyntaxManager,
|
|
12
|
+
CommandSyntaxVersion,
|
|
13
|
+
)
|
|
10
14
|
from rasa.dialogue_understanding.patterns.clarify import FLOW_PATTERN_CLARIFICATION
|
|
11
15
|
from rasa.dialogue_understanding.patterns.continue_interrupted import (
|
|
12
16
|
ContinueInterruptedPatternFlowStackFrame,
|
|
@@ -119,7 +123,14 @@ class StartFlowCommand(Command):
|
|
|
119
123
|
|
|
120
124
|
def to_dsl(self) -> str:
|
|
121
125
|
"""Converts the command to a DSL string."""
|
|
122
|
-
|
|
126
|
+
mapper = {
|
|
127
|
+
CommandSyntaxVersion.v1: f"StartFlow({self.flow})",
|
|
128
|
+
CommandSyntaxVersion.v2: f"start flow {self.flow}",
|
|
129
|
+
}
|
|
130
|
+
return mapper.get(
|
|
131
|
+
CommandSyntaxManager.get_syntax_version(),
|
|
132
|
+
mapper[CommandSyntaxManager.get_default_syntax_version()],
|
|
133
|
+
)
|
|
123
134
|
|
|
124
135
|
@classmethod
|
|
125
136
|
def from_dsl(cls, match: re.Match, **kwargs: Any) -> Optional[StartFlowCommand]:
|
|
@@ -128,7 +139,16 @@ class StartFlowCommand(Command):
|
|
|
128
139
|
|
|
129
140
|
@staticmethod
|
|
130
141
|
def regex_pattern() -> str:
|
|
131
|
-
|
|
142
|
+
mapper = {
|
|
143
|
+
CommandSyntaxVersion.v1: r"StartFlow\(['\"]?([a-zA-Z0-9_-]+)['\"]?\)",
|
|
144
|
+
CommandSyntaxVersion.v2: (
|
|
145
|
+
r"""^[\s\W\d]*start flow ['"`]?([a-zA-Z0-9_-]+)['"`]*"""
|
|
146
|
+
),
|
|
147
|
+
}
|
|
148
|
+
return mapper.get(
|
|
149
|
+
CommandSyntaxManager.get_syntax_version(),
|
|
150
|
+
mapper[CommandSyntaxManager.get_default_syntax_version()],
|
|
151
|
+
)
|
|
132
152
|
|
|
133
153
|
def change_flow_frame_position_in_the_stack(
|
|
134
154
|
self, stack: DialogueStack, tracker: DialogueStateTracker
|
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING, List, Optional, Union
|
|
1
|
+
from typing import TYPE_CHECKING, List, Optional, Tuple, Union
|
|
2
2
|
|
|
3
3
|
import structlog
|
|
4
4
|
|
|
5
|
+
from rasa.dialogue_understanding.patterns.validate_slot import (
|
|
6
|
+
ValidateSlotPatternFlowStackFrame,
|
|
7
|
+
)
|
|
8
|
+
from rasa.shared.constants import (
|
|
9
|
+
ACTION_ASK_PREFIX,
|
|
10
|
+
UTTER_ASK_PREFIX,
|
|
11
|
+
)
|
|
12
|
+
from rasa.shared.core.events import Event, SlotSet
|
|
13
|
+
from rasa.shared.core.slots import Slot
|
|
14
|
+
from rasa.shared.core.trackers import DialogueStateTracker
|
|
15
|
+
|
|
5
16
|
if TYPE_CHECKING:
|
|
6
17
|
from rasa.dialogue_understanding.commands import StartFlowCommand
|
|
7
18
|
from rasa.shared.core.flows import FlowsList
|
|
@@ -25,10 +36,13 @@ def start_flow_by_name(
|
|
|
25
36
|
|
|
26
37
|
def extract_cleaned_options(options_str: str) -> List[str]:
|
|
27
38
|
"""Extract and clean options from a string."""
|
|
39
|
+
delimiters = [",", " "]
|
|
40
|
+
|
|
41
|
+
for delimiter in delimiters:
|
|
42
|
+
options_str = options_str.replace(delimiter, " ")
|
|
43
|
+
|
|
28
44
|
return sorted(
|
|
29
|
-
opt.strip().strip('"').strip("'")
|
|
30
|
-
for opt in options_str.split(",")
|
|
31
|
-
if opt.strip()
|
|
45
|
+
opt.strip().strip('"').strip("'") for opt in options_str.split() if opt.strip()
|
|
32
46
|
)
|
|
33
47
|
|
|
34
48
|
|
|
@@ -62,3 +76,56 @@ def get_nullable_slot_value(slot_value: str) -> Union[str, None]:
|
|
|
62
76
|
The slot value or None if the value is a none value.
|
|
63
77
|
"""
|
|
64
78
|
return slot_value if not is_none_value(slot_value) else None
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def initialize_pattern_validate_slot(
|
|
82
|
+
slot: Slot,
|
|
83
|
+
) -> Optional[ValidateSlotPatternFlowStackFrame]:
|
|
84
|
+
"""Initialize the pattern to validate a slot value."""
|
|
85
|
+
if not slot.requires_validation():
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
validation = slot.validation
|
|
89
|
+
slot_name = slot.name
|
|
90
|
+
return ValidateSlotPatternFlowStackFrame(
|
|
91
|
+
validate=slot_name,
|
|
92
|
+
refill_utter=validation.refill_utter or f"{UTTER_ASK_PREFIX}{slot_name}", # type: ignore[union-attr]
|
|
93
|
+
refill_action=f"{ACTION_ASK_PREFIX}{slot_name}",
|
|
94
|
+
rejections=validation.rejections, # type: ignore[union-attr]
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def create_validate_frames_from_slot_set_events(
|
|
99
|
+
tracker: DialogueStateTracker,
|
|
100
|
+
events: List[Event],
|
|
101
|
+
validate_frames: List[ValidateSlotPatternFlowStackFrame] = [],
|
|
102
|
+
should_break: bool = False,
|
|
103
|
+
) -> Tuple[DialogueStateTracker, List[ValidateSlotPatternFlowStackFrame]]:
|
|
104
|
+
"""Process SlotSet events and create validation frames.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
tracker: The dialogue state tracker.
|
|
108
|
+
events: List of events to process.
|
|
109
|
+
should_break: whether or not to break after the first non-SlotSet event.
|
|
110
|
+
if True, break out of the event loop as soon as the first non-SlotSet
|
|
111
|
+
event is encountered.
|
|
112
|
+
if False, continue processing the events until the end.
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
Tuple of (updated tracker, list of validation frames).
|
|
116
|
+
"""
|
|
117
|
+
for event in events:
|
|
118
|
+
if not isinstance(event, SlotSet):
|
|
119
|
+
if should_break:
|
|
120
|
+
# we want to only process the most recent SlotSet events
|
|
121
|
+
# so we break once we encounter a different event
|
|
122
|
+
break
|
|
123
|
+
continue
|
|
124
|
+
|
|
125
|
+
slot = tracker.slots.get(event.key)
|
|
126
|
+
frame = initialize_pattern_validate_slot(slot)
|
|
127
|
+
|
|
128
|
+
if frame:
|
|
129
|
+
validate_frames.append(frame)
|
|
130
|
+
|
|
131
|
+
return tracker, validate_frames
|
|
@@ -9,6 +9,7 @@ from rasa.dialogue_understanding.generator.multi_step.multi_step_llm_command_gen
|
|
|
9
9
|
MultiStepLLMCommandGenerator,
|
|
10
10
|
)
|
|
11
11
|
from rasa.dialogue_understanding.generator.single_step.single_step_llm_command_generator import ( # noqa: E501
|
|
12
|
+
CompactLLMCommandGenerator,
|
|
12
13
|
SingleStepLLMCommandGenerator,
|
|
13
14
|
)
|
|
14
15
|
|
|
@@ -18,4 +19,5 @@ __all__ = [
|
|
|
18
19
|
"LLMCommandGenerator",
|
|
19
20
|
"MultiStepLLMCommandGenerator",
|
|
20
21
|
"SingleStepLLMCommandGenerator",
|
|
22
|
+
"CompactLLMCommandGenerator",
|
|
21
23
|
]
|
|
@@ -16,6 +16,7 @@ from rasa.dialogue_understanding.commands import (
|
|
|
16
16
|
SkipQuestionCommand,
|
|
17
17
|
StartFlowCommand,
|
|
18
18
|
)
|
|
19
|
+
from rasa.dialogue_understanding.commands.prompt_command import PromptCommand
|
|
19
20
|
from rasa.dialogue_understanding.commands.utils import start_flow_by_name
|
|
20
21
|
from rasa.shared.core.flows import FlowsList
|
|
21
22
|
|
|
@@ -41,8 +42,8 @@ def _get_compiled_pattern(pattern_str: str) -> re.Pattern:
|
|
|
41
42
|
|
|
42
43
|
|
|
43
44
|
def _create_default_commands(
|
|
44
|
-
default_commands_to_remove: Union[List[Type[
|
|
45
|
-
) -> List[Type[
|
|
45
|
+
default_commands_to_remove: Union[List[Type[PromptCommand]], List[str]],
|
|
46
|
+
) -> List[Type[PromptCommand]]:
|
|
46
47
|
"""Return an updated list of default commands after removing the provided commands.
|
|
47
48
|
|
|
48
49
|
Args:
|
|
@@ -64,11 +65,11 @@ def _create_default_commands(
|
|
|
64
65
|
|
|
65
66
|
|
|
66
67
|
def _get_additional_parsing_logic(
|
|
67
|
-
command_clz: Type[
|
|
68
|
-
) -> Optional[Callable[[
|
|
68
|
+
command_clz: Type[PromptCommand],
|
|
69
|
+
) -> Optional[Callable[[PromptCommand, FlowsList], Optional[PromptCommand]]]:
|
|
69
70
|
"""Get additional parsing logic for a command."""
|
|
70
71
|
command_to_parsing_fn_mapper: Dict[
|
|
71
|
-
Type[
|
|
72
|
+
Type[PromptCommand], Callable[..., Optional[PromptCommand]]
|
|
72
73
|
] = {
|
|
73
74
|
ClarifyCommand: _parse_clarify_command,
|
|
74
75
|
SetSlotCommand: _parse_set_slot_command,
|
|
@@ -81,8 +82,10 @@ def parse_commands(
|
|
|
81
82
|
actions: Optional[str],
|
|
82
83
|
flows: FlowsList,
|
|
83
84
|
is_handle_flows_prompt: bool = False,
|
|
84
|
-
additional_commands: Optional[List[Type[
|
|
85
|
-
default_commands_to_remove: Optional[
|
|
85
|
+
additional_commands: Optional[List[Type[PromptCommand]]] = None,
|
|
86
|
+
default_commands_to_remove: Optional[
|
|
87
|
+
Union[List[Type[PromptCommand]], List[str]]
|
|
88
|
+
] = None,
|
|
86
89
|
**kwargs: Any,
|
|
87
90
|
) -> List[Command]:
|
|
88
91
|
"""Parse a list of action commands."""
|
|
@@ -116,7 +119,7 @@ def parse_commands(
|
|
|
116
119
|
|
|
117
120
|
|
|
118
121
|
def _parse_standard_commands(
|
|
119
|
-
standard_commands: List[Type[
|
|
122
|
+
standard_commands: List[Type[PromptCommand]],
|
|
120
123
|
action: str,
|
|
121
124
|
flows: FlowsList,
|
|
122
125
|
**kwargs: Any,
|
|
@@ -135,7 +138,7 @@ def _parse_standard_commands(
|
|
|
135
138
|
|
|
136
139
|
|
|
137
140
|
def _parse_custom_commands(
|
|
138
|
-
custom_commands: List[Type[
|
|
141
|
+
custom_commands: List[Type[PromptCommand]],
|
|
139
142
|
action: str,
|
|
140
143
|
flows: FlowsList,
|
|
141
144
|
**kwargs: Any,
|
|
@@ -152,7 +155,7 @@ def _parse_custom_commands(
|
|
|
152
155
|
|
|
153
156
|
def _parse_set_slot_command(
|
|
154
157
|
parsed_command: Optional[SetSlotCommand], flows: FlowsList, **kwargs: Any
|
|
155
|
-
) -> Optional[
|
|
158
|
+
) -> Optional[PromptCommand]:
|
|
156
159
|
"""Additional parsing logic for the SetSlotCommand."""
|
|
157
160
|
if not parsed_command:
|
|
158
161
|
return None
|
|
@@ -164,7 +167,7 @@ def _parse_set_slot_command(
|
|
|
164
167
|
|
|
165
168
|
def _parse_clarify_command(
|
|
166
169
|
parsed_command: Optional[ClarifyCommand], flows: FlowsList, **kwargs: Any
|
|
167
|
-
) -> Optional[
|
|
170
|
+
) -> Optional[PromptCommand]:
|
|
168
171
|
"""Additional parsing logic for the ClarifyCommand."""
|
|
169
172
|
if not parsed_command:
|
|
170
173
|
return None
|
|
@@ -194,7 +197,7 @@ def _parse_clarify_command(
|
|
|
194
197
|
|
|
195
198
|
def _parse_start_flow_command(
|
|
196
199
|
parsed_command: Optional[StartFlowCommand], flows: FlowsList, **kwargs: Any
|
|
197
|
-
) -> Optional[
|
|
200
|
+
) -> Optional[PromptCommand]:
|
|
198
201
|
"""Additional parsing logic for the StartFlowCommand."""
|
|
199
202
|
if not parsed_command:
|
|
200
203
|
return None
|
|
@@ -27,9 +27,7 @@ from rasa.engine.graph import ExecutionContext, GraphComponent
|
|
|
27
27
|
from rasa.engine.recipes.default_recipe import DefaultV1Recipe
|
|
28
28
|
from rasa.engine.storage.resource import Resource
|
|
29
29
|
from rasa.engine.storage.storage import ModelStorage
|
|
30
|
-
from rasa.shared.core.constants import
|
|
31
|
-
SetSlotExtractor,
|
|
32
|
-
)
|
|
30
|
+
from rasa.shared.core.constants import SetSlotExtractor
|
|
33
31
|
from rasa.shared.core.domain import Domain
|
|
34
32
|
from rasa.shared.core.flows import Flow, FlowsList, FlowStep
|
|
35
33
|
from rasa.shared.core.flows.steps.collect import CollectInformationFlowStep
|
|
@@ -313,11 +311,20 @@ class LLMBasedCommandGenerator(
|
|
|
313
311
|
return filtered_flows
|
|
314
312
|
|
|
315
313
|
@measure_llm_latency
|
|
316
|
-
async def invoke_llm(
|
|
314
|
+
async def invoke_llm(
|
|
315
|
+
self, prompt: Union[List[dict], List[str], str]
|
|
316
|
+
) -> Optional[LLMResponse]:
|
|
317
317
|
"""Use LLM to generate a response.
|
|
318
318
|
|
|
319
319
|
Args:
|
|
320
|
-
prompt: The prompt
|
|
320
|
+
prompt: The prompt can be,
|
|
321
|
+
- a list of preformatted messages. Each message should be a dictionary
|
|
322
|
+
with the following keys:
|
|
323
|
+
- content: The message content.
|
|
324
|
+
- role: The role of the message (e.g. user or system).
|
|
325
|
+
- a list of messages. Each message is a string and will be formatted
|
|
326
|
+
as a user message.
|
|
327
|
+
- a single message as a string which will be formatted as user message.
|
|
321
328
|
|
|
322
329
|
Returns:
|
|
323
330
|
An LLMResponse object.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any, Dict, Optional, Text
|
|
1
|
+
from typing import Any, Dict, List, Optional, Text, Union
|
|
2
2
|
|
|
3
3
|
import structlog
|
|
4
4
|
from deprecated import deprecated # type: ignore[import]
|
|
@@ -25,7 +25,7 @@ structlogger = structlog.get_logger()
|
|
|
25
25
|
@deprecated(
|
|
26
26
|
reason=(
|
|
27
27
|
"The LLMCommandGenerator is deprecated and will be removed in Rasa 4.0.0. "
|
|
28
|
-
"Please use
|
|
28
|
+
"Please use SingleStepLLMCommandGenerator instead."
|
|
29
29
|
)
|
|
30
30
|
)
|
|
31
31
|
class LLMCommandGenerator(SingleStepLLMCommandGenerator):
|
|
@@ -54,7 +54,9 @@ class LLMCommandGenerator(SingleStepLLMCommandGenerator):
|
|
|
54
54
|
**kwargs,
|
|
55
55
|
)
|
|
56
56
|
|
|
57
|
-
async def invoke_llm(
|
|
57
|
+
async def invoke_llm(
|
|
58
|
+
self, prompt: Union[List[dict], List[str], str]
|
|
59
|
+
) -> Optional[LLMResponse]:
|
|
58
60
|
try:
|
|
59
61
|
return await super().invoke_llm(prompt)
|
|
60
62
|
except ProviderClientAPIException:
|
|
@@ -2,6 +2,7 @@ import importlib.resources
|
|
|
2
2
|
from typing import Any, Dict, List, Optional, Text, Tuple, Union
|
|
3
3
|
|
|
4
4
|
import structlog
|
|
5
|
+
from deprecated import deprecated # type: ignore[import]
|
|
5
6
|
from jinja2 import Template
|
|
6
7
|
|
|
7
8
|
import rasa.shared.utils.io
|
|
@@ -51,7 +52,7 @@ from rasa.shared.exceptions import ProviderClientAPIException
|
|
|
51
52
|
from rasa.shared.nlu.constants import TEXT
|
|
52
53
|
from rasa.shared.nlu.training_data.message import Message
|
|
53
54
|
from rasa.shared.providers.llm.llm_response import LLMResponse
|
|
54
|
-
from rasa.shared.utils.io import deep_container_fingerprint
|
|
55
|
+
from rasa.shared.utils.io import deep_container_fingerprint, raise_deprecation_warning
|
|
55
56
|
from rasa.shared.utils.llm import (
|
|
56
57
|
allowed_values_for_slot,
|
|
57
58
|
get_prompt_template,
|
|
@@ -100,6 +101,12 @@ structlogger = structlog.get_logger()
|
|
|
100
101
|
],
|
|
101
102
|
is_trainable=True,
|
|
102
103
|
)
|
|
104
|
+
@deprecated(
|
|
105
|
+
reason=(
|
|
106
|
+
"The MultiStepLLMCommandGenerator is deprecated and will be removed in "
|
|
107
|
+
"Rasa `4.0.0`."
|
|
108
|
+
)
|
|
109
|
+
)
|
|
103
110
|
class MultiStepLLMCommandGenerator(LLMBasedCommandGenerator):
|
|
104
111
|
"""An multi step command generator using LLM."""
|
|
105
112
|
|
|
@@ -111,6 +118,14 @@ class MultiStepLLMCommandGenerator(LLMBasedCommandGenerator):
|
|
|
111
118
|
prompt_templates: Optional[Dict[Text, Optional[Text]]] = None,
|
|
112
119
|
**kwargs: Any,
|
|
113
120
|
) -> None:
|
|
121
|
+
raise_deprecation_warning(
|
|
122
|
+
message=(
|
|
123
|
+
"Support for `MultiStepLLMCommandGenerator` will be removed in Rasa "
|
|
124
|
+
"`4.0.0`. Please modify your assistant's configuration to use other "
|
|
125
|
+
"LLM command generators like the `SingleStepLLMCommandGenerator`."
|
|
126
|
+
)
|
|
127
|
+
)
|
|
128
|
+
|
|
114
129
|
super().__init__(
|
|
115
130
|
config, model_storage, resource, prompt_templates=prompt_templates, **kwargs
|
|
116
131
|
)
|
|
@@ -120,7 +135,6 @@ class MultiStepLLMCommandGenerator(LLMBasedCommandGenerator):
|
|
|
120
135
|
FILL_SLOTS_KEY: None,
|
|
121
136
|
}
|
|
122
137
|
self._init_prompt_templates(prompt_templates)
|
|
123
|
-
|
|
124
138
|
self.trace_prompt_tokens = self.config.get("trace_prompt_tokens", False)
|
|
125
139
|
|
|
126
140
|
### Implementations of LLMBasedCommandGenerator parent
|
|
@@ -212,7 +226,7 @@ class MultiStepLLMCommandGenerator(LLMBasedCommandGenerator):
|
|
|
212
226
|
# be completed, "predict" the ErrorCommand
|
|
213
227
|
commands = [ErrorCommand()]
|
|
214
228
|
|
|
215
|
-
if not commands:
|
|
229
|
+
if not commands and not prior_commands:
|
|
216
230
|
# if for any reason the final list of commands is empty,
|
|
217
231
|
# "predict" CannotHandle
|
|
218
232
|
commands = [CannotHandleCommand()]
|
|
File without changes
|
|
@@ -41,7 +41,9 @@ Based on this information generate a list of actions you want to take. Your job
|
|
|
41
41
|
* Responding to knowledge-oriented user messages, described by "SearchAndReply()"
|
|
42
42
|
* Responding to a casual, non-task-oriented user message, described by "ChitChat()".
|
|
43
43
|
* Handing off to a human, in case the user seems frustrated or explicitly asks to speak to one, described by "HumanHandoff()".
|
|
44
|
+
{% if is_repeat_command_enabled %}
|
|
44
45
|
* Repeat the last bot messages, described by "RepeatLastBotMessages()". This is useful when the user asks to repeat the last bot messages.
|
|
46
|
+
{% endif %}
|
|
45
47
|
|
|
46
48
|
===
|
|
47
49
|
Write out the actions you want to take, one per line, in the order they should take place.
|