rasa-pro 3.11.0__py3-none-any.whl → 3.11.0a2__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 (217) hide show
  1. README.md +396 -17
  2. rasa/__main__.py +15 -31
  3. rasa/api.py +1 -5
  4. rasa/cli/arguments/default_arguments.py +2 -1
  5. rasa/cli/arguments/shell.py +1 -5
  6. rasa/cli/arguments/train.py +0 -14
  7. rasa/cli/e2e_test.py +1 -1
  8. rasa/cli/evaluate.py +8 -8
  9. rasa/cli/inspect.py +5 -7
  10. rasa/cli/interactive.py +0 -1
  11. rasa/cli/llm_fine_tuning.py +1 -1
  12. rasa/cli/project_templates/calm/config.yml +7 -5
  13. rasa/cli/project_templates/calm/endpoints.yml +2 -15
  14. rasa/cli/project_templates/tutorial/config.yml +5 -8
  15. rasa/cli/project_templates/tutorial/data/flows.yml +1 -1
  16. rasa/cli/project_templates/tutorial/data/patterns.yml +0 -5
  17. rasa/cli/project_templates/tutorial/domain.yml +0 -14
  18. rasa/cli/project_templates/tutorial/endpoints.yml +0 -5
  19. rasa/cli/run.py +1 -1
  20. rasa/cli/scaffold.py +2 -4
  21. rasa/cli/studio/studio.py +8 -18
  22. rasa/cli/studio/upload.py +15 -0
  23. rasa/cli/train.py +0 -3
  24. rasa/cli/utils.py +1 -6
  25. rasa/cli/x.py +8 -8
  26. rasa/constants.py +1 -3
  27. rasa/core/actions/action.py +33 -75
  28. rasa/core/actions/e2e_stub_custom_action_executor.py +1 -5
  29. rasa/core/actions/http_custom_action_executor.py +0 -4
  30. rasa/core/channels/channel.py +0 -20
  31. rasa/core/channels/development_inspector.py +2 -8
  32. rasa/core/channels/inspector/dist/assets/{arc-bc141fb2.js → arc-6852c607.js} +1 -1
  33. rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-be2db283.js → c4Diagram-d0fbc5ce-acc952b2.js} +1 -1
  34. rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-55366915.js → classDiagram-936ed81e-848a7597.js} +1 -1
  35. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-bb529518.js → classDiagram-v2-c3cb15f1-a73d3e68.js} +1 -1
  36. rasa/core/channels/inspector/dist/assets/{createText-62fc7601-b0ec81d6.js → createText-62fc7601-e5ee049d.js} +1 -1
  37. rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-6166330c.js → edges-f2ad444c-771e517e.js} +1 -1
  38. rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-5ccc6a8e.js → erDiagram-9d236eb7-aa347178.js} +1 -1
  39. rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-fca3bfe4.js → flowDb-1972c806-651fc57d.js} +1 -1
  40. rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-4739080f.js → flowDiagram-7ea5b25a-ca67804f.js} +1 -1
  41. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-587d82d8.js +1 -0
  42. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-7c1b0e0f.js → flowchart-elk-definition-abe16c3d-2dbc568d.js} +1 -1
  43. rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-772fd050.js → ganttDiagram-9b5ea136-25a65bd8.js} +1 -1
  44. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-8eae1dc9.js → gitGraphDiagram-99d0ae7c-fdc7378d.js} +1 -1
  45. rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-f55afcdf.js → index-2c4b9a3b-6f1fd606.js} +1 -1
  46. rasa/core/channels/inspector/dist/assets/{index-e7cef9de.js → index-efdd30c1.js} +68 -68
  47. rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-124d4a14.js → infoDiagram-736b4530-cb1a041a.js} +1 -1
  48. rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-7c4fae44.js → journeyDiagram-df861f2b-14609879.js} +1 -1
  49. rasa/core/channels/inspector/dist/assets/{layout-b9885fb6.js → layout-2490f52b.js} +1 -1
  50. rasa/core/channels/inspector/dist/assets/{line-7c59abb6.js → line-40186f1f.js} +1 -1
  51. rasa/core/channels/inspector/dist/assets/{linear-4776f780.js → linear-08814e93.js} +1 -1
  52. rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-2332c46c.js → mindmap-definition-beec6740-1a534584.js} +1 -1
  53. rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-8fb39303.js → pieDiagram-dbbf0591-72397b61.js} +1 -1
  54. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-3c7180a2.js → quadrantDiagram-4d7f4fd6-3bb0b6a3.js} +1 -1
  55. rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-e910bcb8.js → requirementDiagram-6fc4c22a-57334f61.js} +1 -1
  56. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-ead16c89.js → sankeyDiagram-8f13d901-111e1297.js} +1 -1
  57. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-29a02a19.js → sequenceDiagram-b655622a-10bcfe62.js} +1 -1
  58. rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-042b3137.js → stateDiagram-59f0c015-acaf7513.js} +1 -1
  59. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-2178c0f3.js → stateDiagram-v2-2b26beab-3ec2a235.js} +1 -1
  60. rasa/core/channels/inspector/dist/assets/{styles-080da4f6-23ffa4fc.js → styles-080da4f6-62730289.js} +1 -1
  61. rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-94f59763.js → styles-3dcbcfbf-5284ee76.js} +1 -1
  62. rasa/core/channels/inspector/dist/assets/{styles-9c745c82-78a6bebc.js → styles-9c745c82-642435e3.js} +1 -1
  63. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-eae2a6f6.js → svgDrawCommon-4835440b-b250a350.js} +1 -1
  64. rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-5c968d92.js → timeline-definition-5b62e21b-c2b147ed.js} +1 -1
  65. rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-fd3db0d5.js → xychartDiagram-2b33534f-f92cfea9.js} +1 -1
  66. rasa/core/channels/inspector/dist/index.html +1 -1
  67. rasa/core/channels/inspector/src/App.tsx +1 -1
  68. rasa/core/channels/inspector/src/helpers/audiostream.ts +16 -77
  69. rasa/core/channels/socketio.py +2 -7
  70. rasa/core/channels/telegram.py +1 -1
  71. rasa/core/channels/twilio.py +1 -1
  72. rasa/core/channels/voice_ready/audiocodes.py +4 -15
  73. rasa/core/channels/voice_ready/jambonz.py +4 -15
  74. rasa/core/channels/voice_ready/twilio_voice.py +21 -6
  75. rasa/core/channels/voice_ready/utils.py +5 -6
  76. rasa/core/channels/voice_stream/asr/asr_engine.py +1 -19
  77. rasa/core/channels/voice_stream/asr/asr_event.py +0 -5
  78. rasa/core/channels/voice_stream/asr/deepgram.py +15 -28
  79. rasa/core/channels/voice_stream/audio_bytes.py +0 -1
  80. rasa/core/channels/voice_stream/browser_audio.py +9 -32
  81. rasa/core/channels/voice_stream/tts/azure.py +3 -9
  82. rasa/core/channels/voice_stream/tts/cartesia.py +8 -12
  83. rasa/core/channels/voice_stream/tts/tts_engine.py +1 -11
  84. rasa/core/channels/voice_stream/twilio_media_streams.py +19 -28
  85. rasa/core/channels/voice_stream/util.py +4 -4
  86. rasa/core/channels/voice_stream/voice_channel.py +42 -222
  87. rasa/core/featurizers/single_state_featurizer.py +1 -22
  88. rasa/core/featurizers/tracker_featurizers.py +18 -115
  89. rasa/core/information_retrieval/qdrant.py +0 -1
  90. rasa/core/nlg/contextual_response_rephraser.py +25 -44
  91. rasa/core/persistor.py +34 -191
  92. rasa/core/policies/enterprise_search_policy.py +60 -119
  93. rasa/core/policies/flows/flow_executor.py +4 -7
  94. rasa/core/policies/intentless_policy.py +22 -82
  95. rasa/core/policies/ted_policy.py +33 -58
  96. rasa/core/policies/unexpected_intent_policy.py +7 -15
  97. rasa/core/processor.py +5 -32
  98. rasa/core/training/interactive.py +35 -34
  99. rasa/core/utils.py +22 -58
  100. rasa/dialogue_understanding/coexistence/llm_based_router.py +12 -39
  101. rasa/dialogue_understanding/commands/__init__.py +0 -4
  102. rasa/dialogue_understanding/commands/change_flow_command.py +0 -6
  103. rasa/dialogue_understanding/commands/utils.py +0 -5
  104. rasa/dialogue_understanding/generator/constants.py +0 -2
  105. rasa/dialogue_understanding/generator/flow_retrieval.py +4 -49
  106. rasa/dialogue_understanding/generator/llm_based_command_generator.py +23 -37
  107. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +10 -57
  108. rasa/dialogue_understanding/generator/nlu_command_adapter.py +1 -19
  109. rasa/dialogue_understanding/generator/single_step/command_prompt_template.jinja2 +0 -3
  110. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +10 -90
  111. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +0 -53
  112. rasa/dialogue_understanding/processor/command_processor.py +1 -21
  113. rasa/e2e_test/assertions.py +16 -133
  114. rasa/e2e_test/assertions_schema.yml +0 -23
  115. rasa/e2e_test/e2e_test_case.py +6 -85
  116. rasa/e2e_test/e2e_test_runner.py +4 -6
  117. rasa/e2e_test/utils/io.py +1 -3
  118. rasa/engine/loader.py +0 -12
  119. rasa/engine/validation.py +11 -541
  120. rasa/keys +1 -0
  121. rasa/llm_fine_tuning/notebooks/unsloth_finetuning.ipynb +407 -0
  122. rasa/model_training.py +7 -29
  123. rasa/nlu/classifiers/diet_classifier.py +25 -38
  124. rasa/nlu/classifiers/logistic_regression_classifier.py +9 -22
  125. rasa/nlu/classifiers/sklearn_intent_classifier.py +16 -37
  126. rasa/nlu/extractors/crf_entity_extractor.py +50 -93
  127. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +16 -45
  128. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +17 -52
  129. rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +3 -5
  130. rasa/nlu/tokenizers/whitespace_tokenizer.py +14 -3
  131. rasa/server.py +1 -3
  132. rasa/shared/constants.py +0 -61
  133. rasa/shared/core/constants.py +0 -9
  134. rasa/shared/core/domain.py +5 -8
  135. rasa/shared/core/flows/flow.py +0 -5
  136. rasa/shared/core/flows/flows_list.py +1 -5
  137. rasa/shared/core/flows/flows_yaml_schema.json +0 -10
  138. rasa/shared/core/flows/validation.py +0 -96
  139. rasa/shared/core/flows/yaml_flows_io.py +4 -13
  140. rasa/shared/core/slots.py +0 -5
  141. rasa/shared/importers/importer.py +2 -19
  142. rasa/shared/importers/rasa.py +1 -5
  143. rasa/shared/nlu/training_data/features.py +2 -120
  144. rasa/shared/nlu/training_data/formats/rasa_yaml.py +3 -18
  145. rasa/shared/providers/_configs/azure_openai_client_config.py +3 -5
  146. rasa/shared/providers/_configs/openai_client_config.py +1 -1
  147. rasa/shared/providers/_configs/self_hosted_llm_client_config.py +0 -1
  148. rasa/shared/providers/_configs/utils.py +0 -16
  149. rasa/shared/providers/embedding/_base_litellm_embedding_client.py +29 -18
  150. rasa/shared/providers/embedding/azure_openai_embedding_client.py +21 -54
  151. rasa/shared/providers/embedding/default_litellm_embedding_client.py +0 -24
  152. rasa/shared/providers/llm/_base_litellm_client.py +31 -63
  153. rasa/shared/providers/llm/azure_openai_llm_client.py +29 -50
  154. rasa/shared/providers/llm/default_litellm_llm_client.py +0 -24
  155. rasa/shared/providers/llm/self_hosted_llm_client.py +29 -17
  156. rasa/shared/providers/mappings.py +0 -19
  157. rasa/shared/utils/common.py +2 -37
  158. rasa/shared/utils/io.py +6 -28
  159. rasa/shared/utils/llm.py +46 -353
  160. rasa/shared/utils/yaml.py +82 -181
  161. rasa/studio/auth.py +5 -3
  162. rasa/studio/config.py +4 -13
  163. rasa/studio/constants.py +0 -1
  164. rasa/studio/data_handler.py +4 -13
  165. rasa/studio/upload.py +80 -175
  166. rasa/telemetry.py +17 -94
  167. rasa/tracing/config.py +1 -3
  168. rasa/tracing/instrumentation/attribute_extractors.py +17 -94
  169. rasa/tracing/instrumentation/instrumentation.py +0 -121
  170. rasa/utils/common.py +0 -5
  171. rasa/utils/endpoints.py +1 -27
  172. rasa/utils/io.py +81 -7
  173. rasa/utils/log_utils.py +2 -9
  174. rasa/utils/tensorflow/model_data.py +193 -2
  175. rasa/validator.py +4 -110
  176. rasa/version.py +1 -1
  177. rasa_pro-3.11.0a2.dist-info/METADATA +576 -0
  178. {rasa_pro-3.11.0.dist-info → rasa_pro-3.11.0a2.dist-info}/RECORD +181 -213
  179. rasa/core/actions/action_repeat_bot_messages.py +0 -89
  180. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-736177bf.js +0 -1
  181. rasa/core/channels/voice_stream/asr/azure.py +0 -129
  182. rasa/core/channels/voice_stream/call_state.py +0 -23
  183. rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +0 -60
  184. rasa/dialogue_understanding/commands/user_silence_command.py +0 -59
  185. rasa/dialogue_understanding/patterns/repeat.py +0 -37
  186. rasa/dialogue_understanding/patterns/user_silence.py +0 -37
  187. rasa/model_manager/__init__.py +0 -0
  188. rasa/model_manager/config.py +0 -40
  189. rasa/model_manager/model_api.py +0 -559
  190. rasa/model_manager/runner_service.py +0 -286
  191. rasa/model_manager/socket_bridge.py +0 -146
  192. rasa/model_manager/studio_jwt_auth.py +0 -86
  193. rasa/model_manager/trainer_service.py +0 -325
  194. rasa/model_manager/utils.py +0 -87
  195. rasa/model_manager/warm_rasa_process.py +0 -187
  196. rasa/model_service.py +0 -112
  197. rasa/shared/core/flows/utils.py +0 -39
  198. rasa/shared/providers/_configs/litellm_router_client_config.py +0 -220
  199. rasa/shared/providers/_configs/model_group_config.py +0 -167
  200. rasa/shared/providers/_configs/rasa_llm_client_config.py +0 -73
  201. rasa/shared/providers/_utils.py +0 -79
  202. rasa/shared/providers/embedding/litellm_router_embedding_client.py +0 -135
  203. rasa/shared/providers/llm/litellm_router_llm_client.py +0 -182
  204. rasa/shared/providers/llm/rasa_llm_client.py +0 -112
  205. rasa/shared/providers/router/__init__.py +0 -0
  206. rasa/shared/providers/router/_base_litellm_router_client.py +0 -183
  207. rasa/shared/providers/router/router_client.py +0 -73
  208. rasa/shared/utils/health_check/__init__.py +0 -0
  209. rasa/shared/utils/health_check/embeddings_health_check_mixin.py +0 -31
  210. rasa/shared/utils/health_check/health_check.py +0 -258
  211. rasa/shared/utils/health_check/llm_health_check_mixin.py +0 -31
  212. rasa/utils/sanic_error_handler.py +0 -32
  213. rasa/utils/tensorflow/feature_array.py +0 -366
  214. rasa_pro-3.11.0.dist-info/METADATA +0 -198
  215. {rasa_pro-3.11.0.dist-info → rasa_pro-3.11.0a2.dist-info}/NOTICE +0 -0
  216. {rasa_pro-3.11.0.dist-info → rasa_pro-3.11.0a2.dist-info}/WHEEL +0 -0
  217. {rasa_pro-3.11.0.dist-info → rasa_pro-3.11.0a2.dist-info}/entry_points.txt +0 -0
rasa/utils/common.py CHANGED
@@ -90,11 +90,6 @@ EXPECTED_WARNINGS: List[Tuple[Type[Warning], str]] = [
90
90
  # Ignore Keras DeprecationWarning since it requires that we
91
91
  # upgrade tensorflow-macos to 2.13.0 version.
92
92
  (DeprecationWarning, "invalid escape sequence*"),
93
- # Ignore importlib open_text and read_text warnings for now
94
- (
95
- DeprecationWarning,
96
- "https://importlib-resources.readthedocs.io/en/latest/using.html#migrating-from-legacy",
97
- ),
98
93
  ]
99
94
 
100
95
  PYTHON_LOGGING_SCHEMA_DOCS = (
rasa/utils/endpoints.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  import ssl
3
3
  from types import ModuleType
4
- from typing import Any, List, Optional, Text, Dict, Union
4
+ from typing import Any, Optional, Text, Dict, Union
5
5
 
6
6
  import aiohttp
7
7
  import structlog
@@ -41,32 +41,6 @@ def read_endpoint_config(
41
41
  return None
42
42
 
43
43
 
44
- def read_property_config_from_endpoints_file(
45
- filename: str, property_name: str
46
- ) -> Optional[Union[Dict[str, Any], List]]:
47
- """Read a property from an endpoint configuration file."""
48
- if not filename:
49
- return None
50
-
51
- try:
52
- content = read_config_file(filename)
53
-
54
- if content.get(property_name) is None:
55
- return None
56
-
57
- return content[property_name]
58
- except FileNotFoundError:
59
- structlogger.error(
60
- "endpoint.read.failed_no_such_file",
61
- filename=os.path.abspath(filename),
62
- event_info=(
63
- "Failed to read endpoint configuration file - "
64
- "the file was not found."
65
- ),
66
- )
67
- return None
68
-
69
-
70
44
  def concat_url(base: Text, subpath: Optional[Text]) -> Text:
71
45
  """Append a subpath to a base url.
72
46
 
rasa/utils/io.py CHANGED
@@ -2,6 +2,7 @@ import asyncio
2
2
  import filecmp
3
3
  import logging
4
4
  import os
5
+ import pickle
5
6
  import tempfile
6
7
  import warnings
7
8
  import re
@@ -18,6 +19,7 @@ from typing import (
18
19
  Type,
19
20
  Callable,
20
21
  TYPE_CHECKING,
22
+ Pattern,
21
23
  )
22
24
 
23
25
  from ruamel import yaml
@@ -96,6 +98,29 @@ def enable_async_loop_debugging(
96
98
  return event_loop
97
99
 
98
100
 
101
+ def pickle_dump(filename: Union[Text, Path], obj: Any) -> None:
102
+ """Saves object to file.
103
+
104
+ Args:
105
+ filename: the filename to save the object to
106
+ obj: the object to store
107
+ """
108
+ with open(filename, "wb") as f:
109
+ pickle.dump(obj, f)
110
+
111
+
112
+ def pickle_load(filename: Union[Text, Path]) -> Any:
113
+ """Loads an object from a file.
114
+
115
+ Args:
116
+ filename: the filename to load the object from
117
+
118
+ Returns: the loaded object
119
+ """
120
+ with open(filename, "rb") as f:
121
+ return pickle.load(f)
122
+
123
+
99
124
  def create_temporary_file(data: Any, suffix: Text = "", mode: Text = "w+") -> Text:
100
125
  """Creates a tempfile.NamedTemporaryFile object for data."""
101
126
  encoding = None if "b" in mode else rasa.shared.utils.io.DEFAULT_ENCODING
@@ -166,14 +191,63 @@ def create_validator(
166
191
  return FunctionValidator
167
192
 
168
193
 
169
- def remove_emojis(s: str) -> str:
170
- import demoji
194
+ def json_unpickle(
195
+ file_name: Union[Text, Path], encode_non_string_keys: bool = False
196
+ ) -> Any:
197
+ """Unpickle an object from file using json.
198
+
199
+ Args:
200
+ file_name: the file to load the object from
201
+ encode_non_string_keys: If set to `True` then jsonpickle will encode non-string
202
+ dictionary keys instead of coercing them into strings via `repr()`.
203
+
204
+ Returns: the object
205
+ """
206
+ import jsonpickle.ext.numpy as jsonpickle_numpy
207
+ import jsonpickle
208
+
209
+ jsonpickle_numpy.register_handlers()
210
+
211
+ file_content = rasa.shared.utils.io.read_file(file_name)
212
+ return jsonpickle.loads(file_content, keys=encode_non_string_keys)
213
+
214
+
215
+ def json_pickle(
216
+ file_name: Union[Text, Path], obj: Any, encode_non_string_keys: bool = False
217
+ ) -> None:
218
+ """Pickle an object to a file using json.
219
+
220
+ Args:
221
+ file_name: the file to store the object to
222
+ obj: the object to store
223
+ encode_non_string_keys: If set to `True` then jsonpickle will encode non-string
224
+ dictionary keys instead of coercing them into strings via `repr()`.
225
+ """
226
+ import jsonpickle.ext.numpy as jsonpickle_numpy
227
+ import jsonpickle
228
+
229
+ jsonpickle_numpy.register_handlers()
171
230
 
172
- replaced = demoji.replace(s)
173
- if replaced == s:
174
- return s
175
- # remove duplicate or trailing whitespaces if emojis were removed
176
- return re.sub(r" +", " ", replaced).strip()
231
+ rasa.shared.utils.io.write_text_file(
232
+ jsonpickle.dumps(obj, keys=encode_non_string_keys), file_name
233
+ )
234
+
235
+
236
+ def get_emoji_regex() -> Pattern:
237
+ """Returns regex to identify emojis."""
238
+ return re.compile(
239
+ "["
240
+ "\U0001f600-\U0001f64f" # emoticons
241
+ "\U0001f300-\U0001f5ff" # symbols & pictographs
242
+ "\U0001f680-\U0001f6ff" # transport & map symbols
243
+ "\U0001f1e0-\U0001f1ff" # flags (iOS)
244
+ "\U00002702-\U000027b0"
245
+ "\U000024c2-\U0001f251"
246
+ "\u200d" # zero width joiner
247
+ "\u200c" # zero width non-joiner
248
+ "]+",
249
+ flags=re.UNICODE,
250
+ )
177
251
 
178
252
 
179
253
  def are_directories_equal(dir1: Path, dir2: Path) -> bool:
rasa/utils/log_utils.py CHANGED
@@ -78,7 +78,6 @@ def _anonymizer(
78
78
 
79
79
  def configure_structlog(
80
80
  log_level: Optional[int] = None,
81
- include_time: bool = False,
82
81
  ) -> None:
83
82
  """Configure logging of the server."""
84
83
  if log_level is None: # Log level NOTSET is 0 so we use `is None` here
@@ -115,9 +114,6 @@ def configure_structlog(
115
114
  SentryProcessor(event_level=logging.FATAL),
116
115
  ]
117
116
 
118
- if include_time:
119
- shared_processors.append(structlog.processors.TimeStamper(fmt="iso"))
120
-
121
117
  if not FORCE_JSON_LOGGING and sys.stderr.isatty():
122
118
  # Pretty printing when we run in a terminal session.
123
119
  # Automatically prints pretty tracebacks when "rich" is installed
@@ -147,14 +143,11 @@ def configure_structlog(
147
143
  # logger.
148
144
  cache_logger_on_first_use=True,
149
145
  )
150
- # doing logger creation inline, to prevent usage of unconfigured logger
151
- structlog.get_logger().debug("structlog.configured")
152
146
 
153
147
 
154
148
  def log_llm(logger: Any, log_module: str, log_event: str, **kwargs: Any) -> None:
155
- """Logs LLM-specific events depending on a flag passed through an env var.
156
-
157
- If the module's flag is set to INFO (e.g.
149
+ """Logs LLM-specific events depending on a flag passed through an environment
150
+ variable. If the module's flag is set to INFO (e.g.
158
151
  LOG_PROMPT_LLM_COMMAND_GENERATOR=INFO), its prompt is logged at INFO level,
159
152
  overriding the general log level setting.
160
153
 
@@ -20,8 +20,6 @@ import numpy as np
20
20
  import scipy.sparse
21
21
  from sklearn.model_selection import train_test_split
22
22
 
23
- from rasa.utils.tensorflow.feature_array import FeatureArray
24
-
25
23
  logger = logging.getLogger(__name__)
26
24
 
27
25
 
@@ -39,6 +37,199 @@ def ragged_array_to_ndarray(ragged_array: Iterable[np.ndarray]) -> np.ndarray:
39
37
  return np.array(ragged_array, dtype=object)
40
38
 
41
39
 
40
+ class FeatureArray(np.ndarray):
41
+ """Stores any kind of features ready to be used by a RasaModel.
42
+
43
+ Next to the input numpy array of features, it also received the number of
44
+ dimensions of the features.
45
+ As our features can have 1 to 4 dimensions we might have different number of numpy
46
+ arrays stacked. The number of dimensions helps us to figure out how to handle this
47
+ particular feature array. Also, it is automatically determined whether the feature
48
+ array is sparse or not and the number of units is determined as well.
49
+
50
+ Subclassing np.array: https://numpy.org/doc/stable/user/basics.subclassing.html
51
+ """
52
+
53
+ def __new__(
54
+ cls, input_array: np.ndarray, number_of_dimensions: int
55
+ ) -> "FeatureArray":
56
+ """Create and return a new object. See help(type) for accurate signature."""
57
+ FeatureArray._validate_number_of_dimensions(number_of_dimensions, input_array)
58
+
59
+ feature_array = np.asarray(input_array).view(cls)
60
+
61
+ if number_of_dimensions <= 2:
62
+ feature_array.units = input_array.shape[-1]
63
+ feature_array.is_sparse = isinstance(input_array[0], scipy.sparse.spmatrix)
64
+ elif number_of_dimensions == 3:
65
+ feature_array.units = input_array[0].shape[-1]
66
+ feature_array.is_sparse = isinstance(input_array[0], scipy.sparse.spmatrix)
67
+ elif number_of_dimensions == 4:
68
+ feature_array.units = input_array[0][0].shape[-1]
69
+ feature_array.is_sparse = isinstance(
70
+ input_array[0][0], scipy.sparse.spmatrix
71
+ )
72
+ else:
73
+ raise ValueError(
74
+ f"Number of dimensions '{number_of_dimensions}' currently not "
75
+ f"supported."
76
+ )
77
+
78
+ feature_array.number_of_dimensions = number_of_dimensions
79
+
80
+ return feature_array
81
+
82
+ def __init__(
83
+ self, input_array: Any, number_of_dimensions: int, **kwargs: Any
84
+ ) -> None:
85
+ """Initialize. FeatureArray.
86
+
87
+ Needed in order to avoid 'Invalid keyword argument number_of_dimensions
88
+ to function FeatureArray.__init__ '
89
+ Args:
90
+ input_array: the array that contains features
91
+ number_of_dimensions: number of dimensions in input_array
92
+ """
93
+ super().__init__(**kwargs)
94
+ self.number_of_dimensions = number_of_dimensions
95
+
96
+ def __array_finalize__(self, obj: Optional[np.ndarray]) -> None:
97
+ """This method is called when the system allocates a new array from obj.
98
+
99
+ Args:
100
+ obj: A subclass (subtype) of ndarray.
101
+ """
102
+ if obj is None:
103
+ return
104
+
105
+ self.units = getattr(obj, "units", None)
106
+ self.number_of_dimensions = getattr(obj, "number_of_dimensions", None) # type: ignore[assignment]
107
+ self.is_sparse = getattr(obj, "is_sparse", None)
108
+
109
+ default_attributes = {
110
+ "units": self.units,
111
+ "number_of_dimensions": self.number_of_dimensions,
112
+ "is_spare": self.is_sparse,
113
+ }
114
+ self.__dict__.update(default_attributes)
115
+
116
+ # pytype: disable=attribute-error
117
+ def __array_ufunc__(
118
+ self, ufunc: Any, method: Text, *inputs: Any, **kwargs: Any
119
+ ) -> Any:
120
+ """Overwrite this method as we are subclassing numpy array.
121
+
122
+ Args:
123
+ ufunc: The ufunc object that was called.
124
+ method: A string indicating which Ufunc method was called
125
+ (one of "__call__", "reduce", "reduceat", "accumulate", "outer",
126
+ "inner").
127
+ *inputs: A tuple of the input arguments to the ufunc.
128
+ **kwargs: Any additional arguments
129
+
130
+ Returns:
131
+ The result of the operation.
132
+ """
133
+ f = {
134
+ "reduce": ufunc.reduce,
135
+ "accumulate": ufunc.accumulate,
136
+ "reduceat": ufunc.reduceat,
137
+ "outer": ufunc.outer,
138
+ "at": ufunc.at,
139
+ "__call__": ufunc,
140
+ }
141
+ # convert the inputs to np.ndarray to prevent recursion, call the function,
142
+ # then cast it back as FeatureArray
143
+ output = FeatureArray(
144
+ f[method](*(i.view(np.ndarray) for i in inputs), **kwargs),
145
+ number_of_dimensions=kwargs["number_of_dimensions"],
146
+ )
147
+ output.__dict__ = self.__dict__ # carry forward attributes
148
+ return output
149
+
150
+ def __reduce__(self) -> Tuple[Any, Any, Any]:
151
+ """Needed in order to pickle this object.
152
+
153
+ Returns:
154
+ A tuple.
155
+ """
156
+ pickled_state = super(FeatureArray, self).__reduce__()
157
+ if isinstance(pickled_state, str):
158
+ raise TypeError("np array __reduce__ returned string instead of tuple.")
159
+ new_state = pickled_state[2] + (
160
+ self.number_of_dimensions,
161
+ self.is_sparse,
162
+ self.units,
163
+ )
164
+ return pickled_state[0], pickled_state[1], new_state
165
+
166
+ def __setstate__(self, state: Any, **kwargs: Any) -> None:
167
+ """Sets the state.
168
+
169
+ Args:
170
+ state: The state argument must be a sequence that contains the following
171
+ elements version, shape, dtype, isFortan, rawdata.
172
+ **kwargs: Any additional parameter
173
+ """
174
+ # Needed in order to load the object
175
+ self.number_of_dimensions = state[-3]
176
+ self.is_sparse = state[-2]
177
+ self.units = state[-1]
178
+ super(FeatureArray, self).__setstate__(state[0:-3], **kwargs)
179
+
180
+ # pytype: enable=attribute-error
181
+
182
+ @staticmethod
183
+ def _validate_number_of_dimensions(
184
+ number_of_dimensions: int, input_array: np.ndarray
185
+ ) -> None:
186
+ """Validates if the the input array has given number of dimensions.
187
+
188
+ Args:
189
+ number_of_dimensions: number of dimensions
190
+ input_array: input array
191
+
192
+ Raises: ValueError in case the dimensions do not match
193
+ """
194
+ _sub_array = input_array
195
+ dim = 0
196
+ # Go number_of_dimensions into the given input_array
197
+ for i in range(1, number_of_dimensions + 1):
198
+ _sub_array = _sub_array[0]
199
+ if isinstance(_sub_array, scipy.sparse.spmatrix):
200
+ dim = i
201
+ break
202
+ if isinstance(_sub_array, np.ndarray) and _sub_array.shape[0] == 0:
203
+ # sequence dimension is 0, we are dealing with "fake" features
204
+ dim = i
205
+ break
206
+
207
+ # If the resulting sub_array is sparse, the remaining number of dimensions
208
+ # should be at least 2
209
+ if isinstance(_sub_array, scipy.sparse.spmatrix):
210
+ if dim > 2:
211
+ raise ValueError(
212
+ f"Given number of dimensions '{number_of_dimensions}' does not "
213
+ f"match dimensions of given input array: {input_array}."
214
+ )
215
+ elif isinstance(_sub_array, np.ndarray) and _sub_array.shape[0] == 0:
216
+ # sequence dimension is 0, we are dealing with "fake" features,
217
+ # but they should be of dim 2
218
+ if dim > 2:
219
+ raise ValueError(
220
+ f"Given number of dimensions '{number_of_dimensions}' does not "
221
+ f"match dimensions of given input array: {input_array}."
222
+ )
223
+ # If the resulting sub_array is dense, the sub_array should be a single number
224
+ elif not np.issubdtype(type(_sub_array), np.integer) and not isinstance(
225
+ _sub_array, (np.float32, np.float64)
226
+ ):
227
+ raise ValueError(
228
+ f"Given number of dimensions '{number_of_dimensions}' does not match "
229
+ f"dimensions of given input array: {input_array}."
230
+ )
231
+
232
+
42
233
  class FeatureSignature(NamedTuple):
43
234
  """Signature of feature arrays.
44
235
 
rasa/validator.py CHANGED
@@ -1,7 +1,6 @@
1
1
  import logging
2
2
  import re
3
3
  import string
4
- import sys
5
4
  from collections import defaultdict
6
5
  from typing import Set, Text, Optional, Dict, Any, List, Tuple
7
6
 
@@ -23,11 +22,6 @@ from rasa.shared.core.flows.steps.collect import CollectInformationFlowStep
23
22
  from rasa.shared.core.flows.steps.action import ActionFlowStep
24
23
  from rasa.shared.core.flows.steps.link import LinkFlowStep
25
24
  from rasa.shared.core.flows import FlowsList
26
- from rasa.shared.core.flows.utils import (
27
- warn_deprecated_collect_step_config,
28
- get_duplicate_slot_persistence_config_error_message,
29
- get_invalid_slot_persistence_config_error_message,
30
- )
31
25
  import rasa.shared.nlu.constants
32
26
  from rasa.shared.constants import (
33
27
  ASSISTANT_ID_DEFAULT_VALUE,
@@ -61,7 +55,6 @@ from rasa.shared.importers.importer import TrainingDataImporter
61
55
  from rasa.shared.nlu.constants import COMMANDS
62
56
  from rasa.shared.nlu.training_data.message import Message
63
57
  from rasa.shared.nlu.training_data.training_data import TrainingData
64
-
65
58
  import rasa.shared.utils.cli
66
59
  import rasa.shared.utils.io
67
60
 
@@ -305,7 +298,7 @@ class Validator:
305
298
  return any(cls.check_for_placeholder(i) for i in value)
306
299
  return False
307
300
 
308
- def check_for_no_empty_parenthesis_in_responses(self) -> bool:
301
+ def check_for_no_empty_paranthesis_in_responses(self) -> bool:
309
302
  """Checks if there are no empty parenthesis in utterances."""
310
303
  everything_is_alright = True
311
304
 
@@ -316,12 +309,12 @@ class Validator:
316
309
  for key in RESPONSE_KEYS_TO_INTERPOLATE
317
310
  ):
318
311
  structlogger.error(
319
- "validator.empty_parenthesis_in_utterances",
312
+ "validator.empty_paranthesis_in_utterances",
320
313
  response=response_text,
321
314
  event_info=(
322
315
  f"The response '{response_text}' in the domain file "
323
- f"contains empty parenthesis, which is not permitted. "
324
- f"Please remove the empty parenthesis."
316
+ f"contains empty parenthesis, which is not permitted."
317
+ f" Please remove the empty parenthesis."
325
318
  ),
326
319
  )
327
320
  everything_is_alright = False
@@ -1244,7 +1237,6 @@ class Validator:
1244
1237
  self.verify_flows_steps_against_domain(),
1245
1238
  self.verify_unique_flows(),
1246
1239
  self.verify_predicates(),
1247
- self.verify_slot_persistence_configuration(),
1248
1240
  ]
1249
1241
 
1250
1242
  all_good = all(flow_validation_conditions)
@@ -1541,101 +1533,3 @@ class Validator:
1541
1533
  ),
1542
1534
  )
1543
1535
  return False
1544
-
1545
- def verify_slot_persistence_configuration(self) -> bool:
1546
- """Verifies the validity of slot persistence after flow ends configuration.
1547
-
1548
- Only slots used in either a collect step or a set_slot step can be persisted and
1549
- the configuration can either set at the flow level or the collect step level,
1550
- but not both.
1551
-
1552
- Returns:
1553
- bool: True if all slot persistence configuration is valid, False otherwise.
1554
-
1555
- Raises:
1556
- DeprecationWarning: If reset_after_flow_ends is used in collect steps.
1557
- """
1558
- all_good = True
1559
-
1560
- for flow in self.flows.underlying_flows:
1561
- flow_id = flow.id
1562
- persist_slots = flow.persisted_slots
1563
- has_flow_level_persistence = True if persist_slots else False
1564
- flow_slots = set()
1565
-
1566
- for step in flow.steps_with_calls_resolved:
1567
- if isinstance(step, SetSlotsFlowStep):
1568
- flow_slots.update([slot["key"] for slot in step.slots])
1569
-
1570
- elif isinstance(step, CollectInformationFlowStep):
1571
- collect_step = step.collect
1572
- flow_slots.add(collect_step)
1573
- if not step.reset_after_flow_ends:
1574
- warn_deprecated_collect_step_config(flow_id, collect_step)
1575
-
1576
- if has_flow_level_persistence:
1577
- structlogger.error(
1578
- "validator.verify_slot_persistence_configuration.duplicate_config",
1579
- flow=flow_id,
1580
- collect_step=collect_step,
1581
- event_info=get_duplicate_slot_persistence_config_error_message(
1582
- flow_id, collect_step
1583
- ),
1584
- )
1585
- all_good = False
1586
-
1587
- if has_flow_level_persistence:
1588
- if not self._is_persist_slots_valid(persist_slots, flow_slots, flow_id):
1589
- all_good = False
1590
- return all_good
1591
-
1592
- def _is_persist_slots_valid(
1593
- self, persist_slots: List[str], flow_slots: Set[str], flow_id: str
1594
- ) -> bool:
1595
- invalid_slots = set(persist_slots) - flow_slots
1596
- is_valid = False if invalid_slots else True
1597
-
1598
- if invalid_slots:
1599
- structlogger.error(
1600
- "validator.verify_slot_persistence_configuration.invalid_persist_slot",
1601
- flow=flow_id,
1602
- event_info=get_invalid_slot_persistence_config_error_message(
1603
- flow_id, invalid_slots
1604
- ),
1605
- )
1606
- return is_valid
1607
-
1608
- def verify_studio_supported_validations(self) -> bool:
1609
- """Validates the assistant project for Rasa Studio supported features.
1610
-
1611
- Ensure to add new validations here if they are required for
1612
- Rasa Studio Upload CLI.
1613
- """
1614
- if self.domain.is_empty():
1615
- structlogger.error(
1616
- "rasa.validator.verify_studio_supported_validations.empty_domain",
1617
- event_info="Encountered empty domain during validation.",
1618
- )
1619
- sys.exit(1)
1620
-
1621
- self.warn_if_config_mandatory_keys_are_not_set()
1622
-
1623
- valid_responses = (
1624
- self.check_for_no_empty_parenthesis_in_responses()
1625
- and self.validate_button_payloads()
1626
- )
1627
- valid_nlu = self.verify_nlu()
1628
- valid_flows = all(
1629
- [
1630
- self.verify_flows_steps_against_domain(),
1631
- self.verify_unique_flows(),
1632
- self.verify_predicates(),
1633
- ]
1634
- )
1635
- valid_calm_slot_mappings = self.validate_CALM_slot_mappings()
1636
-
1637
- all_good = (
1638
- valid_responses and valid_nlu and valid_flows and valid_calm_slot_mappings
1639
- )
1640
-
1641
- return all_good
rasa/version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  # this file will automatically be changed,
2
2
  # do not add anything but the version number here!
3
- __version__ = "3.11.0"
3
+ __version__ = "3.11.0a2"