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.

Files changed (190) hide show
  1. README.md +26 -57
  2. rasa/__init__.py +1 -2
  3. rasa/__main__.py +5 -0
  4. rasa/anonymization/anonymization_rule_executor.py +2 -2
  5. rasa/api.py +26 -22
  6. rasa/cli/arguments/data.py +27 -2
  7. rasa/cli/arguments/default_arguments.py +25 -3
  8. rasa/cli/arguments/run.py +9 -9
  9. rasa/cli/arguments/train.py +2 -0
  10. rasa/cli/data.py +70 -8
  11. rasa/cli/e2e_test.py +108 -433
  12. rasa/cli/interactive.py +1 -0
  13. rasa/cli/llm_fine_tuning.py +395 -0
  14. rasa/cli/project_templates/calm/endpoints.yml +1 -1
  15. rasa/cli/project_templates/tutorial/endpoints.yml +1 -1
  16. rasa/cli/run.py +14 -13
  17. rasa/cli/scaffold.py +10 -8
  18. rasa/cli/train.py +8 -7
  19. rasa/cli/utils.py +15 -0
  20. rasa/constants.py +7 -1
  21. rasa/core/actions/action.py +98 -49
  22. rasa/core/actions/action_run_slot_rejections.py +4 -1
  23. rasa/core/actions/custom_action_executor.py +9 -6
  24. rasa/core/actions/direct_custom_actions_executor.py +80 -0
  25. rasa/core/actions/e2e_stub_custom_action_executor.py +68 -0
  26. rasa/core/actions/grpc_custom_action_executor.py +2 -2
  27. rasa/core/actions/http_custom_action_executor.py +6 -5
  28. rasa/core/agent.py +21 -17
  29. rasa/core/channels/__init__.py +2 -0
  30. rasa/core/channels/audiocodes.py +1 -16
  31. rasa/core/channels/inspector/dist/index.html +0 -2
  32. rasa/core/channels/inspector/index.html +0 -2
  33. rasa/core/channels/voice_aware/__init__.py +0 -0
  34. rasa/core/channels/voice_aware/jambonz.py +103 -0
  35. rasa/core/channels/voice_aware/jambonz_protocol.py +344 -0
  36. rasa/core/channels/voice_aware/utils.py +20 -0
  37. rasa/core/channels/voice_native/__init__.py +0 -0
  38. rasa/core/constants.py +6 -1
  39. rasa/core/featurizers/single_state_featurizer.py +1 -22
  40. rasa/core/featurizers/tracker_featurizers.py +18 -115
  41. rasa/core/information_retrieval/faiss.py +7 -4
  42. rasa/core/information_retrieval/information_retrieval.py +8 -0
  43. rasa/core/information_retrieval/milvus.py +9 -2
  44. rasa/core/information_retrieval/qdrant.py +1 -1
  45. rasa/core/nlg/contextual_response_rephraser.py +32 -10
  46. rasa/core/nlg/summarize.py +4 -3
  47. rasa/core/policies/enterprise_search_policy.py +100 -44
  48. rasa/core/policies/flows/flow_executor.py +130 -94
  49. rasa/core/policies/intentless_policy.py +52 -28
  50. rasa/core/policies/ted_policy.py +33 -58
  51. rasa/core/policies/unexpected_intent_policy.py +7 -15
  52. rasa/core/processor.py +20 -53
  53. rasa/core/run.py +5 -4
  54. rasa/core/tracker_store.py +8 -4
  55. rasa/core/utils.py +45 -56
  56. rasa/dialogue_understanding/coexistence/llm_based_router.py +45 -12
  57. rasa/dialogue_understanding/commands/__init__.py +4 -0
  58. rasa/dialogue_understanding/commands/change_flow_command.py +0 -6
  59. rasa/dialogue_understanding/commands/session_start_command.py +59 -0
  60. rasa/dialogue_understanding/commands/set_slot_command.py +1 -5
  61. rasa/dialogue_understanding/commands/utils.py +38 -0
  62. rasa/dialogue_understanding/generator/constants.py +10 -3
  63. rasa/dialogue_understanding/generator/flow_retrieval.py +14 -5
  64. rasa/dialogue_understanding/generator/llm_based_command_generator.py +12 -2
  65. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +106 -87
  66. rasa/dialogue_understanding/generator/nlu_command_adapter.py +28 -6
  67. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +90 -37
  68. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +15 -15
  69. rasa/dialogue_understanding/patterns/session_start.py +37 -0
  70. rasa/dialogue_understanding/processor/command_processor.py +13 -14
  71. rasa/e2e_test/aggregate_test_stats_calculator.py +124 -0
  72. rasa/e2e_test/assertions.py +1181 -0
  73. rasa/e2e_test/assertions_schema.yml +106 -0
  74. rasa/e2e_test/constants.py +20 -0
  75. rasa/e2e_test/e2e_config.py +220 -0
  76. rasa/e2e_test/e2e_config_schema.yml +26 -0
  77. rasa/e2e_test/e2e_test_case.py +131 -8
  78. rasa/e2e_test/e2e_test_converter.py +363 -0
  79. rasa/e2e_test/e2e_test_converter_prompt.jinja2 +70 -0
  80. rasa/e2e_test/e2e_test_coverage_report.py +364 -0
  81. rasa/e2e_test/e2e_test_result.py +26 -6
  82. rasa/e2e_test/e2e_test_runner.py +491 -72
  83. rasa/e2e_test/e2e_test_schema.yml +96 -0
  84. rasa/e2e_test/pykwalify_extensions.py +39 -0
  85. rasa/e2e_test/stub_custom_action.py +70 -0
  86. rasa/e2e_test/utils/__init__.py +0 -0
  87. rasa/e2e_test/utils/e2e_yaml_utils.py +55 -0
  88. rasa/e2e_test/utils/io.py +596 -0
  89. rasa/e2e_test/utils/validation.py +80 -0
  90. rasa/engine/recipes/default_components.py +0 -2
  91. rasa/engine/storage/local_model_storage.py +0 -1
  92. rasa/env.py +9 -0
  93. rasa/keys +1 -0
  94. rasa/llm_fine_tuning/__init__.py +0 -0
  95. rasa/llm_fine_tuning/annotation_module.py +241 -0
  96. rasa/llm_fine_tuning/conversations.py +144 -0
  97. rasa/llm_fine_tuning/llm_data_preparation_module.py +178 -0
  98. rasa/llm_fine_tuning/notebooks/unsloth_finetuning.ipynb +407 -0
  99. rasa/llm_fine_tuning/paraphrasing/__init__.py +0 -0
  100. rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +281 -0
  101. rasa/llm_fine_tuning/paraphrasing/default_rephrase_prompt_template.jina2 +44 -0
  102. rasa/llm_fine_tuning/paraphrasing/rephrase_validator.py +121 -0
  103. rasa/llm_fine_tuning/paraphrasing/rephrased_user_message.py +10 -0
  104. rasa/llm_fine_tuning/paraphrasing_module.py +128 -0
  105. rasa/llm_fine_tuning/storage.py +174 -0
  106. rasa/llm_fine_tuning/train_test_split_module.py +441 -0
  107. rasa/model_training.py +48 -16
  108. rasa/nlu/classifiers/diet_classifier.py +25 -38
  109. rasa/nlu/classifiers/logistic_regression_classifier.py +9 -44
  110. rasa/nlu/classifiers/sklearn_intent_classifier.py +16 -37
  111. rasa/nlu/extractors/crf_entity_extractor.py +50 -93
  112. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +45 -78
  113. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +17 -52
  114. rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +3 -5
  115. rasa/nlu/persistor.py +129 -32
  116. rasa/server.py +45 -10
  117. rasa/shared/constants.py +63 -15
  118. rasa/shared/core/domain.py +15 -12
  119. rasa/shared/core/events.py +28 -2
  120. rasa/shared/core/flows/flow.py +208 -13
  121. rasa/shared/core/flows/flow_path.py +84 -0
  122. rasa/shared/core/flows/flows_list.py +28 -10
  123. rasa/shared/core/flows/flows_yaml_schema.json +269 -193
  124. rasa/shared/core/flows/validation.py +112 -25
  125. rasa/shared/core/flows/yaml_flows_io.py +149 -10
  126. rasa/shared/core/trackers.py +6 -0
  127. rasa/shared/core/training_data/visualization.html +2 -2
  128. rasa/shared/exceptions.py +4 -0
  129. rasa/shared/importers/importer.py +60 -11
  130. rasa/shared/importers/remote_importer.py +196 -0
  131. rasa/shared/nlu/constants.py +2 -0
  132. rasa/shared/nlu/training_data/features.py +2 -120
  133. rasa/shared/providers/_configs/__init__.py +0 -0
  134. rasa/shared/providers/_configs/azure_openai_client_config.py +181 -0
  135. rasa/shared/providers/_configs/client_config.py +57 -0
  136. rasa/shared/providers/_configs/default_litellm_client_config.py +130 -0
  137. rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +234 -0
  138. rasa/shared/providers/_configs/openai_client_config.py +175 -0
  139. rasa/shared/providers/_configs/self_hosted_llm_client_config.py +171 -0
  140. rasa/shared/providers/_configs/utils.py +101 -0
  141. rasa/shared/providers/_ssl_verification_utils.py +124 -0
  142. rasa/shared/providers/embedding/__init__.py +0 -0
  143. rasa/shared/providers/embedding/_base_litellm_embedding_client.py +254 -0
  144. rasa/shared/providers/embedding/_langchain_embedding_client_adapter.py +74 -0
  145. rasa/shared/providers/embedding/azure_openai_embedding_client.py +277 -0
  146. rasa/shared/providers/embedding/default_litellm_embedding_client.py +102 -0
  147. rasa/shared/providers/embedding/embedding_client.py +90 -0
  148. rasa/shared/providers/embedding/embedding_response.py +41 -0
  149. rasa/shared/providers/embedding/huggingface_local_embedding_client.py +191 -0
  150. rasa/shared/providers/embedding/openai_embedding_client.py +172 -0
  151. rasa/shared/providers/llm/__init__.py +0 -0
  152. rasa/shared/providers/llm/_base_litellm_client.py +227 -0
  153. rasa/shared/providers/llm/azure_openai_llm_client.py +338 -0
  154. rasa/shared/providers/llm/default_litellm_llm_client.py +84 -0
  155. rasa/shared/providers/llm/llm_client.py +76 -0
  156. rasa/shared/providers/llm/llm_response.py +50 -0
  157. rasa/shared/providers/llm/openai_llm_client.py +155 -0
  158. rasa/shared/providers/llm/self_hosted_llm_client.py +169 -0
  159. rasa/shared/providers/mappings.py +75 -0
  160. rasa/shared/utils/cli.py +30 -0
  161. rasa/shared/utils/io.py +65 -3
  162. rasa/shared/utils/llm.py +223 -200
  163. rasa/shared/utils/yaml.py +122 -7
  164. rasa/studio/download.py +19 -13
  165. rasa/studio/train.py +2 -3
  166. rasa/studio/upload.py +2 -3
  167. rasa/telemetry.py +113 -58
  168. rasa/tracing/config.py +2 -3
  169. rasa/tracing/instrumentation/attribute_extractors.py +29 -17
  170. rasa/tracing/instrumentation/instrumentation.py +4 -47
  171. rasa/utils/common.py +18 -19
  172. rasa/utils/endpoints.py +7 -4
  173. rasa/utils/io.py +66 -0
  174. rasa/utils/json_utils.py +60 -0
  175. rasa/utils/licensing.py +9 -1
  176. rasa/utils/ml_utils.py +4 -2
  177. rasa/utils/tensorflow/model_data.py +193 -2
  178. rasa/validator.py +196 -1
  179. rasa/version.py +1 -1
  180. {rasa_pro-3.9.18.dist-info → rasa_pro-3.10.4.dist-info}/METADATA +47 -72
  181. {rasa_pro-3.9.18.dist-info → rasa_pro-3.10.4.dist-info}/RECORD +186 -121
  182. rasa/nlu/classifiers/llm_intent_classifier.py +0 -519
  183. rasa/shared/providers/openai/clients.py +0 -43
  184. rasa/shared/providers/openai/session_handler.py +0 -110
  185. rasa/utils/tensorflow/feature_array.py +0 -366
  186. /rasa/{shared/providers/openai → cli/project_templates/tutorial/actions}/__init__.py +0 -0
  187. /rasa/cli/project_templates/tutorial/{actions.py → actions/actions.py} +0 -0
  188. {rasa_pro-3.9.18.dist-info → rasa_pro-3.10.4.dist-info}/NOTICE +0 -0
  189. {rasa_pro-3.9.18.dist-info → rasa_pro-3.10.4.dist-info}/WHEEL +0 -0
  190. {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 typing import Optional, Text, Tuple, TYPE_CHECKING
6
+ from enum import Enum
7
+ from typing import TYPE_CHECKING, List, Optional, Text, Tuple, Union
6
8
 
7
- from rasa.shared.exceptions import RasaException
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
- def get_persistor(name: Text) -> Optional["Persistor"]:
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 name == "aws":
85
+ if storage == RemoteStorageType.AWS.value:
25
86
  return AWSPersistor(
26
- os.environ.get("BUCKET_NAME"), os.environ.get("AWS_ENDPOINT_URL")
87
+ os.environ.get(BUCKET_NAME_ENV), os.environ.get(AWS_ENDPOINT_URL_ENV)
27
88
  )
28
- if name == "gcs":
29
- return GCSPersistor(os.environ.get("BUCKET_NAME"))
89
+ if storage == RemoteStorageType.GCS.value:
90
+ return GCSPersistor(os.environ.get(BUCKET_NAME_ENV))
30
91
 
31
- if name == "azure":
92
+ if storage == RemoteStorageType.AZURE.value:
32
93
  return AzurePersistor(
33
- os.environ.get("AZURE_CONTAINER"),
34
- os.environ.get("AZURE_ACCOUNT_NAME"),
35
- os.environ.get("AZURE_ACCOUNT_KEY"),
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
- if name:
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(name)
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 {name}. Please make sure to "
44
- "either use an included model persistor (`aws`, `gcs` "
45
- "or `azure`) or specify the module path to an external "
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, model_directory: Text, model_name: Text) -> None:
55
- """Uploads a model persisted in the `target_dir` to cloud storage."""
56
- if not os.path.isdir(model_directory):
57
- raise ValueError(f"Target directory '{model_directory}' not found.")
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
- file_key, tar_path = self._compress(model_directory, model_name)
60
- self._persist_tar(file_key, tar_path)
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
- def retrieve(self, model_name: Text, target_path: Text) -> None:
63
- """Downloads a model that has been persisted to cloud storage."""
64
- tar_name = model_name
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
- if not model_name.endswith("tar.gz"):
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 = ".tar.gz" if include_extension else ""
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 == 403:
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 == 404:
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 # type: ignore[attr-defined]
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 InvalidDomain, Domain
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
- remote_storage = request.json.get("remote_storage", None)
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
- OPENAI_API_BASE_CONFIG_KEY = "openai_api_base"
152
- OPENAI_API_BASE_NO_PREFIX_CONFIG_KEY = "api_base"
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
- OPENAI_DEPLOYMENT_NAME_CONFIG_KEY = "deployment_name"
155
- OPENAI_DEPLOYMENT_CONFIG_KEY = "deployment"
156
- OPENAI_ENGINE_CONFIG_KEY = "engine"
169
+ REQUEST_TIMEOUT_CONFIG_KEY = "request_timeout" # deprecated
170
+ TIMEOUT_CONFIG_KEY = "timeout"
157
171
 
158
- RASA_TYPE_CONFIG_KEY = "type"
159
- LANGCHAIN_TYPE_CONFIG_KEY = "_type"
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"
@@ -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
- INTENT_NAME_KEY,
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": cls._collect_actions_which_explicitly_need_domain( # noqa: E501
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]],
@@ -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(self.metadata)
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(self.metadata), self.timestamp
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: