rasa-pro 3.9.18__py3-none-any.whl → 3.10.4__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 +26 -57
- rasa/__init__.py +1 -2
- rasa/__main__.py +5 -0
- rasa/anonymization/anonymization_rule_executor.py +2 -2
- rasa/api.py +26 -22
- rasa/cli/arguments/data.py +27 -2
- rasa/cli/arguments/default_arguments.py +25 -3
- rasa/cli/arguments/run.py +9 -9
- rasa/cli/arguments/train.py +2 -0
- rasa/cli/data.py +70 -8
- rasa/cli/e2e_test.py +108 -433
- rasa/cli/interactive.py +1 -0
- rasa/cli/llm_fine_tuning.py +395 -0
- rasa/cli/project_templates/calm/endpoints.yml +1 -1
- rasa/cli/project_templates/tutorial/endpoints.yml +1 -1
- rasa/cli/run.py +14 -13
- rasa/cli/scaffold.py +10 -8
- rasa/cli/train.py +8 -7
- rasa/cli/utils.py +15 -0
- rasa/constants.py +7 -1
- rasa/core/actions/action.py +98 -49
- rasa/core/actions/action_run_slot_rejections.py +4 -1
- rasa/core/actions/custom_action_executor.py +9 -6
- rasa/core/actions/direct_custom_actions_executor.py +80 -0
- rasa/core/actions/e2e_stub_custom_action_executor.py +68 -0
- rasa/core/actions/grpc_custom_action_executor.py +2 -2
- rasa/core/actions/http_custom_action_executor.py +6 -5
- rasa/core/agent.py +21 -17
- rasa/core/channels/__init__.py +2 -0
- rasa/core/channels/audiocodes.py +1 -16
- rasa/core/channels/inspector/dist/index.html +0 -2
- rasa/core/channels/inspector/index.html +0 -2
- rasa/core/channels/voice_aware/__init__.py +0 -0
- rasa/core/channels/voice_aware/jambonz.py +103 -0
- rasa/core/channels/voice_aware/jambonz_protocol.py +344 -0
- rasa/core/channels/voice_aware/utils.py +20 -0
- rasa/core/channels/voice_native/__init__.py +0 -0
- rasa/core/constants.py +6 -1
- rasa/core/featurizers/single_state_featurizer.py +1 -22
- rasa/core/featurizers/tracker_featurizers.py +18 -115
- rasa/core/information_retrieval/faiss.py +7 -4
- rasa/core/information_retrieval/information_retrieval.py +8 -0
- rasa/core/information_retrieval/milvus.py +9 -2
- rasa/core/information_retrieval/qdrant.py +1 -1
- rasa/core/nlg/contextual_response_rephraser.py +32 -10
- rasa/core/nlg/summarize.py +4 -3
- rasa/core/policies/enterprise_search_policy.py +100 -44
- rasa/core/policies/flows/flow_executor.py +130 -94
- rasa/core/policies/intentless_policy.py +52 -28
- rasa/core/policies/ted_policy.py +33 -58
- rasa/core/policies/unexpected_intent_policy.py +7 -15
- rasa/core/processor.py +20 -53
- rasa/core/run.py +5 -4
- rasa/core/tracker_store.py +8 -4
- rasa/core/utils.py +45 -56
- rasa/dialogue_understanding/coexistence/llm_based_router.py +45 -12
- rasa/dialogue_understanding/commands/__init__.py +4 -0
- rasa/dialogue_understanding/commands/change_flow_command.py +0 -6
- rasa/dialogue_understanding/commands/session_start_command.py +59 -0
- rasa/dialogue_understanding/commands/set_slot_command.py +1 -5
- rasa/dialogue_understanding/commands/utils.py +38 -0
- rasa/dialogue_understanding/generator/constants.py +10 -3
- rasa/dialogue_understanding/generator/flow_retrieval.py +14 -5
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +12 -2
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +106 -87
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +28 -6
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +90 -37
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +15 -15
- rasa/dialogue_understanding/patterns/session_start.py +37 -0
- rasa/dialogue_understanding/processor/command_processor.py +13 -14
- rasa/e2e_test/aggregate_test_stats_calculator.py +124 -0
- rasa/e2e_test/assertions.py +1181 -0
- rasa/e2e_test/assertions_schema.yml +106 -0
- rasa/e2e_test/constants.py +20 -0
- rasa/e2e_test/e2e_config.py +220 -0
- rasa/e2e_test/e2e_config_schema.yml +26 -0
- rasa/e2e_test/e2e_test_case.py +131 -8
- rasa/e2e_test/e2e_test_converter.py +363 -0
- rasa/e2e_test/e2e_test_converter_prompt.jinja2 +70 -0
- rasa/e2e_test/e2e_test_coverage_report.py +364 -0
- rasa/e2e_test/e2e_test_result.py +26 -6
- rasa/e2e_test/e2e_test_runner.py +491 -72
- rasa/e2e_test/e2e_test_schema.yml +96 -0
- rasa/e2e_test/pykwalify_extensions.py +39 -0
- rasa/e2e_test/stub_custom_action.py +70 -0
- rasa/e2e_test/utils/__init__.py +0 -0
- rasa/e2e_test/utils/e2e_yaml_utils.py +55 -0
- rasa/e2e_test/utils/io.py +596 -0
- rasa/e2e_test/utils/validation.py +80 -0
- rasa/engine/recipes/default_components.py +0 -2
- rasa/engine/storage/local_model_storage.py +0 -1
- rasa/env.py +9 -0
- rasa/keys +1 -0
- rasa/llm_fine_tuning/__init__.py +0 -0
- rasa/llm_fine_tuning/annotation_module.py +241 -0
- rasa/llm_fine_tuning/conversations.py +144 -0
- rasa/llm_fine_tuning/llm_data_preparation_module.py +178 -0
- rasa/llm_fine_tuning/notebooks/unsloth_finetuning.ipynb +407 -0
- rasa/llm_fine_tuning/paraphrasing/__init__.py +0 -0
- rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +281 -0
- rasa/llm_fine_tuning/paraphrasing/default_rephrase_prompt_template.jina2 +44 -0
- rasa/llm_fine_tuning/paraphrasing/rephrase_validator.py +121 -0
- rasa/llm_fine_tuning/paraphrasing/rephrased_user_message.py +10 -0
- rasa/llm_fine_tuning/paraphrasing_module.py +128 -0
- rasa/llm_fine_tuning/storage.py +174 -0
- rasa/llm_fine_tuning/train_test_split_module.py +441 -0
- rasa/model_training.py +48 -16
- rasa/nlu/classifiers/diet_classifier.py +25 -38
- rasa/nlu/classifiers/logistic_regression_classifier.py +9 -44
- rasa/nlu/classifiers/sklearn_intent_classifier.py +16 -37
- rasa/nlu/extractors/crf_entity_extractor.py +50 -93
- rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +45 -78
- rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +17 -52
- rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +3 -5
- rasa/nlu/persistor.py +129 -32
- rasa/server.py +45 -10
- rasa/shared/constants.py +63 -15
- rasa/shared/core/domain.py +15 -12
- rasa/shared/core/events.py +28 -2
- rasa/shared/core/flows/flow.py +208 -13
- rasa/shared/core/flows/flow_path.py +84 -0
- rasa/shared/core/flows/flows_list.py +28 -10
- rasa/shared/core/flows/flows_yaml_schema.json +269 -193
- rasa/shared/core/flows/validation.py +112 -25
- rasa/shared/core/flows/yaml_flows_io.py +149 -10
- rasa/shared/core/trackers.py +6 -0
- rasa/shared/core/training_data/visualization.html +2 -2
- rasa/shared/exceptions.py +4 -0
- rasa/shared/importers/importer.py +60 -11
- rasa/shared/importers/remote_importer.py +196 -0
- rasa/shared/nlu/constants.py +2 -0
- rasa/shared/nlu/training_data/features.py +2 -120
- rasa/shared/providers/_configs/__init__.py +0 -0
- rasa/shared/providers/_configs/azure_openai_client_config.py +181 -0
- rasa/shared/providers/_configs/client_config.py +57 -0
- rasa/shared/providers/_configs/default_litellm_client_config.py +130 -0
- rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +234 -0
- rasa/shared/providers/_configs/openai_client_config.py +175 -0
- rasa/shared/providers/_configs/self_hosted_llm_client_config.py +171 -0
- rasa/shared/providers/_configs/utils.py +101 -0
- rasa/shared/providers/_ssl_verification_utils.py +124 -0
- rasa/shared/providers/embedding/__init__.py +0 -0
- rasa/shared/providers/embedding/_base_litellm_embedding_client.py +254 -0
- rasa/shared/providers/embedding/_langchain_embedding_client_adapter.py +74 -0
- rasa/shared/providers/embedding/azure_openai_embedding_client.py +277 -0
- rasa/shared/providers/embedding/default_litellm_embedding_client.py +102 -0
- rasa/shared/providers/embedding/embedding_client.py +90 -0
- rasa/shared/providers/embedding/embedding_response.py +41 -0
- rasa/shared/providers/embedding/huggingface_local_embedding_client.py +191 -0
- rasa/shared/providers/embedding/openai_embedding_client.py +172 -0
- rasa/shared/providers/llm/__init__.py +0 -0
- rasa/shared/providers/llm/_base_litellm_client.py +227 -0
- rasa/shared/providers/llm/azure_openai_llm_client.py +338 -0
- rasa/shared/providers/llm/default_litellm_llm_client.py +84 -0
- rasa/shared/providers/llm/llm_client.py +76 -0
- rasa/shared/providers/llm/llm_response.py +50 -0
- rasa/shared/providers/llm/openai_llm_client.py +155 -0
- rasa/shared/providers/llm/self_hosted_llm_client.py +169 -0
- rasa/shared/providers/mappings.py +75 -0
- rasa/shared/utils/cli.py +30 -0
- rasa/shared/utils/io.py +65 -3
- rasa/shared/utils/llm.py +223 -200
- rasa/shared/utils/yaml.py +122 -7
- rasa/studio/download.py +19 -13
- rasa/studio/train.py +2 -3
- rasa/studio/upload.py +2 -3
- rasa/telemetry.py +113 -58
- rasa/tracing/config.py +2 -3
- rasa/tracing/instrumentation/attribute_extractors.py +29 -17
- rasa/tracing/instrumentation/instrumentation.py +4 -47
- rasa/utils/common.py +18 -19
- rasa/utils/endpoints.py +7 -4
- rasa/utils/io.py +66 -0
- rasa/utils/json_utils.py +60 -0
- rasa/utils/licensing.py +9 -1
- rasa/utils/ml_utils.py +4 -2
- rasa/utils/tensorflow/model_data.py +193 -2
- rasa/validator.py +196 -1
- rasa/version.py +1 -1
- {rasa_pro-3.9.18.dist-info → rasa_pro-3.10.4.dist-info}/METADATA +47 -72
- {rasa_pro-3.9.18.dist-info → rasa_pro-3.10.4.dist-info}/RECORD +186 -121
- rasa/nlu/classifiers/llm_intent_classifier.py +0 -519
- rasa/shared/providers/openai/clients.py +0 -43
- rasa/shared/providers/openai/session_handler.py +0 -110
- rasa/utils/tensorflow/feature_array.py +0 -366
- /rasa/{shared/providers/openai → cli/project_templates/tutorial/actions}/__init__.py +0 -0
- /rasa/cli/project_templates/tutorial/{actions.py → actions/actions.py} +0 -0
- {rasa_pro-3.9.18.dist-info → rasa_pro-3.10.4.dist-info}/NOTICE +0 -0
- {rasa_pro-3.9.18.dist-info → rasa_pro-3.10.4.dist-info}/WHEEL +0 -0
- {rasa_pro-3.9.18.dist-info → rasa_pro-3.10.4.dist-info}/entry_points.txt +0 -0
rasa/nlu/persistor.py
CHANGED
|
@@ -1,13 +1,30 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import abc
|
|
2
|
-
import structlog
|
|
3
4
|
import os
|
|
4
5
|
import shutil
|
|
5
|
-
from
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from typing import TYPE_CHECKING, List, Optional, Text, Tuple, Union
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
import structlog
|
|
8
10
|
|
|
9
11
|
import rasa.shared.utils.common
|
|
10
12
|
import rasa.utils.common
|
|
13
|
+
from rasa.constants import (
|
|
14
|
+
HTTP_STATUS_FORBIDDEN,
|
|
15
|
+
HTTP_STATUS_NOT_FOUND,
|
|
16
|
+
MODEL_ARCHIVE_EXTENSION,
|
|
17
|
+
)
|
|
18
|
+
from rasa.env import (
|
|
19
|
+
AWS_ENDPOINT_URL_ENV,
|
|
20
|
+
AZURE_ACCOUNT_KEY_ENV,
|
|
21
|
+
AZURE_ACCOUNT_NAME_ENV,
|
|
22
|
+
AZURE_CONTAINER_ENV,
|
|
23
|
+
BUCKET_NAME_ENV,
|
|
24
|
+
REMOTE_STORAGE_PATH_ENV,
|
|
25
|
+
)
|
|
26
|
+
from rasa.shared.exceptions import RasaException
|
|
27
|
+
from rasa.shared.utils.io import raise_warning
|
|
11
28
|
|
|
12
29
|
if TYPE_CHECKING:
|
|
13
30
|
from azure.storage.blob import ContainerClient
|
|
@@ -15,34 +32,80 @@ if TYPE_CHECKING:
|
|
|
15
32
|
structlogger = structlog.get_logger()
|
|
16
33
|
|
|
17
34
|
|
|
18
|
-
|
|
35
|
+
class RemoteStorageType(Enum):
|
|
36
|
+
"""Enum for the different remote storage types."""
|
|
37
|
+
|
|
38
|
+
AWS = "aws"
|
|
39
|
+
GCS = "gcs"
|
|
40
|
+
AZURE = "azure"
|
|
41
|
+
|
|
42
|
+
@classmethod
|
|
43
|
+
def list(cls) -> List[str]:
|
|
44
|
+
"""Returns a list of all available storage types."""
|
|
45
|
+
return [item.value for item in cls]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
"""Storage can be a built-in one or a module path to a custom persistor."""
|
|
49
|
+
StorageType = Union[RemoteStorageType, str]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def parse_remote_storage(value: str) -> StorageType:
|
|
53
|
+
try:
|
|
54
|
+
return RemoteStorageType(value)
|
|
55
|
+
except ValueError:
|
|
56
|
+
# if the value is not a valid storage type,
|
|
57
|
+
# but it is a string we assume it is a custom class
|
|
58
|
+
# and return it as is
|
|
59
|
+
|
|
60
|
+
supported_storages_help_text = (
|
|
61
|
+
f"Supported storages are: {RemoteStorageType.list()} "
|
|
62
|
+
"or path to a python class which implements `Persistor` interface."
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
if isinstance(value, str):
|
|
66
|
+
if value == "":
|
|
67
|
+
raise ValueError(
|
|
68
|
+
f"The value can't be an empty string."
|
|
69
|
+
f" {supported_storages_help_text}"
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
return value
|
|
73
|
+
|
|
74
|
+
raise ValueError(
|
|
75
|
+
f"Invalid storage type '{value}'. {supported_storages_help_text}"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def get_persistor(storage: StorageType) -> Optional[Persistor]:
|
|
19
80
|
"""Returns an instance of the requested persistor.
|
|
20
81
|
|
|
21
82
|
Currently, `aws`, `gcs`, `azure` and providing module paths are supported remote
|
|
22
83
|
storages.
|
|
23
84
|
"""
|
|
24
|
-
if
|
|
85
|
+
if storage == RemoteStorageType.AWS.value:
|
|
25
86
|
return AWSPersistor(
|
|
26
|
-
os.environ.get(
|
|
87
|
+
os.environ.get(BUCKET_NAME_ENV), os.environ.get(AWS_ENDPOINT_URL_ENV)
|
|
27
88
|
)
|
|
28
|
-
if
|
|
29
|
-
return GCSPersistor(os.environ.get(
|
|
89
|
+
if storage == RemoteStorageType.GCS.value:
|
|
90
|
+
return GCSPersistor(os.environ.get(BUCKET_NAME_ENV))
|
|
30
91
|
|
|
31
|
-
if
|
|
92
|
+
if storage == RemoteStorageType.AZURE.value:
|
|
32
93
|
return AzurePersistor(
|
|
33
|
-
os.environ.get(
|
|
34
|
-
os.environ.get(
|
|
35
|
-
os.environ.get(
|
|
94
|
+
os.environ.get(AZURE_CONTAINER_ENV),
|
|
95
|
+
os.environ.get(AZURE_ACCOUNT_NAME_ENV),
|
|
96
|
+
os.environ.get(AZURE_ACCOUNT_KEY_ENV),
|
|
36
97
|
)
|
|
37
|
-
|
|
98
|
+
# If the persistor is not a built-in one, it is assumed to be a module path
|
|
99
|
+
# to a persistor implementation supplied by the user.
|
|
100
|
+
if storage:
|
|
38
101
|
try:
|
|
39
|
-
persistor = rasa.shared.utils.common.class_from_module_path(
|
|
102
|
+
persistor = rasa.shared.utils.common.class_from_module_path(storage)
|
|
40
103
|
return persistor()
|
|
41
104
|
except ImportError:
|
|
42
105
|
raise ImportError(
|
|
43
|
-
f"Unknown model persistor {
|
|
44
|
-
"either use an included model persistor (
|
|
45
|
-
"or
|
|
106
|
+
f"Unknown model persistor {storage}. Please make sure to "
|
|
107
|
+
f"either use an included model persistor ({RemoteStorageType.list()}) "
|
|
108
|
+
f"or specify the module path to an external "
|
|
46
109
|
"model persistor."
|
|
47
110
|
)
|
|
48
111
|
return None
|
|
@@ -51,25 +114,35 @@ def get_persistor(name: Text) -> Optional["Persistor"]:
|
|
|
51
114
|
class Persistor(abc.ABC):
|
|
52
115
|
"""Store models in cloud and fetch them when needed."""
|
|
53
116
|
|
|
54
|
-
def persist(self,
|
|
55
|
-
"""Uploads a model persisted in the `target_dir` to cloud storage."""
|
|
56
|
-
|
|
57
|
-
|
|
117
|
+
def persist(self, trained_model: str) -> None:
|
|
118
|
+
"""Uploads a trained model persisted in the `target_dir` to cloud storage."""
|
|
119
|
+
file_key = self._create_file_key(trained_model)
|
|
120
|
+
self._persist_tar(file_key, trained_model)
|
|
58
121
|
|
|
59
|
-
|
|
60
|
-
|
|
122
|
+
def retrieve(self, model_name: Text, target_path: Text) -> Text:
|
|
123
|
+
"""Downloads a model that has been persisted to cloud storage.
|
|
61
124
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
125
|
+
Downloaded model will be saved to the `target_path`.
|
|
126
|
+
If `target_path` is a directory, the model will be saved to that directory.
|
|
127
|
+
If `target_path` is a file, the model will be saved to that file.
|
|
65
128
|
|
|
66
|
-
|
|
129
|
+
Args:
|
|
130
|
+
model_name: The name of the model to retrieve.
|
|
131
|
+
target_path: The path to which the model should be saved.
|
|
132
|
+
"""
|
|
133
|
+
tar_name = model_name
|
|
134
|
+
if not model_name.endswith(MODEL_ARCHIVE_EXTENSION):
|
|
67
135
|
# ensure backward compatibility
|
|
68
136
|
tar_name = self._tar_name(model_name)
|
|
69
|
-
|
|
137
|
+
tar_name = self._create_file_key(tar_name)
|
|
70
138
|
self._retrieve_tar(tar_name)
|
|
71
139
|
self._copy(os.path.basename(tar_name), target_path)
|
|
72
140
|
|
|
141
|
+
if os.path.isdir(target_path):
|
|
142
|
+
return os.path.join(target_path, model_name)
|
|
143
|
+
|
|
144
|
+
return target_path
|
|
145
|
+
|
|
73
146
|
@abc.abstractmethod
|
|
74
147
|
def _retrieve_tar(self, filename: Text) -> None:
|
|
75
148
|
"""Downloads a model previously persisted to cloud storage."""
|
|
@@ -97,13 +170,37 @@ class Persistor(abc.ABC):
|
|
|
97
170
|
|
|
98
171
|
@staticmethod
|
|
99
172
|
def _tar_name(model_name: Text, include_extension: bool = True) -> Text:
|
|
100
|
-
ext = ".
|
|
173
|
+
ext = f".{MODEL_ARCHIVE_EXTENSION}" if include_extension else ""
|
|
101
174
|
return f"{model_name}{ext}"
|
|
102
175
|
|
|
103
176
|
@staticmethod
|
|
104
177
|
def _copy(compressed_path: Text, target_path: Text) -> None:
|
|
105
178
|
shutil.copy2(compressed_path, target_path)
|
|
106
179
|
|
|
180
|
+
@staticmethod
|
|
181
|
+
def _create_file_key(model_path: str) -> Text:
|
|
182
|
+
"""Appends remote storage folders when provided to upload or retrieve file"""
|
|
183
|
+
bucket_object_path = os.environ.get(REMOTE_STORAGE_PATH_ENV)
|
|
184
|
+
|
|
185
|
+
# To keep the backward compatibility, if REMOTE_STORAGE_PATH is not provided,
|
|
186
|
+
# the model_name (which might be a complete path) will be returned as it is.
|
|
187
|
+
if bucket_object_path is None:
|
|
188
|
+
return str(model_path)
|
|
189
|
+
else:
|
|
190
|
+
raise_warning(
|
|
191
|
+
f"{REMOTE_STORAGE_PATH_ENV} is deprecated and will be "
|
|
192
|
+
"removed in future versions. "
|
|
193
|
+
"Please use the -m path/to/model.tar.gz option to "
|
|
194
|
+
"specify the model path when loading a model."
|
|
195
|
+
"Or use --output and --fixed-model-name to specify the "
|
|
196
|
+
"output directory and the model name when saving a "
|
|
197
|
+
"trained model to remote storage.",
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
file_key = os.path.basename(model_path)
|
|
201
|
+
file_key = os.path.join(bucket_object_path, file_key)
|
|
202
|
+
return file_key
|
|
203
|
+
|
|
107
204
|
|
|
108
205
|
class AWSPersistor(Persistor):
|
|
109
206
|
"""Store models on S3.
|
|
@@ -137,7 +234,7 @@ class AWSPersistor(Persistor):
|
|
|
137
234
|
self.s3.meta.client.head_bucket(Bucket=bucket_name)
|
|
138
235
|
except botocore.exceptions.ClientError as e:
|
|
139
236
|
error_code = int(e.response["Error"]["Code"])
|
|
140
|
-
if error_code ==
|
|
237
|
+
if error_code == HTTP_STATUS_FORBIDDEN:
|
|
141
238
|
log = (
|
|
142
239
|
f"Access to the specified bucket '{bucket_name}' is forbidden. "
|
|
143
240
|
"Please make sure you have the necessary "
|
|
@@ -149,7 +246,7 @@ class AWSPersistor(Persistor):
|
|
|
149
246
|
event_info=log,
|
|
150
247
|
)
|
|
151
248
|
raise RasaException(log)
|
|
152
|
-
elif error_code ==
|
|
249
|
+
elif error_code == HTTP_STATUS_NOT_FOUND:
|
|
153
250
|
log = (
|
|
154
251
|
f"The specified bucket '{bucket_name}' does not exist. "
|
|
155
252
|
"Please make sure to create the bucket first."
|
|
@@ -183,7 +280,7 @@ class GCSPersistor(Persistor):
|
|
|
183
280
|
"""Initialise class with client and bucket."""
|
|
184
281
|
# there are no type hints in this repo for now
|
|
185
282
|
# https://github.com/googleapis/python-storage/issues/393
|
|
186
|
-
from google.cloud import storage
|
|
283
|
+
from google.cloud import storage
|
|
187
284
|
|
|
188
285
|
super().__init__()
|
|
189
286
|
|
rasa/server.py
CHANGED
|
@@ -11,17 +11,17 @@ from http import HTTPStatus
|
|
|
11
11
|
from inspect import isawaitable
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
from typing import (
|
|
14
|
+
TYPE_CHECKING,
|
|
14
15
|
Any,
|
|
15
16
|
Callable,
|
|
17
|
+
Coroutine,
|
|
16
18
|
DefaultDict,
|
|
19
|
+
Dict,
|
|
17
20
|
List,
|
|
21
|
+
NoReturn,
|
|
18
22
|
Optional,
|
|
19
23
|
Text,
|
|
20
24
|
Union,
|
|
21
|
-
Dict,
|
|
22
|
-
TYPE_CHECKING,
|
|
23
|
-
NoReturn,
|
|
24
|
-
Coroutine,
|
|
25
25
|
)
|
|
26
26
|
|
|
27
27
|
import aiohttp
|
|
@@ -54,15 +54,16 @@ from rasa.core.test import test
|
|
|
54
54
|
from rasa.core.utils import AvailableEndpoints
|
|
55
55
|
from rasa.nlu.emulators.emulator import Emulator
|
|
56
56
|
from rasa.nlu.emulators.no_emulator import NoEmulator
|
|
57
|
+
from rasa.nlu.persistor import parse_remote_storage
|
|
57
58
|
from rasa.nlu.test import CVEvaluationResult
|
|
58
59
|
from rasa.shared.constants import (
|
|
59
|
-
DOCS_URL_TRAINING_DATA,
|
|
60
|
-
DOCS_BASE_URL,
|
|
61
|
-
DEFAULT_SENDER_ID,
|
|
62
60
|
DEFAULT_MODELS_PATH,
|
|
61
|
+
DEFAULT_SENDER_ID,
|
|
62
|
+
DOCS_BASE_URL,
|
|
63
|
+
DOCS_URL_TRAINING_DATA,
|
|
63
64
|
TEST_STORIES_FILE_PREFIX,
|
|
64
65
|
)
|
|
65
|
-
from rasa.shared.core.domain import
|
|
66
|
+
from rasa.shared.core.domain import Domain, InvalidDomain
|
|
66
67
|
from rasa.shared.core.events import Event
|
|
67
68
|
from rasa.shared.core.trackers import (
|
|
68
69
|
DialogueStateTracker,
|
|
@@ -80,8 +81,10 @@ from rasa.utils.endpoints import EndpointConfig
|
|
|
80
81
|
|
|
81
82
|
if TYPE_CHECKING:
|
|
82
83
|
from ssl import SSLContext
|
|
84
|
+
|
|
85
|
+
from mypy_extensions import Arg, KwArg, VarArg
|
|
86
|
+
|
|
83
87
|
from rasa.core.processor import MessageProcessor
|
|
84
|
-
from mypy_extensions import Arg, VarArg, KwArg
|
|
85
88
|
|
|
86
89
|
SanicResponse = Union[
|
|
87
90
|
response.HTTPResponse, Coroutine[Any, Any, response.HTTPResponse]
|
|
@@ -532,6 +535,32 @@ def add_root_route(app: Sanic) -> None:
|
|
|
532
535
|
"""
|
|
533
536
|
return response.html(html_content)
|
|
534
537
|
|
|
538
|
+
@app.get("/license")
|
|
539
|
+
async def license(request: Request) -> HTTPResponse:
|
|
540
|
+
"""Respond with the license expiration date."""
|
|
541
|
+
from rasa.utils.licensing import (
|
|
542
|
+
get_license_expiration_date,
|
|
543
|
+
property_of_active_license,
|
|
544
|
+
)
|
|
545
|
+
|
|
546
|
+
body = {
|
|
547
|
+
"id": property_of_active_license(lambda active_license: active_license.jti),
|
|
548
|
+
"company": property_of_active_license(
|
|
549
|
+
lambda active_license: active_license.company
|
|
550
|
+
),
|
|
551
|
+
"scope": property_of_active_license(
|
|
552
|
+
lambda active_license: active_license.scope
|
|
553
|
+
),
|
|
554
|
+
"email": property_of_active_license(
|
|
555
|
+
lambda active_license: active_license.email
|
|
556
|
+
),
|
|
557
|
+
"expires": get_license_expiration_date(),
|
|
558
|
+
}
|
|
559
|
+
return response.json(
|
|
560
|
+
body=body,
|
|
561
|
+
headers={"Content-Type": "application/json"},
|
|
562
|
+
)
|
|
563
|
+
|
|
535
564
|
|
|
536
565
|
def async_if_callback_url(f: Callable[..., Coroutine]) -> Callable:
|
|
537
566
|
"""Decorator to enable async request handling.
|
|
@@ -1351,7 +1380,13 @@ def create_app(
|
|
|
1351
1380
|
|
|
1352
1381
|
model_path = request.json.get("model_file", None)
|
|
1353
1382
|
model_server = request.json.get("model_server", None)
|
|
1354
|
-
|
|
1383
|
+
|
|
1384
|
+
remote_storage_argument = request.json.get("remote_storage", None)
|
|
1385
|
+
remote_storage = (
|
|
1386
|
+
parse_remote_storage(remote_storage_argument)
|
|
1387
|
+
if remote_storage_argument
|
|
1388
|
+
else None
|
|
1389
|
+
)
|
|
1355
1390
|
|
|
1356
1391
|
if model_server:
|
|
1357
1392
|
try:
|
rasa/shared/constants.py
CHANGED
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import List, Text
|
|
4
4
|
|
|
5
|
+
from rasa.shared.engine.caching import get_local_cache_location
|
|
5
6
|
|
|
6
7
|
DOCS_BASE_URL = "https://rasa.com/docs/rasa-pro"
|
|
7
8
|
DOCS_URL_CONCEPTS = DOCS_BASE_URL + "/concepts"
|
|
@@ -51,6 +52,8 @@ MODEL_CONFIG_SCHEMA_FILE = "shared/utils/schemas/model_config.yml"
|
|
|
51
52
|
CONFIG_SCHEMA_FILE = "shared/utils/schemas/config.yml"
|
|
52
53
|
RESPONSES_SCHEMA_FILE = "shared/nlu/training_data/schemas/responses.yml"
|
|
53
54
|
SCHEMA_EXTENSIONS_FILE = "shared/utils/pykwalify_extensions.py"
|
|
55
|
+
ASSERTIONS_SCHEMA_FILE = "e2e_test/assertions_schema.yml"
|
|
56
|
+
ASSERTIONS_SCHEMA_EXTENSIONS_FILE = "e2e_test/pykwalify_extensions.py"
|
|
54
57
|
LATEST_TRAINING_DATA_FORMAT_VERSION = "3.1"
|
|
55
58
|
|
|
56
59
|
DOMAIN_SCHEMA_FILE = "shared/utils/schemas/domain.yml"
|
|
@@ -83,6 +86,8 @@ ENV_LOG_LEVEL_LLM_MODULE_NAMES = {
|
|
|
83
86
|
"EnterpriseSearchPolicy": "LOG_LEVEL_LLM_ENTERPRISE_SEARCH",
|
|
84
87
|
"IntentlessPolicy": "LOG_LEVEL_LLM_INTENTLESS_POLICY",
|
|
85
88
|
"ContextualResponseRephraser": "LOG_LEVEL_LLM_REPHRASER",
|
|
89
|
+
"NLUCommandAdapter": "LOG_LEVEL_NLU_COMMAND_ADAPTER",
|
|
90
|
+
"LLMBasedRouter": "LOG_LEVEL_LLM_BASED_ROUTER",
|
|
86
91
|
}
|
|
87
92
|
TCP_PROTOCOL = "TCP"
|
|
88
93
|
|
|
@@ -137,34 +142,82 @@ DIAGNOSTIC_DATA = "diagnostic_data"
|
|
|
137
142
|
RESPONSE_CONDITION = "condition"
|
|
138
143
|
CHANNEL = "channel"
|
|
139
144
|
|
|
145
|
+
API_KEY = "api_key"
|
|
146
|
+
|
|
147
|
+
AZURE_API_KEY_ENV_VAR = "AZURE_API_KEY"
|
|
148
|
+
AZURE_AD_TOKEN_ENV_VAR = "AZURE_AD_TOKEN"
|
|
149
|
+
AZURE_API_BASE_ENV_VAR = "AZURE_API_BASE"
|
|
150
|
+
AZURE_API_VERSION_ENV_VAR = "AZURE_API_VERSION"
|
|
151
|
+
AZURE_API_TYPE_ENV_VAR = "AZURE_API_TYPE"
|
|
152
|
+
|
|
140
153
|
OPENAI_API_KEY_ENV_VAR = "OPENAI_API_KEY"
|
|
141
154
|
OPENAI_API_TYPE_ENV_VAR = "OPENAI_API_TYPE"
|
|
142
155
|
OPENAI_API_VERSION_ENV_VAR = "OPENAI_API_VERSION"
|
|
143
156
|
OPENAI_API_BASE_ENV_VAR = "OPENAI_API_BASE"
|
|
144
157
|
|
|
158
|
+
OPENAI_API_BASE_CONFIG_KEY = "openai_api_base"
|
|
145
159
|
OPENAI_API_TYPE_CONFIG_KEY = "openai_api_type"
|
|
146
|
-
OPENAI_API_TYPE_NO_PREFIX_CONFIG_KEY = "api_type"
|
|
147
|
-
|
|
148
160
|
OPENAI_API_VERSION_CONFIG_KEY = "openai_api_version"
|
|
149
|
-
OPENAI_API_VERSION_NO_PREFIX_CONFIG_KEY = "api_version"
|
|
150
161
|
|
|
151
|
-
|
|
152
|
-
|
|
162
|
+
API_BASE_CONFIG_KEY = "api_base"
|
|
163
|
+
API_TYPE_CONFIG_KEY = "api_type"
|
|
164
|
+
API_VERSION_CONFIG_KEY = "api_version"
|
|
165
|
+
LANGCHAIN_TYPE_CONFIG_KEY = "_type"
|
|
166
|
+
RASA_TYPE_CONFIG_KEY = "type"
|
|
167
|
+
PROVIDER_CONFIG_KEY = "provider"
|
|
153
168
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
OPENAI_ENGINE_CONFIG_KEY = "engine"
|
|
169
|
+
REQUEST_TIMEOUT_CONFIG_KEY = "request_timeout" # deprecated
|
|
170
|
+
TIMEOUT_CONFIG_KEY = "timeout"
|
|
157
171
|
|
|
158
|
-
|
|
159
|
-
|
|
172
|
+
DEPLOYMENT_NAME_CONFIG_KEY = "deployment_name"
|
|
173
|
+
DEPLOYMENT_CONFIG_KEY = "deployment"
|
|
174
|
+
EMBEDDINGS_CONFIG_KEY = "embeddings"
|
|
175
|
+
ENGINE_CONFIG_KEY = "engine"
|
|
176
|
+
LLM_CONFIG_KEY = "llm"
|
|
177
|
+
MODEL_CONFIG_KEY = "model"
|
|
178
|
+
MODEL_NAME_CONFIG_KEY = "model_name"
|
|
179
|
+
PROMPT_CONFIG_KEY = "prompt"
|
|
180
|
+
PROMPT_TEMPLATE_CONFIG_KEY = "prompt_template"
|
|
181
|
+
|
|
182
|
+
STREAM_CONFIG_KEY = "stream"
|
|
183
|
+
N_REPHRASES_CONFIG_KEY = "n"
|
|
184
|
+
|
|
185
|
+
AZURE_API_KEY_ENV_VAR = "AZURE_API_KEY"
|
|
186
|
+
AZURE_AD_TOKEN_ENV_VAR = "AZURE_AD_TOKEN"
|
|
187
|
+
AZURE_API_BASE_ENV_VAR = "AZURE_API_BASE"
|
|
188
|
+
AZURE_API_VERSION_ENV_VAR = "AZURE_API_VERSION"
|
|
189
|
+
AZURE_API_TYPE_ENV_VAR = "AZURE_API_TYPE"
|
|
190
|
+
|
|
191
|
+
HUGGINGFACE_MULTIPROCESS_CONFIG_KEY = "multi_process"
|
|
192
|
+
HUGGINGFACE_CACHE_FOLDER_CONFIG_KEY = "cache_folder"
|
|
193
|
+
HUGGINGFACE_SHOW_PROGRESS_CONFIG_KEY = "show_progress"
|
|
194
|
+
HUGGINGFACE_MODEL_KWARGS_CONFIG_KEY = "model_kwargs"
|
|
195
|
+
HUGGINGFACE_ENCODE_KWARGS_CONFIG_KEY = "encode_kwargs"
|
|
196
|
+
HUGGINGFACE_LOCAL_EMBEDDING_CACHING_FOLDER = (
|
|
197
|
+
get_local_cache_location() / "huggingface_local_embeddings"
|
|
198
|
+
)
|
|
160
199
|
|
|
161
200
|
REQUESTS_CA_BUNDLE_ENV_VAR = "REQUESTS_CA_BUNDLE"
|
|
162
201
|
REQUESTS_SSL_CONTEXT_PURPOSE_ENV_VAR = "REQUESTS_SSL_CONTEXT_PURPOSE"
|
|
202
|
+
RASA_CA_BUNDLE_ENV_VAR = "RASA_CA_BUNDLE" # used in verify
|
|
203
|
+
RASA_SSL_CERTIFICATE_ENV_VAR = "RASA_SSL_CERTIFICATE" # used in cert (client side)
|
|
204
|
+
LITELLM_SSL_VERIFY_ENV_VAR = "SSL_VERIFY"
|
|
205
|
+
LITELLM_SSL_CERTIFICATE_ENV_VAR = "SSL_CERTIFICATE"
|
|
206
|
+
|
|
207
|
+
OPENAI_PROVIDER = "openai"
|
|
208
|
+
AZURE_OPENAI_PROVIDER = "azure"
|
|
209
|
+
SELF_HOSTED_PROVIDER = "self-hosted"
|
|
210
|
+
HUGGINGFACE_LOCAL_EMBEDDING_PROVIDER = "huggingface_local"
|
|
163
211
|
|
|
212
|
+
AZURE_API_TYPE = "azure"
|
|
213
|
+
OPENAI_API_TYPE = "openai"
|
|
164
214
|
|
|
165
215
|
RASA_DEFAULT_FLOW_PATTERN_PREFIX = "pattern_"
|
|
166
216
|
CONTEXT = "context"
|
|
167
217
|
|
|
218
|
+
RASA_PATTERN_INTERNAL_ERROR = "pattern_internal_error"
|
|
219
|
+
RASA_PATTERN_HUMAN_HANDOFF = "pattern_human_handoff"
|
|
220
|
+
|
|
168
221
|
RASA_INTERNAL_ERROR_PREFIX = "rasa_internal_error_"
|
|
169
222
|
RASA_PATTERN_INTERNAL_ERROR_DEFAULT = RASA_INTERNAL_ERROR_PREFIX + "default"
|
|
170
223
|
RASA_PATTERN_INTERNAL_ERROR_USER_INPUT_TOO_LONG = (
|
|
@@ -185,8 +238,3 @@ RASA_PATTERN_CANNOT_HANDLE_INVALID_INTENT = (
|
|
|
185
238
|
)
|
|
186
239
|
|
|
187
240
|
ROUTE_TO_CALM_SLOT = "route_session_to_calm"
|
|
188
|
-
EMBEDDINGS_CONFIG_KEY = "embeddings"
|
|
189
|
-
MODEL_CONFIG_KEY = "model"
|
|
190
|
-
MODEL_NAME_CONFIG_KEY = "model_name"
|
|
191
|
-
PROMPT_CONFIG_KEY = "prompt"
|
|
192
|
-
PROMPT_TEMPLATE_CONFIG_KEY = "prompt_template"
|
rasa/shared/core/domain.py
CHANGED
|
@@ -11,7 +11,6 @@ from typing import (
|
|
|
11
11
|
Dict,
|
|
12
12
|
Iterable,
|
|
13
13
|
List,
|
|
14
|
-
MutableMapping,
|
|
15
14
|
NamedTuple,
|
|
16
15
|
NoReturn,
|
|
17
16
|
Optional,
|
|
@@ -20,6 +19,7 @@ from typing import (
|
|
|
20
19
|
Tuple,
|
|
21
20
|
Union,
|
|
22
21
|
cast,
|
|
22
|
+
MutableMapping,
|
|
23
23
|
)
|
|
24
24
|
|
|
25
25
|
import structlog
|
|
@@ -51,11 +51,11 @@ from rasa.shared.core.constants import (
|
|
|
51
51
|
)
|
|
52
52
|
from rasa.shared.core.events import SlotSet, UserUttered
|
|
53
53
|
from rasa.shared.core.slots import (
|
|
54
|
-
AnySlot,
|
|
55
|
-
CategoricalSlot,
|
|
56
|
-
ListSlot,
|
|
57
54
|
Slot,
|
|
55
|
+
CategoricalSlot,
|
|
58
56
|
TextSlot,
|
|
57
|
+
AnySlot,
|
|
58
|
+
ListSlot,
|
|
59
59
|
)
|
|
60
60
|
from rasa.shared.exceptions import (
|
|
61
61
|
RasaException,
|
|
@@ -63,21 +63,21 @@ from rasa.shared.exceptions import (
|
|
|
63
63
|
YamlSyntaxException,
|
|
64
64
|
)
|
|
65
65
|
from rasa.shared.nlu.constants import (
|
|
66
|
-
ENTITIES,
|
|
67
|
-
ENTITY_ATTRIBUTE_GROUP,
|
|
68
|
-
ENTITY_ATTRIBUTE_ROLE,
|
|
69
66
|
ENTITY_ATTRIBUTE_TYPE,
|
|
70
|
-
|
|
67
|
+
ENTITY_ATTRIBUTE_ROLE,
|
|
68
|
+
ENTITY_ATTRIBUTE_GROUP,
|
|
71
69
|
RESPONSE_IDENTIFIER_DELIMITER,
|
|
70
|
+
INTENT_NAME_KEY,
|
|
71
|
+
ENTITIES,
|
|
72
72
|
)
|
|
73
73
|
from rasa.shared.utils.cli import print_error_and_exit
|
|
74
74
|
from rasa.shared.utils.yaml import (
|
|
75
75
|
KEY_TRAINING_DATA_FORMAT_VERSION,
|
|
76
|
-
dump_obj_as_yaml_to_string,
|
|
77
76
|
read_yaml,
|
|
77
|
+
validate_training_data_format_version,
|
|
78
78
|
read_yaml_file,
|
|
79
|
+
dump_obj_as_yaml_to_string,
|
|
79
80
|
validate_raw_yaml_using_schema_file_with_responses,
|
|
80
|
-
validate_training_data_format_version,
|
|
81
81
|
)
|
|
82
82
|
|
|
83
83
|
if TYPE_CHECKING:
|
|
@@ -271,8 +271,8 @@ class Domain:
|
|
|
271
271
|
|
|
272
272
|
additional_arguments = {
|
|
273
273
|
**data.get("config", {}),
|
|
274
|
-
"actions_which_explicitly_need_domain":
|
|
275
|
-
domain_actions
|
|
274
|
+
"actions_which_explicitly_need_domain": (
|
|
275
|
+
cls._collect_actions_which_explicitly_need_domain(domain_actions)
|
|
276
276
|
),
|
|
277
277
|
}
|
|
278
278
|
session_config = cls._get_session_config(data.get(SESSION_CONFIG_KEY, {}))
|
|
@@ -2047,6 +2047,9 @@ class Domain:
|
|
|
2047
2047
|
|
|
2048
2048
|
return action_names
|
|
2049
2049
|
|
|
2050
|
+
def is_custom_action(self, action_name: str) -> bool:
|
|
2051
|
+
return action_name in self._custom_actions
|
|
2052
|
+
|
|
2050
2053
|
|
|
2051
2054
|
def warn_about_duplicates_found_during_domain_merging(
|
|
2052
2055
|
duplicates: Dict[Text, List[Text]],
|
rasa/shared/core/events.py
CHANGED
|
@@ -930,16 +930,42 @@ class BotUttered(SkipEventInMDStoryMixin):
|
|
|
930
930
|
|
|
931
931
|
return self.__members() == other.__members()
|
|
932
932
|
|
|
933
|
+
def _clean_up_metadata(self) -> Dict[str, Any]:
|
|
934
|
+
"""Removes search_results metadata key from the metadata.
|
|
935
|
+
|
|
936
|
+
This is intended to prevent increasing the string representation
|
|
937
|
+
character length of the bot event.
|
|
938
|
+
"""
|
|
939
|
+
from rasa.core.policies.enterprise_search_policy import (
|
|
940
|
+
SEARCH_RESULTS_METADATA_KEY,
|
|
941
|
+
)
|
|
942
|
+
|
|
943
|
+
metadata = copy.deepcopy(self.metadata)
|
|
944
|
+
|
|
945
|
+
if SEARCH_RESULTS_METADATA_KEY in self.metadata:
|
|
946
|
+
metadata.pop(SEARCH_RESULTS_METADATA_KEY)
|
|
947
|
+
structlogger.debug(
|
|
948
|
+
"search_results.metadata.removed",
|
|
949
|
+
event_info="Removed search_results metadata key only "
|
|
950
|
+
"from the string representation of the bot event.",
|
|
951
|
+
)
|
|
952
|
+
|
|
953
|
+
return metadata
|
|
954
|
+
|
|
933
955
|
def __str__(self) -> Text:
|
|
934
956
|
"""Returns text representation of event."""
|
|
957
|
+
metadata = self._clean_up_metadata()
|
|
958
|
+
|
|
935
959
|
return "BotUttered(text: {}, data: {}, metadata: {})".format(
|
|
936
|
-
self.text, json.dumps(self.data), json.dumps(
|
|
960
|
+
self.text, json.dumps(self.data), json.dumps(metadata)
|
|
937
961
|
)
|
|
938
962
|
|
|
939
963
|
def __repr__(self) -> Text:
|
|
940
964
|
"""Returns text representation of event for debugging."""
|
|
965
|
+
metadata = self._clean_up_metadata()
|
|
966
|
+
|
|
941
967
|
return "BotUttered('{}', {}, {}, {})".format(
|
|
942
|
-
self.text, json.dumps(self.data), json.dumps(
|
|
968
|
+
self.text, json.dumps(self.data), json.dumps(metadata), self.timestamp
|
|
943
969
|
)
|
|
944
970
|
|
|
945
971
|
def apply_to(self, tracker: "DialogueStateTracker") -> None:
|