rasa-pro 3.12.0.dev12__py3-none-any.whl → 3.12.0rc1__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.
- rasa/anonymization/anonymization_rule_executor.py +16 -10
- rasa/cli/data.py +16 -0
- rasa/cli/inspect.py +20 -1
- rasa/cli/project_templates/calm/config.yml +2 -2
- rasa/cli/project_templates/calm/endpoints.yml +2 -2
- rasa/cli/shell.py +3 -3
- rasa/cli/utils.py +12 -0
- rasa/core/actions/action.py +99 -193
- rasa/core/actions/action_handle_digressions.py +142 -0
- rasa/core/actions/action_run_slot_rejections.py +16 -4
- rasa/core/actions/forms.py +10 -5
- rasa/core/channels/__init__.py +4 -0
- rasa/core/channels/studio_chat.py +19 -0
- rasa/core/channels/telegram.py +42 -24
- rasa/core/channels/voice_ready/audiocodes.py +42 -23
- 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 +5 -1
- rasa/core/channels/voice_stream/call_state.py +10 -1
- rasa/core/channels/voice_stream/genesys.py +335 -0
- rasa/core/channels/voice_stream/tts/azure.py +11 -2
- rasa/core/channels/voice_stream/tts/cartesia.py +29 -10
- rasa/core/channels/voice_stream/twilio_media_streams.py +2 -1
- rasa/core/channels/voice_stream/voice_channel.py +25 -3
- rasa/core/constants.py +2 -0
- rasa/core/migrate.py +2 -2
- 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 +47 -46
- rasa/core/processor.py +72 -9
- rasa/core/run.py +4 -3
- rasa/dialogue_understanding/commands/can_not_handle_command.py +20 -2
- rasa/dialogue_understanding/commands/cancel_flow_command.py +80 -4
- 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/correct_slots_command.py +11 -2
- rasa/dialogue_understanding/commands/handle_digressions_command.py +150 -0
- 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 +29 -15
- rasa/dialogue_understanding/commands/skip_question_command.py +20 -2
- rasa/dialogue_understanding/commands/start_flow_command.py +61 -2
- rasa/dialogue_understanding/commands/utils.py +98 -4
- rasa/dialogue_understanding/constants.py +1 -0
- rasa/dialogue_understanding/generator/__init__.py +2 -0
- rasa/dialogue_understanding/generator/command_generator.py +110 -73
- rasa/dialogue_understanding/generator/command_parser.py +16 -13
- rasa/dialogue_understanding/generator/constants.py +3 -0
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +170 -5
- rasa/dialogue_understanding/generator/llm_command_generator.py +5 -3
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +26 -4
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +44 -3
- rasa/dialogue_understanding/generator/prompt_templates/__init__.py +0 -0
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_template.jinja2 +60 -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/{single_step/command_prompt_template.jinja2 → prompt_templates/command_prompt_v2_gpt_4o_2024_11_20_template.jinja2} +1 -1
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +460 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +12 -318
- rasa/dialogue_understanding/generator/utils.py +32 -1
- rasa/dialogue_understanding/patterns/collect_information.py +1 -1
- rasa/dialogue_understanding/patterns/correction.py +13 -1
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +78 -2
- rasa/dialogue_understanding/patterns/handle_digressions.py +81 -0
- rasa/dialogue_understanding/patterns/validate_slot.py +65 -0
- rasa/dialogue_understanding/processor/command_processor.py +154 -28
- rasa/dialogue_understanding/utils.py +31 -0
- rasa/dialogue_understanding_test/README.md +50 -0
- rasa/dialogue_understanding_test/du_test_case.py +28 -8
- rasa/dialogue_understanding_test/du_test_result.py +13 -9
- rasa/dialogue_understanding_test/io.py +14 -0
- rasa/dialogue_understanding_test/test_case_simulation/test_case_tracker_simulator.py +3 -3
- 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/model_manager/runner_service.py +7 -4
- rasa/model_manager/socket_bridge.py +7 -6
- rasa/model_manager/warm_rasa_process.py +0 -1
- rasa/model_training.py +24 -27
- rasa/shared/constants.py +15 -13
- rasa/shared/core/constants.py +30 -3
- rasa/shared/core/domain.py +13 -20
- rasa/shared/core/events.py +13 -2
- rasa/shared/core/flows/constants.py +11 -0
- rasa/shared/core/flows/flow.py +100 -19
- rasa/shared/core/flows/flows_yaml_schema.json +69 -3
- rasa/shared/core/flows/steps/collect.py +19 -37
- rasa/shared/core/flows/utils.py +43 -4
- rasa/shared/core/flows/validation.py +1 -1
- rasa/shared/core/slot_mappings.py +350 -111
- rasa/shared/core/slots.py +154 -3
- rasa/shared/core/trackers.py +77 -2
- rasa/shared/importers/importer.py +50 -2
- rasa/shared/nlu/constants.py +1 -0
- 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 +31 -8
- rasa/shared/utils/pykwalify_extensions.py +24 -0
- rasa/shared/utils/schemas/domain.yml +26 -1
- rasa/telemetry.py +45 -14
- 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/utils/common.py +0 -1
- rasa/validator.py +561 -89
- rasa/version.py +1 -1
- {rasa_pro-3.12.0.dev12.dist-info → rasa_pro-3.12.0rc1.dist-info}/METADATA +2 -1
- {rasa_pro-3.12.0.dev12.dist-info → rasa_pro-3.12.0rc1.dist-info}/RECORD +153 -134
- {rasa_pro-3.12.0.dev12.dist-info → rasa_pro-3.12.0rc1.dist-info}/NOTICE +0 -0
- {rasa_pro-3.12.0.dev12.dist-info → rasa_pro-3.12.0rc1.dist-info}/WHEEL +0 -0
- {rasa_pro-3.12.0.dev12.dist-info → rasa_pro-3.12.0rc1.dist-info}/entry_points.txt +0 -0
rasa/e2e_test/utils/io.py
CHANGED
|
@@ -49,7 +49,6 @@ if TYPE_CHECKING:
|
|
|
49
49
|
from rasa.e2e_test.e2e_test_result import TestResult
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
RASA_PRO_BETA_E2E_ASSERTIONS_ENV_VAR_NAME = "RASA_PRO_BETA_E2E_ASSERTIONS"
|
|
53
52
|
RASA_PRO_BETA_STUB_CUSTOM_ACTION_ENV_VAR_NAME = "RASA_PRO_BETA_STUB_CUSTOM_ACTION"
|
|
54
53
|
|
|
55
54
|
structlogger = structlog.get_logger()
|
|
@@ -278,16 +277,6 @@ def split_into_passed_failed(
|
|
|
278
277
|
return passed_cases, failed_cases
|
|
279
278
|
|
|
280
279
|
|
|
281
|
-
def has_test_case_with_assertions(test_cases: List[TestCase]) -> bool:
|
|
282
|
-
"""Check if the test cases contain assertions."""
|
|
283
|
-
try:
|
|
284
|
-
next(test_case for test_case in test_cases if test_case.uses_assertions())
|
|
285
|
-
except StopIteration:
|
|
286
|
-
return False
|
|
287
|
-
|
|
288
|
-
return True
|
|
289
|
-
|
|
290
|
-
|
|
291
280
|
@lru_cache(maxsize=1)
|
|
292
281
|
def extract_test_case_from_path(path: str) -> Tuple[str, str]:
|
|
293
282
|
"""Extract test case from path if specified.
|
|
@@ -442,7 +431,6 @@ def read_test_cases(path: str) -> TestSuite:
|
|
|
442
431
|
fixtures: Dict[str, Fixture] = {}
|
|
443
432
|
metadata: Dict[str, Metadata] = {}
|
|
444
433
|
stub_custom_actions: Dict[str, StubCustomAction] = {}
|
|
445
|
-
beta_flag_verified = False
|
|
446
434
|
|
|
447
435
|
# Process each test file
|
|
448
436
|
for test_file in test_files:
|
|
@@ -460,10 +448,6 @@ def read_test_cases(path: str) -> TestSuite:
|
|
|
460
448
|
stub_custom_actions.update(
|
|
461
449
|
extract_stub_custom_actions(test_file_content, test_file)
|
|
462
450
|
)
|
|
463
|
-
|
|
464
|
-
beta_flag_verified = verify_beta_feature_flag_for_assertions(
|
|
465
|
-
test_cases, beta_flag_verified
|
|
466
|
-
)
|
|
467
451
|
input_test_cases.extend(test_cases)
|
|
468
452
|
|
|
469
453
|
validate_test_case(test_case_name, input_test_cases, fixtures, metadata)
|
|
@@ -489,27 +473,6 @@ def check_beta_feature_flag_for_custom_actions_stubs() -> None:
|
|
|
489
473
|
rasa.shared.utils.cli.print_error_and_exit(str(exc))
|
|
490
474
|
|
|
491
475
|
|
|
492
|
-
def verify_beta_feature_flag_for_assertions(
|
|
493
|
-
test_cases: List[TestCase], beta_flag_verified: bool
|
|
494
|
-
) -> bool:
|
|
495
|
-
"""Verify the beta feature flag for assertions."""
|
|
496
|
-
if beta_flag_verified:
|
|
497
|
-
return True
|
|
498
|
-
|
|
499
|
-
if not has_test_case_with_assertions(test_cases):
|
|
500
|
-
return beta_flag_verified
|
|
501
|
-
|
|
502
|
-
try:
|
|
503
|
-
ensure_beta_feature_is_enabled(
|
|
504
|
-
"end-to-end testing with assertions",
|
|
505
|
-
RASA_PRO_BETA_E2E_ASSERTIONS_ENV_VAR_NAME,
|
|
506
|
-
)
|
|
507
|
-
except BetaNotEnabledException as exc:
|
|
508
|
-
rasa.shared.utils.cli.print_error_and_exit(str(exc))
|
|
509
|
-
|
|
510
|
-
return True
|
|
511
|
-
|
|
512
|
-
|
|
513
476
|
def _save_coverage_report(
|
|
514
477
|
report: Optional[pd.DataFrame], test_status: str, output_dir: str
|
|
515
478
|
) -> None:
|
rasa/engine/graph.py
CHANGED
rasa/engine/language.py
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Any, Dict, Text
|
|
3
|
+
|
|
4
|
+
from langcodes import Language as LangcodesLanguage
|
|
5
|
+
|
|
6
|
+
from rasa.shared.exceptions import RasaException
|
|
7
|
+
|
|
8
|
+
CUSTOM_LANGUAGE_CODE_PREFIX = "x-"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class Language:
|
|
13
|
+
code: str
|
|
14
|
+
label: str
|
|
15
|
+
is_default: bool
|
|
16
|
+
|
|
17
|
+
@classmethod
|
|
18
|
+
def from_language_code(
|
|
19
|
+
cls, language_code: str, is_default: bool = False
|
|
20
|
+
) -> "Language":
|
|
21
|
+
"""Creates a Language object from a language code.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
language_code: The language code.
|
|
25
|
+
is_default: Whether the language is the default language.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
A Language object.
|
|
29
|
+
|
|
30
|
+
Raises:
|
|
31
|
+
RasaException: If the language code or custom language code is invalid.
|
|
32
|
+
"""
|
|
33
|
+
language = LangcodesLanguage.make(language_code)
|
|
34
|
+
cls.validate_language(language)
|
|
35
|
+
|
|
36
|
+
return cls(
|
|
37
|
+
code=language_code,
|
|
38
|
+
label=cls.get_language_label(language),
|
|
39
|
+
is_default=is_default,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
@staticmethod
|
|
43
|
+
def get_language_label(language: LangcodesLanguage) -> str:
|
|
44
|
+
"""Gets the display name of a language.
|
|
45
|
+
|
|
46
|
+
For custom languages (in the format "x-<base_lang>-<custom_label>"),
|
|
47
|
+
the label is derived from the base language code.
|
|
48
|
+
This method considers that the language code has previously been validated.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
language: The language code.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
The display name of the language.
|
|
55
|
+
"""
|
|
56
|
+
language_code = str(language)
|
|
57
|
+
|
|
58
|
+
if language_code.startswith(CUSTOM_LANGUAGE_CODE_PREFIX):
|
|
59
|
+
# If it's a custom language, derive the label from the base language code.
|
|
60
|
+
parts = language_code.split("-")
|
|
61
|
+
base_language_code = parts[1]
|
|
62
|
+
base_language = LangcodesLanguage.make(base_language_code)
|
|
63
|
+
return base_language.display_name()
|
|
64
|
+
else:
|
|
65
|
+
return language.display_name()
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def validate_language(cls, language: LangcodesLanguage) -> None:
|
|
69
|
+
"""Validates a language code.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
language: The language object to validate.
|
|
73
|
+
|
|
74
|
+
Raises:
|
|
75
|
+
RasaException: If the language validation fails.
|
|
76
|
+
"""
|
|
77
|
+
if not language.is_valid():
|
|
78
|
+
raise RasaException(f"Language '{language}' is not a valid language code.")
|
|
79
|
+
|
|
80
|
+
language_code = str(language)
|
|
81
|
+
if language_code.startswith(CUSTOM_LANGUAGE_CODE_PREFIX):
|
|
82
|
+
cls.validate_custom_language(language_code)
|
|
83
|
+
|
|
84
|
+
@staticmethod
|
|
85
|
+
def validate_custom_language(custom_language_code: str) -> None:
|
|
86
|
+
"""Validates a custom language code.
|
|
87
|
+
|
|
88
|
+
A valid custom language code should adhere to the format:
|
|
89
|
+
"x-<existing_language_code>-<custom_label>"
|
|
90
|
+
Example: x-en-formal
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
custom_language_code: The custom language code to validate.
|
|
94
|
+
|
|
95
|
+
Raises:
|
|
96
|
+
RasaException: If the custom language code validation fails.
|
|
97
|
+
"""
|
|
98
|
+
# Ensure the custom language code starts with the custom prefix.
|
|
99
|
+
if not custom_language_code.startswith(CUSTOM_LANGUAGE_CODE_PREFIX):
|
|
100
|
+
raise RasaException(
|
|
101
|
+
f"Custom language '{custom_language_code}' must "
|
|
102
|
+
f"start with '{CUSTOM_LANGUAGE_CODE_PREFIX}'."
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Split the language code into parts.
|
|
106
|
+
parts = custom_language_code.split("-")
|
|
107
|
+
if len(parts) != 3:
|
|
108
|
+
raise RasaException(
|
|
109
|
+
f"Custom language '{custom_language_code}' must be in the format "
|
|
110
|
+
f"'{CUSTOM_LANGUAGE_CODE_PREFIX}<language_code>-<custom_label>'."
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Validate the base language code using langcodes.
|
|
114
|
+
base_language_code = parts[1]
|
|
115
|
+
base_language = LangcodesLanguage.make(base_language_code)
|
|
116
|
+
if not base_language.is_valid():
|
|
117
|
+
raise RasaException(
|
|
118
|
+
f"Base language '{base_language_code}' in custom language "
|
|
119
|
+
f"'{custom_language_code}' is not a valid language code."
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# Ensure the custom label is not empty.
|
|
123
|
+
custom_label = parts[2]
|
|
124
|
+
if not custom_label:
|
|
125
|
+
raise RasaException(
|
|
126
|
+
f"Custom label in custom language "
|
|
127
|
+
f"'{custom_language_code}' cannot be empty."
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
def as_dict(self) -> Dict[Text, Any]:
|
|
131
|
+
"""Converts the Language dataclass instance into a dictionary.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
A dictionary representing the Language object.
|
|
135
|
+
"""
|
|
136
|
+
return {
|
|
137
|
+
"code": self.code,
|
|
138
|
+
"label": self.label,
|
|
139
|
+
"is_default": self.is_default,
|
|
140
|
+
}
|
|
@@ -9,6 +9,10 @@ assistant_id: placeholder_default
|
|
|
9
9
|
# Configuration for the Rasa NLU components.
|
|
10
10
|
# https://rasa.com/docs/rasa-pro/nlu-based-assistants/components
|
|
11
11
|
language: en
|
|
12
|
+
additional_languages:
|
|
13
|
+
- it
|
|
14
|
+
- de
|
|
15
|
+
- es
|
|
12
16
|
|
|
13
17
|
pipeline:
|
|
14
18
|
- name: WhitespaceTokenizer
|
|
@@ -49,6 +49,7 @@ from rasa.graph_components.providers.training_tracker_provider import (
|
|
|
49
49
|
)
|
|
50
50
|
from rasa.shared.constants import (
|
|
51
51
|
ASSISTANT_ID_KEY,
|
|
52
|
+
CONFIG_ADDITIONAL_LANGUAGES_KEY,
|
|
52
53
|
CONFIG_LANGUAGE_KEY,
|
|
53
54
|
CONFIG_NAME_KEY,
|
|
54
55
|
CONFIG_PIPELINE_KEY,
|
|
@@ -247,6 +248,7 @@ class DefaultV1Recipe(Recipe):
|
|
|
247
248
|
language=config.get(CONFIG_LANGUAGE_KEY),
|
|
248
249
|
core_target=core_target,
|
|
249
250
|
nlu_target=f"{GRAPH_NODE_RUN_PREFIX}{RegexMessageHandler.__name__}",
|
|
251
|
+
additional_languages=config.get(CONFIG_ADDITIONAL_LANGUAGES_KEY),
|
|
250
252
|
)
|
|
251
253
|
|
|
252
254
|
def _create_train_nodes(
|
|
@@ -5,6 +5,7 @@ from rasa.engine.graph import GraphModelConfiguration, GraphSchema
|
|
|
5
5
|
from rasa.engine.recipes.recipe import Recipe
|
|
6
6
|
from rasa.shared.constants import (
|
|
7
7
|
ASSISTANT_ID_KEY,
|
|
8
|
+
CONFIG_ADDITIONAL_LANGUAGES_KEY,
|
|
8
9
|
CONFIG_LANGUAGE_KEY,
|
|
9
10
|
DOCS_URL_GRAPH_RECIPE,
|
|
10
11
|
)
|
|
@@ -76,4 +77,5 @@ class GraphV1Recipe(Recipe):
|
|
|
76
77
|
language=config.get(CONFIG_LANGUAGE_KEY),
|
|
77
78
|
core_target=core_target,
|
|
78
79
|
nlu_target=nlu_target,
|
|
80
|
+
additional_languages=config.get(CONFIG_ADDITIONAL_LANGUAGES_KEY),
|
|
79
81
|
)
|
|
@@ -240,6 +240,7 @@ class LocalModelStorage(ModelStorage):
|
|
|
240
240
|
training_type=model_configuration.training_type,
|
|
241
241
|
project_fingerprint=rasa.model.project_fingerprint(),
|
|
242
242
|
language=model_configuration.language,
|
|
243
|
+
additional_languages=model_configuration.additional_languages,
|
|
243
244
|
core_target=model_configuration.core_target,
|
|
244
245
|
nlu_target=model_configuration.nlu_target,
|
|
245
246
|
)
|
rasa/engine/storage/storage.py
CHANGED
|
@@ -7,7 +7,7 @@ from contextlib import contextmanager
|
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
from datetime import datetime
|
|
9
9
|
from pathlib import Path
|
|
10
|
-
from typing import Any, Dict, Generator, Optional, Text, Tuple, Union
|
|
10
|
+
from typing import Any, Dict, Generator, List, Optional, Text, Tuple, Union
|
|
11
11
|
|
|
12
12
|
from packaging import version
|
|
13
13
|
|
|
@@ -142,6 +142,7 @@ class ModelMetadata:
|
|
|
142
142
|
core_target: Optional[Text]
|
|
143
143
|
nlu_target: Text
|
|
144
144
|
language: Optional[Text]
|
|
145
|
+
additional_languages: Optional[List[Text]]
|
|
145
146
|
training_type: TrainingType = TrainingType.BOTH
|
|
146
147
|
|
|
147
148
|
def __post_init__(self) -> None:
|
|
@@ -171,6 +172,7 @@ class ModelMetadata:
|
|
|
171
172
|
"core_target": self.core_target,
|
|
172
173
|
"nlu_target": self.nlu_target,
|
|
173
174
|
"language": self.language,
|
|
175
|
+
"additional_languages": self.additional_languages,
|
|
174
176
|
}
|
|
175
177
|
|
|
176
178
|
@classmethod
|
|
@@ -198,4 +200,5 @@ class ModelMetadata:
|
|
|
198
200
|
core_target=serialized["core_target"],
|
|
199
201
|
nlu_target=serialized["nlu_target"],
|
|
200
202
|
language=serialized["language"],
|
|
203
|
+
additional_languages=serialized.get("additional_languages"),
|
|
201
204
|
)
|
|
@@ -258,10 +258,13 @@ def run_bot(
|
|
|
258
258
|
|
|
259
259
|
async def update_bot_status(bot: BotSession) -> None:
|
|
260
260
|
"""Update the status of a bot based on the process return code."""
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
261
|
+
try:
|
|
262
|
+
if bot.has_died_recently():
|
|
263
|
+
set_bot_status_to_stopped(bot)
|
|
264
|
+
elif await bot.completed_startup_recently():
|
|
265
|
+
set_bot_status_to_running(bot)
|
|
266
|
+
except Exception as e:
|
|
267
|
+
structlogger.error("model_runner.update_bot_status.error", error=str(e))
|
|
265
268
|
|
|
266
269
|
|
|
267
270
|
def terminate_bot(bot: BotSession) -> None:
|
|
@@ -4,6 +4,7 @@ from typing import Any, Dict, Optional
|
|
|
4
4
|
import structlog
|
|
5
5
|
from socketio import AsyncServer
|
|
6
6
|
from socketio.asyncio_client import AsyncClient
|
|
7
|
+
from socketio.exceptions import ConnectionRefusedError
|
|
7
8
|
|
|
8
9
|
from rasa.model_manager.runner_service import BotSession
|
|
9
10
|
from rasa.model_manager.studio_jwt_auth import (
|
|
@@ -29,7 +30,7 @@ async def socketio_websocket_traffic_wrapper(
|
|
|
29
30
|
|
|
30
31
|
if auth_token is None:
|
|
31
32
|
structlogger.error("model_runner.user_no_token", sid=sid)
|
|
32
|
-
|
|
33
|
+
raise ConnectionRefusedError("model_runner.user_no_token")
|
|
33
34
|
|
|
34
35
|
try:
|
|
35
36
|
authenticate_user_to_service(auth_token)
|
|
@@ -38,22 +39,22 @@ async def socketio_websocket_traffic_wrapper(
|
|
|
38
39
|
structlogger.error(
|
|
39
40
|
"model_runner.user_authentication_failed", sid=sid, error=str(error)
|
|
40
41
|
)
|
|
41
|
-
|
|
42
|
+
raise ConnectionRefusedError("model_runner.user_authentication_failed")
|
|
42
43
|
|
|
43
44
|
deployment_id = auth.get("deployment_id") if auth else None
|
|
44
45
|
|
|
45
46
|
if deployment_id is None:
|
|
46
47
|
structlogger.error("model_runner.bot_no_deployment_id", sid=sid)
|
|
47
|
-
|
|
48
|
+
raise ConnectionRefusedError("model_runner.bot_no_deployment_id")
|
|
48
49
|
|
|
49
50
|
bot = running_bots.get(deployment_id)
|
|
50
51
|
if bot is None:
|
|
51
52
|
structlogger.error("model_runner.bot_not_found", deployment_id=deployment_id)
|
|
52
|
-
|
|
53
|
+
raise ConnectionRefusedError("model_runner.bot_not_found")
|
|
53
54
|
|
|
54
55
|
if not bot.is_alive():
|
|
55
56
|
structlogger.error("model_runner.bot_not_alive", deployment_id=deployment_id)
|
|
56
|
-
|
|
57
|
+
raise ConnectionRefusedError("model_runner.bot_not_alive")
|
|
57
58
|
|
|
58
59
|
client = await create_bridge_client(sio, bot.internal_url, sid, deployment_id)
|
|
59
60
|
|
|
@@ -67,7 +68,7 @@ async def socketio_websocket_traffic_wrapper(
|
|
|
67
68
|
structlogger.error(
|
|
68
69
|
"model_runner.bot_connection_failed", deployment_id=deployment_id
|
|
69
70
|
)
|
|
70
|
-
|
|
71
|
+
raise ConnectionRefusedError("model_runner.bot_connection_failed")
|
|
71
72
|
|
|
72
73
|
|
|
73
74
|
def create_bridge_server(sio: AsyncServer, running_bots: Dict[str, BotSession]) -> None:
|
rasa/model_training.py
CHANGED
|
@@ -352,34 +352,31 @@ 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
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
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
|
+
),
|
|
364
379
|
)
|
|
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
|
-
)
|
|
383
380
|
|
|
384
381
|
return TrainingResult(str(full_model_path), 0)
|
|
385
382
|
|
rasa/shared/constants.py
CHANGED
|
@@ -83,6 +83,7 @@ ENV_LOG_LEVEL_LLM = "LOG_LEVEL_LLM"
|
|
|
83
83
|
ENV_LOG_LEVEL_LLM_MODULE_NAMES = {
|
|
84
84
|
"LLMCommandGenerator": "LOG_LEVEL_LLM_COMMAND_GENERATOR",
|
|
85
85
|
"SingleStepLLMCommandGenerator": "LOG_LEVEL_LLM_COMMAND_GENERATOR",
|
|
86
|
+
"CompactLLMCommandGenerator": "LOG_LEVEL_LLM_COMMAND_GENERATOR",
|
|
86
87
|
"MultiStepLLMCommandGenerator": "LOG_LEVEL_LLM_COMMAND_GENERATOR",
|
|
87
88
|
"EnterpriseSearchPolicy": "LOG_LEVEL_LLM_ENTERPRISE_SEARCH",
|
|
88
89
|
"IntentlessPolicy": "LOG_LEVEL_LLM_INTENTLESS_POLICY",
|
|
@@ -106,6 +107,7 @@ CONFIG_NAME_KEY = "name"
|
|
|
106
107
|
CONFIG_POLICIES_KEY = "policies"
|
|
107
108
|
CONFIG_PIPELINE_KEY = "pipeline"
|
|
108
109
|
CONFIG_LANGUAGE_KEY = "language"
|
|
110
|
+
CONFIG_ADDITIONAL_LANGUAGES_KEY = "additional_languages"
|
|
109
111
|
CONFIG_RECIPE_KEY = "recipe"
|
|
110
112
|
CONFIG_LLM_KEY = "llm"
|
|
111
113
|
CONFIG_MODEL_NAME_KEY = "model_name"
|
|
@@ -150,6 +152,8 @@ DEFAULT_MARKERS_CONFIG_PATH = "markers/config"
|
|
|
150
152
|
DEFAULT_MARKERS_OUTPUT_PATH = "markers/output"
|
|
151
153
|
DEFAULT_MARKERS_STATS_PATH = "markers/stats"
|
|
152
154
|
|
|
155
|
+
DEFAULT_PROMPT_PACKAGE_NAME = "rasa.dialogue_understanding.generator.prompt_templates"
|
|
156
|
+
|
|
153
157
|
DIAGNOSTIC_DATA = "diagnostic_data"
|
|
154
158
|
|
|
155
159
|
RESPONSE_CONDITION = "condition"
|
|
@@ -162,6 +166,7 @@ AZURE_AD_TOKEN_ENV_VAR = "AZURE_AD_TOKEN"
|
|
|
162
166
|
AZURE_API_BASE_ENV_VAR = "AZURE_API_BASE"
|
|
163
167
|
AZURE_API_VERSION_ENV_VAR = "AZURE_API_VERSION"
|
|
164
168
|
AZURE_API_TYPE_ENV_VAR = "AZURE_API_TYPE"
|
|
169
|
+
AZURE_AD_SCOPES_ENV_VAR = "AZURE_AD_SCOPES"
|
|
165
170
|
AZURE_SPEECH_API_KEY_ENV_VAR = "AZURE_SPEECH_API_KEY"
|
|
166
171
|
|
|
167
172
|
DEEPGRAM_API_KEY_ENV_VAR = "DEEPGRAM_API_KEY"
|
|
@@ -198,7 +203,6 @@ MODEL_CONFIG_KEY = "model"
|
|
|
198
203
|
MODEL_NAME_CONFIG_KEY = "model_name"
|
|
199
204
|
PROMPT_CONFIG_KEY = "prompt"
|
|
200
205
|
PROMPT_TEMPLATE_CONFIG_KEY = "prompt_template"
|
|
201
|
-
|
|
202
206
|
STREAM_CONFIG_KEY = "stream"
|
|
203
207
|
N_REPHRASES_CONFIG_KEY = "n"
|
|
204
208
|
USE_CHAT_COMPLETIONS_ENDPOINT_CONFIG_KEY = "use_chat_completions_endpoint"
|
|
@@ -232,12 +236,6 @@ LITELLM_PARAMS_KEY = "litellm_params"
|
|
|
232
236
|
LLM_API_HEALTH_CHECK_ENV_VAR = "LLM_API_HEALTH_CHECK"
|
|
233
237
|
LLM_API_HEALTH_CHECK_DEFAULT_VALUE = "false"
|
|
234
238
|
|
|
235
|
-
AZURE_API_KEY_ENV_VAR = "AZURE_API_KEY"
|
|
236
|
-
AZURE_AD_TOKEN_ENV_VAR = "AZURE_AD_TOKEN"
|
|
237
|
-
AZURE_API_BASE_ENV_VAR = "AZURE_API_BASE"
|
|
238
|
-
AZURE_API_VERSION_ENV_VAR = "AZURE_API_VERSION"
|
|
239
|
-
AZURE_API_TYPE_ENV_VAR = "AZURE_API_TYPE"
|
|
240
|
-
|
|
241
239
|
AWS_REGION_NAME_CONFIG_KEY = "aws_region_name"
|
|
242
240
|
AWS_ACCESS_KEY_ID_CONFIG_KEY = "aws_access_key_id"
|
|
243
241
|
AWS_SECRET_ACCESS_KEY_CONFIG_KEY = "aws_secret_access_key"
|
|
@@ -273,17 +271,11 @@ RASA_PROVIDER = "rasa"
|
|
|
273
271
|
SELF_HOSTED_VLLM_PREFIX = "hosted_vllm"
|
|
274
272
|
SELF_HOSTED_VLLM_API_KEY_ENV_VAR = "HOSTED_VLLM_API_KEY"
|
|
275
273
|
|
|
276
|
-
SELF_HOSTED_VLLM_PREFIX = "hosted_vllm"
|
|
277
|
-
SELF_HOSTED_VLLM_API_KEY_ENV_VAR = "HOSTED_VLLM_API_KEY"
|
|
278
|
-
|
|
279
274
|
VALID_PROVIDERS_FOR_API_TYPE_CONFIG_KEY = [
|
|
280
275
|
OPENAI_PROVIDER,
|
|
281
276
|
AZURE_OPENAI_PROVIDER,
|
|
282
277
|
]
|
|
283
278
|
|
|
284
|
-
SELF_HOSTED_VLLM_PREFIX = "hosted_vllm"
|
|
285
|
-
SELF_HOSTED_VLLM_API_KEY_ENV_VAR = "HOSTED_VLLM_API_KEY"
|
|
286
|
-
|
|
287
279
|
AZURE_API_TYPE = "azure"
|
|
288
280
|
OPENAI_API_TYPE = "openai"
|
|
289
281
|
|
|
@@ -329,3 +321,13 @@ BUTTONS = "buttons"
|
|
|
329
321
|
ATTACHMENT = "attachment"
|
|
330
322
|
IMAGE = "image"
|
|
331
323
|
CUSTOM = "custom"
|
|
324
|
+
TITLE = "title"
|
|
325
|
+
PAYLOAD = "payload"
|
|
326
|
+
|
|
327
|
+
# Used for LLM command generation
|
|
328
|
+
ROLE_USER = "user"
|
|
329
|
+
ROLE_SYSTEM = "system"
|
|
330
|
+
|
|
331
|
+
# Used for key values in ValidateSlotPatternFlowStackFrame
|
|
332
|
+
REFILL_UTTER = "refill_utter"
|
|
333
|
+
REJECTIONS = "rejections"
|
rasa/shared/core/constants.py
CHANGED
|
@@ -13,6 +13,7 @@ USER_INTENT_SESSION_START = "session_start"
|
|
|
13
13
|
USER_INTENT_SESSION_END = "session_end"
|
|
14
14
|
USER_INTENT_SILENCE_TIMEOUT = "silence_timeout"
|
|
15
15
|
SESSION_START_METADATA_SLOT = "session_started_metadata"
|
|
16
|
+
LANGUAGE_SLOT = "language"
|
|
16
17
|
|
|
17
18
|
DEFAULT_INTENTS = [
|
|
18
19
|
USER_INTENT_RESTART,
|
|
@@ -51,6 +52,8 @@ ACTION_TRIGGER_CHITCHAT = "action_trigger_chitchat"
|
|
|
51
52
|
ACTION_RESET_ROUTING = "action_reset_routing"
|
|
52
53
|
ACTION_HANGUP = "action_hangup"
|
|
53
54
|
ACTION_REPEAT_BOT_MESSAGES = "action_repeat_bot_messages"
|
|
55
|
+
ACTION_BLOCK_DIGRESSION = "action_block_digression"
|
|
56
|
+
ACTION_CONTINUE_DIGRESSION = "action_continue_digression"
|
|
54
57
|
|
|
55
58
|
ACTION_METADATA_EXECUTION_SUCCESS = "execution_success"
|
|
56
59
|
ACTION_METADATA_EXECUTION_ERROR_MESSAGE = "execution_error_message"
|
|
@@ -81,6 +84,8 @@ DEFAULT_ACTION_NAMES = [
|
|
|
81
84
|
ACTION_RESET_ROUTING,
|
|
82
85
|
ACTION_HANGUP,
|
|
83
86
|
ACTION_REPEAT_BOT_MESSAGES,
|
|
87
|
+
ACTION_BLOCK_DIGRESSION,
|
|
88
|
+
ACTION_CONTINUE_DIGRESSION,
|
|
84
89
|
]
|
|
85
90
|
|
|
86
91
|
ACTION_SHOULD_SEND_DOMAIN = "send_domain"
|
|
@@ -137,7 +142,11 @@ DEFAULT_SLOT_NAMES = {
|
|
|
137
142
|
|
|
138
143
|
SLOT_MAPPINGS = "mappings"
|
|
139
144
|
MAPPING_CONDITIONS = "conditions"
|
|
140
|
-
|
|
145
|
+
KEY_MAPPING_TYPE = "type"
|
|
146
|
+
KEY_ALLOW_NLU_CORRECTION = "allow_nlu_correction"
|
|
147
|
+
KEY_ACTION = "action"
|
|
148
|
+
KEY_RUN_ACTION_EVERY_TURN = "run_action_every_turn"
|
|
149
|
+
KEY_COEXISTENCE_SYSTEM = "coexistence_system"
|
|
141
150
|
|
|
142
151
|
|
|
143
152
|
class SlotMappingType(Enum):
|
|
@@ -148,7 +157,7 @@ class SlotMappingType(Enum):
|
|
|
148
157
|
FROM_TRIGGER_INTENT = "from_trigger_intent"
|
|
149
158
|
FROM_TEXT = "from_text"
|
|
150
159
|
FROM_LLM = "from_llm"
|
|
151
|
-
|
|
160
|
+
CONTROLLED = "controlled"
|
|
152
161
|
|
|
153
162
|
def __str__(self) -> str:
|
|
154
163
|
"""Returns the string representation that should be used in config files."""
|
|
@@ -156,7 +165,21 @@ class SlotMappingType(Enum):
|
|
|
156
165
|
|
|
157
166
|
def is_predefined_type(self) -> bool:
|
|
158
167
|
"""Returns True if the mapping type is NLU-predefined."""
|
|
159
|
-
return not (
|
|
168
|
+
return not (
|
|
169
|
+
self == SlotMappingType.CONTROLLED or self == SlotMappingType.FROM_LLM
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class SetSlotExtractor(Enum):
|
|
174
|
+
"""The extractors that can set a slot."""
|
|
175
|
+
|
|
176
|
+
LLM = "LLM"
|
|
177
|
+
COMMAND_PAYLOAD_READER = "CommandPayloadReader"
|
|
178
|
+
NLU = "NLU"
|
|
179
|
+
CUSTOM = "CUSTOM"
|
|
180
|
+
|
|
181
|
+
def __str__(self) -> str:
|
|
182
|
+
return self.value
|
|
160
183
|
|
|
161
184
|
|
|
162
185
|
# the keys for `State` (USER, PREVIOUS_ACTION, SLOTS, ACTIVE_LOOP)
|
|
@@ -181,3 +204,7 @@ POLICY_NAME_RULE = "RulePolicy"
|
|
|
181
204
|
CLASSIFIER_NAME_FALLBACK = "FallbackClassifier"
|
|
182
205
|
|
|
183
206
|
POLICIES_THAT_EXTRACT_ENTITIES = {"TEDPolicy"}
|
|
207
|
+
|
|
208
|
+
# digression constants
|
|
209
|
+
KEY_ASK_CONFIRM_DIGRESSIONS = "ask_confirm_digressions"
|
|
210
|
+
KEY_BLOCK_DIGRESSIONS = "block_digressions"
|