rasa-pro 3.10.15__py3-none-any.whl → 3.11.0__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/__main__.py +31 -15
- rasa/api.py +12 -2
- rasa/cli/arguments/default_arguments.py +24 -4
- rasa/cli/arguments/run.py +15 -0
- rasa/cli/arguments/shell.py +5 -1
- rasa/cli/arguments/train.py +17 -9
- rasa/cli/evaluate.py +7 -7
- rasa/cli/inspect.py +19 -7
- rasa/cli/interactive.py +1 -0
- rasa/cli/project_templates/calm/config.yml +5 -7
- rasa/cli/project_templates/calm/endpoints.yml +15 -2
- rasa/cli/project_templates/tutorial/config.yml +8 -5
- rasa/cli/project_templates/tutorial/data/flows.yml +1 -1
- rasa/cli/project_templates/tutorial/data/patterns.yml +5 -0
- rasa/cli/project_templates/tutorial/domain.yml +14 -0
- rasa/cli/project_templates/tutorial/endpoints.yml +5 -0
- rasa/cli/run.py +7 -0
- rasa/cli/scaffold.py +4 -2
- rasa/cli/studio/upload.py +0 -15
- rasa/cli/train.py +14 -53
- rasa/cli/utils.py +14 -11
- rasa/cli/x.py +7 -7
- rasa/constants.py +3 -1
- rasa/core/actions/action.py +77 -33
- rasa/core/actions/action_hangup.py +29 -0
- rasa/core/actions/action_repeat_bot_messages.py +89 -0
- rasa/core/actions/e2e_stub_custom_action_executor.py +5 -1
- rasa/core/actions/http_custom_action_executor.py +4 -0
- rasa/core/agent.py +2 -2
- rasa/core/brokers/kafka.py +3 -1
- rasa/core/brokers/pika.py +3 -1
- rasa/core/channels/__init__.py +10 -6
- rasa/core/channels/channel.py +41 -4
- rasa/core/channels/development_inspector.py +150 -46
- rasa/core/channels/inspector/README.md +1 -1
- rasa/core/channels/inspector/dist/assets/{arc-b6e548fe.js → arc-bc141fb2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-fa03ac9e.js → c4Diagram-d0fbc5ce-be2db283.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-ee67392a.js → classDiagram-936ed81e-55366915.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-9b283fae.js → classDiagram-v2-c3cb15f1-bb529518.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{createText-62fc7601-8b6fcc2a.js → createText-62fc7601-b0ec81d6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-22e77f4f.js → edges-f2ad444c-6166330c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-60ffc87f.js → erDiagram-9d236eb7-5ccc6a8e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-9dd802e4.js → flowDb-1972c806-fca3bfe4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-5fa1912f.js → flowDiagram-7ea5b25a-4739080f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-736177bf.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-622a1fd2.js → flowchart-elk-definition-abe16c3d-7c1b0e0f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-e285a63a.js → ganttDiagram-9b5ea136-772fd050.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-f237bdca.js → gitGraphDiagram-99d0ae7c-8eae1dc9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-4b03d70e.js → index-2c4b9a3b-f55afcdf.js} +1 -1
- rasa/core/channels/inspector/dist/assets/index-e7cef9de.js +1317 -0
- rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-72a0fa5f.js → infoDiagram-736b4530-124d4a14.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-82218c41.js → journeyDiagram-df861f2b-7c4fae44.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-78cff630.js → layout-b9885fb6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-5038b469.js → line-7c59abb6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-c4fc4098.js → linear-4776f780.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-c33c8ea6.js → mindmap-definition-beec6740-2332c46c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-a8d03059.js → pieDiagram-dbbf0591-8fb39303.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-6a0e56b2.js → quadrantDiagram-4d7f4fd6-3c7180a2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-2dc7c7bd.js → requirementDiagram-6fc4c22a-e910bcb8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-2360fe39.js → sankeyDiagram-8f13d901-ead16c89.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-41b9f9ad.js → sequenceDiagram-b655622a-29a02a19.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-0aad326f.js → stateDiagram-59f0c015-042b3137.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-9847d984.js → stateDiagram-v2-2b26beab-2178c0f3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-080da4f6-564d890e.js → styles-080da4f6-23ffa4fc.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-38957613.js → styles-3dcbcfbf-94f59763.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9c745c82-f0fc6921.js → styles-9c745c82-78a6bebc.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-ef3c5a77.js → svgDrawCommon-4835440b-eae2a6f6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-bf3e91c1.js → timeline-definition-5b62e21b-5c968d92.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-4d4026c0.js → xychartDiagram-2b33534f-fd3db0d5.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +18 -15
- rasa/core/channels/inspector/index.html +17 -14
- rasa/core/channels/inspector/package.json +5 -1
- rasa/core/channels/inspector/src/App.tsx +118 -68
- rasa/core/channels/inspector/src/components/Chat.tsx +95 -0
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +11 -10
- rasa/core/channels/inspector/src/components/DialogueStack.tsx +10 -25
- rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +6 -3
- rasa/core/channels/inspector/src/helpers/audiostream.ts +165 -0
- rasa/core/channels/inspector/src/helpers/formatters.test.ts +10 -0
- rasa/core/channels/inspector/src/helpers/formatters.ts +107 -41
- rasa/core/channels/inspector/src/helpers/utils.ts +92 -7
- rasa/core/channels/inspector/src/types.ts +21 -1
- rasa/core/channels/inspector/yarn.lock +94 -1
- rasa/core/channels/rest.py +51 -46
- rasa/core/channels/socketio.py +28 -1
- rasa/core/channels/telegram.py +1 -1
- rasa/core/channels/twilio.py +1 -1
- rasa/core/channels/{audiocodes.py → voice_ready/audiocodes.py} +122 -69
- rasa/core/channels/{voice_aware → voice_ready}/jambonz.py +26 -8
- rasa/core/channels/{voice_aware → voice_ready}/jambonz_protocol.py +57 -5
- rasa/core/channels/{twilio_voice.py → voice_ready/twilio_voice.py} +64 -28
- rasa/core/channels/voice_ready/utils.py +37 -0
- rasa/core/channels/voice_stream/asr/__init__.py +0 -0
- rasa/core/channels/voice_stream/asr/asr_engine.py +89 -0
- rasa/core/channels/voice_stream/asr/asr_event.py +18 -0
- rasa/core/channels/voice_stream/asr/azure.py +129 -0
- rasa/core/channels/voice_stream/asr/deepgram.py +90 -0
- rasa/core/channels/voice_stream/audio_bytes.py +8 -0
- rasa/core/channels/voice_stream/browser_audio.py +107 -0
- rasa/core/channels/voice_stream/call_state.py +23 -0
- rasa/core/channels/voice_stream/tts/__init__.py +0 -0
- rasa/core/channels/voice_stream/tts/azure.py +106 -0
- rasa/core/channels/voice_stream/tts/cartesia.py +118 -0
- rasa/core/channels/voice_stream/tts/tts_cache.py +27 -0
- rasa/core/channels/voice_stream/tts/tts_engine.py +58 -0
- rasa/core/channels/voice_stream/twilio_media_streams.py +173 -0
- rasa/core/channels/voice_stream/util.py +57 -0
- rasa/core/channels/voice_stream/voice_channel.py +427 -0
- rasa/core/information_retrieval/qdrant.py +1 -0
- rasa/core/nlg/contextual_response_rephraser.py +45 -17
- rasa/{nlu → core}/persistor.py +203 -68
- rasa/core/policies/enterprise_search_policy.py +119 -63
- rasa/core/policies/flows/flow_executor.py +15 -22
- rasa/core/policies/intentless_policy.py +83 -28
- rasa/core/processor.py +25 -0
- rasa/core/run.py +12 -2
- 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/training/interactive.py +33 -34
- rasa/core/utils.py +47 -21
- rasa/dialogue_understanding/coexistence/llm_based_router.py +41 -14
- rasa/dialogue_understanding/commands/__init__.py +6 -0
- rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +60 -0
- rasa/dialogue_understanding/commands/session_end_command.py +61 -0
- rasa/dialogue_understanding/commands/user_silence_command.py +59 -0
- rasa/dialogue_understanding/commands/utils.py +5 -0
- rasa/dialogue_understanding/generator/constants.py +2 -0
- rasa/dialogue_understanding/generator/flow_retrieval.py +47 -9
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +38 -15
- rasa/dialogue_understanding/generator/llm_command_generator.py +1 -1
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +35 -13
- rasa/dialogue_understanding/generator/single_step/command_prompt_template.jinja2 +3 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +60 -13
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +53 -0
- rasa/dialogue_understanding/patterns/repeat.py +37 -0
- rasa/dialogue_understanding/patterns/user_silence.py +37 -0
- rasa/dialogue_understanding/processor/command_processor.py +21 -1
- rasa/e2e_test/aggregate_test_stats_calculator.py +1 -11
- rasa/e2e_test/assertions.py +136 -61
- rasa/e2e_test/assertions_schema.yml +23 -0
- rasa/e2e_test/e2e_test_case.py +85 -6
- rasa/e2e_test/e2e_test_runner.py +2 -3
- rasa/engine/graph.py +0 -1
- rasa/engine/loader.py +12 -0
- 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/runner/dask.py +2 -2
- rasa/engine/storage/local_model_storage.py +12 -42
- rasa/engine/storage/storage.py +1 -5
- rasa/engine/validation.py +527 -74
- rasa/model_manager/__init__.py +0 -0
- rasa/model_manager/config.py +40 -0
- rasa/model_manager/model_api.py +559 -0
- rasa/model_manager/runner_service.py +286 -0
- rasa/model_manager/socket_bridge.py +146 -0
- rasa/model_manager/studio_jwt_auth.py +86 -0
- rasa/model_manager/trainer_service.py +325 -0
- rasa/model_manager/utils.py +87 -0
- rasa/model_manager/warm_rasa_process.py +187 -0
- rasa/model_service.py +112 -0
- rasa/model_training.py +42 -23
- rasa/nlu/tokenizers/whitespace_tokenizer.py +3 -14
- rasa/server.py +4 -2
- rasa/shared/constants.py +60 -8
- rasa/shared/core/constants.py +13 -0
- rasa/shared/core/domain.py +107 -50
- rasa/shared/core/events.py +29 -0
- rasa/shared/core/flows/flow.py +5 -0
- rasa/shared/core/flows/flows_list.py +19 -6
- rasa/shared/core/flows/flows_yaml_schema.json +10 -0
- rasa/shared/core/flows/utils.py +39 -0
- rasa/shared/core/flows/validation.py +121 -0
- rasa/shared/core/flows/yaml_flows_io.py +15 -27
- rasa/shared/core/slots.py +5 -0
- rasa/shared/importers/importer.py +59 -41
- rasa/shared/importers/multi_project.py +23 -11
- rasa/shared/importers/rasa.py +12 -3
- rasa/shared/importers/remote_importer.py +196 -0
- rasa/shared/importers/utils.py +3 -1
- rasa/shared/nlu/training_data/formats/rasa_yaml.py +18 -3
- rasa/shared/nlu/training_data/training_data.py +18 -19
- rasa/shared/providers/_configs/litellm_router_client_config.py +220 -0
- rasa/shared/providers/_configs/model_group_config.py +167 -0
- rasa/shared/providers/_configs/openai_client_config.py +1 -1
- rasa/shared/providers/_configs/rasa_llm_client_config.py +73 -0
- rasa/shared/providers/_configs/self_hosted_llm_client_config.py +1 -0
- rasa/shared/providers/_configs/utils.py +16 -0
- rasa/shared/providers/_utils.py +79 -0
- rasa/shared/providers/embedding/_base_litellm_embedding_client.py +13 -29
- rasa/shared/providers/embedding/azure_openai_embedding_client.py +54 -21
- rasa/shared/providers/embedding/default_litellm_embedding_client.py +24 -0
- rasa/shared/providers/embedding/litellm_router_embedding_client.py +135 -0
- rasa/shared/providers/llm/_base_litellm_client.py +34 -22
- rasa/shared/providers/llm/azure_openai_llm_client.py +50 -29
- rasa/shared/providers/llm/default_litellm_llm_client.py +24 -0
- rasa/shared/providers/llm/litellm_router_llm_client.py +182 -0
- rasa/shared/providers/llm/rasa_llm_client.py +112 -0
- rasa/shared/providers/llm/self_hosted_llm_client.py +5 -29
- rasa/shared/providers/mappings.py +19 -0
- rasa/shared/providers/router/__init__.py +0 -0
- rasa/shared/providers/router/_base_litellm_router_client.py +183 -0
- rasa/shared/providers/router/router_client.py +73 -0
- rasa/shared/utils/common.py +40 -24
- rasa/shared/utils/health_check/__init__.py +0 -0
- rasa/shared/utils/health_check/embeddings_health_check_mixin.py +31 -0
- rasa/shared/utils/health_check/health_check.py +258 -0
- rasa/shared/utils/health_check/llm_health_check_mixin.py +31 -0
- rasa/shared/utils/io.py +27 -6
- rasa/shared/utils/llm.py +353 -43
- rasa/shared/utils/schemas/events.py +2 -0
- rasa/shared/utils/schemas/model_config.yml +0 -10
- rasa/shared/utils/yaml.py +181 -38
- rasa/studio/data_handler.py +3 -1
- rasa/studio/upload.py +160 -74
- rasa/telemetry.py +94 -17
- rasa/tracing/config.py +3 -1
- rasa/tracing/instrumentation/attribute_extractors.py +95 -18
- rasa/tracing/instrumentation/instrumentation.py +121 -0
- rasa/utils/common.py +5 -0
- rasa/utils/endpoints.py +27 -1
- rasa/utils/io.py +8 -16
- rasa/utils/log_utils.py +9 -2
- rasa/utils/sanic_error_handler.py +32 -0
- rasa/validator.py +110 -4
- rasa/version.py +1 -1
- {rasa_pro-3.10.15.dist-info → rasa_pro-3.11.0.dist-info}/METADATA +14 -12
- {rasa_pro-3.10.15.dist-info → rasa_pro-3.11.0.dist-info}/RECORD +234 -183
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-1844e5a5.js +0 -1
- rasa/core/channels/inspector/dist/assets/index-a5d3e69d.js +0 -1040
- rasa/core/channels/voice_aware/utils.py +0 -20
- rasa/llm_fine_tuning/notebooks/unsloth_finetuning.ipynb +0 -407
- /rasa/core/channels/{voice_aware → voice_ready}/__init__.py +0 -0
- /rasa/core/channels/{voice_native → voice_stream}/__init__.py +0 -0
- {rasa_pro-3.10.15.dist-info → rasa_pro-3.11.0.dist-info}/NOTICE +0 -0
- {rasa_pro-3.10.15.dist-info → rasa_pro-3.11.0.dist-info}/WHEEL +0 -0
- {rasa_pro-3.10.15.dist-info → rasa_pro-3.11.0.dist-info}/entry_points.txt +0 -0
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import re
|
|
4
4
|
import typing
|
|
5
5
|
from collections import defaultdict
|
|
6
|
+
from dataclasses import dataclass
|
|
6
7
|
from typing import Optional, Set, Text, List
|
|
7
8
|
|
|
8
9
|
from rasa.shared.constants import (
|
|
@@ -26,6 +27,12 @@ from rasa.shared.core.flows.steps.call import CallFlowStep
|
|
|
26
27
|
from rasa.shared.core.flows.steps.collect import CollectInformationFlowStep
|
|
27
28
|
from rasa.shared.core.flows.steps.constants import CONTINUE_STEP_PREFIX, DEFAULT_STEPS
|
|
28
29
|
from rasa.shared.core.flows.steps.link import LinkFlowStep
|
|
30
|
+
from rasa.shared.core.flows.steps.set_slots import SetSlotsFlowStep
|
|
31
|
+
from rasa.shared.core.flows.utils import (
|
|
32
|
+
warn_deprecated_collect_step_config,
|
|
33
|
+
get_duplicate_slot_persistence_config_error_message,
|
|
34
|
+
get_invalid_slot_persistence_config_error_message,
|
|
35
|
+
)
|
|
29
36
|
from rasa.shared.exceptions import RasaException
|
|
30
37
|
|
|
31
38
|
if typing.TYPE_CHECKING:
|
|
@@ -101,6 +108,31 @@ class DuplicatedStepIdException(RasaException):
|
|
|
101
108
|
)
|
|
102
109
|
|
|
103
110
|
|
|
111
|
+
class DuplicatedFlowIdException(RasaException):
|
|
112
|
+
"""Raised when a flow is using the same id as another flow."""
|
|
113
|
+
|
|
114
|
+
def __init__(
|
|
115
|
+
self, flow_id: str, first_file_path: str, second_file_path: str
|
|
116
|
+
) -> None:
|
|
117
|
+
"""Initializes the exception."""
|
|
118
|
+
self.flow_id = flow_id
|
|
119
|
+
self.first_file_path = first_file_path
|
|
120
|
+
self.second_file_path = second_file_path
|
|
121
|
+
|
|
122
|
+
def __str__(self) -> str:
|
|
123
|
+
"""Return a string representation of the exception."""
|
|
124
|
+
if self.first_file_path == self.second_file_path:
|
|
125
|
+
return (
|
|
126
|
+
f"Flow '{self.flow_id}' is used twice in `{self.first_file_path}`. "
|
|
127
|
+
f"Please make sure flow IDs are unique across all files."
|
|
128
|
+
)
|
|
129
|
+
return (
|
|
130
|
+
f"Flow '{self.flow_id}' is used in both "
|
|
131
|
+
f"`{self.first_file_path}` and `{self.second_file_path}`. "
|
|
132
|
+
f"Please make sure flow IDs are unique across all files."
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
|
|
104
136
|
class MissingElseBranchException(RasaException):
|
|
105
137
|
"""Raised when a flow step is missing an else branch."""
|
|
106
138
|
|
|
@@ -354,6 +386,42 @@ class FlowIdNamingException(RasaException):
|
|
|
354
386
|
)
|
|
355
387
|
|
|
356
388
|
|
|
389
|
+
class DuplicateSlotPersistConfigException(RasaException):
|
|
390
|
+
"""Raised when a slot persist configuration is duplicated."""
|
|
391
|
+
|
|
392
|
+
def __init__(self, flow_id: str, collect_step: str) -> None:
|
|
393
|
+
"""Initializes the exception."""
|
|
394
|
+
self.flow_id = flow_id
|
|
395
|
+
self.collect_step = collect_step
|
|
396
|
+
|
|
397
|
+
def __str__(self) -> str:
|
|
398
|
+
"""Return a string representation of the exception."""
|
|
399
|
+
return get_duplicate_slot_persistence_config_error_message(
|
|
400
|
+
self.flow_id, self.collect_step
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
class InvalidPersistSlotsException(RasaException):
|
|
405
|
+
"""Raised when a slot persist configuration is duplicated."""
|
|
406
|
+
|
|
407
|
+
def __init__(self, flow_id: str, invalid_slots: Set[str]) -> None:
|
|
408
|
+
"""Initializes the exception."""
|
|
409
|
+
self.flow_id = flow_id
|
|
410
|
+
self.invalid_slots = invalid_slots
|
|
411
|
+
|
|
412
|
+
def __str__(self) -> str:
|
|
413
|
+
"""Return a string representation of the exception."""
|
|
414
|
+
return get_invalid_slot_persistence_config_error_message(
|
|
415
|
+
self.flow_id, self.invalid_slots
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
@dataclass
|
|
420
|
+
class ValidationResult:
|
|
421
|
+
is_valid: bool
|
|
422
|
+
invalid_slots: Set[str]
|
|
423
|
+
|
|
424
|
+
|
|
357
425
|
def validate_flow(flow: Flow) -> None:
|
|
358
426
|
"""Validates the flow configuration.
|
|
359
427
|
|
|
@@ -362,6 +430,8 @@ def validate_flow(flow: Flow) -> None:
|
|
|
362
430
|
- whether all next links point to existing steps
|
|
363
431
|
- whether all steps can be reached from the start step
|
|
364
432
|
"""
|
|
433
|
+
from rasa.cli.utils import is_skip_validation_flag_set
|
|
434
|
+
|
|
365
435
|
validate_flow_not_empty(flow)
|
|
366
436
|
validate_no_empty_step_sequences(flow)
|
|
367
437
|
validate_all_steps_next_property(flow)
|
|
@@ -372,6 +442,12 @@ def validate_flow(flow: Flow) -> None:
|
|
|
372
442
|
validate_slot_names_to_be_collected(flow)
|
|
373
443
|
validate_flow_id(flow)
|
|
374
444
|
|
|
445
|
+
if is_skip_validation_flag_set():
|
|
446
|
+
# we only want to run this validation if the --skip-validation flag is used
|
|
447
|
+
# during training because Flow Validation exceptions are raised one by one
|
|
448
|
+
# as opposed to all at once with the Validator class
|
|
449
|
+
validate_slot_persistence_configuration(flow)
|
|
450
|
+
|
|
375
451
|
|
|
376
452
|
def validate_flow_not_empty(flow: Flow) -> None:
|
|
377
453
|
"""Validate that the flow is not empty."""
|
|
@@ -612,3 +688,48 @@ def validate_flow_id(flow: Flow) -> None:
|
|
|
612
688
|
flow_re = re.compile(FLOW_ID_REGEX)
|
|
613
689
|
if not flow_re.search(flow.id):
|
|
614
690
|
raise FlowIdNamingException(flow.id)
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
def validate_slot_persistence_configuration(flow: Flow) -> None:
|
|
694
|
+
"""Validates that slot persistence configuration is valid.
|
|
695
|
+
|
|
696
|
+
Only slots used in either a collect step or a set_slot step can be persisted
|
|
697
|
+
and the configuration can either be set at the flow level or the collect step level,
|
|
698
|
+
but not both.
|
|
699
|
+
|
|
700
|
+
Args:
|
|
701
|
+
flow: The flow to validate.
|
|
702
|
+
|
|
703
|
+
Raises:
|
|
704
|
+
DuplicateSlotPersistConfigException: If slot persist config is duplicated.
|
|
705
|
+
"""
|
|
706
|
+
|
|
707
|
+
def _is_persist_slots_valid(
|
|
708
|
+
persist_slots: List[str], flow_slots: Set[str]
|
|
709
|
+
) -> ValidationResult:
|
|
710
|
+
"""Validates that the slots that should be persisted are used in the flow."""
|
|
711
|
+
invalid_slots = set(persist_slots) - flow_slots
|
|
712
|
+
is_valid = False if invalid_slots else True
|
|
713
|
+
|
|
714
|
+
return ValidationResult(is_valid, invalid_slots)
|
|
715
|
+
|
|
716
|
+
flow_id = flow.id
|
|
717
|
+
persist_slots = flow.persisted_slots
|
|
718
|
+
has_flow_level_persistence = True if persist_slots else False
|
|
719
|
+
flow_slots = set()
|
|
720
|
+
|
|
721
|
+
for step in flow.steps_with_calls_resolved:
|
|
722
|
+
if isinstance(step, SetSlotsFlowStep):
|
|
723
|
+
flow_slots.update([slot["key"] for slot in step.slots])
|
|
724
|
+
elif isinstance(step, CollectInformationFlowStep):
|
|
725
|
+
flow_slots.add(step.collect)
|
|
726
|
+
if not step.reset_after_flow_ends:
|
|
727
|
+
collect_step = step.collect
|
|
728
|
+
warn_deprecated_collect_step_config(flow_id, collect_step)
|
|
729
|
+
if has_flow_level_persistence:
|
|
730
|
+
raise DuplicateSlotPersistConfigException(flow_id, collect_step)
|
|
731
|
+
|
|
732
|
+
if has_flow_level_persistence:
|
|
733
|
+
result = _is_persist_slots_valid(persist_slots, flow_slots)
|
|
734
|
+
if not result.is_valid:
|
|
735
|
+
raise InvalidPersistSlotsException(flow_id, result.invalid_slots)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import textwrap
|
|
2
1
|
from pathlib import Path
|
|
3
|
-
from typing import Any, Dict, List, Text, Union
|
|
2
|
+
from typing import Any, ClassVar, Dict, List, Optional, Text, Union
|
|
4
3
|
|
|
5
4
|
import jsonschema
|
|
6
5
|
import ruamel.yaml.nodes as yaml_nodes
|
|
@@ -12,12 +11,11 @@ import rasa.shared.utils.io
|
|
|
12
11
|
from rasa.shared.core.flows.flow import Flow
|
|
13
12
|
from rasa.shared.core.flows.flows_list import FlowsList
|
|
14
13
|
from rasa.shared.exceptions import RasaException, YamlException
|
|
15
|
-
from rasa.shared.importers.importer import FlowSyncImporter
|
|
16
14
|
from rasa.shared.utils.yaml import (
|
|
17
|
-
validate_yaml_with_jsonschema,
|
|
18
|
-
read_yaml,
|
|
19
15
|
dump_obj_as_yaml_to_string,
|
|
20
16
|
is_key_in_yaml,
|
|
17
|
+
read_yaml,
|
|
18
|
+
validate_yaml_with_jsonschema,
|
|
21
19
|
)
|
|
22
20
|
|
|
23
21
|
FLOWS_SCHEMA_FILE = "shared/core/flows/flows_yaml_schema.json"
|
|
@@ -27,6 +25,8 @@ KEY_FLOWS = "flows"
|
|
|
27
25
|
class YAMLFlowsReader:
|
|
28
26
|
"""Class that reads flows information in YAML format."""
|
|
29
27
|
|
|
28
|
+
expand_env_vars: ClassVar[bool] = True
|
|
29
|
+
|
|
30
30
|
@classmethod
|
|
31
31
|
def read_from_file(
|
|
32
32
|
cls, filename: Union[Text, Path], add_line_numbers: bool = True
|
|
@@ -219,14 +219,21 @@ class YAMLFlowsReader:
|
|
|
219
219
|
`Flow`s read from `string`.
|
|
220
220
|
"""
|
|
221
221
|
validate_yaml_with_jsonschema(
|
|
222
|
-
string,
|
|
222
|
+
string,
|
|
223
|
+
FLOWS_SCHEMA_FILE,
|
|
224
|
+
humanize_error=cls.humanize_flow_error,
|
|
225
|
+
expand_env_vars=cls.expand_env_vars,
|
|
223
226
|
)
|
|
224
227
|
if add_line_numbers:
|
|
225
|
-
yaml_content = read_yaml(
|
|
228
|
+
yaml_content = read_yaml(
|
|
229
|
+
string,
|
|
230
|
+
custom_constructor=line_number_constructor,
|
|
231
|
+
expand_env_vars=cls.expand_env_vars,
|
|
232
|
+
)
|
|
226
233
|
yaml_content = process_yaml_content(yaml_content)
|
|
227
234
|
|
|
228
235
|
else:
|
|
229
|
-
yaml_content = read_yaml(string)
|
|
236
|
+
yaml_content = read_yaml(string, expand_env_vars=cls.expand_env_vars)
|
|
230
237
|
|
|
231
238
|
return FlowsList.from_json(yaml_content.get(KEY_FLOWS, {}), file_path=file_path)
|
|
232
239
|
|
|
@@ -262,25 +269,6 @@ class YamlFlowsWriter:
|
|
|
262
269
|
rasa.shared.utils.io.write_text_file(YamlFlowsWriter.dumps(flows), filename)
|
|
263
270
|
|
|
264
271
|
|
|
265
|
-
def flows_from_str(yaml_str: str) -> FlowsList:
|
|
266
|
-
"""Reads flows from a YAML string."""
|
|
267
|
-
flows = YAMLFlowsReader.read_from_string(
|
|
268
|
-
textwrap.dedent(yaml_str), add_line_numbers=False
|
|
269
|
-
)
|
|
270
|
-
flows.validate()
|
|
271
|
-
return flows
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
def flows_from_str_including_defaults(yaml_str: str) -> FlowsList:
|
|
275
|
-
"""Reads flows from a YAML string and combine them with default flows."""
|
|
276
|
-
flows = YAMLFlowsReader.read_from_string(
|
|
277
|
-
textwrap.dedent(yaml_str), add_line_numbers=False
|
|
278
|
-
)
|
|
279
|
-
all_flows = FlowSyncImporter.merge_with_default_flows(flows)
|
|
280
|
-
all_flows.validate()
|
|
281
|
-
return all_flows
|
|
282
|
-
|
|
283
|
-
|
|
284
272
|
def is_flows_file(file_path: Union[Text, Path]) -> bool:
|
|
285
273
|
"""Check if file contains Flow training data.
|
|
286
274
|
|
rasa/shared/core/slots.py
CHANGED
|
@@ -193,6 +193,11 @@ class Slot(ABC):
|
|
|
193
193
|
data.update(self.persistence_info())
|
|
194
194
|
return rasa.shared.utils.io.get_dictionary_fingerprint(data)
|
|
195
195
|
|
|
196
|
+
def __eq__(self, other: Any) -> bool:
|
|
197
|
+
if not isinstance(other, Slot):
|
|
198
|
+
return False
|
|
199
|
+
return self.name == other.name and self.value == other.value
|
|
200
|
+
|
|
196
201
|
|
|
197
202
|
class FloatSlot(Slot):
|
|
198
203
|
"""A slot storing a float value."""
|
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
1
|
import logging
|
|
4
2
|
from abc import ABC, abstractmethod
|
|
5
3
|
from functools import reduce
|
|
6
|
-
from typing import
|
|
4
|
+
from typing import (
|
|
5
|
+
Any,
|
|
6
|
+
Dict,
|
|
7
|
+
List,
|
|
8
|
+
Optional,
|
|
9
|
+
Set,
|
|
10
|
+
Text,
|
|
11
|
+
Tuple,
|
|
12
|
+
Type,
|
|
13
|
+
Union,
|
|
14
|
+
cast,
|
|
15
|
+
)
|
|
7
16
|
|
|
8
17
|
import importlib_resources
|
|
9
18
|
|
|
@@ -25,6 +34,7 @@ from rasa.shared.core.training_data.structures import StoryGraph
|
|
|
25
34
|
from rasa.shared.nlu.constants import ACTION_NAME, ENTITIES
|
|
26
35
|
from rasa.shared.nlu.training_data.message import Message
|
|
27
36
|
from rasa.shared.nlu.training_data.training_data import TrainingData
|
|
37
|
+
from rasa.shared.utils.common import cached_method
|
|
28
38
|
from rasa.shared.utils.yaml import read_config_file
|
|
29
39
|
|
|
30
40
|
logger = logging.getLogger(__name__)
|
|
@@ -115,8 +125,8 @@ class TrainingDataImporter(ABC):
|
|
|
115
125
|
config_path: Text,
|
|
116
126
|
domain_path: Optional[Text] = None,
|
|
117
127
|
training_data_paths: Optional[List[Text]] = None,
|
|
118
|
-
args: Optional[Dict[Text, Any]] =
|
|
119
|
-
) -> TrainingDataImporter:
|
|
128
|
+
args: Optional[Dict[Text, Any]] = None,
|
|
129
|
+
) -> "TrainingDataImporter":
|
|
120
130
|
"""Loads a `TrainingDataImporter` instance from a configuration file."""
|
|
121
131
|
config = read_config_file(config_path)
|
|
122
132
|
return TrainingDataImporter.load_from_dict(
|
|
@@ -128,8 +138,8 @@ class TrainingDataImporter(ABC):
|
|
|
128
138
|
config_path: Text,
|
|
129
139
|
domain_path: Optional[Text] = None,
|
|
130
140
|
training_data_paths: Optional[List[Text]] = None,
|
|
131
|
-
args: Optional[Dict[Text, Any]] =
|
|
132
|
-
) -> TrainingDataImporter:
|
|
141
|
+
args: Optional[Dict[Text, Any]] = None,
|
|
142
|
+
) -> "TrainingDataImporter":
|
|
133
143
|
"""Loads core `TrainingDataImporter` instance.
|
|
134
144
|
|
|
135
145
|
Instance loaded from configuration file will only read Core training data.
|
|
@@ -144,8 +154,8 @@ class TrainingDataImporter(ABC):
|
|
|
144
154
|
config_path: Text,
|
|
145
155
|
domain_path: Optional[Text] = None,
|
|
146
156
|
training_data_paths: Optional[List[Text]] = None,
|
|
147
|
-
args: Optional[Dict[Text, Any]] =
|
|
148
|
-
) -> TrainingDataImporter:
|
|
157
|
+
args: Optional[Dict[Text, Any]] = None,
|
|
158
|
+
) -> "TrainingDataImporter":
|
|
149
159
|
"""Loads nlu `TrainingDataImporter` instance.
|
|
150
160
|
|
|
151
161
|
Instance loaded from configuration file will only read NLU training data.
|
|
@@ -168,7 +178,8 @@ class TrainingDataImporter(ABC):
|
|
|
168
178
|
domain_path: Optional[Text] = None,
|
|
169
179
|
training_data_paths: Optional[List[Text]] = None,
|
|
170
180
|
args: Optional[Dict[Text, Any]] = None,
|
|
171
|
-
|
|
181
|
+
expand_env_vars: bool = True,
|
|
182
|
+
) -> "TrainingDataImporter":
|
|
172
183
|
"""Loads a `TrainingDataImporter` instance from a dictionary."""
|
|
173
184
|
from rasa.shared.importers.rasa import RasaFileImporter
|
|
174
185
|
|
|
@@ -183,7 +194,12 @@ class TrainingDataImporter(ABC):
|
|
|
183
194
|
importers = [importer for importer in importers if importer]
|
|
184
195
|
if not importers:
|
|
185
196
|
importers = [
|
|
186
|
-
RasaFileImporter(
|
|
197
|
+
RasaFileImporter(
|
|
198
|
+
config_path,
|
|
199
|
+
domain_path,
|
|
200
|
+
training_data_paths,
|
|
201
|
+
expand_env_vars=expand_env_vars,
|
|
202
|
+
)
|
|
187
203
|
]
|
|
188
204
|
|
|
189
205
|
return E2EImporter(
|
|
@@ -197,15 +213,18 @@ class TrainingDataImporter(ABC):
|
|
|
197
213
|
domain_path: Optional[Text] = None,
|
|
198
214
|
training_data_paths: Optional[List[Text]] = None,
|
|
199
215
|
args: Optional[Dict[Text, Any]] = None,
|
|
200
|
-
) -> Optional[TrainingDataImporter]:
|
|
216
|
+
) -> Optional["TrainingDataImporter"]:
|
|
201
217
|
from rasa.shared.importers.multi_project import MultiProjectImporter
|
|
202
218
|
from rasa.shared.importers.rasa import RasaFileImporter
|
|
219
|
+
from rasa.shared.importers.remote_importer import RemoteTrainingDataImporter
|
|
203
220
|
|
|
204
221
|
module_path = importer_config.pop("name", None)
|
|
205
222
|
if module_path == RasaFileImporter.__name__:
|
|
206
223
|
importer_class: Type[TrainingDataImporter] = RasaFileImporter
|
|
207
224
|
elif module_path == MultiProjectImporter.__name__:
|
|
208
225
|
importer_class = MultiProjectImporter
|
|
226
|
+
elif module_path == RemoteTrainingDataImporter.__name__:
|
|
227
|
+
importer_class = RemoteTrainingDataImporter
|
|
209
228
|
else:
|
|
210
229
|
try:
|
|
211
230
|
importer_class = rasa.shared.utils.common.class_from_module_path(
|
|
@@ -225,7 +244,8 @@ class TrainingDataImporter(ABC):
|
|
|
225
244
|
**constructor_arguments,
|
|
226
245
|
)
|
|
227
246
|
|
|
228
|
-
|
|
247
|
+
@staticmethod
|
|
248
|
+
def fingerprint() -> Text:
|
|
229
249
|
"""Returns a random fingerprint as data shouldn't be cached."""
|
|
230
250
|
return rasa.shared.utils.io.random_string(25)
|
|
231
251
|
|
|
@@ -281,7 +301,6 @@ class NluDataImporter(TrainingDataImporter):
|
|
|
281
301
|
"""Retrieves NLU training data (see parent class for full docstring)."""
|
|
282
302
|
return self._importer.get_nlu_data(language)
|
|
283
303
|
|
|
284
|
-
@rasa.shared.utils.common.cached_method
|
|
285
304
|
def get_config_file_for_auto_config(self) -> Optional[Text]:
|
|
286
305
|
"""Returns config file path for auto-config only if there is a single one."""
|
|
287
306
|
return self._importer.get_config_file_for_auto_config()
|
|
@@ -297,14 +316,14 @@ class CombinedDataImporter(TrainingDataImporter):
|
|
|
297
316
|
def __init__(self, importers: List[TrainingDataImporter]):
|
|
298
317
|
self._importers = importers
|
|
299
318
|
|
|
300
|
-
@
|
|
319
|
+
@cached_method
|
|
301
320
|
def get_config(self) -> Dict:
|
|
302
321
|
"""Retrieves model config (see parent class for full docstring)."""
|
|
303
322
|
configs = [importer.get_config() for importer in self._importers]
|
|
304
323
|
|
|
305
324
|
return reduce(lambda merged, other: {**merged, **(other or {})}, configs, {})
|
|
306
325
|
|
|
307
|
-
@
|
|
326
|
+
@cached_method
|
|
308
327
|
def get_domain(self) -> Domain:
|
|
309
328
|
"""Retrieves model domain (see parent class for full docstring)."""
|
|
310
329
|
domains = [importer.get_domain() for importer in self._importers]
|
|
@@ -315,7 +334,7 @@ class CombinedDataImporter(TrainingDataImporter):
|
|
|
315
334
|
Domain.empty(),
|
|
316
335
|
)
|
|
317
336
|
|
|
318
|
-
@
|
|
337
|
+
@cached_method
|
|
319
338
|
def get_stories(self, exclusion_percentage: Optional[int] = None) -> StoryGraph:
|
|
320
339
|
"""Retrieves training stories / rules (see parent class for full docstring)."""
|
|
321
340
|
stories = [
|
|
@@ -326,7 +345,7 @@ class CombinedDataImporter(TrainingDataImporter):
|
|
|
326
345
|
lambda merged, other: merged.merge(other), stories, StoryGraph([])
|
|
327
346
|
)
|
|
328
347
|
|
|
329
|
-
@
|
|
348
|
+
@cached_method
|
|
330
349
|
def get_flows(self) -> FlowsList:
|
|
331
350
|
"""Retrieves training stories / rules (see parent class for full docstring)."""
|
|
332
351
|
flow_lists = [importer.get_flows() for importer in self._importers]
|
|
@@ -337,7 +356,7 @@ class CombinedDataImporter(TrainingDataImporter):
|
|
|
337
356
|
FlowsList(underlying_flows=[]),
|
|
338
357
|
)
|
|
339
358
|
|
|
340
|
-
@
|
|
359
|
+
@cached_method
|
|
341
360
|
def get_conversation_tests(self) -> StoryGraph:
|
|
342
361
|
"""Retrieves conversation test stories (see parent class for full docstring)."""
|
|
343
362
|
stories = [importer.get_conversation_tests() for importer in self._importers]
|
|
@@ -346,7 +365,7 @@ class CombinedDataImporter(TrainingDataImporter):
|
|
|
346
365
|
lambda merged, other: merged.merge(other), stories, StoryGraph([])
|
|
347
366
|
)
|
|
348
367
|
|
|
349
|
-
@
|
|
368
|
+
@cached_method
|
|
350
369
|
def get_nlu_data(self, language: Optional[Text] = "en") -> TrainingData:
|
|
351
370
|
"""Retrieves NLU training data (see parent class for full docstring)."""
|
|
352
371
|
nlu_data = [importer.get_nlu_data(language) for importer in self._importers]
|
|
@@ -355,7 +374,7 @@ class CombinedDataImporter(TrainingDataImporter):
|
|
|
355
374
|
lambda merged, other: merged.merge(other), nlu_data, TrainingData()
|
|
356
375
|
)
|
|
357
376
|
|
|
358
|
-
@
|
|
377
|
+
@cached_method
|
|
359
378
|
def get_config_file_for_auto_config(self) -> Optional[Text]:
|
|
360
379
|
"""Returns config file path for auto-config only if there is a single one."""
|
|
361
380
|
if len(self._importers) != 1:
|
|
@@ -414,26 +433,22 @@ class FlowSyncImporter(PassThroughImporter):
|
|
|
414
433
|
"""Loads the default flows from the file system."""
|
|
415
434
|
from rasa.shared.core.flows.yaml_flows_io import YAMLFlowsReader
|
|
416
435
|
|
|
417
|
-
|
|
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)
|
|
436
|
+
flows = YAMLFlowsReader.read_from_file(FlowSyncImporter.default_pattern_path())
|
|
424
437
|
flows.validate()
|
|
425
438
|
return flows
|
|
426
439
|
|
|
427
440
|
@staticmethod
|
|
428
|
-
def
|
|
429
|
-
|
|
430
|
-
default_flows_file = str(
|
|
441
|
+
def default_pattern_path() -> str:
|
|
442
|
+
return str(
|
|
431
443
|
importlib_resources.files("rasa.dialogue_understanding.patterns").joinpath(
|
|
432
444
|
DEFAULT_PATTERN_FLOWS_FILE_NAME
|
|
433
445
|
)
|
|
434
446
|
)
|
|
435
447
|
|
|
436
|
-
|
|
448
|
+
@staticmethod
|
|
449
|
+
def load_default_pattern_flows_domain() -> Domain:
|
|
450
|
+
"""Loads the default flows from the file system."""
|
|
451
|
+
return Domain.from_path(FlowSyncImporter.default_pattern_path())
|
|
437
452
|
|
|
438
453
|
@classmethod
|
|
439
454
|
def merge_with_default_flows(cls, flows: FlowsList) -> FlowsList:
|
|
@@ -459,7 +474,7 @@ class FlowSyncImporter(PassThroughImporter):
|
|
|
459
474
|
|
|
460
475
|
return flows.merge(FlowsList(missing_default_flows))
|
|
461
476
|
|
|
462
|
-
@
|
|
477
|
+
@cached_method
|
|
463
478
|
def get_flows(self) -> FlowsList:
|
|
464
479
|
flows = self._importer.get_flows()
|
|
465
480
|
|
|
@@ -469,11 +484,11 @@ class FlowSyncImporter(PassThroughImporter):
|
|
|
469
484
|
|
|
470
485
|
return self.merge_with_default_flows(flows)
|
|
471
486
|
|
|
472
|
-
@
|
|
487
|
+
@cached_method
|
|
473
488
|
def get_user_flows(self) -> FlowsList:
|
|
474
489
|
return self._importer.get_flows()
|
|
475
490
|
|
|
476
|
-
@
|
|
491
|
+
@cached_method
|
|
477
492
|
def get_domain(self) -> Domain:
|
|
478
493
|
"""Merge existing domain with properties of flows."""
|
|
479
494
|
# load domain data from user defined domain files
|
|
@@ -515,7 +530,7 @@ class ResponsesSyncImporter(PassThroughImporter):
|
|
|
515
530
|
back to the Domain.
|
|
516
531
|
"""
|
|
517
532
|
|
|
518
|
-
@
|
|
533
|
+
@cached_method
|
|
519
534
|
def get_domain(self) -> Domain:
|
|
520
535
|
"""Merge existing domain with properties of retrieval intents in NLU data."""
|
|
521
536
|
existing_domain = self._importer.get_domain()
|
|
@@ -597,7 +612,7 @@ class ResponsesSyncImporter(PassThroughImporter):
|
|
|
597
612
|
}
|
|
598
613
|
)
|
|
599
614
|
|
|
600
|
-
@
|
|
615
|
+
@cached_method
|
|
601
616
|
def get_nlu_data(self, language: Optional[Text] = "en") -> TrainingData:
|
|
602
617
|
"""Updates NLU data with responses for retrieval intents from domain."""
|
|
603
618
|
existing_nlu_data = self._importer.get_nlu_data(language)
|
|
@@ -632,7 +647,7 @@ class E2EImporter(PassThroughImporter):
|
|
|
632
647
|
- adds potential end-to-end bot messages from stories as actions to the domain
|
|
633
648
|
"""
|
|
634
649
|
|
|
635
|
-
@
|
|
650
|
+
@cached_method
|
|
636
651
|
def get_user_flows(self) -> FlowsList:
|
|
637
652
|
if not isinstance(self._importer, FlowSyncImporter):
|
|
638
653
|
raise NotImplementedError(
|
|
@@ -641,9 +656,12 @@ class E2EImporter(PassThroughImporter):
|
|
|
641
656
|
|
|
642
657
|
return self._importer.get_user_flows()
|
|
643
658
|
|
|
644
|
-
@
|
|
659
|
+
@cached_method
|
|
645
660
|
def get_domain(self) -> Domain:
|
|
646
|
-
"""
|
|
661
|
+
"""Merge existing domain with properties of end-to-end actions in stories.
|
|
662
|
+
|
|
663
|
+
Returns: Domain with end-to-end actions added to action names.
|
|
664
|
+
"""
|
|
647
665
|
original = self._importer.get_domain()
|
|
648
666
|
e2e_domain = self._get_domain_with_e2e_actions()
|
|
649
667
|
|
|
@@ -673,7 +691,7 @@ class E2EImporter(PassThroughImporter):
|
|
|
673
691
|
|
|
674
692
|
return Domain.from_dict({KEY_E2E_ACTIONS: list(additional_e2e_action_names)})
|
|
675
693
|
|
|
676
|
-
@
|
|
694
|
+
@cached_method
|
|
677
695
|
def get_nlu_data(self, language: Optional[Text] = "en") -> TrainingData:
|
|
678
696
|
"""Retrieves NLU training data (see parent class for full docstring)."""
|
|
679
697
|
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)
|