rasa-pro 3.10.16__py3-none-any.whl → 3.11.0a1__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 (185) hide show
  1. README.md +396 -17
  2. rasa/api.py +9 -3
  3. rasa/cli/arguments/default_arguments.py +23 -2
  4. rasa/cli/arguments/run.py +15 -0
  5. rasa/cli/arguments/train.py +3 -9
  6. rasa/cli/e2e_test.py +1 -1
  7. rasa/cli/evaluate.py +1 -1
  8. rasa/cli/inspect.py +8 -4
  9. rasa/cli/llm_fine_tuning.py +12 -15
  10. rasa/cli/run.py +8 -1
  11. rasa/cli/studio/studio.py +8 -18
  12. rasa/cli/train.py +11 -53
  13. rasa/cli/utils.py +8 -10
  14. rasa/cli/x.py +1 -1
  15. rasa/constants.py +1 -1
  16. rasa/core/actions/action.py +2 -0
  17. rasa/core/actions/action_hangup.py +29 -0
  18. rasa/core/agent.py +2 -2
  19. rasa/core/brokers/kafka.py +3 -1
  20. rasa/core/brokers/pika.py +3 -1
  21. rasa/core/channels/__init__.py +8 -6
  22. rasa/core/channels/channel.py +21 -4
  23. rasa/core/channels/development_inspector.py +143 -46
  24. rasa/core/channels/inspector/README.md +1 -1
  25. rasa/core/channels/inspector/dist/assets/{arc-b6e548fe.js → arc-86942a71.js} +1 -1
  26. rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-fa03ac9e.js → c4Diagram-d0fbc5ce-b0290676.js} +1 -1
  27. rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-ee67392a.js → classDiagram-936ed81e-f6405f6e.js} +1 -1
  28. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-9b283fae.js → classDiagram-v2-c3cb15f1-ef61ac77.js} +1 -1
  29. rasa/core/channels/inspector/dist/assets/{createText-62fc7601-8b6fcc2a.js → createText-62fc7601-f0411e58.js} +1 -1
  30. rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-22e77f4f.js → edges-f2ad444c-7dcc4f3b.js} +1 -1
  31. rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-60ffc87f.js → erDiagram-9d236eb7-e0c092d7.js} +1 -1
  32. rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-9dd802e4.js → flowDb-1972c806-fba2e3ce.js} +1 -1
  33. rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-5fa1912f.js → flowDiagram-7ea5b25a-7a70b71a.js} +1 -1
  34. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-24a5f41a.js +1 -0
  35. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-622a1fd2.js → flowchart-elk-definition-abe16c3d-00a59b68.js} +1 -1
  36. rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-e285a63a.js → ganttDiagram-9b5ea136-293c91fa.js} +1 -1
  37. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-f237bdca.js → gitGraphDiagram-99d0ae7c-07b2d68c.js} +1 -1
  38. rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-4b03d70e.js → index-2c4b9a3b-bc959fbd.js} +1 -1
  39. rasa/core/channels/inspector/dist/assets/index-3a8a5a28.js +1317 -0
  40. rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-72a0fa5f.js → infoDiagram-736b4530-4a350f72.js} +1 -1
  41. rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-82218c41.js → journeyDiagram-df861f2b-af464fb7.js} +1 -1
  42. rasa/core/channels/inspector/dist/assets/{layout-78cff630.js → layout-0071f036.js} +1 -1
  43. rasa/core/channels/inspector/dist/assets/{line-5038b469.js → line-2f73cc83.js} +1 -1
  44. rasa/core/channels/inspector/dist/assets/{linear-c4fc4098.js → linear-f014b4cc.js} +1 -1
  45. rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-c33c8ea6.js → mindmap-definition-beec6740-d2426fb6.js} +1 -1
  46. rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-a8d03059.js → pieDiagram-dbbf0591-776f01a2.js} +1 -1
  47. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-6a0e56b2.js → quadrantDiagram-4d7f4fd6-82e00b57.js} +1 -1
  48. rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-2dc7c7bd.js → requirementDiagram-6fc4c22a-ea13c6bb.js} +1 -1
  49. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-2360fe39.js → sankeyDiagram-8f13d901-1feca7e9.js} +1 -1
  50. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-41b9f9ad.js → sequenceDiagram-b655622a-070c61d2.js} +1 -1
  51. rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-0aad326f.js → stateDiagram-59f0c015-24f46263.js} +1 -1
  52. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-9847d984.js → stateDiagram-v2-2b26beab-c9056051.js} +1 -1
  53. rasa/core/channels/inspector/dist/assets/{styles-080da4f6-564d890e.js → styles-080da4f6-08abc34a.js} +1 -1
  54. rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-38957613.js → styles-3dcbcfbf-bc74c25a.js} +1 -1
  55. rasa/core/channels/inspector/dist/assets/{styles-9c745c82-f0fc6921.js → styles-9c745c82-4e5d66de.js} +1 -1
  56. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-ef3c5a77.js → svgDrawCommon-4835440b-849c4517.js} +1 -1
  57. rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-bf3e91c1.js → timeline-definition-5b62e21b-d0fb1598.js} +1 -1
  58. rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-4d4026c0.js → xychartDiagram-2b33534f-04d115e2.js} +1 -1
  59. rasa/core/channels/inspector/dist/index.html +18 -17
  60. rasa/core/channels/inspector/index.html +17 -16
  61. rasa/core/channels/inspector/package.json +5 -1
  62. rasa/core/channels/inspector/src/App.tsx +117 -67
  63. rasa/core/channels/inspector/src/components/Chat.tsx +95 -0
  64. rasa/core/channels/inspector/src/components/DiagramFlow.tsx +11 -10
  65. rasa/core/channels/inspector/src/components/DialogueStack.tsx +10 -25
  66. rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +1 -1
  67. rasa/core/channels/inspector/src/helpers/formatters.test.ts +10 -0
  68. rasa/core/channels/inspector/src/helpers/formatters.ts +107 -41
  69. rasa/core/channels/inspector/src/helpers/utils.ts +92 -7
  70. rasa/core/channels/inspector/src/types.ts +21 -1
  71. rasa/core/channels/inspector/yarn.lock +94 -1
  72. rasa/core/channels/rest.py +51 -46
  73. rasa/core/channels/socketio.py +22 -0
  74. rasa/core/channels/{audiocodes.py → voice_ready/audiocodes.py} +110 -68
  75. rasa/core/channels/{voice_aware → voice_ready}/jambonz.py +11 -4
  76. rasa/core/channels/{voice_aware → voice_ready}/jambonz_protocol.py +57 -5
  77. rasa/core/channels/{twilio_voice.py → voice_ready/twilio_voice.py} +58 -7
  78. rasa/core/channels/{voice_aware → voice_ready}/utils.py +16 -0
  79. rasa/core/channels/voice_stream/asr/__init__.py +0 -0
  80. rasa/core/channels/voice_stream/asr/asr_engine.py +71 -0
  81. rasa/core/channels/voice_stream/asr/asr_event.py +13 -0
  82. rasa/core/channels/voice_stream/asr/deepgram.py +77 -0
  83. rasa/core/channels/voice_stream/audio_bytes.py +7 -0
  84. rasa/core/channels/voice_stream/tts/__init__.py +0 -0
  85. rasa/core/channels/voice_stream/tts/azure.py +100 -0
  86. rasa/core/channels/voice_stream/tts/cartesia.py +114 -0
  87. rasa/core/channels/voice_stream/tts/tts_cache.py +27 -0
  88. rasa/core/channels/voice_stream/tts/tts_engine.py +48 -0
  89. rasa/core/channels/voice_stream/twilio_media_streams.py +164 -0
  90. rasa/core/channels/voice_stream/util.py +57 -0
  91. rasa/core/channels/voice_stream/voice_channel.py +247 -0
  92. rasa/core/featurizers/single_state_featurizer.py +1 -22
  93. rasa/core/featurizers/tracker_featurizers.py +18 -115
  94. rasa/core/nlg/contextual_response_rephraser.py +11 -2
  95. rasa/{nlu → core}/persistor.py +16 -38
  96. rasa/core/policies/enterprise_search_policy.py +12 -15
  97. rasa/core/policies/flows/flow_executor.py +8 -18
  98. rasa/core/policies/intentless_policy.py +10 -15
  99. rasa/core/policies/ted_policy.py +33 -58
  100. rasa/core/policies/unexpected_intent_policy.py +7 -15
  101. rasa/core/processor.py +13 -64
  102. rasa/core/run.py +11 -1
  103. rasa/core/secrets_manager/constants.py +4 -0
  104. rasa/core/secrets_manager/factory.py +8 -0
  105. rasa/core/secrets_manager/vault.py +11 -1
  106. rasa/core/training/interactive.py +1 -1
  107. rasa/core/utils.py +1 -11
  108. rasa/dialogue_understanding/coexistence/llm_based_router.py +10 -10
  109. rasa/dialogue_understanding/commands/__init__.py +2 -0
  110. rasa/dialogue_understanding/commands/change_flow_command.py +0 -6
  111. rasa/dialogue_understanding/commands/session_end_command.py +61 -0
  112. rasa/dialogue_understanding/generator/flow_retrieval.py +0 -7
  113. rasa/dialogue_understanding/generator/llm_based_command_generator.py +12 -3
  114. rasa/dialogue_understanding/generator/llm_command_generator.py +1 -1
  115. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +3 -28
  116. rasa/dialogue_understanding/generator/nlu_command_adapter.py +1 -19
  117. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +4 -37
  118. rasa/e2e_test/aggregate_test_stats_calculator.py +1 -11
  119. rasa/e2e_test/assertions.py +6 -48
  120. rasa/e2e_test/e2e_test_runner.py +6 -9
  121. rasa/e2e_test/utils/e2e_yaml_utils.py +1 -1
  122. rasa/e2e_test/utils/io.py +1 -3
  123. rasa/engine/graph.py +3 -10
  124. rasa/engine/recipes/config_files/default_config.yml +0 -3
  125. rasa/engine/recipes/default_recipe.py +0 -1
  126. rasa/engine/recipes/graph_recipe.py +0 -1
  127. rasa/engine/runner/dask.py +2 -2
  128. rasa/engine/storage/local_model_storage.py +12 -42
  129. rasa/engine/storage/storage.py +1 -5
  130. rasa/engine/validation.py +1 -78
  131. rasa/keys +1 -0
  132. rasa/model_training.py +13 -16
  133. rasa/nlu/classifiers/diet_classifier.py +25 -38
  134. rasa/nlu/classifiers/logistic_regression_classifier.py +9 -22
  135. rasa/nlu/classifiers/sklearn_intent_classifier.py +16 -37
  136. rasa/nlu/extractors/crf_entity_extractor.py +50 -93
  137. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +16 -45
  138. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +17 -52
  139. rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +3 -5
  140. rasa/server.py +1 -1
  141. rasa/shared/constants.py +3 -12
  142. rasa/shared/core/constants.py +4 -0
  143. rasa/shared/core/domain.py +101 -47
  144. rasa/shared/core/events.py +29 -0
  145. rasa/shared/core/flows/flows_list.py +20 -11
  146. rasa/shared/core/flows/validation.py +25 -0
  147. rasa/shared/core/flows/yaml_flows_io.py +3 -24
  148. rasa/shared/importers/importer.py +40 -39
  149. rasa/shared/importers/multi_project.py +23 -11
  150. rasa/shared/importers/rasa.py +7 -2
  151. rasa/shared/importers/remote_importer.py +196 -0
  152. rasa/shared/importers/utils.py +3 -1
  153. rasa/shared/nlu/training_data/features.py +2 -120
  154. rasa/shared/nlu/training_data/training_data.py +18 -19
  155. rasa/shared/providers/_configs/azure_openai_client_config.py +3 -5
  156. rasa/shared/providers/embedding/_base_litellm_embedding_client.py +1 -6
  157. rasa/shared/providers/llm/_base_litellm_client.py +11 -31
  158. rasa/shared/providers/llm/self_hosted_llm_client.py +3 -15
  159. rasa/shared/utils/common.py +3 -22
  160. rasa/shared/utils/io.py +0 -1
  161. rasa/shared/utils/llm.py +30 -27
  162. rasa/shared/utils/schemas/events.py +2 -0
  163. rasa/shared/utils/schemas/model_config.yml +0 -10
  164. rasa/shared/utils/yaml.py +44 -0
  165. rasa/studio/auth.py +5 -3
  166. rasa/studio/config.py +4 -13
  167. rasa/studio/constants.py +0 -1
  168. rasa/studio/data_handler.py +3 -10
  169. rasa/studio/upload.py +8 -17
  170. rasa/tracing/instrumentation/attribute_extractors.py +1 -1
  171. rasa/utils/io.py +66 -0
  172. rasa/utils/tensorflow/model_data.py +193 -2
  173. rasa/validator.py +0 -12
  174. rasa/version.py +1 -1
  175. rasa_pro-3.11.0a1.dist-info/METADATA +576 -0
  176. {rasa_pro-3.10.16.dist-info → rasa_pro-3.11.0a1.dist-info}/RECORD +181 -164
  177. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-1844e5a5.js +0 -1
  178. rasa/core/channels/inspector/dist/assets/index-a5d3e69d.js +0 -1040
  179. rasa/utils/tensorflow/feature_array.py +0 -366
  180. rasa_pro-3.10.16.dist-info/METADATA +0 -196
  181. /rasa/core/channels/{voice_aware → voice_ready}/__init__.py +0 -0
  182. /rasa/core/channels/{voice_native → voice_stream}/__init__.py +0 -0
  183. {rasa_pro-3.10.16.dist-info → rasa_pro-3.11.0a1.dist-info}/NOTICE +0 -0
  184. {rasa_pro-3.10.16.dist-info → rasa_pro-3.11.0a1.dist-info}/WHEEL +0 -0
  185. {rasa_pro-3.10.16.dist-info → rasa_pro-3.11.0a1.dist-info}/entry_points.txt +0 -0
@@ -1,5 +1,3 @@
1
- from __future__ import annotations
2
-
3
1
  import logging
4
2
  from abc import ABC, abstractmethod
5
3
  from functools import reduce
@@ -25,6 +23,7 @@ from rasa.shared.core.training_data.structures import StoryGraph
25
23
  from rasa.shared.nlu.constants import ACTION_NAME, ENTITIES
26
24
  from rasa.shared.nlu.training_data.message import Message
27
25
  from rasa.shared.nlu.training_data.training_data import TrainingData
26
+ from rasa.shared.utils.common import cached_method
28
27
  from rasa.shared.utils.yaml import read_config_file
29
28
 
30
29
  logger = logging.getLogger(__name__)
@@ -115,8 +114,8 @@ class TrainingDataImporter(ABC):
115
114
  config_path: Text,
116
115
  domain_path: Optional[Text] = None,
117
116
  training_data_paths: Optional[List[Text]] = None,
118
- args: Optional[Dict[Text, Any]] = {},
119
- ) -> TrainingDataImporter:
117
+ args: Optional[Dict[Text, Any]] = None,
118
+ ) -> "TrainingDataImporter":
120
119
  """Loads a `TrainingDataImporter` instance from a configuration file."""
121
120
  config = read_config_file(config_path)
122
121
  return TrainingDataImporter.load_from_dict(
@@ -128,8 +127,8 @@ class TrainingDataImporter(ABC):
128
127
  config_path: Text,
129
128
  domain_path: Optional[Text] = None,
130
129
  training_data_paths: Optional[List[Text]] = None,
131
- args: Optional[Dict[Text, Any]] = {},
132
- ) -> TrainingDataImporter:
130
+ args: Optional[Dict[Text, Any]] = None,
131
+ ) -> "TrainingDataImporter":
133
132
  """Loads core `TrainingDataImporter` instance.
134
133
 
135
134
  Instance loaded from configuration file will only read Core training data.
@@ -144,8 +143,8 @@ class TrainingDataImporter(ABC):
144
143
  config_path: Text,
145
144
  domain_path: Optional[Text] = None,
146
145
  training_data_paths: Optional[List[Text]] = None,
147
- args: Optional[Dict[Text, Any]] = {},
148
- ) -> TrainingDataImporter:
146
+ args: Optional[Dict[Text, Any]] = None,
147
+ ) -> "TrainingDataImporter":
149
148
  """Loads nlu `TrainingDataImporter` instance.
150
149
 
151
150
  Instance loaded from configuration file will only read NLU training data.
@@ -168,7 +167,7 @@ class TrainingDataImporter(ABC):
168
167
  domain_path: Optional[Text] = None,
169
168
  training_data_paths: Optional[List[Text]] = None,
170
169
  args: Optional[Dict[Text, Any]] = None,
171
- ) -> TrainingDataImporter:
170
+ ) -> "TrainingDataImporter":
172
171
  """Loads a `TrainingDataImporter` instance from a dictionary."""
173
172
  from rasa.shared.importers.rasa import RasaFileImporter
174
173
 
@@ -197,15 +196,18 @@ class TrainingDataImporter(ABC):
197
196
  domain_path: Optional[Text] = None,
198
197
  training_data_paths: Optional[List[Text]] = None,
199
198
  args: Optional[Dict[Text, Any]] = None,
200
- ) -> Optional[TrainingDataImporter]:
199
+ ) -> Optional["TrainingDataImporter"]:
201
200
  from rasa.shared.importers.multi_project import MultiProjectImporter
202
201
  from rasa.shared.importers.rasa import RasaFileImporter
202
+ from rasa.shared.importers.remote_importer import RemoteTrainingDataImporter
203
203
 
204
204
  module_path = importer_config.pop("name", None)
205
205
  if module_path == RasaFileImporter.__name__:
206
206
  importer_class: Type[TrainingDataImporter] = RasaFileImporter
207
207
  elif module_path == MultiProjectImporter.__name__:
208
208
  importer_class = MultiProjectImporter
209
+ elif module_path == RemoteTrainingDataImporter.__name__:
210
+ importer_class = RemoteTrainingDataImporter
209
211
  else:
210
212
  try:
211
213
  importer_class = rasa.shared.utils.common.class_from_module_path(
@@ -225,7 +227,8 @@ class TrainingDataImporter(ABC):
225
227
  **constructor_arguments,
226
228
  )
227
229
 
228
- def fingerprint(self) -> Text:
230
+ @staticmethod
231
+ def fingerprint() -> Text:
229
232
  """Returns a random fingerprint as data shouldn't be cached."""
230
233
  return rasa.shared.utils.io.random_string(25)
231
234
 
@@ -281,7 +284,6 @@ class NluDataImporter(TrainingDataImporter):
281
284
  """Retrieves NLU training data (see parent class for full docstring)."""
282
285
  return self._importer.get_nlu_data(language)
283
286
 
284
- @rasa.shared.utils.common.cached_method
285
287
  def get_config_file_for_auto_config(self) -> Optional[Text]:
286
288
  """Returns config file path for auto-config only if there is a single one."""
287
289
  return self._importer.get_config_file_for_auto_config()
@@ -297,14 +299,14 @@ class CombinedDataImporter(TrainingDataImporter):
297
299
  def __init__(self, importers: List[TrainingDataImporter]):
298
300
  self._importers = importers
299
301
 
300
- @rasa.shared.utils.common.cached_method
302
+ @cached_method
301
303
  def get_config(self) -> Dict:
302
304
  """Retrieves model config (see parent class for full docstring)."""
303
305
  configs = [importer.get_config() for importer in self._importers]
304
306
 
305
307
  return reduce(lambda merged, other: {**merged, **(other or {})}, configs, {})
306
308
 
307
- @rasa.shared.utils.common.cached_method
309
+ @cached_method
308
310
  def get_domain(self) -> Domain:
309
311
  """Retrieves model domain (see parent class for full docstring)."""
310
312
  domains = [importer.get_domain() for importer in self._importers]
@@ -315,7 +317,7 @@ class CombinedDataImporter(TrainingDataImporter):
315
317
  Domain.empty(),
316
318
  )
317
319
 
318
- @rasa.shared.utils.common.cached_method
320
+ @cached_method
319
321
  def get_stories(self, exclusion_percentage: Optional[int] = None) -> StoryGraph:
320
322
  """Retrieves training stories / rules (see parent class for full docstring)."""
321
323
  stories = [
@@ -326,7 +328,7 @@ class CombinedDataImporter(TrainingDataImporter):
326
328
  lambda merged, other: merged.merge(other), stories, StoryGraph([])
327
329
  )
328
330
 
329
- @rasa.shared.utils.common.cached_method
331
+ @cached_method
330
332
  def get_flows(self) -> FlowsList:
331
333
  """Retrieves training stories / rules (see parent class for full docstring)."""
332
334
  flow_lists = [importer.get_flows() for importer in self._importers]
@@ -337,7 +339,7 @@ class CombinedDataImporter(TrainingDataImporter):
337
339
  FlowsList(underlying_flows=[]),
338
340
  )
339
341
 
340
- @rasa.shared.utils.common.cached_method
342
+ @cached_method
341
343
  def get_conversation_tests(self) -> StoryGraph:
342
344
  """Retrieves conversation test stories (see parent class for full docstring)."""
343
345
  stories = [importer.get_conversation_tests() for importer in self._importers]
@@ -346,7 +348,7 @@ class CombinedDataImporter(TrainingDataImporter):
346
348
  lambda merged, other: merged.merge(other), stories, StoryGraph([])
347
349
  )
348
350
 
349
- @rasa.shared.utils.common.cached_method
351
+ @cached_method
350
352
  def get_nlu_data(self, language: Optional[Text] = "en") -> TrainingData:
351
353
  """Retrieves NLU training data (see parent class for full docstring)."""
352
354
  nlu_data = [importer.get_nlu_data(language) for importer in self._importers]
@@ -355,7 +357,7 @@ class CombinedDataImporter(TrainingDataImporter):
355
357
  lambda merged, other: merged.merge(other), nlu_data, TrainingData()
356
358
  )
357
359
 
358
- @rasa.shared.utils.common.cached_method
360
+ @cached_method
359
361
  def get_config_file_for_auto_config(self) -> Optional[Text]:
360
362
  """Returns config file path for auto-config only if there is a single one."""
361
363
  if len(self._importers) != 1:
@@ -414,26 +416,22 @@ class FlowSyncImporter(PassThroughImporter):
414
416
  """Loads the default flows from the file system."""
415
417
  from rasa.shared.core.flows.yaml_flows_io import YAMLFlowsReader
416
418
 
417
- default_flows_file = str(
418
- importlib_resources.files("rasa.dialogue_understanding.patterns").joinpath(
419
- DEFAULT_PATTERN_FLOWS_FILE_NAME
420
- )
421
- )
422
-
423
- flows = YAMLFlowsReader.read_from_file(default_flows_file)
419
+ flows = YAMLFlowsReader.read_from_file(FlowSyncImporter.default_pattern_path())
424
420
  flows.validate()
425
421
  return flows
426
422
 
427
423
  @staticmethod
428
- def load_default_pattern_flows_domain() -> Domain:
429
- """Loads the default flows from the file system."""
430
- default_flows_file = str(
424
+ def default_pattern_path() -> str:
425
+ return str(
431
426
  importlib_resources.files("rasa.dialogue_understanding.patterns").joinpath(
432
427
  DEFAULT_PATTERN_FLOWS_FILE_NAME
433
428
  )
434
429
  )
435
430
 
436
- return Domain.from_path(default_flows_file)
431
+ @staticmethod
432
+ def load_default_pattern_flows_domain() -> Domain:
433
+ """Loads the default flows from the file system."""
434
+ return Domain.from_path(FlowSyncImporter.default_pattern_path())
437
435
 
438
436
  @classmethod
439
437
  def merge_with_default_flows(cls, flows: FlowsList) -> FlowsList:
@@ -459,7 +457,7 @@ class FlowSyncImporter(PassThroughImporter):
459
457
 
460
458
  return flows.merge(FlowsList(missing_default_flows))
461
459
 
462
- @rasa.shared.utils.common.cached_method
460
+ @cached_method
463
461
  def get_flows(self) -> FlowsList:
464
462
  flows = self._importer.get_flows()
465
463
 
@@ -469,11 +467,11 @@ class FlowSyncImporter(PassThroughImporter):
469
467
 
470
468
  return self.merge_with_default_flows(flows)
471
469
 
472
- @rasa.shared.utils.common.cached_method
470
+ @cached_method
473
471
  def get_user_flows(self) -> FlowsList:
474
472
  return self._importer.get_flows()
475
473
 
476
- @rasa.shared.utils.common.cached_method
474
+ @cached_method
477
475
  def get_domain(self) -> Domain:
478
476
  """Merge existing domain with properties of flows."""
479
477
  # load domain data from user defined domain files
@@ -515,7 +513,7 @@ class ResponsesSyncImporter(PassThroughImporter):
515
513
  back to the Domain.
516
514
  """
517
515
 
518
- @rasa.shared.utils.common.cached_method
516
+ @cached_method
519
517
  def get_domain(self) -> Domain:
520
518
  """Merge existing domain with properties of retrieval intents in NLU data."""
521
519
  existing_domain = self._importer.get_domain()
@@ -597,7 +595,7 @@ class ResponsesSyncImporter(PassThroughImporter):
597
595
  }
598
596
  )
599
597
 
600
- @rasa.shared.utils.common.cached_method
598
+ @cached_method
601
599
  def get_nlu_data(self, language: Optional[Text] = "en") -> TrainingData:
602
600
  """Updates NLU data with responses for retrieval intents from domain."""
603
601
  existing_nlu_data = self._importer.get_nlu_data(language)
@@ -632,7 +630,7 @@ class E2EImporter(PassThroughImporter):
632
630
  - adds potential end-to-end bot messages from stories as actions to the domain
633
631
  """
634
632
 
635
- @rasa.shared.utils.common.cached_method
633
+ @cached_method
636
634
  def get_user_flows(self) -> FlowsList:
637
635
  if not isinstance(self._importer, FlowSyncImporter):
638
636
  raise NotImplementedError(
@@ -641,9 +639,12 @@ class E2EImporter(PassThroughImporter):
641
639
 
642
640
  return self._importer.get_user_flows()
643
641
 
644
- @rasa.shared.utils.common.cached_method
642
+ @cached_method
645
643
  def get_domain(self) -> Domain:
646
- """Retrieves model domain (see parent class for full docstring)."""
644
+ """Merge existing domain with properties of end-to-end actions in stories.
645
+
646
+ Returns: Domain with end-to-end actions added to action names.
647
+ """
647
648
  original = self._importer.get_domain()
648
649
  e2e_domain = self._get_domain_with_e2e_actions()
649
650
 
@@ -673,7 +674,7 @@ class E2EImporter(PassThroughImporter):
673
674
 
674
675
  return Domain.from_dict({KEY_E2E_ACTIONS: list(additional_e2e_action_names)})
675
676
 
676
- @rasa.shared.utils.common.cached_method
677
+ @cached_method
677
678
  def get_nlu_data(self, language: Optional[Text] = "en") -> TrainingData:
678
679
  """Retrieves NLU training data (see parent class for full docstring)."""
679
680
  training_datasets = [
@@ -1,22 +1,23 @@
1
- import logging
2
- from functools import reduce
3
- from typing import Text, Set, Dict, Optional, List, Union, Any
4
1
  import os
2
+ from functools import reduce
3
+ from typing import Any, Dict, List, Optional, Set, Text, Union
4
+
5
+ import structlog
5
6
 
6
7
  import rasa.shared.data
7
8
  import rasa.shared.utils.io
8
9
  from rasa.shared.core.domain import Domain
9
- from rasa.shared.importers.importer import TrainingDataImporter
10
- from rasa.shared.importers import utils
11
- from rasa.shared.nlu.training_data.training_data import TrainingData
12
- from rasa.shared.core.training_data.structures import StoryGraph
13
- from rasa.shared.utils.common import mark_as_experimental_feature
14
10
  from rasa.shared.core.training_data.story_reader.yaml_story_reader import (
15
11
  YAMLStoryReader,
16
12
  )
13
+ from rasa.shared.core.training_data.structures import StoryGraph
14
+ from rasa.shared.importers import utils
15
+ from rasa.shared.importers.importer import TrainingDataImporter
16
+ from rasa.shared.nlu.training_data.training_data import TrainingData
17
+ from rasa.shared.utils.common import cached_method, mark_as_experimental_feature
17
18
  from rasa.shared.utils.yaml import read_config_file, read_model_configuration
18
19
 
19
- logger = logging.getLogger(__name__)
20
+ structlogger = structlog.get_logger()
20
21
 
21
22
 
22
23
  class MultiProjectImporter(TrainingDataImporter):
@@ -50,8 +51,13 @@ class MultiProjectImporter(TrainingDataImporter):
50
51
  self._story_paths += extra_story_files
51
52
  self._nlu_paths += extra_nlu_files
52
53
 
53
- logger.debug(
54
- "Selected projects: {}".format("".join([f"\n-{i}" for i in self._imports]))
54
+ structlogger.debug(
55
+ "multi_project_importer.initialisation",
56
+ event_info=(
57
+ "Selected projects: {}".format(
58
+ "".join([f"\n-{i}" for i in self._imports])
59
+ )
60
+ ),
55
61
  )
56
62
 
57
63
  mark_as_experimental_feature(feature_name="MultiProjectImporter")
@@ -135,6 +141,7 @@ class MultiProjectImporter(TrainingDataImporter):
135
141
 
136
142
  return training_paths
137
143
 
144
+ @cached_method
138
145
  def is_imported(self, path: Text) -> bool:
139
146
  """Checks whether a path is imported by a skill.
140
147
 
@@ -175,6 +182,7 @@ class MultiProjectImporter(TrainingDataImporter):
175
182
  [rasa.shared.utils.io.is_subdirectory(path, i) for i in self._imports]
176
183
  )
177
184
 
185
+ @cached_method
178
186
  def get_domain(self) -> Domain:
179
187
  """Retrieves model domain (see parent class for full docstring)."""
180
188
  domains = [Domain.load(path) for path in self._domain_paths]
@@ -184,20 +192,24 @@ class MultiProjectImporter(TrainingDataImporter):
184
192
  Domain.empty(),
185
193
  )
186
194
 
195
+ @cached_method
187
196
  def get_stories(self, exclusion_percentage: Optional[int] = None) -> StoryGraph:
188
197
  """Retrieves training stories / rules (see parent class for full docstring)."""
189
198
  return utils.story_graph_from_paths(
190
199
  self._story_paths, self.get_domain(), exclusion_percentage
191
200
  )
192
201
 
202
+ @cached_method
193
203
  def get_conversation_tests(self) -> StoryGraph:
194
204
  """Retrieves conversation test stories (see parent class for full docstring)."""
195
205
  return utils.story_graph_from_paths(self._e2e_story_paths, self.get_domain())
196
206
 
207
+ @cached_method
197
208
  def get_config(self) -> Dict:
198
209
  """Retrieves model config (see parent class for full docstring)."""
199
210
  return self.config
200
211
 
212
+ @cached_method
201
213
  def get_nlu_data(self, language: Optional[Text] = "en") -> TrainingData:
202
214
  """Retrieves NLU training data (see parent class for full docstring)."""
203
215
  return utils.training_data_from_paths(self._nlu_paths, language)
@@ -6,7 +6,6 @@ import rasa.shared.core.flows.yaml_flows_io
6
6
  from rasa.shared.core.flows import FlowsList
7
7
 
8
8
  import rasa.shared.data
9
- import rasa.shared.utils.common
10
9
  import rasa.shared.utils.io
11
10
  from rasa.shared.core.training_data.structures import StoryGraph
12
11
  from rasa.shared.importers import utils
@@ -16,6 +15,7 @@ from rasa.shared.core.domain import InvalidDomain, Domain
16
15
  from rasa.shared.core.training_data.story_reader.yaml_story_reader import (
17
16
  YAMLStoryReader,
18
17
  )
18
+ from rasa.shared.utils.common import cached_method
19
19
  from rasa.shared.utils.yaml import read_model_configuration
20
20
 
21
21
  logger = logging.getLogger(__name__)
@@ -47,6 +47,7 @@ class RasaFileImporter(TrainingDataImporter):
47
47
 
48
48
  self.config_file = config_file
49
49
 
50
+ @cached_method
50
51
  def get_config(self) -> Dict:
51
52
  """Retrieves model config (see parent class for full docstring)."""
52
53
  if not self.config_file or not os.path.exists(self.config_file):
@@ -56,31 +57,35 @@ class RasaFileImporter(TrainingDataImporter):
56
57
  config = read_model_configuration(self.config_file)
57
58
  return config
58
59
 
59
- @rasa.shared.utils.common.cached_method
60
60
  def get_config_file_for_auto_config(self) -> Optional[Text]:
61
61
  """Returns config file path for auto-config only if there is a single one."""
62
62
  return self.config_file
63
63
 
64
+ @cached_method
64
65
  def get_stories(self, exclusion_percentage: Optional[int] = None) -> StoryGraph:
65
66
  """Retrieves training stories / rules (see parent class for full docstring)."""
66
67
  return utils.story_graph_from_paths(
67
68
  self._story_files, self.get_domain(), exclusion_percentage
68
69
  )
69
70
 
71
+ @cached_method
70
72
  def get_flows(self) -> FlowsList:
71
73
  """Retrieves training stories / rules (see parent class for full docstring)."""
72
74
  return utils.flows_from_paths(self._flow_files)
73
75
 
76
+ @cached_method
74
77
  def get_conversation_tests(self) -> StoryGraph:
75
78
  """Retrieves conversation test stories (see parent class for full docstring)."""
76
79
  return utils.story_graph_from_paths(
77
80
  self._conversation_test_files, self.get_domain()
78
81
  )
79
82
 
83
+ @cached_method
80
84
  def get_nlu_data(self, language: Optional[Text] = "en") -> TrainingData:
81
85
  """Retrieves NLU training data (see parent class for full docstring)."""
82
86
  return utils.training_data_from_paths(self._nlu_files, language)
83
87
 
88
+ @cached_method
84
89
  def get_domain(self) -> Domain:
85
90
  """Retrieves model domain (see parent class for full docstring)."""
86
91
  domain = Domain.empty()
@@ -0,0 +1,196 @@
1
+ import os
2
+ from typing import Dict, List, Optional, Text, Union
3
+
4
+ import structlog
5
+ from tarsafe import TarSafe
6
+
7
+ import rasa.shared.core.flows.yaml_flows_io
8
+ import rasa.shared.data
9
+ import rasa.shared.utils.common
10
+ import rasa.shared.utils.io
11
+ from rasa.core.persistor import StorageType
12
+ from rasa.shared.core.domain import Domain, InvalidDomain
13
+ from rasa.shared.core.flows import FlowsList
14
+ from rasa.shared.core.training_data.story_reader.yaml_story_reader import (
15
+ YAMLStoryReader,
16
+ )
17
+ from rasa.shared.core.training_data.structures import StoryGraph
18
+ from rasa.shared.exceptions import RasaException
19
+ from rasa.shared.importers import utils
20
+ from rasa.shared.importers.importer import TrainingDataImporter
21
+ from rasa.shared.nlu.training_data.training_data import TrainingData
22
+ from rasa.shared.utils.yaml import read_model_configuration
23
+
24
+ structlogger = structlog.get_logger()
25
+
26
+ TRAINING_DATA_ARCHIVE = "training_data.tar.gz"
27
+
28
+
29
+ class RemoteTrainingDataImporter(TrainingDataImporter):
30
+ """Remote `TrainingFileImporter` implementation.
31
+
32
+ Fetches training data from a remote storage and extracts it to a local directory.
33
+ Extracted training data is then used to load flows, NLU, stories,
34
+ domain, and config files.
35
+ """
36
+
37
+ def __init__(
38
+ self,
39
+ config_file: Optional[Text] = None,
40
+ domain_path: Optional[Text] = None,
41
+ training_data_paths: Optional[Union[List[Text], Text]] = None,
42
+ project_directory: Optional[Text] = None,
43
+ remote_storage: Optional[StorageType] = None,
44
+ training_data_path: Optional[Text] = None,
45
+ ):
46
+ """Initializes `RemoteTrainingDataImporter`.
47
+
48
+ Args:
49
+ config_file: Path to the model configuration file.
50
+ domain_path: Path to the domain file.
51
+ training_data_paths: List of paths to the training data files.
52
+ project_directory: Path to the project directory.
53
+ remote_storage: Storage to use to load the training data.
54
+ training_data_path: Path to the training data.
55
+ """
56
+ self.remote_storage = remote_storage
57
+ self.training_data_path = training_data_path
58
+
59
+ self.extracted_path = self._fetch_and_extract_training_archive(
60
+ TRAINING_DATA_ARCHIVE, self.training_data_path
61
+ )
62
+
63
+ self._nlu_files = rasa.shared.data.get_data_files(
64
+ self.extracted_path, rasa.shared.data.is_nlu_file
65
+ )
66
+ self._story_files = rasa.shared.data.get_data_files(
67
+ self.extracted_path, YAMLStoryReader.is_stories_file
68
+ )
69
+ self._flow_files = rasa.shared.data.get_data_files(
70
+ self.extracted_path, rasa.shared.core.flows.yaml_flows_io.is_flows_file
71
+ )
72
+ self._conversation_test_files = rasa.shared.data.get_data_files(
73
+ self.extracted_path, YAMLStoryReader.is_test_stories_file
74
+ )
75
+
76
+ self.config_file = config_file
77
+
78
+ def _fetch_training_archive(
79
+ self, training_file: str, training_data_path: Optional[str] = None
80
+ ) -> str:
81
+ """Fetches training files from remote storage."""
82
+ from rasa.core.persistor import get_persistor
83
+
84
+ persistor = get_persistor(self.remote_storage)
85
+ if persistor is None:
86
+ raise RasaException(
87
+ f"Could not find a persistor for "
88
+ f"the storage type '{self.remote_storage}'."
89
+ )
90
+
91
+ return persistor.retrieve(training_file, training_data_path)
92
+
93
+ def _fetch_and_extract_training_archive(
94
+ self, training_file: str, training_data_path: Optional[Text] = None
95
+ ) -> Optional[str]:
96
+ """Fetches and extracts training files from remote storage.
97
+
98
+ If the `training_data_path` is not provided, the training
99
+ data is extracted to the current working directory.
100
+
101
+ Args:
102
+ training_file: Name of the training data archive file.
103
+ training_data_path: Path to the training data.
104
+
105
+ Returns:
106
+ Path to the extracted training data.
107
+ """
108
+
109
+ if training_data_path is None:
110
+ training_data_path = os.path.join(os.getcwd(), "data")
111
+
112
+ if os.path.isfile(training_data_path):
113
+ raise ValueError(
114
+ f"Training data path '{training_data_path}' is a file. "
115
+ f"Please provide a directory path."
116
+ )
117
+
118
+ structlogger.debug(
119
+ "rasa.importers.remote_training_data_importer.fetch_training_archive",
120
+ training_data_path=training_data_path,
121
+ )
122
+ training_archive_file_path = self._fetch_training_archive(
123
+ training_file, training_data_path
124
+ )
125
+
126
+ if not os.path.isfile(training_archive_file_path):
127
+ raise FileNotFoundError(
128
+ f"Training data archive '{training_archive_file_path}' not found. "
129
+ f"Please make sure to provide the correct path."
130
+ )
131
+
132
+ structlogger.debug(
133
+ "rasa.importers.remote_training_data_importer.extract_training_archive",
134
+ training_archive_file_path=training_archive_file_path,
135
+ training_data_path=training_data_path,
136
+ )
137
+ with TarSafe.open(training_archive_file_path, "r:gz") as tar:
138
+ tar.extractall(path=training_data_path)
139
+
140
+ structlogger.debug(
141
+ "rasa.importers.remote_training_data_importer.remove_downloaded_archive",
142
+ training_data_path=training_data_path,
143
+ )
144
+ os.remove(training_archive_file_path)
145
+ return training_data_path
146
+
147
+ def get_config(self) -> Dict:
148
+ """Retrieves model config (see parent class for full docstring)."""
149
+ if not self.config_file or not os.path.exists(self.config_file):
150
+ structlogger.debug(
151
+ "rasa.importers.remote_training_data_importer.no_config_file",
152
+ message="No configuration file was provided to the RasaFileImporter.",
153
+ )
154
+ return {}
155
+
156
+ config = read_model_configuration(self.config_file)
157
+ return config
158
+
159
+ @rasa.shared.utils.common.cached_method
160
+ def get_config_file_for_auto_config(self) -> Optional[Text]:
161
+ """Returns config file path for auto-config only if there is a single one."""
162
+ return self.config_file
163
+
164
+ def get_stories(self, exclusion_percentage: Optional[int] = None) -> StoryGraph:
165
+ """Retrieves training stories / rules (see parent class for full docstring)."""
166
+ return utils.story_graph_from_paths(
167
+ self._story_files, self.get_domain(), exclusion_percentage
168
+ )
169
+
170
+ def get_flows(self) -> FlowsList:
171
+ """Retrieves training stories / rules (see parent class for full docstring)."""
172
+ return utils.flows_from_paths(self._flow_files)
173
+
174
+ def get_conversation_tests(self) -> StoryGraph:
175
+ """Retrieves conversation test stories (see parent class for full docstring)."""
176
+ return utils.story_graph_from_paths(
177
+ self._conversation_test_files, self.get_domain()
178
+ )
179
+
180
+ def get_nlu_data(self, language: Optional[Text] = "en") -> TrainingData:
181
+ """Retrieves NLU training data (see parent class for full docstring)."""
182
+ return utils.training_data_from_paths(self._nlu_files, language)
183
+
184
+ def get_domain(self) -> Domain:
185
+ """Retrieves model domain (see parent class for full docstring)."""
186
+ domain = Domain.empty()
187
+ domain_path = f"{self.extracted_path}"
188
+ try:
189
+ domain = Domain.load(domain_path)
190
+ except InvalidDomain as e:
191
+ rasa.shared.utils.io.raise_warning(
192
+ f"Loading domain from '{domain_path}' failed. Using "
193
+ f"empty domain. Error: '{e}'"
194
+ )
195
+
196
+ return domain
@@ -29,6 +29,8 @@ def flows_from_paths(files: List[Text]) -> FlowsList:
29
29
 
30
30
  flows = FlowsList(underlying_flows=[])
31
31
  for file in files:
32
- flows = flows.merge(YAMLFlowsReader.read_from_file(file))
32
+ flows = flows.merge(
33
+ YAMLFlowsReader.read_from_file(file), ignore_duplicates=False
34
+ )
33
35
  flows.validate()
34
36
  return flows