rasa-pro 3.13.0.dev3__py3-none-any.whl → 3.13.0.dev5__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 +3 -1
- rasa/cli/inspect.py +8 -4
- rasa/cli/project_templates/default/config.yml +5 -32
- rasa/cli/project_templates/{calm → default}/e2e_tests/cancelations/user_cancels_during_a_correction.yml +1 -1
- rasa/cli/project_templates/{calm → default}/e2e_tests/cancelations/user_changes_mind_on_a_whim.yml +1 -1
- rasa/cli/project_templates/{calm → default}/e2e_tests/corrections/user_corrects_contact_handle.yml +1 -1
- rasa/cli/project_templates/{calm → default}/e2e_tests/corrections/user_corrects_contact_name.yml +1 -1
- rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_adds_contact_to_their_list.yml +1 -1
- rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_lists_contacts.yml +1 -1
- rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_removes_contact.yml +1 -1
- rasa/cli/project_templates/{calm → default}/e2e_tests/happy_paths/user_removes_contact_from_list.yml +1 -1
- rasa/cli/project_templates/default/endpoints.yml +18 -2
- rasa/cli/scaffold.py +3 -4
- rasa/cli/studio/download.py +1 -1
- rasa/cli/studio/upload.py +0 -6
- rasa/core/channels/channel.py +68 -5
- rasa/core/channels/inspector/dist/assets/{arc-c7691751.js → arc-9f75cc3b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-ab99dff7.js → blockDiagram-38ab4fdb-7f34db23.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-08c35a6b.js → c4Diagram-3d4e48cf-948bab2c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/channel-dfa68278.js +1 -0
- rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-9e9c71c9.js → classDiagram-70f12bd4-53b0dd0e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-15e7e2bf.js → classDiagram-v2-f2320105-fdf789e7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/clone-edb7f119.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-9c105cb1.js → createText-2e5e7dd3-87c4ece5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-77e89e48.js → edges-e0da2a9e-5a8b0749.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-7a011646.js → erDiagram-9861fffd-66da90e2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-b6f105ac.js → flowDb-956e92f1-10044f05.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-ce4f18c2.js → flowDiagram-66a62f08-f338f66a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-65e7c670.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-cb5f6da4.js → flowchart-elk-definition-4a651766-b13140aa.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-e4d19e28.js → ganttDiagram-c361ad54-f2b4a55a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-727b1c33.js → gitGraphDiagram-72cf32ee-dedc298d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-6e2ab9a7.js → graph-4ede11ff.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3862675e-84ec700f.js → index-3862675e-65549d37.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-098a1a24.js → index-3a23e736.js} +142 -129
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-78dda442.js → infoDiagram-f8f76790-65439671.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-f1cc6dd1.js → journeyDiagram-49397b02-56d03d98.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-d98dcd0c.js → layout-dd48f7f4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-838e3d82.js → line-1569ad2c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-eae72406.js → linear-48bf4935.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-c96fd84b.js → mindmap-definition-fc14e90a-688504c1.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-c936d4e2.js → pieDiagram-8a3498a8-78b6d7e6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-b338eb8f.js → quadrantDiagram-120e2f19-048b84b3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-c6b6c0d5.js → requirementDiagram-deff3bca-dd67f107.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-b9372e19.js → sankeyDiagram-04a897e0-8128436e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-479e0a3f.js → sequenceDiagram-704730f1-1a0d1461.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-fd26eebc.js → stateDiagram-587899a1-46d388ed.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-3233e0ae.js → stateDiagram-v2-d93cdb3a-ea42951a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-1fdd392b.js → styles-6aaf32cf-7427ed0c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-6d7bfa1b.js → styles-9a916d00-ff5e5a16.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-f86aab11.js → styles-c10674c1-7b3680cf.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-e3e49d7a.js → svgDrawCommon-08f97a94-f860f2ad.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-6fe08b4d.js → timeline-definition-85554ec2-2eebf0c8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-c2e06fd6.js → xychartDiagram-e933f94c-5d7f4e96.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +1 -1
- rasa/core/channels/inspector/src/App.tsx +3 -2
- rasa/core/channels/inspector/src/components/Chat.tsx +23 -2
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +2 -5
- rasa/core/channels/inspector/src/helpers/conversation.ts +16 -0
- rasa/core/channels/inspector/src/types.ts +1 -1
- rasa/core/channels/voice_ready/audiocodes.py +41 -15
- rasa/core/channels/voice_ready/twilio_voice.py +48 -1
- rasa/core/channels/voice_stream/tts/azure.py +11 -2
- rasa/core/channels/voice_stream/twilio_media_streams.py +101 -26
- rasa/core/channels/voice_stream/voice_channel.py +28 -2
- rasa/core/concurrent_lock_store.py +24 -10
- rasa/core/lock_store.py +151 -60
- rasa/dialogue_understanding_test/du_test_case.py +16 -8
- rasa/plugin.py +0 -3
- rasa/shared/constants.py +1 -0
- rasa/shared/core/domain.py +165 -11
- rasa/shared/core/flows/flow.py +155 -131
- rasa/shared/core/flows/flow_step.py +19 -3
- rasa/shared/core/flows/flow_step_links.py +15 -0
- rasa/shared/core/flows/flow_step_sequence.py +6 -0
- rasa/shared/core/flows/nlu_trigger.py +13 -0
- rasa/shared/core/flows/steps/action.py +7 -4
- rasa/shared/core/flows/steps/call.py +11 -4
- rasa/shared/core/flows/steps/collect.py +27 -6
- rasa/shared/core/flows/steps/internal.py +6 -1
- rasa/shared/core/flows/steps/link.py +7 -4
- rasa/shared/core/flows/steps/no_operation.py +7 -4
- rasa/shared/core/flows/steps/set_slots.py +8 -4
- rasa/shared/core/flows/yaml_flows_io.py +106 -5
- rasa/shared/importers/importer.py +8 -0
- rasa/shared/providers/_utils.py +83 -0
- rasa/shared/providers/llm/_base_litellm_client.py +6 -3
- rasa/shared/providers/llm/azure_openai_llm_client.py +6 -68
- rasa/shared/providers/router/_base_litellm_router_client.py +53 -1
- rasa/shared/utils/common.py +42 -0
- rasa/studio/download/domains.py +49 -0
- rasa/studio/download/download.py +439 -0
- rasa/studio/download/flows.py +359 -0
- rasa/studio/results_logger.py +6 -1
- rasa/studio/upload.py +69 -5
- rasa/utils/common.py +36 -0
- rasa/utils/endpoints.py +22 -1
- rasa/utils/licensing.py +1 -1
- rasa/validator.py +1 -2
- rasa/version.py +1 -1
- {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev5.dist-info}/METADATA +8 -8
- {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev5.dist-info}/RECORD +119 -125
- rasa/cli/project_templates/calm/config.yml +0 -10
- rasa/cli/project_templates/calm/credentials.yml +0 -33
- rasa/cli/project_templates/calm/endpoints.yml +0 -58
- rasa/cli/project_templates/default/actions/actions.py +0 -27
- rasa/cli/project_templates/default/data/nlu.yml +0 -91
- rasa/cli/project_templates/default/data/rules.yml +0 -13
- rasa/cli/project_templates/default/data/stories.yml +0 -30
- rasa/cli/project_templates/default/domain.yml +0 -34
- rasa/cli/project_templates/default/tests/test_stories.yml +0 -91
- rasa/core/channels/inspector/dist/assets/channel-11268142.js +0 -1
- rasa/core/channels/inspector/dist/assets/clone-ff7f2ce7.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-cba7ae20.js +0 -1
- rasa/studio/download.py +0 -489
- /rasa/cli/project_templates/{calm → default}/actions/action_template.py +0 -0
- /rasa/cli/project_templates/{calm → default}/actions/add_contact.py +0 -0
- /rasa/cli/project_templates/{calm → default}/actions/db.py +0 -0
- /rasa/cli/project_templates/{calm → default}/actions/list_contacts.py +0 -0
- /rasa/cli/project_templates/{calm → default}/actions/remove_contact.py +0 -0
- /rasa/cli/project_templates/{calm → default}/data/flows/add_contact.yml +0 -0
- /rasa/cli/project_templates/{calm → default}/data/flows/list_contacts.yml +0 -0
- /rasa/cli/project_templates/{calm → default}/data/flows/remove_contact.yml +0 -0
- /rasa/cli/project_templates/{calm → default}/db/contacts.json +0 -0
- /rasa/cli/project_templates/{calm → default}/domain/add_contact.yml +0 -0
- /rasa/cli/project_templates/{calm → default}/domain/list_contacts.yml +0 -0
- /rasa/cli/project_templates/{calm → default}/domain/remove_contact.yml +0 -0
- /rasa/cli/project_templates/{calm → default}/domain/shared.yml +0 -0
- /rasa/{cli/project_templates/calm/actions → studio/download}/__init__.py +0 -0
- {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev5.dist-info}/NOTICE +0 -0
- {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev5.dist-info}/WHEEL +0 -0
- {rasa_pro-3.13.0.dev3.dist-info → rasa_pro-3.13.0.dev5.dist-info}/entry_points.txt +0 -0
rasa/studio/download.py
DELETED
|
@@ -1,489 +0,0 @@
|
|
|
1
|
-
import argparse
|
|
2
|
-
import logging
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from typing import Any, Dict, List, Optional, Set, Tuple
|
|
5
|
-
|
|
6
|
-
import questionary
|
|
7
|
-
import structlog
|
|
8
|
-
|
|
9
|
-
import rasa.cli.utils
|
|
10
|
-
import rasa.shared.utils.cli
|
|
11
|
-
from rasa.shared.constants import (
|
|
12
|
-
DEFAULT_CONFIG_PATH,
|
|
13
|
-
DEFAULT_DATA_PATH,
|
|
14
|
-
DEFAULT_DOMAIN_PATH,
|
|
15
|
-
DEFAULT_ENDPOINTS_PATH,
|
|
16
|
-
)
|
|
17
|
-
from rasa.shared.core.domain import Domain
|
|
18
|
-
from rasa.shared.core.flows.yaml_flows_io import YamlFlowsWriter
|
|
19
|
-
from rasa.shared.importers.importer import TrainingDataImporter
|
|
20
|
-
from rasa.shared.utils.yaml import read_yaml
|
|
21
|
-
from rasa.studio import data_handler
|
|
22
|
-
from rasa.studio.config import StudioConfig
|
|
23
|
-
from rasa.studio.constants import (
|
|
24
|
-
STUDIO_DOMAIN_FILENAME,
|
|
25
|
-
STUDIO_FLOWS_FILENAME,
|
|
26
|
-
STUDIO_NLU_FILENAME,
|
|
27
|
-
)
|
|
28
|
-
from rasa.studio.data_handler import (
|
|
29
|
-
StudioDataHandler,
|
|
30
|
-
import_data_from_studio,
|
|
31
|
-
)
|
|
32
|
-
from rasa.utils.mapper import RasaPrimitiveStorageMapper
|
|
33
|
-
|
|
34
|
-
logger = logging.getLogger(__name__)
|
|
35
|
-
structlogger = structlog.getLogger(__name__)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def _handle_file_overwrite(
|
|
39
|
-
file_path: Optional[str], default_path: str, file_type: str
|
|
40
|
-
) -> Tuple[Optional[Path], bool]:
|
|
41
|
-
"""Handles the logic for determining whether to
|
|
42
|
-
overwrite an existing file or create a new one.
|
|
43
|
-
Works for config and endpoints at this moment
|
|
44
|
-
|
|
45
|
-
Args:
|
|
46
|
-
file_path (Optional[str]): The path to the file
|
|
47
|
-
provided by the user. Can be None.
|
|
48
|
-
default_path (str): The default path to use if `file_path`
|
|
49
|
-
is None or invalid. Must be a file path.
|
|
50
|
-
file_type (str): The type of the file (e.g., "config",
|
|
51
|
-
"endpoints") for logging and messaging purposes.
|
|
52
|
-
|
|
53
|
-
Returns:
|
|
54
|
-
tuple[Optional[Path], bool]: A tuple containing the
|
|
55
|
-
resolved file path and a boolean
|
|
56
|
-
indicating whether to write the file.
|
|
57
|
-
"""
|
|
58
|
-
file_already_exists = rasa.cli.utils.get_validated_path(
|
|
59
|
-
file_path, file_type, default_path, none_is_valid=True
|
|
60
|
-
)
|
|
61
|
-
write_file = False
|
|
62
|
-
path = None
|
|
63
|
-
file_or_default_path = file_path or default_path
|
|
64
|
-
|
|
65
|
-
if file_already_exists is None:
|
|
66
|
-
path = Path(file_or_default_path)
|
|
67
|
-
if path.is_dir():
|
|
68
|
-
path = path / default_path
|
|
69
|
-
return path, True
|
|
70
|
-
|
|
71
|
-
if questionary.confirm(
|
|
72
|
-
f"{file_type.capitalize()} file '{file_or_default_path}' "
|
|
73
|
-
f"already exists. Do you want to overwrite it?"
|
|
74
|
-
).ask():
|
|
75
|
-
write_file = True
|
|
76
|
-
path = Path(file_or_default_path)
|
|
77
|
-
return path, write_file
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def _prepare_data_and_domain_paths(args: argparse.Namespace) -> Tuple[Path, List[Path]]:
|
|
81
|
-
"""Handles the logic for preparing the domain and data paths
|
|
82
|
-
based on the provided arguments.
|
|
83
|
-
|
|
84
|
-
Args:
|
|
85
|
-
args (argparse.Namespace): The parsed arguments.
|
|
86
|
-
|
|
87
|
-
Returns:
|
|
88
|
-
tuple[Path, list[Path]]: A tuple containing the domain path
|
|
89
|
-
and a list of data paths.
|
|
90
|
-
"""
|
|
91
|
-
# prepare domain
|
|
92
|
-
domain_path = rasa.cli.utils.get_validated_path(
|
|
93
|
-
args.domain, "domain", DEFAULT_DOMAIN_PATH, none_is_valid=True
|
|
94
|
-
)
|
|
95
|
-
domain_or_default_path = args.domain or DEFAULT_DOMAIN_PATH
|
|
96
|
-
|
|
97
|
-
if domain_path is None:
|
|
98
|
-
# If the path is None, use the provided domain path
|
|
99
|
-
domain_path = Path(domain_or_default_path)
|
|
100
|
-
domain_path.touch()
|
|
101
|
-
|
|
102
|
-
if isinstance(domain_path, str):
|
|
103
|
-
domain_path = Path(domain_path)
|
|
104
|
-
|
|
105
|
-
if domain_path.is_file():
|
|
106
|
-
if not args.overwrite:
|
|
107
|
-
domain_path.unlink()
|
|
108
|
-
domain_path.touch()
|
|
109
|
-
|
|
110
|
-
if domain_path.is_dir():
|
|
111
|
-
if not args.overwrite:
|
|
112
|
-
domain_path = domain_path / STUDIO_DOMAIN_FILENAME
|
|
113
|
-
domain_path.touch()
|
|
114
|
-
|
|
115
|
-
# prepare data
|
|
116
|
-
data_paths = []
|
|
117
|
-
|
|
118
|
-
for f in args.data:
|
|
119
|
-
data_path = rasa.cli.utils.get_validated_path(
|
|
120
|
-
f, "data", DEFAULT_DATA_PATH, none_is_valid=True
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
if data_path is None:
|
|
124
|
-
# If the path is None, use the default data path
|
|
125
|
-
data_path = Path(f)
|
|
126
|
-
data_path.mkdir(parents=True, exist_ok=True)
|
|
127
|
-
else:
|
|
128
|
-
data_path = Path(data_path)
|
|
129
|
-
|
|
130
|
-
if data_path.is_file() or data_path.is_dir():
|
|
131
|
-
# If it's a file, add it directly
|
|
132
|
-
data_paths.append(data_path)
|
|
133
|
-
else:
|
|
134
|
-
# If it doesn't exist, create the directory
|
|
135
|
-
data_path.mkdir(parents=True, exist_ok=True)
|
|
136
|
-
data_paths.append(data_path)
|
|
137
|
-
|
|
138
|
-
# Remove duplicates while preserving order
|
|
139
|
-
data_paths = list(dict.fromkeys(data_paths))
|
|
140
|
-
|
|
141
|
-
return domain_path, data_paths
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
def handle_download(args: argparse.Namespace) -> None:
|
|
145
|
-
handler = StudioDataHandler(
|
|
146
|
-
studio_config=StudioConfig.read_config(), assistant_name=args.assistant_name[0]
|
|
147
|
-
)
|
|
148
|
-
handler.request_all_data()
|
|
149
|
-
|
|
150
|
-
domain_path, data_paths = _prepare_data_and_domain_paths(args)
|
|
151
|
-
|
|
152
|
-
# handle config and endpoints
|
|
153
|
-
config_path, write_config = _handle_file_overwrite(
|
|
154
|
-
args.config, DEFAULT_CONFIG_PATH, "config"
|
|
155
|
-
)
|
|
156
|
-
endpoints_path, write_endpoints = _handle_file_overwrite(
|
|
157
|
-
args.endpoints, DEFAULT_ENDPOINTS_PATH, "endpoints"
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
# generate log message if we write the config or endpoints
|
|
161
|
-
message_parts = []
|
|
162
|
-
|
|
163
|
-
config_path = config_path if write_config else None
|
|
164
|
-
endpoints_path = endpoints_path if write_endpoints else None
|
|
165
|
-
|
|
166
|
-
if config_path:
|
|
167
|
-
config_data = handler.get_config()
|
|
168
|
-
if not config_data:
|
|
169
|
-
rasa.shared.utils.cli.print_error_and_exit("No config data found.")
|
|
170
|
-
with open(config_path, "w") as f:
|
|
171
|
-
f.write(config_data)
|
|
172
|
-
message_parts.append(f"config to '{config_path}'")
|
|
173
|
-
|
|
174
|
-
if endpoints_path:
|
|
175
|
-
endpoints_data = handler.get_endpoints()
|
|
176
|
-
if not endpoints_data:
|
|
177
|
-
raise ValueError("No endpoints data found.")
|
|
178
|
-
|
|
179
|
-
with open(endpoints_path, "w") as f:
|
|
180
|
-
f.write(endpoints_data)
|
|
181
|
-
message_parts.append(f"endpoints to '{endpoints_path}'")
|
|
182
|
-
|
|
183
|
-
if message_parts:
|
|
184
|
-
message = "Downloaded " + " and ".join(message_parts)
|
|
185
|
-
structlogger.info("studio.download.config_endpoints", event_info=message)
|
|
186
|
-
|
|
187
|
-
if not args.overwrite:
|
|
188
|
-
_handle_download_no_overwrite(
|
|
189
|
-
handler=handler,
|
|
190
|
-
domain_path=domain_path,
|
|
191
|
-
data_paths=data_paths,
|
|
192
|
-
)
|
|
193
|
-
else:
|
|
194
|
-
_handle_download_with_overwrite(
|
|
195
|
-
handler=handler,
|
|
196
|
-
domain_path=domain_path,
|
|
197
|
-
data_paths=data_paths,
|
|
198
|
-
)
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
def _handle_download_no_overwrite(
|
|
202
|
-
handler: StudioDataHandler,
|
|
203
|
-
domain_path: Path,
|
|
204
|
-
data_paths: List[Path],
|
|
205
|
-
) -> None:
|
|
206
|
-
data_from_studio, data_original = import_data_from_studio(
|
|
207
|
-
handler, domain_path, data_paths
|
|
208
|
-
)
|
|
209
|
-
|
|
210
|
-
if domain_path.is_dir():
|
|
211
|
-
studio_domain_path = domain_path / STUDIO_DOMAIN_FILENAME
|
|
212
|
-
new_domain_data = data_handler.combine_domains(
|
|
213
|
-
data_from_studio.get_user_domain().as_dict(),
|
|
214
|
-
data_original.get_user_domain().as_dict(),
|
|
215
|
-
)
|
|
216
|
-
studio_domain = Domain.from_dict(new_domain_data)
|
|
217
|
-
if not studio_domain.is_empty():
|
|
218
|
-
studio_domain.persist(studio_domain_path)
|
|
219
|
-
else:
|
|
220
|
-
logger.warning("No additional domain data found.")
|
|
221
|
-
elif domain_path.is_file():
|
|
222
|
-
domain_merged = data_original.get_user_domain().merge(
|
|
223
|
-
data_from_studio.get_user_domain()
|
|
224
|
-
)
|
|
225
|
-
domain_merged.persist(domain_path)
|
|
226
|
-
|
|
227
|
-
if len(data_paths) == 1 and data_paths[0].is_file():
|
|
228
|
-
data_path = data_paths[0]
|
|
229
|
-
if handler.has_nlu():
|
|
230
|
-
data_nlu = data_original.get_nlu_data().merge(
|
|
231
|
-
data_from_studio.get_nlu_data()
|
|
232
|
-
)
|
|
233
|
-
data_nlu.persist_nlu(data_path)
|
|
234
|
-
if handler.has_flows():
|
|
235
|
-
data_flows = data_original.get_user_flows().merge(
|
|
236
|
-
data_from_studio.get_user_flows()
|
|
237
|
-
)
|
|
238
|
-
YamlFlowsWriter.dump(data_flows.underlying_flows, data_path)
|
|
239
|
-
|
|
240
|
-
elif len(data_paths) == 1 and data_paths[0].is_dir():
|
|
241
|
-
if handler.has_nlu():
|
|
242
|
-
data_path = data_paths[0] / Path(STUDIO_NLU_FILENAME)
|
|
243
|
-
_persist_nlu_diff(data_original, data_from_studio, data_path)
|
|
244
|
-
if handler.has_flows():
|
|
245
|
-
data_path = data_paths[0] / Path(STUDIO_FLOWS_FILENAME)
|
|
246
|
-
_persist_flows_diff(data_original, data_from_studio, data_path)
|
|
247
|
-
else:
|
|
248
|
-
if data_paths[0].is_dir():
|
|
249
|
-
logger.info(f"Saving data to {data_paths[0]}.")
|
|
250
|
-
data_path = data_paths[0] / Path(STUDIO_NLU_FILENAME)
|
|
251
|
-
else:
|
|
252
|
-
logger.info(f"Saving data to {STUDIO_NLU_FILENAME}.")
|
|
253
|
-
data_path = Path(STUDIO_NLU_FILENAME)
|
|
254
|
-
if handler.has_nlu():
|
|
255
|
-
_persist_nlu_diff(data_original, data_from_studio, data_path)
|
|
256
|
-
if handler.has_flows():
|
|
257
|
-
_persist_flows_diff(data_original, data_from_studio, data_path)
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
def _persist_nlu_diff(
|
|
261
|
-
data_original: TrainingDataImporter,
|
|
262
|
-
data_from_studio: TrainingDataImporter,
|
|
263
|
-
data_path: Path,
|
|
264
|
-
) -> None:
|
|
265
|
-
"""Creates a new nlu file from the diff of original and studio data."""
|
|
266
|
-
new_nlu_data = data_handler.create_new_nlu_from_diff(
|
|
267
|
-
read_yaml(data_from_studio.get_nlu_data().nlu_as_yaml()),
|
|
268
|
-
read_yaml(data_original.get_nlu_data().nlu_as_yaml()),
|
|
269
|
-
)
|
|
270
|
-
if new_nlu_data["nlu"]:
|
|
271
|
-
pretty_write_nlu_yaml(new_nlu_data, data_path)
|
|
272
|
-
else:
|
|
273
|
-
logger.warning("No additional nlu data found.")
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
def _persist_flows_diff(
|
|
277
|
-
data_original: TrainingDataImporter,
|
|
278
|
-
data_from_studio: TrainingDataImporter,
|
|
279
|
-
data_path: Path,
|
|
280
|
-
) -> None:
|
|
281
|
-
"""Creates a new flows file from the diff of original and studio data."""
|
|
282
|
-
new_flows_data = data_handler.create_new_flows_from_diff(
|
|
283
|
-
data_from_studio.get_user_flows().underlying_flows,
|
|
284
|
-
data_original.get_user_flows().underlying_flows,
|
|
285
|
-
)
|
|
286
|
-
if new_flows_data:
|
|
287
|
-
YamlFlowsWriter.dump(new_flows_data, data_path)
|
|
288
|
-
else:
|
|
289
|
-
logger.warning("No additional flows data found.")
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
def pretty_write_nlu_yaml(data: Dict, file: Path) -> None:
|
|
293
|
-
"""Writes the nlu yaml in a pretty way.
|
|
294
|
-
|
|
295
|
-
Args:
|
|
296
|
-
data: The data to write.
|
|
297
|
-
file: The file to write to.
|
|
298
|
-
"""
|
|
299
|
-
from ruamel import yaml
|
|
300
|
-
from ruamel.yaml.scalarstring import LiteralScalarString
|
|
301
|
-
|
|
302
|
-
dumper = yaml.YAML()
|
|
303
|
-
for item in data["nlu"]:
|
|
304
|
-
if item.get("examples"):
|
|
305
|
-
item["examples"] = LiteralScalarString(item["examples"])
|
|
306
|
-
|
|
307
|
-
with file.open("w", encoding="utf-8") as outfile:
|
|
308
|
-
dumper.dump(data, outfile)
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
def _handle_download_with_overwrite(
|
|
312
|
-
handler: StudioDataHandler,
|
|
313
|
-
domain_path: Path,
|
|
314
|
-
data_paths: List[Path],
|
|
315
|
-
) -> None:
|
|
316
|
-
data_from_studio, data_original = import_data_from_studio(
|
|
317
|
-
handler, domain_path, data_paths
|
|
318
|
-
)
|
|
319
|
-
mapper = RasaPrimitiveStorageMapper(
|
|
320
|
-
domain_path=domain_path, training_data_paths=data_paths
|
|
321
|
-
)
|
|
322
|
-
|
|
323
|
-
if domain_path.is_file():
|
|
324
|
-
domain_merged = data_from_studio.get_user_domain().merge(
|
|
325
|
-
data_original.get_user_domain()
|
|
326
|
-
)
|
|
327
|
-
domain_merged.persist(domain_path)
|
|
328
|
-
elif domain_path.is_dir():
|
|
329
|
-
default = domain_path / Path(STUDIO_DOMAIN_FILENAME)
|
|
330
|
-
studio_domain = data_from_studio.get_user_domain()
|
|
331
|
-
|
|
332
|
-
paths = get_domain_path(domain_path, data_from_studio, mapper)
|
|
333
|
-
|
|
334
|
-
_persist_domain_part(
|
|
335
|
-
{"intents": studio_domain.as_dict().get("intents", [])},
|
|
336
|
-
default,
|
|
337
|
-
paths["intent_path"],
|
|
338
|
-
)
|
|
339
|
-
_persist_domain_part(
|
|
340
|
-
{"entities": studio_domain.as_dict().get("entities", [])},
|
|
341
|
-
default,
|
|
342
|
-
paths["entities_path"],
|
|
343
|
-
)
|
|
344
|
-
_persist_domain_part(
|
|
345
|
-
{"actions": studio_domain.as_dict().get("actions", [])},
|
|
346
|
-
default,
|
|
347
|
-
paths["action_path"],
|
|
348
|
-
)
|
|
349
|
-
_persist_domain_part(
|
|
350
|
-
{"slots": studio_domain.as_dict().get("slots", {})},
|
|
351
|
-
default,
|
|
352
|
-
paths["slot_path"],
|
|
353
|
-
)
|
|
354
|
-
_persist_domain_part(
|
|
355
|
-
{"responses": studio_domain.as_dict().get("responses", {})},
|
|
356
|
-
default,
|
|
357
|
-
paths["response_path"],
|
|
358
|
-
)
|
|
359
|
-
|
|
360
|
-
if len(data_paths) == 1 and data_paths[0].is_file():
|
|
361
|
-
if handler.has_nlu():
|
|
362
|
-
nlu_data_merged = data_from_studio.get_nlu_data().merge(
|
|
363
|
-
data_original.get_nlu_data()
|
|
364
|
-
)
|
|
365
|
-
nlu_data_merged.persist_nlu(data_paths[0])
|
|
366
|
-
if handler.has_flows():
|
|
367
|
-
flows_data_merged = data_from_studio.get_user_flows().merge(
|
|
368
|
-
data_original.get_user_flows()
|
|
369
|
-
)
|
|
370
|
-
YamlFlowsWriter.dump(flows_data_merged.underlying_flows, data_paths[0])
|
|
371
|
-
elif len(data_paths) == 1 and data_paths[0].is_dir():
|
|
372
|
-
data_path = data_paths[0]
|
|
373
|
-
paths = get_training_path(data_path, data_original, mapper)
|
|
374
|
-
if handler.has_nlu():
|
|
375
|
-
nlu_data = data_from_studio.get_nlu_data()
|
|
376
|
-
if paths["nlu_path"].exists():
|
|
377
|
-
nlu_file = TrainingDataImporter.load_from_dict(
|
|
378
|
-
training_data_paths=[str(paths["nlu_path"])]
|
|
379
|
-
)
|
|
380
|
-
nlu_data = nlu_data.merge(nlu_file.get_nlu_data())
|
|
381
|
-
pretty_write_nlu_yaml(read_yaml(nlu_data.nlu_as_yaml()), paths["nlu_path"])
|
|
382
|
-
if handler.has_flows():
|
|
383
|
-
flows_data = data_from_studio.get_user_flows()
|
|
384
|
-
if paths["flow_path"].exists():
|
|
385
|
-
flows_file = TrainingDataImporter.load_from_dict(
|
|
386
|
-
training_data_paths=[str(paths["flow_path"])]
|
|
387
|
-
)
|
|
388
|
-
flows_data = flows_data.merge(flows_file.get_user_flows())
|
|
389
|
-
YamlFlowsWriter.dump(flows_data.underlying_flows, paths["flow_path"])
|
|
390
|
-
else:
|
|
391
|
-
# TODO: we are not handling the case of multiple data paths?
|
|
392
|
-
raise NotImplementedError("Multiple data paths are not supported yet.")
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
def _persist_domain_part(
|
|
396
|
-
domain_part: Dict[str, Any], default: Path, path: Optional[Path]
|
|
397
|
-
) -> None:
|
|
398
|
-
domain = Domain.from_dict(domain_part)
|
|
399
|
-
if (path is not None) and path.exists():
|
|
400
|
-
domain = Domain.from_file(path).merge(domain, override=True)
|
|
401
|
-
domain.persist(path)
|
|
402
|
-
else:
|
|
403
|
-
domain.persist(default)
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
def get_training_path(
|
|
407
|
-
path: Path,
|
|
408
|
-
data_original: TrainingDataImporter,
|
|
409
|
-
mapper: RasaPrimitiveStorageMapper,
|
|
410
|
-
) -> Dict[str, Path]:
|
|
411
|
-
nlu_paths = set()
|
|
412
|
-
flow_paths = set()
|
|
413
|
-
for intent in data_original.get_nlu_data().intents:
|
|
414
|
-
for path in mapper.get_file(intent, "intents").get("training", []):
|
|
415
|
-
nlu_paths.add(path)
|
|
416
|
-
flows = [flow.id for flow in data_original.get_user_flows().underlying_flows]
|
|
417
|
-
for flow in flows:
|
|
418
|
-
for path in mapper.get_file(flow, "flows").get("training", []):
|
|
419
|
-
flow_paths.add(path)
|
|
420
|
-
|
|
421
|
-
return {
|
|
422
|
-
"nlu_path": _select_path(nlu_paths, "nlu", path, STUDIO_NLU_FILENAME),
|
|
423
|
-
"flow_path": _select_path(flow_paths, "flows", path, STUDIO_FLOWS_FILENAME),
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
def get_domain_path(
|
|
428
|
-
domain_path: Path,
|
|
429
|
-
data_from_studio: TrainingDataImporter,
|
|
430
|
-
mapper: RasaPrimitiveStorageMapper,
|
|
431
|
-
) -> Dict[str, Path]:
|
|
432
|
-
intent_paths = set()
|
|
433
|
-
entities_paths = set()
|
|
434
|
-
slot_paths = set()
|
|
435
|
-
action_paths = set()
|
|
436
|
-
response_paths = set()
|
|
437
|
-
# nlu-based
|
|
438
|
-
for intent in data_from_studio.get_domain().intents:
|
|
439
|
-
for path in mapper.get_file(intent, "intents").get("domain", []):
|
|
440
|
-
intent_paths.add(path)
|
|
441
|
-
for entity in data_from_studio.get_domain().entities:
|
|
442
|
-
for path in mapper.get_file(entity, "entities").get("domain", []):
|
|
443
|
-
entities_paths.add(path)
|
|
444
|
-
# flow-based
|
|
445
|
-
slot_list = [slot.name for slot in data_from_studio.get_domain().slots]
|
|
446
|
-
for slot in slot_list:
|
|
447
|
-
for path in mapper.get_file(slot, "slots").get("domain", []):
|
|
448
|
-
slot_paths.add(path)
|
|
449
|
-
for action in data_from_studio.get_domain().action_names_or_texts:
|
|
450
|
-
for path in mapper.get_file(action, "actions").get("domain", []):
|
|
451
|
-
action_paths.add(path)
|
|
452
|
-
for response in data_from_studio.get_domain().responses:
|
|
453
|
-
for path in mapper.get_file(response, "responses").get("domain", []):
|
|
454
|
-
response_paths.add(path)
|
|
455
|
-
|
|
456
|
-
return {
|
|
457
|
-
"intent_path": _select_path(
|
|
458
|
-
intent_paths, "intents", domain_path, STUDIO_DOMAIN_FILENAME
|
|
459
|
-
),
|
|
460
|
-
"entities_path": _select_path(
|
|
461
|
-
entities_paths, "entities", domain_path, STUDIO_DOMAIN_FILENAME
|
|
462
|
-
),
|
|
463
|
-
"slot_path": _select_path(
|
|
464
|
-
slot_paths, "slots", domain_path, STUDIO_DOMAIN_FILENAME
|
|
465
|
-
),
|
|
466
|
-
"action_path": _select_path(
|
|
467
|
-
action_paths, "actions", domain_path, STUDIO_DOMAIN_FILENAME
|
|
468
|
-
),
|
|
469
|
-
"response_path": _select_path(
|
|
470
|
-
response_paths, "responses", domain_path, STUDIO_DOMAIN_FILENAME
|
|
471
|
-
),
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
def _select_path(
|
|
476
|
-
paths: Set[Path], primitive_type: str, default_path: Path, default: str
|
|
477
|
-
) -> Path:
|
|
478
|
-
if len(paths) == 1:
|
|
479
|
-
path = paths.pop()
|
|
480
|
-
elif len(paths) > 1:
|
|
481
|
-
path = paths.pop()
|
|
482
|
-
logger.warning(
|
|
483
|
-
f"Saving {primitive_type} to {path}."
|
|
484
|
-
f"Please keep Studio related {primitive_type} in a single file."
|
|
485
|
-
)
|
|
486
|
-
else: # no path in paths
|
|
487
|
-
path = default_path / Path(default)
|
|
488
|
-
logger.info(f"Saving {primitive_type} to {path}.")
|
|
489
|
-
return path
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|