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.
- rasa/api.py +8 -2
- rasa/cli/arguments/default_arguments.py +23 -2
- rasa/cli/arguments/run.py +2 -0
- rasa/cli/e2e_test.py +10 -8
- rasa/cli/inspect.py +5 -2
- rasa/cli/run.py +7 -0
- rasa/cli/studio/studio.py +1 -21
- rasa/cli/train.py +9 -4
- rasa/cli/utils.py +3 -3
- rasa/core/agent.py +2 -2
- rasa/core/brokers/kafka.py +3 -1
- rasa/core/brokers/pika.py +3 -1
- rasa/core/channels/voice_aware/utils.py +6 -5
- rasa/core/nlg/contextual_response_rephraser.py +11 -2
- rasa/{nlu → core}/persistor.py +1 -1
- rasa/core/policies/enterprise_search_policy.py +11 -2
- rasa/core/policies/intentless_policy.py +9 -2
- rasa/core/run.py +2 -1
- rasa/core/secrets_manager/constants.py +4 -0
- rasa/core/secrets_manager/factory.py +8 -0
- rasa/core/secrets_manager/vault.py +11 -1
- rasa/core/utils.py +30 -19
- rasa/dialogue_understanding/coexistence/llm_based_router.py +9 -2
- rasa/dialogue_understanding/commands/set_slot_command.py +1 -5
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +11 -2
- rasa/dialogue_understanding/generator/llm_command_generator.py +1 -1
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +15 -15
- rasa/e2e_test/e2e_test_runner.py +1 -1
- rasa/engine/graph.py +0 -1
- rasa/engine/recipes/config_files/default_config.yml +0 -3
- rasa/engine/recipes/default_recipe.py +0 -1
- rasa/engine/recipes/graph_recipe.py +0 -1
- rasa/engine/storage/local_model_storage.py +0 -1
- rasa/engine/storage/storage.py +1 -5
- rasa/model_manager/__init__.py +0 -0
- rasa/model_manager/config.py +7 -0
- rasa/model_manager/model_api.py +424 -0
- rasa/model_manager/runner_service.py +185 -0
- rasa/model_manager/socket_bridge.py +44 -0
- rasa/model_manager/trainer_service.py +240 -0
- rasa/model_manager/utils.py +27 -0
- rasa/model_service.py +43 -0
- rasa/model_training.py +11 -6
- rasa/server.py +1 -1
- rasa/shared/constants.py +2 -0
- rasa/shared/core/domain.py +101 -47
- rasa/shared/core/flows/flows_list.py +19 -6
- rasa/shared/core/flows/validation.py +25 -0
- rasa/shared/core/flows/yaml_flows_io.py +3 -24
- rasa/shared/importers/importer.py +32 -32
- rasa/shared/importers/multi_project.py +23 -11
- rasa/shared/importers/rasa.py +7 -2
- rasa/shared/importers/remote_importer.py +2 -2
- rasa/shared/importers/utils.py +3 -1
- rasa/shared/nlu/training_data/training_data.py +18 -19
- rasa/shared/utils/common.py +3 -22
- rasa/shared/utils/llm.py +28 -2
- rasa/shared/utils/schemas/model_config.yml +0 -10
- rasa/studio/auth.py +0 -4
- rasa/tracing/instrumentation/attribute_extractors.py +1 -1
- rasa/validator.py +2 -5
- rasa/version.py +1 -1
- {rasa_pro-3.10.7.dist-info → rasa_pro-3.10.7.dev1.dist-info}/METADATA +4 -4
- {rasa_pro-3.10.7.dist-info → rasa_pro-3.10.7.dev1.dist-info}/RECORD +67 -59
- {rasa_pro-3.10.7.dist-info → rasa_pro-3.10.7.dev1.dist-info}/NOTICE +0 -0
- {rasa_pro-3.10.7.dist-info → rasa_pro-3.10.7.dev1.dist-info}/WHEEL +0 -0
- {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
|
-
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
|
|
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
|
|
430
|
-
|
|
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
|
-
|
|
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
|
-
@
|
|
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
|
-
@
|
|
470
|
+
@cached_method
|
|
474
471
|
def get_user_flows(self) -> FlowsList:
|
|
475
472
|
return self._importer.get_flows()
|
|
476
473
|
|
|
477
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
642
|
+
@cached_method
|
|
646
643
|
def get_domain(self) -> Domain:
|
|
647
|
-
"""
|
|
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
|
-
@
|
|
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
|
-
|
|
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
|
-
|
|
54
|
-
"
|
|
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)
|
rasa/shared/importers/rasa.py
CHANGED
|
@@ -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.
|
|
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.
|
|
82
|
+
from rasa.core.persistor import get_persistor
|
|
83
83
|
|
|
84
84
|
persistor = get_persistor(self.remote_storage)
|
|
85
85
|
if persistor is None:
|
rasa/shared/importers/utils.py
CHANGED
|
@@ -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(
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
|
430
|
-
|
|
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
|
|
rasa/shared/utils/common.py
CHANGED
|
@@ -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.
|
|
180
|
-
|
|
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
|
-
) ->
|
|
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
|
+
)
|
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),
|