rasa-pro 3.8.18__py3-none-any.whl → 3.9.15__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 (278) hide show
  1. README.md +6 -42
  2. rasa/__main__.py +14 -9
  3. rasa/anonymization/anonymization_pipeline.py +0 -1
  4. rasa/anonymization/anonymization_rule_executor.py +3 -3
  5. rasa/anonymization/utils.py +4 -3
  6. rasa/api.py +2 -2
  7. rasa/cli/arguments/default_arguments.py +1 -1
  8. rasa/cli/arguments/run.py +2 -2
  9. rasa/cli/arguments/test.py +1 -1
  10. rasa/cli/arguments/train.py +10 -10
  11. rasa/cli/e2e_test.py +27 -7
  12. rasa/cli/export.py +0 -1
  13. rasa/cli/license.py +3 -3
  14. rasa/cli/project_templates/calm/actions/action_template.py +1 -1
  15. rasa/cli/project_templates/calm/config.yml +1 -1
  16. rasa/cli/project_templates/calm/credentials.yml +1 -1
  17. rasa/cli/project_templates/calm/data/flows/add_contact.yml +1 -1
  18. rasa/cli/project_templates/calm/data/flows/remove_contact.yml +1 -1
  19. rasa/cli/project_templates/calm/domain/add_contact.yml +8 -2
  20. rasa/cli/project_templates/calm/domain/list_contacts.yml +3 -0
  21. rasa/cli/project_templates/calm/domain/remove_contact.yml +9 -2
  22. rasa/cli/project_templates/calm/domain/shared.yml +5 -0
  23. rasa/cli/project_templates/calm/endpoints.yml +4 -4
  24. rasa/cli/project_templates/default/actions/actions.py +1 -1
  25. rasa/cli/project_templates/default/config.yml +5 -5
  26. rasa/cli/project_templates/default/credentials.yml +1 -1
  27. rasa/cli/project_templates/default/endpoints.yml +4 -4
  28. rasa/cli/project_templates/default/tests/test_stories.yml +1 -1
  29. rasa/cli/project_templates/tutorial/config.yml +1 -1
  30. rasa/cli/project_templates/tutorial/credentials.yml +1 -1
  31. rasa/cli/project_templates/tutorial/data/patterns.yml +6 -0
  32. rasa/cli/project_templates/tutorial/domain.yml +4 -0
  33. rasa/cli/project_templates/tutorial/endpoints.yml +6 -6
  34. rasa/cli/run.py +0 -1
  35. rasa/cli/scaffold.py +3 -2
  36. rasa/cli/studio/download.py +11 -0
  37. rasa/cli/studio/studio.py +180 -24
  38. rasa/cli/studio/upload.py +0 -8
  39. rasa/cli/telemetry.py +18 -6
  40. rasa/cli/utils.py +21 -10
  41. rasa/cli/x.py +3 -2
  42. rasa/constants.py +1 -1
  43. rasa/core/actions/action.py +90 -315
  44. rasa/core/actions/action_exceptions.py +24 -0
  45. rasa/core/actions/constants.py +3 -0
  46. rasa/core/actions/custom_action_executor.py +188 -0
  47. rasa/core/actions/forms.py +11 -7
  48. rasa/core/actions/grpc_custom_action_executor.py +251 -0
  49. rasa/core/actions/http_custom_action_executor.py +140 -0
  50. rasa/core/actions/loops.py +3 -0
  51. rasa/core/actions/two_stage_fallback.py +1 -1
  52. rasa/core/agent.py +2 -4
  53. rasa/core/brokers/pika.py +1 -2
  54. rasa/core/channels/audiocodes.py +1 -1
  55. rasa/core/channels/botframework.py +0 -1
  56. rasa/core/channels/callback.py +0 -1
  57. rasa/core/channels/console.py +6 -8
  58. rasa/core/channels/development_inspector.py +1 -1
  59. rasa/core/channels/facebook.py +0 -3
  60. rasa/core/channels/hangouts.py +0 -6
  61. rasa/core/channels/inspector/dist/assets/{arc-5623b6dc.js → arc-b6e548fe.js} +1 -1
  62. rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-685c106a.js → c4Diagram-d0fbc5ce-fa03ac9e.js} +1 -1
  63. rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-8cbed007.js → classDiagram-936ed81e-ee67392a.js} +1 -1
  64. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-5889cf12.js → classDiagram-v2-c3cb15f1-9b283fae.js} +1 -1
  65. rasa/core/channels/inspector/dist/assets/{createText-62fc7601-24c249d7.js → createText-62fc7601-8b6fcc2a.js} +1 -1
  66. rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-7dd06a75.js → edges-f2ad444c-22e77f4f.js} +1 -1
  67. rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-62c1e54c.js → erDiagram-9d236eb7-60ffc87f.js} +1 -1
  68. rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-ce49b86f.js → flowDb-1972c806-9dd802e4.js} +1 -1
  69. rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-4067e48f.js → flowDiagram-7ea5b25a-5fa1912f.js} +1 -1
  70. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-1844e5a5.js +1 -0
  71. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-59fe4051.js → flowchart-elk-definition-abe16c3d-622a1fd2.js} +1 -1
  72. rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-47e3a43b.js → ganttDiagram-9b5ea136-e285a63a.js} +1 -1
  73. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-5a2ac0d9.js → gitGraphDiagram-99d0ae7c-f237bdca.js} +1 -1
  74. rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-dfb8efc4.js → index-2c4b9a3b-4b03d70e.js} +1 -1
  75. rasa/core/channels/inspector/dist/assets/{index-268a75c0.js → index-a5d3e69d.js} +4 -4
  76. rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-b0c470f2.js → infoDiagram-736b4530-72a0fa5f.js} +1 -1
  77. rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-2edb829a.js → journeyDiagram-df861f2b-82218c41.js} +1 -1
  78. rasa/core/channels/inspector/dist/assets/{layout-b6873d69.js → layout-78cff630.js} +1 -1
  79. rasa/core/channels/inspector/dist/assets/{line-1efc5781.js → line-5038b469.js} +1 -1
  80. rasa/core/channels/inspector/dist/assets/{linear-661e9b94.js → linear-c4fc4098.js} +1 -1
  81. rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-2d2e727f.js → mindmap-definition-beec6740-c33c8ea6.js} +1 -1
  82. rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-9d3ea93d.js → pieDiagram-dbbf0591-a8d03059.js} +1 -1
  83. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-06a178a2.js → quadrantDiagram-4d7f4fd6-6a0e56b2.js} +1 -1
  84. rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-0bfedffc.js → requirementDiagram-6fc4c22a-2dc7c7bd.js} +1 -1
  85. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-d76d0a04.js → sankeyDiagram-8f13d901-2360fe39.js} +1 -1
  86. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-37bb4341.js → sequenceDiagram-b655622a-41b9f9ad.js} +1 -1
  87. rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-f52f7f57.js → stateDiagram-59f0c015-0aad326f.js} +1 -1
  88. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-4a986a20.js → stateDiagram-v2-2b26beab-9847d984.js} +1 -1
  89. rasa/core/channels/inspector/dist/assets/{styles-080da4f6-7dd9ae12.js → styles-080da4f6-564d890e.js} +1 -1
  90. rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-46e1ca14.js → styles-3dcbcfbf-38957613.js} +1 -1
  91. rasa/core/channels/inspector/dist/assets/{styles-9c745c82-4a97439a.js → styles-9c745c82-f0fc6921.js} +1 -1
  92. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-823917a3.js → svgDrawCommon-4835440b-ef3c5a77.js} +1 -1
  93. rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-9ea72896.js → timeline-definition-5b62e21b-bf3e91c1.js} +1 -1
  94. rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-b631a8b6.js → xychartDiagram-2b33534f-4d4026c0.js} +1 -1
  95. rasa/core/channels/inspector/dist/index.html +1 -1
  96. rasa/core/channels/inspector/src/components/DiagramFlow.tsx +10 -0
  97. rasa/core/channels/inspector/src/helpers/formatters.test.ts +4 -7
  98. rasa/core/channels/inspector/src/helpers/formatters.ts +3 -2
  99. rasa/core/channels/rest.py +36 -21
  100. rasa/core/channels/rocketchat.py +0 -1
  101. rasa/core/channels/socketio.py +1 -1
  102. rasa/core/channels/telegram.py +3 -3
  103. rasa/core/channels/webexteams.py +0 -1
  104. rasa/core/concurrent_lock_store.py +1 -1
  105. rasa/core/evaluation/marker_base.py +1 -3
  106. rasa/core/evaluation/marker_stats.py +1 -2
  107. rasa/core/featurizers/single_state_featurizer.py +3 -26
  108. rasa/core/featurizers/tracker_featurizers.py +18 -122
  109. rasa/core/information_retrieval/__init__.py +7 -0
  110. rasa/core/information_retrieval/faiss.py +9 -4
  111. rasa/core/information_retrieval/information_retrieval.py +64 -7
  112. rasa/core/information_retrieval/milvus.py +7 -14
  113. rasa/core/information_retrieval/qdrant.py +8 -15
  114. rasa/core/lock_store.py +0 -1
  115. rasa/core/migrate.py +1 -2
  116. rasa/core/nlg/callback.py +3 -4
  117. rasa/core/policies/enterprise_search_policy.py +86 -22
  118. rasa/core/policies/enterprise_search_prompt_template.jinja2 +4 -41
  119. rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +60 -0
  120. rasa/core/policies/flows/flow_executor.py +104 -2
  121. rasa/core/policies/intentless_policy.py +7 -9
  122. rasa/core/policies/memoization.py +3 -3
  123. rasa/core/policies/policy.py +18 -9
  124. rasa/core/policies/rule_policy.py +8 -11
  125. rasa/core/policies/ted_policy.py +61 -88
  126. rasa/core/policies/unexpected_intent_policy.py +8 -17
  127. rasa/core/processor.py +136 -47
  128. rasa/core/run.py +41 -25
  129. rasa/core/secrets_manager/endpoints.py +2 -2
  130. rasa/core/secrets_manager/vault.py +6 -8
  131. rasa/core/test.py +3 -5
  132. rasa/core/tracker_store.py +49 -14
  133. rasa/core/train.py +1 -3
  134. rasa/core/training/interactive.py +9 -6
  135. rasa/core/utils.py +5 -10
  136. rasa/dialogue_understanding/coexistence/intent_based_router.py +11 -4
  137. rasa/dialogue_understanding/coexistence/llm_based_router.py +2 -3
  138. rasa/dialogue_understanding/commands/__init__.py +4 -0
  139. rasa/dialogue_understanding/commands/can_not_handle_command.py +9 -0
  140. rasa/dialogue_understanding/commands/cancel_flow_command.py +9 -0
  141. rasa/dialogue_understanding/commands/change_flow_command.py +38 -0
  142. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +9 -0
  143. rasa/dialogue_understanding/commands/clarify_command.py +9 -0
  144. rasa/dialogue_understanding/commands/correct_slots_command.py +9 -0
  145. rasa/dialogue_understanding/commands/error_command.py +12 -0
  146. rasa/dialogue_understanding/commands/handle_code_change_command.py +9 -0
  147. rasa/dialogue_understanding/commands/human_handoff_command.py +9 -0
  148. rasa/dialogue_understanding/commands/knowledge_answer_command.py +9 -0
  149. rasa/dialogue_understanding/commands/noop_command.py +9 -0
  150. rasa/dialogue_understanding/commands/set_slot_command.py +38 -3
  151. rasa/dialogue_understanding/commands/skip_question_command.py +9 -0
  152. rasa/dialogue_understanding/commands/start_flow_command.py +9 -0
  153. rasa/dialogue_understanding/generator/__init__.py +16 -1
  154. rasa/dialogue_understanding/generator/command_generator.py +92 -6
  155. rasa/dialogue_understanding/generator/constants.py +18 -0
  156. rasa/dialogue_understanding/generator/flow_retrieval.py +7 -5
  157. rasa/dialogue_understanding/generator/llm_based_command_generator.py +467 -0
  158. rasa/dialogue_understanding/generator/llm_command_generator.py +39 -609
  159. rasa/dialogue_understanding/generator/multi_step/__init__.py +0 -0
  160. rasa/dialogue_understanding/generator/multi_step/fill_slots_prompt.jinja2 +62 -0
  161. rasa/dialogue_understanding/generator/multi_step/handle_flows_prompt.jinja2 +38 -0
  162. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +827 -0
  163. rasa/dialogue_understanding/generator/nlu_command_adapter.py +69 -8
  164. rasa/dialogue_understanding/generator/single_step/__init__.py +0 -0
  165. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +345 -0
  166. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +36 -31
  167. rasa/dialogue_understanding/processor/command_processor.py +112 -3
  168. rasa/e2e_test/constants.py +1 -0
  169. rasa/e2e_test/e2e_test_case.py +44 -0
  170. rasa/e2e_test/e2e_test_runner.py +114 -11
  171. rasa/e2e_test/e2e_test_schema.yml +18 -0
  172. rasa/engine/caching.py +0 -1
  173. rasa/engine/graph.py +18 -6
  174. rasa/engine/recipes/config_files/default_config.yml +3 -3
  175. rasa/engine/recipes/default_components.py +1 -1
  176. rasa/engine/recipes/default_recipe.py +4 -5
  177. rasa/engine/recipes/recipe.py +1 -1
  178. rasa/engine/runner/dask.py +3 -9
  179. rasa/engine/storage/local_model_storage.py +0 -2
  180. rasa/engine/validation.py +179 -145
  181. rasa/exceptions.py +2 -2
  182. rasa/graph_components/validators/default_recipe_validator.py +3 -5
  183. rasa/hooks.py +0 -1
  184. rasa/model.py +1 -1
  185. rasa/model_training.py +1 -0
  186. rasa/nlu/classifiers/diet_classifier.py +33 -52
  187. rasa/nlu/classifiers/logistic_regression_classifier.py +9 -22
  188. rasa/nlu/classifiers/sklearn_intent_classifier.py +16 -37
  189. rasa/nlu/extractors/crf_entity_extractor.py +54 -97
  190. rasa/nlu/extractors/duckling_entity_extractor.py +1 -1
  191. rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +1 -5
  192. rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +0 -4
  193. rasa/nlu/featurizers/featurizer.py +1 -1
  194. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +18 -49
  195. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +26 -64
  196. rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +3 -5
  197. rasa/nlu/persistor.py +68 -26
  198. rasa/nlu/selectors/response_selector.py +7 -10
  199. rasa/nlu/test.py +0 -3
  200. rasa/nlu/utils/hugging_face/registry.py +1 -1
  201. rasa/nlu/utils/spacy_utils.py +1 -3
  202. rasa/server.py +22 -7
  203. rasa/shared/constants.py +12 -1
  204. rasa/shared/core/command_payload_reader.py +109 -0
  205. rasa/shared/core/constants.py +4 -5
  206. rasa/shared/core/domain.py +57 -56
  207. rasa/shared/core/events.py +4 -7
  208. rasa/shared/core/flows/flow.py +9 -0
  209. rasa/shared/core/flows/flows_list.py +12 -0
  210. rasa/shared/core/flows/steps/action.py +7 -2
  211. rasa/shared/core/generator.py +12 -11
  212. rasa/shared/core/slot_mappings.py +315 -24
  213. rasa/shared/core/slots.py +4 -2
  214. rasa/shared/core/trackers.py +32 -14
  215. rasa/shared/core/training_data/loading.py +0 -1
  216. rasa/shared/core/training_data/story_reader/story_reader.py +3 -3
  217. rasa/shared/core/training_data/story_reader/yaml_story_reader.py +11 -11
  218. rasa/shared/core/training_data/story_writer/yaml_story_writer.py +5 -3
  219. rasa/shared/core/training_data/structures.py +1 -1
  220. rasa/shared/core/training_data/visualization.py +1 -1
  221. rasa/shared/data.py +58 -1
  222. rasa/shared/exceptions.py +36 -2
  223. rasa/shared/importers/importer.py +1 -2
  224. rasa/shared/importers/rasa.py +0 -1
  225. rasa/shared/nlu/constants.py +2 -0
  226. rasa/shared/nlu/training_data/entities_parser.py +1 -2
  227. rasa/shared/nlu/training_data/features.py +2 -120
  228. rasa/shared/nlu/training_data/formats/dialogflow.py +3 -2
  229. rasa/shared/nlu/training_data/formats/rasa_yaml.py +3 -5
  230. rasa/shared/nlu/training_data/formats/readerwriter.py +0 -1
  231. rasa/shared/nlu/training_data/message.py +13 -0
  232. rasa/shared/nlu/training_data/training_data.py +0 -2
  233. rasa/shared/providers/openai/session_handler.py +2 -2
  234. rasa/shared/utils/constants.py +3 -0
  235. rasa/shared/utils/io.py +11 -1
  236. rasa/shared/utils/llm.py +1 -2
  237. rasa/shared/utils/pykwalify_extensions.py +1 -0
  238. rasa/shared/utils/schemas/domain.yml +3 -0
  239. rasa/shared/utils/yaml.py +44 -35
  240. rasa/studio/auth.py +26 -10
  241. rasa/studio/constants.py +2 -0
  242. rasa/studio/data_handler.py +114 -107
  243. rasa/studio/download.py +160 -27
  244. rasa/studio/results_logger.py +137 -0
  245. rasa/studio/train.py +6 -7
  246. rasa/studio/upload.py +159 -134
  247. rasa/telemetry.py +188 -34
  248. rasa/tracing/config.py +18 -3
  249. rasa/tracing/constants.py +26 -2
  250. rasa/tracing/instrumentation/attribute_extractors.py +50 -41
  251. rasa/tracing/instrumentation/instrumentation.py +290 -44
  252. rasa/tracing/instrumentation/intentless_policy_instrumentation.py +7 -5
  253. rasa/tracing/instrumentation/metrics.py +109 -21
  254. rasa/tracing/metric_instrument_provider.py +83 -3
  255. rasa/utils/cli.py +2 -1
  256. rasa/utils/common.py +1 -1
  257. rasa/utils/endpoints.py +1 -2
  258. rasa/utils/io.py +72 -6
  259. rasa/utils/licensing.py +246 -31
  260. rasa/utils/ml_utils.py +1 -1
  261. rasa/utils/tensorflow/data_generator.py +1 -1
  262. rasa/utils/tensorflow/environment.py +1 -1
  263. rasa/utils/tensorflow/model_data.py +201 -12
  264. rasa/utils/tensorflow/model_data_utils.py +499 -500
  265. rasa/utils/tensorflow/models.py +5 -6
  266. rasa/utils/tensorflow/rasa_layers.py +15 -15
  267. rasa/utils/train_utils.py +1 -1
  268. rasa/utils/url_tools.py +53 -0
  269. rasa/validator.py +305 -3
  270. rasa/version.py +1 -1
  271. {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.15.dist-info}/METADATA +25 -61
  272. {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.15.dist-info}/RECORD +276 -259
  273. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-85583a23.js +0 -1
  274. rasa/utils/tensorflow/feature_array.py +0 -370
  275. /rasa/dialogue_understanding/generator/{command_prompt_template.jinja2 → single_step/command_prompt_template.jinja2} +0 -0
  276. {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.15.dist-info}/NOTICE +0 -0
  277. {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.15.dist-info}/WHEEL +0 -0
  278. {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.15.dist-info}/entry_points.txt +0 -0
@@ -1 +0,0 @@
1
- import{p as e,f as o}from"./flowDb-1972c806-ce49b86f.js";import{f as t,g as a}from"./styles-080da4f6-7dd9ae12.js";import{t as s}from"./index-268a75c0.js";import"./layout-b6873d69.js";import"./index-2c4b9a3b-dfb8efc4.js";import"./edges-f2ad444c-7dd06a75.js";import"./createText-62fc7601-24c249d7.js";import"./line-1efc5781.js";import"./array-9f3ba611.js";import"./path-53f90ab3.js";const k={parser:e,db:o,renderer:t,styles:a,init:r=>{r.flowchart||(r.flowchart={}),r.flowchart.arrowMarkerAbsolute=r.arrowMarkerAbsolute,s({flowchart:{arrowMarkerAbsolute:r.arrowMarkerAbsolute}}),t.setConf(r.flowchart),o.clear(),o.setGen("gen-2")}};export{k as diagram};
@@ -1,370 +0,0 @@
1
- from typing import Dict, Any, List, Tuple, Optional, Union
2
-
3
- import numpy as np
4
- import scipy.sparse
5
- from safetensors.numpy import load_file
6
- from safetensors.numpy import save_file
7
-
8
- import rasa.shared.utils.io
9
-
10
-
11
- def _recursive_serialize(
12
- array: Any, prefix: str, data_dict: Dict[str, Any], metadata: List[Dict[str, Any]]
13
- ) -> None:
14
- """Recursively serialize arrays and matrices for high dimensional data."""
15
- if isinstance(array, np.ndarray) and array.ndim <= 2:
16
- data_key = f"{prefix}_array"
17
- data_dict[data_key] = array
18
- metadata.append({"type": "dense", "key": data_key, "shape": array.shape})
19
-
20
- elif isinstance(array, list) and all([isinstance(v, float) for v in array]):
21
- data_key = f"{prefix}_list"
22
- data_dict[data_key] = np.array(array, dtype=np.float32)
23
- metadata.append({"type": "list", "key": data_key})
24
-
25
- elif isinstance(array, list) and all([isinstance(v, int) for v in array]):
26
- data_key = f"{prefix}_list"
27
- data_dict[data_key] = np.array(array, dtype=np.int64)
28
- metadata.append({"type": "list", "key": data_key})
29
-
30
- elif isinstance(array, scipy.sparse.spmatrix):
31
- data_key_data = f"{prefix}_data"
32
- data_key_row = f"{prefix}_row"
33
- data_key_col = f"{prefix}_col"
34
- array = array.tocoo()
35
- data_dict.update(
36
- {
37
- data_key_data: array.data,
38
- data_key_row: array.row,
39
- data_key_col: array.col,
40
- }
41
- )
42
- metadata.append({"type": "sparse", "key": prefix, "shape": array.shape})
43
-
44
- elif isinstance(array, list) or isinstance(array, np.ndarray):
45
- group_metadata = {"type": "group", "subcomponents": []}
46
- for idx, item in enumerate(array):
47
- new_prefix = f"{prefix}_{idx}"
48
- _recursive_serialize(
49
- item, new_prefix, data_dict, group_metadata["subcomponents"]
50
- )
51
- metadata.append(group_metadata)
52
-
53
-
54
- def _serialize_nested_data(
55
- nested_data: Dict[str, Dict[str, List["FeatureArray"]]],
56
- prefix: str,
57
- data_dict: Dict[str, np.ndarray],
58
- metadata: List[Dict[str, Union[str, List]]],
59
- ) -> None:
60
- """Handle serialization across dictionary and list levels."""
61
- for outer_key, inner_dict in nested_data.items():
62
- inner_metadata = {"key": outer_key, "components": []}
63
-
64
- for inner_key, feature_arrays in inner_dict.items():
65
- array_metadata = {
66
- "key": inner_key,
67
- "number_of_dimensions": feature_arrays[0].number_of_dimensions,
68
- "features": [],
69
- }
70
-
71
- for idx, feature_array in enumerate(feature_arrays):
72
- feature_prefix = f"{prefix}_{outer_key}_{inner_key}_{idx}"
73
- _recursive_serialize(
74
- feature_array.tolist(),
75
- feature_prefix,
76
- data_dict,
77
- array_metadata["features"],
78
- )
79
-
80
- inner_metadata["components"].append( # type:ignore[attr-defined]
81
- array_metadata
82
- )
83
-
84
- metadata.append(inner_metadata)
85
-
86
-
87
- def serialize_nested_feature_arrays(
88
- nested_feature_array: Dict[str, Dict[str, List["FeatureArray"]]],
89
- data_filename: str,
90
- metadata_filename: str,
91
- ) -> None:
92
- data_dict: Dict[str, np.ndarray] = {}
93
- metadata: List[Dict[str, Union[str, List]]] = []
94
-
95
- _serialize_nested_data(nested_feature_array, "component", data_dict, metadata)
96
-
97
- # Save serialized data and metadata
98
- save_file(data_dict, data_filename)
99
- rasa.shared.utils.io.dump_obj_as_json_to_file(metadata_filename, metadata)
100
-
101
-
102
- def _recursive_deserialize(
103
- metadata: List[Dict[str, Any]], data: Dict[str, Any]
104
- ) -> List[Any]:
105
- """Recursively deserialize arrays and matrices for high dimensional data."""
106
- result = []
107
-
108
- for item in metadata:
109
- if item["type"] == "dense":
110
- key = item["key"]
111
- array = np.asarray(data[key]).reshape(item["shape"])
112
- result.append(array)
113
-
114
- elif item["type"] == "list":
115
- key = item["key"]
116
- result.append(list(data[key]))
117
-
118
- elif item["type"] == "sparse":
119
- data_vals = data[f"{item['key']}_data"]
120
- row_vals = data[f"{item['key']}_row"]
121
- col_vals = data[f"{item['key']}_col"]
122
- sparse_matrix = scipy.sparse.coo_matrix(
123
- (data_vals, (row_vals, col_vals)), shape=item["shape"]
124
- )
125
- result.append(sparse_matrix)
126
- elif item["type"] == "group":
127
- sublist = _recursive_deserialize(item["subcomponents"], data)
128
- result.append(sublist)
129
-
130
- return result
131
-
132
-
133
- def _deserialize_nested_data(
134
- metadata: List[Dict[str, Any]], data_dict: Dict[str, Any]
135
- ) -> Dict[str, Dict[str, List["FeatureArray"]]]:
136
- """Handle deserialization across all dictionary and list levels."""
137
- result: Dict[str, Dict[str, List["FeatureArray"]]] = {}
138
-
139
- for outer_item in metadata:
140
- outer_key = outer_item["key"]
141
- result[outer_key] = {}
142
-
143
- for inner_item in outer_item["components"]:
144
- inner_key = inner_item["key"]
145
- feature_arrays = []
146
-
147
- # Reconstruct the list of FeatureArrays
148
- for feature_item in inner_item["features"]:
149
- # Reconstruct the list of FeatureArrays
150
- feature_array_data = _recursive_deserialize([feature_item], data_dict)
151
- # Prepare the input for the FeatureArray;
152
- # ensure it is np.ndarray compatible
153
- input_array = np.array(feature_array_data[0], dtype=object)
154
- feature_array = FeatureArray(
155
- input_array, inner_item["number_of_dimensions"]
156
- )
157
- feature_arrays.append(feature_array)
158
-
159
- result[outer_key][inner_key] = feature_arrays
160
-
161
- return result
162
-
163
-
164
- def deserialize_nested_feature_arrays(
165
- data_filename: str, metadata_filename: str
166
- ) -> Dict[str, Dict[str, List["FeatureArray"]]]:
167
- metadata = rasa.shared.utils.io.read_json_file(metadata_filename)
168
- data_dict = load_file(data_filename)
169
-
170
- return _deserialize_nested_data(metadata, data_dict)
171
-
172
-
173
- class FeatureArray(np.ndarray):
174
- """Stores any kind of features ready to be used by a RasaModel.
175
-
176
- Next to the input numpy array of features, it also received the number of
177
- dimensions of the features.
178
- As our features can have 1 to 4 dimensions we might have different number of numpy
179
- arrays stacked. The number of dimensions helps us to figure out how to handle this
180
- particular feature array. Also, it is automatically determined whether the feature
181
- array is sparse or not and the number of units is determined as well.
182
-
183
- Subclassing np.array: https://numpy.org/doc/stable/user/basics.subclassing.html
184
- """
185
-
186
- def __new__(
187
- cls, input_array: np.ndarray, number_of_dimensions: int
188
- ) -> "FeatureArray":
189
- """Create and return a new object. See help(type) for accurate signature."""
190
- FeatureArray._validate_number_of_dimensions(number_of_dimensions, input_array)
191
-
192
- feature_array = np.asarray(input_array).view(cls)
193
-
194
- if number_of_dimensions <= 2:
195
- feature_array.units = input_array.shape[-1]
196
- feature_array.is_sparse = isinstance(input_array[0], scipy.sparse.spmatrix)
197
- elif number_of_dimensions == 3:
198
- feature_array.units = input_array[0].shape[-1]
199
- feature_array.is_sparse = isinstance(input_array[0], scipy.sparse.spmatrix)
200
- elif number_of_dimensions == 4:
201
- feature_array.units = input_array[0][0].shape[-1]
202
- feature_array.is_sparse = isinstance(
203
- input_array[0][0], scipy.sparse.spmatrix
204
- )
205
- else:
206
- raise ValueError(
207
- f"Number of dimensions '{number_of_dimensions}' currently not "
208
- f"supported."
209
- )
210
-
211
- feature_array.number_of_dimensions = number_of_dimensions
212
-
213
- return feature_array
214
-
215
- def __init__(
216
- self, input_array: Any, number_of_dimensions: int, **kwargs: Any
217
- ) -> None:
218
- """Initialize. FeatureArray.
219
-
220
- Needed in order to avoid 'Invalid keyword argument number_of_dimensions
221
- to function FeatureArray.__init__ '
222
- Args:
223
- input_array: the array that contains features
224
- number_of_dimensions: number of dimensions in input_array
225
- """
226
- super().__init__(**kwargs)
227
- self.number_of_dimensions = number_of_dimensions
228
-
229
- def __array_finalize__(self, obj: Optional[np.ndarray]) -> None:
230
- """This method is called when the system allocates a new array from obj.
231
-
232
- Args:
233
- obj: A subclass (subtype) of ndarray.
234
- """
235
- if obj is None:
236
- return
237
-
238
- self.units = getattr(obj, "units", None)
239
- self.number_of_dimensions = getattr( # type:ignore[assignment]
240
- obj, "number_of_dimensions", None
241
- )
242
- self.is_sparse = getattr(obj, "is_sparse", None)
243
-
244
- default_attributes = {
245
- "units": self.units,
246
- "number_of_dimensions": self.number_of_dimensions,
247
- "is_spare": self.is_sparse,
248
- }
249
- self.__dict__.update(default_attributes)
250
-
251
- # pytype: disable=attribute-error
252
- def __array_ufunc__(
253
- self, ufunc: Any, method: str, *inputs: Any, **kwargs: Any
254
- ) -> Any:
255
- """Overwrite this method as we are subclassing numpy array.
256
-
257
- Args:
258
- ufunc: The ufunc object that was called.
259
- method: A string indicating which Ufunc method was called
260
- (one of "__call__", "reduce", "reduceat", "accumulate", "outer",
261
- "inner").
262
- *inputs: A tuple of the input arguments to the ufunc.
263
- **kwargs: Any additional arguments
264
-
265
- Returns:
266
- The result of the operation.
267
- """
268
- f = {
269
- "reduce": ufunc.reduce,
270
- "accumulate": ufunc.accumulate,
271
- "reduceat": ufunc.reduceat,
272
- "outer": ufunc.outer,
273
- "at": ufunc.at,
274
- "__call__": ufunc,
275
- }
276
- # convert the inputs to np.ndarray to prevent recursion, call the function,
277
- # then cast it back as FeatureArray
278
- output = FeatureArray(
279
- f[method](*(i.view(np.ndarray) for i in inputs), **kwargs),
280
- number_of_dimensions=kwargs["number_of_dimensions"],
281
- )
282
- output.__dict__ = self.__dict__ # carry forward attributes
283
- return output
284
-
285
- def __reduce__(self) -> Tuple[Any, Any, Any]:
286
- """Needed in order to pickle this object.
287
-
288
- Returns:
289
- A tuple.
290
- """
291
- pickled_state = super(FeatureArray, self).__reduce__()
292
- if isinstance(pickled_state, str):
293
- raise TypeError("np array __reduce__ returned string instead of tuple.")
294
- new_state = pickled_state[2] + (
295
- self.number_of_dimensions,
296
- self.is_sparse,
297
- self.units,
298
- )
299
- return pickled_state[0], pickled_state[1], new_state
300
-
301
- def __setstate__(self, state: Any, **kwargs: Any) -> None:
302
- """Sets the state.
303
-
304
- Args:
305
- state: The state argument must be a sequence that contains the following
306
- elements version, shape, dtype, isFortan, rawdata.
307
- **kwargs: Any additional parameter
308
- """
309
- # Needed in order to load the object
310
- self.number_of_dimensions = state[-3]
311
- self.is_sparse = state[-2]
312
- self.units = state[-1]
313
- super(FeatureArray, self).__setstate__(state[0:-3], **kwargs)
314
-
315
- # pytype: enable=attribute-error
316
-
317
- @staticmethod
318
- def _validate_number_of_dimensions(
319
- number_of_dimensions: int, input_array: np.ndarray
320
- ) -> None:
321
- """Validates if the input array has given number of dimensions.
322
-
323
- Args:
324
- number_of_dimensions: number of dimensions
325
- input_array: input array
326
-
327
- Raises: ValueError in case the dimensions do not match
328
- """
329
- # when loading the feature arrays from disk, the shape represents
330
- # the correct number of dimensions
331
- if len(input_array.shape) == number_of_dimensions:
332
- return
333
-
334
- _sub_array = input_array
335
- dim = 0
336
- # Go number_of_dimensions into the given input_array
337
- for i in range(1, number_of_dimensions + 1):
338
- _sub_array = _sub_array[0]
339
- if isinstance(_sub_array, scipy.sparse.spmatrix):
340
- dim = i
341
- break
342
- if isinstance(_sub_array, np.ndarray) and _sub_array.shape[0] == 0:
343
- # sequence dimension is 0, we are dealing with "fake" features
344
- dim = i
345
- break
346
-
347
- # If the resulting sub_array is sparse, the remaining number of dimensions
348
- # should be at least 2
349
- if isinstance(_sub_array, scipy.sparse.spmatrix):
350
- if dim > 2:
351
- raise ValueError(
352
- f"Given number of dimensions '{number_of_dimensions}' does not "
353
- f"match dimensions of given input array: {input_array}."
354
- )
355
- elif isinstance(_sub_array, np.ndarray) and _sub_array.shape[0] == 0:
356
- # sequence dimension is 0, we are dealing with "fake" features,
357
- # but they should be of dim 2
358
- if dim > 2:
359
- raise ValueError(
360
- f"Given number of dimensions '{number_of_dimensions}' does not "
361
- f"match dimensions of given input array: {input_array}."
362
- )
363
- # If the resulting sub_array is dense, the sub_array should be a single number
364
- elif not np.issubdtype(type(_sub_array), np.integer) and not isinstance(
365
- _sub_array, (np.float32, np.float64)
366
- ):
367
- raise ValueError(
368
- f"Given number of dimensions '{number_of_dimensions}' does not match "
369
- f"dimensions of given input array: {input_array}."
370
- )