rasa-pro 3.10.7__py3-none-any.whl → 3.10.7.dev1__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 (67) hide show
  1. rasa/api.py +8 -2
  2. rasa/cli/arguments/default_arguments.py +23 -2
  3. rasa/cli/arguments/run.py +2 -0
  4. rasa/cli/e2e_test.py +10 -8
  5. rasa/cli/inspect.py +5 -2
  6. rasa/cli/run.py +7 -0
  7. rasa/cli/studio/studio.py +1 -21
  8. rasa/cli/train.py +9 -4
  9. rasa/cli/utils.py +3 -3
  10. rasa/core/agent.py +2 -2
  11. rasa/core/brokers/kafka.py +3 -1
  12. rasa/core/brokers/pika.py +3 -1
  13. rasa/core/channels/voice_aware/utils.py +6 -5
  14. rasa/core/nlg/contextual_response_rephraser.py +11 -2
  15. rasa/{nlu → core}/persistor.py +1 -1
  16. rasa/core/policies/enterprise_search_policy.py +11 -2
  17. rasa/core/policies/intentless_policy.py +9 -2
  18. rasa/core/run.py +2 -1
  19. rasa/core/secrets_manager/constants.py +4 -0
  20. rasa/core/secrets_manager/factory.py +8 -0
  21. rasa/core/secrets_manager/vault.py +11 -1
  22. rasa/core/utils.py +30 -19
  23. rasa/dialogue_understanding/coexistence/llm_based_router.py +9 -2
  24. rasa/dialogue_understanding/commands/set_slot_command.py +1 -5
  25. rasa/dialogue_understanding/generator/llm_based_command_generator.py +11 -2
  26. rasa/dialogue_understanding/generator/llm_command_generator.py +1 -1
  27. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +15 -15
  28. rasa/e2e_test/e2e_test_runner.py +1 -1
  29. rasa/engine/graph.py +0 -1
  30. rasa/engine/recipes/config_files/default_config.yml +0 -3
  31. rasa/engine/recipes/default_recipe.py +0 -1
  32. rasa/engine/recipes/graph_recipe.py +0 -1
  33. rasa/engine/storage/local_model_storage.py +0 -1
  34. rasa/engine/storage/storage.py +1 -5
  35. rasa/model_manager/__init__.py +0 -0
  36. rasa/model_manager/config.py +7 -0
  37. rasa/model_manager/model_api.py +424 -0
  38. rasa/model_manager/runner_service.py +185 -0
  39. rasa/model_manager/socket_bridge.py +44 -0
  40. rasa/model_manager/trainer_service.py +240 -0
  41. rasa/model_manager/utils.py +27 -0
  42. rasa/model_service.py +43 -0
  43. rasa/model_training.py +11 -6
  44. rasa/server.py +1 -1
  45. rasa/shared/constants.py +2 -0
  46. rasa/shared/core/domain.py +101 -47
  47. rasa/shared/core/flows/flows_list.py +19 -6
  48. rasa/shared/core/flows/validation.py +25 -0
  49. rasa/shared/core/flows/yaml_flows_io.py +3 -24
  50. rasa/shared/importers/importer.py +32 -32
  51. rasa/shared/importers/multi_project.py +23 -11
  52. rasa/shared/importers/rasa.py +7 -2
  53. rasa/shared/importers/remote_importer.py +2 -2
  54. rasa/shared/importers/utils.py +3 -1
  55. rasa/shared/nlu/training_data/training_data.py +18 -19
  56. rasa/shared/utils/common.py +3 -22
  57. rasa/shared/utils/llm.py +28 -2
  58. rasa/shared/utils/schemas/model_config.yml +0 -10
  59. rasa/studio/auth.py +0 -4
  60. rasa/tracing/instrumentation/attribute_extractors.py +1 -1
  61. rasa/validator.py +2 -5
  62. rasa/version.py +1 -1
  63. {rasa_pro-3.10.7.dist-info → rasa_pro-3.10.7.dev1.dist-info}/METADATA +4 -4
  64. {rasa_pro-3.10.7.dist-info → rasa_pro-3.10.7.dev1.dist-info}/RECORD +67 -59
  65. {rasa_pro-3.10.7.dist-info → rasa_pro-3.10.7.dev1.dist-info}/NOTICE +0 -0
  66. {rasa_pro-3.10.7.dist-info → rasa_pro-3.10.7.dev1.dist-info}/WHEEL +0 -0
  67. {rasa_pro-3.10.7.dist-info → rasa_pro-3.10.7.dev1.dist-info}/entry_points.txt +0 -0
@@ -23,6 +23,7 @@ from rasa.shared.core.training_data.structures import StoryGraph
23
23
  from rasa.shared.nlu.constants import ACTION_NAME, ENTITIES
24
24
  from rasa.shared.nlu.training_data.message import Message
25
25
  from rasa.shared.nlu.training_data.training_data import TrainingData
26
+ from rasa.shared.utils.common import cached_method
26
27
  from rasa.shared.utils.yaml import read_config_file
27
28
 
28
29
  logger = logging.getLogger(__name__)
@@ -113,7 +114,7 @@ class TrainingDataImporter(ABC):
113
114
  config_path: Text,
114
115
  domain_path: Optional[Text] = None,
115
116
  training_data_paths: Optional[List[Text]] = None,
116
- args: Optional[Dict[Text, Any]] = {},
117
+ args: Optional[Dict[Text, Any]] = None,
117
118
  ) -> "TrainingDataImporter":
118
119
  """Loads a `TrainingDataImporter` instance from a configuration file."""
119
120
  config = read_config_file(config_path)
@@ -126,7 +127,7 @@ class TrainingDataImporter(ABC):
126
127
  config_path: Text,
127
128
  domain_path: Optional[Text] = None,
128
129
  training_data_paths: Optional[List[Text]] = None,
129
- args: Optional[Dict[Text, Any]] = {},
130
+ args: Optional[Dict[Text, Any]] = None,
130
131
  ) -> "TrainingDataImporter":
131
132
  """Loads core `TrainingDataImporter` instance.
132
133
 
@@ -142,7 +143,7 @@ class TrainingDataImporter(ABC):
142
143
  config_path: Text,
143
144
  domain_path: Optional[Text] = None,
144
145
  training_data_paths: Optional[List[Text]] = None,
145
- args: Optional[Dict[Text, Any]] = {},
146
+ args: Optional[Dict[Text, Any]] = None,
146
147
  ) -> "TrainingDataImporter":
147
148
  """Loads nlu `TrainingDataImporter` instance.
148
149
 
@@ -226,7 +227,8 @@ class TrainingDataImporter(ABC):
226
227
  **constructor_arguments,
227
228
  )
228
229
 
229
- def fingerprint(self) -> Text:
230
+ @staticmethod
231
+ def fingerprint() -> Text:
230
232
  """Returns a random fingerprint as data shouldn't be cached."""
231
233
  return rasa.shared.utils.io.random_string(25)
232
234
 
@@ -282,7 +284,6 @@ class NluDataImporter(TrainingDataImporter):
282
284
  """Retrieves NLU training data (see parent class for full docstring)."""
283
285
  return self._importer.get_nlu_data(language)
284
286
 
285
- @rasa.shared.utils.common.cached_method
286
287
  def get_config_file_for_auto_config(self) -> Optional[Text]:
287
288
  """Returns config file path for auto-config only if there is a single one."""
288
289
  return self._importer.get_config_file_for_auto_config()
@@ -298,14 +299,14 @@ class CombinedDataImporter(TrainingDataImporter):
298
299
  def __init__(self, importers: List[TrainingDataImporter]):
299
300
  self._importers = importers
300
301
 
301
- @rasa.shared.utils.common.cached_method
302
+ @cached_method
302
303
  def get_config(self) -> Dict:
303
304
  """Retrieves model config (see parent class for full docstring)."""
304
305
  configs = [importer.get_config() for importer in self._importers]
305
306
 
306
307
  return reduce(lambda merged, other: {**merged, **(other or {})}, configs, {})
307
308
 
308
- @rasa.shared.utils.common.cached_method
309
+ @cached_method
309
310
  def get_domain(self) -> Domain:
310
311
  """Retrieves model domain (see parent class for full docstring)."""
311
312
  domains = [importer.get_domain() for importer in self._importers]
@@ -316,7 +317,7 @@ class CombinedDataImporter(TrainingDataImporter):
316
317
  Domain.empty(),
317
318
  )
318
319
 
319
- @rasa.shared.utils.common.cached_method
320
+ @cached_method
320
321
  def get_stories(self, exclusion_percentage: Optional[int] = None) -> StoryGraph:
321
322
  """Retrieves training stories / rules (see parent class for full docstring)."""
322
323
  stories = [
@@ -327,7 +328,7 @@ class CombinedDataImporter(TrainingDataImporter):
327
328
  lambda merged, other: merged.merge(other), stories, StoryGraph([])
328
329
  )
329
330
 
330
- @rasa.shared.utils.common.cached_method
331
+ @cached_method
331
332
  def get_flows(self) -> FlowsList:
332
333
  """Retrieves training stories / rules (see parent class for full docstring)."""
333
334
  flow_lists = [importer.get_flows() for importer in self._importers]
@@ -338,7 +339,7 @@ class CombinedDataImporter(TrainingDataImporter):
338
339
  FlowsList(underlying_flows=[]),
339
340
  )
340
341
 
341
- @rasa.shared.utils.common.cached_method
342
+ @cached_method
342
343
  def get_conversation_tests(self) -> StoryGraph:
343
344
  """Retrieves conversation test stories (see parent class for full docstring)."""
344
345
  stories = [importer.get_conversation_tests() for importer in self._importers]
@@ -347,7 +348,7 @@ class CombinedDataImporter(TrainingDataImporter):
347
348
  lambda merged, other: merged.merge(other), stories, StoryGraph([])
348
349
  )
349
350
 
350
- @rasa.shared.utils.common.cached_method
351
+ @cached_method
351
352
  def get_nlu_data(self, language: Optional[Text] = "en") -> TrainingData:
352
353
  """Retrieves NLU training data (see parent class for full docstring)."""
353
354
  nlu_data = [importer.get_nlu_data(language) for importer in self._importers]
@@ -356,7 +357,7 @@ class CombinedDataImporter(TrainingDataImporter):
356
357
  lambda merged, other: merged.merge(other), nlu_data, TrainingData()
357
358
  )
358
359
 
359
- @rasa.shared.utils.common.cached_method
360
+ @cached_method
360
361
  def get_config_file_for_auto_config(self) -> Optional[Text]:
361
362
  """Returns config file path for auto-config only if there is a single one."""
362
363
  if len(self._importers) != 1:
@@ -415,26 +416,22 @@ class FlowSyncImporter(PassThroughImporter):
415
416
  """Loads the default flows from the file system."""
416
417
  from rasa.shared.core.flows.yaml_flows_io import YAMLFlowsReader
417
418
 
418
- default_flows_file = str(
419
- importlib_resources.files("rasa.dialogue_understanding.patterns").joinpath(
420
- DEFAULT_PATTERN_FLOWS_FILE_NAME
421
- )
422
- )
423
-
424
- flows = YAMLFlowsReader.read_from_file(default_flows_file)
419
+ flows = YAMLFlowsReader.read_from_file(FlowSyncImporter.default_pattern_path())
425
420
  flows.validate()
426
421
  return flows
427
422
 
428
423
  @staticmethod
429
- def load_default_pattern_flows_domain() -> Domain:
430
- """Loads the default flows from the file system."""
431
- default_flows_file = str(
424
+ def default_pattern_path() -> str:
425
+ return str(
432
426
  importlib_resources.files("rasa.dialogue_understanding.patterns").joinpath(
433
427
  DEFAULT_PATTERN_FLOWS_FILE_NAME
434
428
  )
435
429
  )
436
430
 
437
- 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())
438
435
 
439
436
  @classmethod
440
437
  def merge_with_default_flows(cls, flows: FlowsList) -> FlowsList:
@@ -460,7 +457,7 @@ class FlowSyncImporter(PassThroughImporter):
460
457
 
461
458
  return flows.merge(FlowsList(missing_default_flows))
462
459
 
463
- @rasa.shared.utils.common.cached_method
460
+ @cached_method
464
461
  def get_flows(self) -> FlowsList:
465
462
  flows = self._importer.get_flows()
466
463
 
@@ -470,11 +467,11 @@ class FlowSyncImporter(PassThroughImporter):
470
467
 
471
468
  return self.merge_with_default_flows(flows)
472
469
 
473
- @rasa.shared.utils.common.cached_method
470
+ @cached_method
474
471
  def get_user_flows(self) -> FlowsList:
475
472
  return self._importer.get_flows()
476
473
 
477
- @rasa.shared.utils.common.cached_method
474
+ @cached_method
478
475
  def get_domain(self) -> Domain:
479
476
  """Merge existing domain with properties of flows."""
480
477
  # load domain data from user defined domain files
@@ -516,7 +513,7 @@ class ResponsesSyncImporter(PassThroughImporter):
516
513
  back to the Domain.
517
514
  """
518
515
 
519
- @rasa.shared.utils.common.cached_method
516
+ @cached_method
520
517
  def get_domain(self) -> Domain:
521
518
  """Merge existing domain with properties of retrieval intents in NLU data."""
522
519
  existing_domain = self._importer.get_domain()
@@ -598,7 +595,7 @@ class ResponsesSyncImporter(PassThroughImporter):
598
595
  }
599
596
  )
600
597
 
601
- @rasa.shared.utils.common.cached_method
598
+ @cached_method
602
599
  def get_nlu_data(self, language: Optional[Text] = "en") -> TrainingData:
603
600
  """Updates NLU data with responses for retrieval intents from domain."""
604
601
  existing_nlu_data = self._importer.get_nlu_data(language)
@@ -633,7 +630,7 @@ class E2EImporter(PassThroughImporter):
633
630
  - adds potential end-to-end bot messages from stories as actions to the domain
634
631
  """
635
632
 
636
- @rasa.shared.utils.common.cached_method
633
+ @cached_method
637
634
  def get_user_flows(self) -> FlowsList:
638
635
  if not isinstance(self._importer, FlowSyncImporter):
639
636
  raise NotImplementedError(
@@ -642,9 +639,12 @@ class E2EImporter(PassThroughImporter):
642
639
 
643
640
  return self._importer.get_user_flows()
644
641
 
645
- @rasa.shared.utils.common.cached_method
642
+ @cached_method
646
643
  def get_domain(self) -> Domain:
647
- """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
+ """
648
648
  original = self._importer.get_domain()
649
649
  e2e_domain = self._get_domain_with_e2e_actions()
650
650
 
@@ -674,7 +674,7 @@ class E2EImporter(PassThroughImporter):
674
674
 
675
675
  return Domain.from_dict({KEY_E2E_ACTIONS: list(additional_e2e_action_names)})
676
676
 
677
- @rasa.shared.utils.common.cached_method
677
+ @cached_method
678
678
  def get_nlu_data(self, language: Optional[Text] = "en") -> TrainingData:
679
679
  """Retrieves NLU training data (see parent class for full docstring)."""
680
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()
@@ -8,7 +8,7 @@ import rasa.shared.core.flows.yaml_flows_io
8
8
  import rasa.shared.data
9
9
  import rasa.shared.utils.common
10
10
  import rasa.shared.utils.io
11
- from rasa.nlu.persistor import StorageType
11
+ from rasa.core.persistor import StorageType
12
12
  from rasa.shared.core.domain import Domain, InvalidDomain
13
13
  from rasa.shared.core.flows import FlowsList
14
14
  from rasa.shared.core.training_data.story_reader.yaml_story_reader import (
@@ -79,7 +79,7 @@ class RemoteTrainingDataImporter(TrainingDataImporter):
79
79
  self, training_file: str, training_data_path: Optional[str] = None
80
80
  ) -> str:
81
81
  """Fetches training files from remote storage."""
82
- from rasa.nlu.persistor import get_persistor
82
+ from rasa.core.persistor import get_persistor
83
83
 
84
84
  persistor = get_persistor(self.remote_storage)
85
85
  if persistor is None:
@@ -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
@@ -1,5 +1,6 @@
1
1
  import logging
2
2
  import os
3
+ from functools import cached_property
3
4
  from pathlib import Path
4
5
  import random
5
6
  from collections import Counter, OrderedDict
@@ -9,7 +10,6 @@ from typing import Any, Dict, List, Optional, Set, Text, Tuple, Callable
9
10
  import operator
10
11
 
11
12
  import rasa.shared.data
12
- from rasa.shared.utils.common import lazy_property
13
13
  import rasa.shared.utils.io
14
14
  from rasa.shared.nlu.constants import (
15
15
  RESPONSE,
@@ -202,7 +202,7 @@ class TrainingData:
202
202
 
203
203
  return list(OrderedDict.fromkeys(examples))
204
204
 
205
- @lazy_property
205
+ @cached_property
206
206
  def nlu_examples(self) -> List[Message]:
207
207
  """Return examples which have come from NLU training data.
208
208
 
@@ -215,32 +215,32 @@ class TrainingData:
215
215
  ex for ex in self.training_examples if not ex.is_core_or_domain_message()
216
216
  ]
217
217
 
218
- @lazy_property
218
+ @cached_property
219
219
  def intent_examples(self) -> List[Message]:
220
220
  """Returns the list of examples that have intent."""
221
221
  return [ex for ex in self.nlu_examples if ex.get(INTENT)]
222
222
 
223
- @lazy_property
223
+ @cached_property
224
224
  def response_examples(self) -> List[Message]:
225
225
  """Returns the list of examples that have response."""
226
226
  return [ex for ex in self.nlu_examples if ex.get(INTENT_RESPONSE_KEY)]
227
227
 
228
- @lazy_property
228
+ @cached_property
229
229
  def entity_examples(self) -> List[Message]:
230
230
  """Returns the list of examples that have entities."""
231
231
  return [ex for ex in self.nlu_examples if ex.get(ENTITIES)]
232
232
 
233
- @lazy_property
233
+ @cached_property
234
234
  def intents(self) -> Set[Text]:
235
235
  """Returns the set of intents in the training data."""
236
236
  return {ex.get(INTENT) for ex in self.training_examples} - {None}
237
237
 
238
- @lazy_property
238
+ @cached_property
239
239
  def action_names(self) -> Set[Text]:
240
240
  """Returns the set of action names in the training data."""
241
241
  return {ex.get(ACTION_NAME) for ex in self.training_examples} - {None}
242
242
 
243
- @lazy_property
243
+ @cached_property
244
244
  def retrieval_intents(self) -> Set[Text]:
245
245
  """Returns the total number of response types in the training data."""
246
246
  return {
@@ -249,13 +249,13 @@ class TrainingData:
249
249
  if ex.get(INTENT_RESPONSE_KEY)
250
250
  }
251
251
 
252
- @lazy_property
252
+ @cached_property
253
253
  def number_of_examples_per_intent(self) -> Dict[Text, int]:
254
254
  """Calculates the number of examples per intent."""
255
255
  intents = [ex.get(INTENT) for ex in self.nlu_examples]
256
256
  return dict(Counter(intents))
257
257
 
258
- @lazy_property
258
+ @cached_property
259
259
  def number_of_examples_per_response(self) -> Dict[Text, int]:
260
260
  """Calculates the number of examples per response."""
261
261
  responses = [
@@ -265,12 +265,12 @@ class TrainingData:
265
265
  ]
266
266
  return dict(Counter(responses))
267
267
 
268
- @lazy_property
268
+ @cached_property
269
269
  def entities(self) -> Set[Text]:
270
270
  """Returns the set of entity types in the training data."""
271
271
  return {e.get(ENTITY_ATTRIBUTE_TYPE) for e in self.sorted_entities()}
272
272
 
273
- @lazy_property
273
+ @cached_property
274
274
  def entity_roles(self) -> Set[Text]:
275
275
  """Returns the set of entity roles in the training data."""
276
276
  entity_types = {
@@ -280,7 +280,7 @@ class TrainingData:
280
280
  }
281
281
  return entity_types - {NO_ENTITY_TAG}
282
282
 
283
- @lazy_property
283
+ @cached_property
284
284
  def entity_groups(self) -> Set[Text]:
285
285
  """Returns the set of entity groups in the training data."""
286
286
  entity_types = {
@@ -299,7 +299,7 @@ class TrainingData:
299
299
 
300
300
  return entity_groups_used or entity_roles_used
301
301
 
302
- @lazy_property
302
+ @cached_property
303
303
  def number_of_examples_per_entity(self) -> Dict[Text, int]:
304
304
  """Calculates the number of examples per entity."""
305
305
  entities = []
@@ -426,8 +426,9 @@ class TrainingData:
426
426
  def persist(
427
427
  self, dir_name: Text, filename: Text = DEFAULT_TRAINING_DATA_OUTPUT_PATH
428
428
  ) -> Dict[Text, Any]:
429
- """Persists this training data to disk and returns necessary
430
- information to load it again.
429
+ """Persists this training data to disk.
430
+
431
+ Returns: necessary information to load it again.
431
432
  """
432
433
  if not os.path.exists(dir_name):
433
434
  os.makedirs(dir_name)
@@ -498,9 +499,7 @@ class TrainingData:
498
499
  def train_test_split(
499
500
  self, train_frac: float = 0.8, random_seed: Optional[int] = None
500
501
  ) -> Tuple["TrainingData", "TrainingData"]:
501
- """Split into a training and test dataset,
502
- preserving the fraction of examples per intent.
503
- """
502
+ """Split into a training and test dataset, preserving the fraction of examples per intent.""" # noqa: E501
504
503
  # collect all nlu data
505
504
  test, train = self.split_nlu_examples(train_frac, random_seed)
506
505
 
@@ -86,31 +86,11 @@ def sort_list_of_dicts_by_first_key(dicts: List[Dict]) -> List[Dict]:
86
86
  return sorted(dicts, key=lambda d: next(iter(d.keys())))
87
87
 
88
88
 
89
- def lazy_property(function: Callable) -> Any:
90
- """Allows to avoid recomputing a property over and over.
91
-
92
- The result gets stored in a local var. Computation of the property
93
- will happen once, on the first call of the property. All
94
- succeeding calls will use the value stored in the private property.
95
- """
96
- attr_name = "_lazy_" + function.__name__
97
-
98
- def _lazyprop(self: Any) -> Any:
99
- if not hasattr(self, attr_name):
100
- setattr(self, attr_name, function(self))
101
- return getattr(self, attr_name)
102
-
103
- return property(_lazyprop)
104
-
105
-
106
89
  def cached_method(f: Callable[..., Any]) -> Callable[..., Any]:
107
90
  """Caches method calls based on the call's `args` and `kwargs`.
108
-
109
91
  Works for `async` and `sync` methods. Don't apply this to functions.
110
-
111
92
  Args:
112
93
  f: The decorated method whose return value should be cached.
113
-
114
94
  Returns:
115
95
  The return value which the method gives for the first call with the given
116
96
  arguments.
@@ -176,8 +156,9 @@ def transform_collection_to_sentence(collection: Collection[Text]) -> Text:
176
156
  def minimal_kwargs(
177
157
  kwargs: Dict[Text, Any], func: Callable, excluded_keys: Optional[List] = None
178
158
  ) -> Dict[Text, Any]:
179
- """Returns only the kwargs which are required by a function. Keys, contained in
180
- the exception list, are not included.
159
+ """Returns only the kwargs which are required by a function.
160
+
161
+ Keys, contained in the exception list, are not included.
181
162
 
182
163
  Args:
183
164
  kwargs: All available kwargs.
rasa/shared/utils/llm.py CHANGED
@@ -410,10 +410,10 @@ def try_instantiate_llm_client(
410
410
  default_llm_config: Optional[Dict],
411
411
  log_source_function: str,
412
412
  log_source_component: str,
413
- ) -> None:
413
+ ) -> LLMClient:
414
414
  """Validate llm configuration."""
415
415
  try:
416
- llm_factory(custom_llm_config, default_llm_config)
416
+ return llm_factory(custom_llm_config, default_llm_config)
417
417
  except (ProviderClientValidationError, ValueError) as e:
418
418
  structlogger.error(
419
419
  f"{log_source_function}.llm_instantiation_failed",
@@ -425,3 +425,29 @@ def try_instantiate_llm_client(
425
425
  f"Please make sure you specified the required environment variables. "
426
426
  f"Error: {e}"
427
427
  )
428
+
429
+
430
+ def llm_api_health_check(
431
+ llm_client: LLMClient, log_source_function: str, log_source_component: str
432
+ ) -> None:
433
+ """Perform a health check on the LLM API."""
434
+ structlogger.info(
435
+ f"{log_source_function}.llm_api_call",
436
+ event_info=(
437
+ f"Performing a health check on the LLM API for the component - "
438
+ f"{log_source_component}."
439
+ ),
440
+ config=llm_client.config,
441
+ )
442
+ try:
443
+ llm_client.completion("hello")
444
+ except Exception as e:
445
+ structlogger.error(
446
+ f"{log_source_function}.llm_api_call_failed",
447
+ event_info="call to the LLM API failed.",
448
+ error=e,
449
+ )
450
+ print_error_and_exit(
451
+ f"Call to the LLM API failed for component - {log_source_component}. "
452
+ f"Error: {e}"
453
+ )
@@ -34,13 +34,3 @@ mapping:
34
34
  name:
35
35
  type: str
36
36
  required: True
37
- spaces:
38
- type: "seq"
39
- required: False
40
- sequence:
41
- - type: "map"
42
- allowempty: True
43
- mapping:
44
- name:
45
- type: str
46
- required: True
rasa/studio/auth.py CHANGED
@@ -21,19 +21,15 @@ from rasa.studio.results_logger import with_studio_error_handler, StudioResult
21
21
 
22
22
 
23
23
  class StudioAuth:
24
- """Handles the authentication with the Rasa Studio authentication server."""
25
-
26
24
  def __init__(
27
25
  self,
28
26
  studio_config: StudioConfig,
29
- verify: bool = True,
30
27
  ) -> None:
31
28
  self.config = studio_config
32
29
  self.keycloak_openid = KeycloakOpenID(
33
30
  server_url=studio_config.authentication_server_url,
34
31
  client_id=studio_config.client_id,
35
32
  realm_name=studio_config.realm_name,
36
- verify=verify,
37
33
  )
38
34
 
39
35
  def health_check(self) -> bool:
@@ -664,7 +664,7 @@ def extract_attrs_for_custom_action_executor_run(
664
664
 
665
665
  attrs: Dict[str, Any] = {
666
666
  "class_name": self.__class__.__name__,
667
- "action_name": self.action_name,
667
+ "action_name": self.action_name if hasattr(self, "action_name") else "None",
668
668
  "sender_id": tracker.sender_id,
669
669
  "url": str(url),
670
670
  "actions_module": str(actions_module),