rasa-pro 3.13.0rc1__py3-none-any.whl → 3.13.0rc2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of rasa-pro might be problematic. Click here for more details.

Files changed (41) hide show
  1. rasa/cli/studio/link.py +0 -16
  2. rasa/cli/studio/train.py +1 -4
  3. rasa/cli/studio/upload.py +1 -1
  4. rasa/core/agent.py +6 -0
  5. rasa/core/channels/__init__.py +1 -0
  6. rasa/core/channels/voice_ready/jambonz.py +5 -6
  7. rasa/core/channels/voice_ready/twilio_voice.py +13 -12
  8. rasa/core/channels/voice_ready/utils.py +22 -0
  9. rasa/core/channels/voice_stream/audiocodes.py +4 -10
  10. rasa/core/channels/voice_stream/genesys.py +35 -16
  11. rasa/core/channels/voice_stream/jambonz.py +69 -3
  12. rasa/core/channels/voice_stream/twilio_media_streams.py +5 -7
  13. rasa/core/channels/voice_stream/voice_channel.py +39 -10
  14. rasa/core/policies/enterprise_search_policy.py +38 -2
  15. rasa/core/processor.py +6 -0
  16. rasa/dialogue_understanding/coexistence/llm_based_router.py +11 -0
  17. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +3 -2
  18. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +9 -0
  19. rasa/dialogue_understanding/processor/command_processor.py +3 -3
  20. rasa/e2e_test/constants.py +1 -1
  21. rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +1 -1
  22. rasa/model_manager/runner_service.py +20 -4
  23. rasa/model_manager/trainer_service.py +6 -0
  24. rasa/privacy/privacy_manager.py +26 -11
  25. rasa/shared/constants.py +2 -0
  26. rasa/shared/utils/llm.py +86 -2
  27. rasa/studio/data_handler.py +27 -13
  28. rasa/studio/download.py +5 -1
  29. rasa/studio/link.py +12 -1
  30. rasa/studio/prompts.py +5 -7
  31. rasa/studio/pull/pull.py +6 -2
  32. rasa/studio/push.py +2 -0
  33. rasa/studio/upload.py +61 -5
  34. rasa/studio/utils.py +33 -0
  35. rasa/tracing/instrumentation/attribute_extractors.py +1 -1
  36. rasa/version.py +1 -1
  37. {rasa_pro-3.13.0rc1.dist-info → rasa_pro-3.13.0rc2.dist-info}/METADATA +1 -1
  38. {rasa_pro-3.13.0rc1.dist-info → rasa_pro-3.13.0rc2.dist-info}/RECORD +41 -40
  39. {rasa_pro-3.13.0rc1.dist-info → rasa_pro-3.13.0rc2.dist-info}/NOTICE +0 -0
  40. {rasa_pro-3.13.0rc1.dist-info → rasa_pro-3.13.0rc2.dist-info}/WHEEL +0 -0
  41. {rasa_pro-3.13.0rc1.dist-info → rasa_pro-3.13.0rc2.dist-info}/entry_points.txt +0 -0
@@ -16,6 +16,7 @@ from rasa.shared.constants import (
16
16
  PROMPT_CONFIG_KEY,
17
17
  PROMPT_TEMPLATE_CONFIG_KEY,
18
18
  )
19
+ from rasa.shared.utils.io import raise_deprecation_warning
19
20
  from rasa.shared.utils.llm import (
20
21
  check_prompt_config_keys_and_warn_if_deprecated,
21
22
  get_prompt_template,
@@ -47,6 +48,14 @@ class SingleStepLLMCommandGenerator(SingleStepBasedLLMCommandGenerator):
47
48
  prompt_template: Optional[Text] = None,
48
49
  **kwargs: Any,
49
50
  ) -> None:
51
+ raise_deprecation_warning(
52
+ message=(
53
+ "Support for `SingleStepLLMCommandGenerator` will be removed in Rasa "
54
+ "`4.0.0`. Please modify your assistant's configuration to use the "
55
+ "`CompactLLMCommandGenerator` or `SearchReadyLLMCommandGenerator` "
56
+ "instead."
57
+ )
58
+ )
50
59
  super().__init__(
51
60
  config,
52
61
  model_storage,
@@ -639,9 +639,9 @@ def clean_up_slot_command(
639
639
  resulting_commands.append(command)
640
640
  return resulting_commands
641
641
 
642
- if (slot := tracker.slots.get(command.name)) is not None and slot.value == str(
643
- command.value
644
- ):
642
+ if (slot := tracker.slots.get(command.name)) is not None and str(
643
+ slot.value
644
+ ) == str(command.value):
645
645
  # the slot is already set, we don't need to set it again
646
646
  structlogger.debug(
647
647
  "command_processor.clean_up_slot_command.skip_command_slot_already_set",
@@ -40,7 +40,7 @@ DEFAULT_GROUNDEDNESS_PROMPT_TEMPLATE_FILE_NAME = "groundedness_prompt_template.j
40
40
  DEFAULT_ANSWER_RELEVANCE_PROMPT_TEMPLATE_FILE_NAME = (
41
41
  "answer_relevance_prompt_template.jinja2"
42
42
  )
43
- DEFAULT_E2E_TESTING_MODEL = "gpt-4o-mini"
43
+ DEFAULT_E2E_TESTING_MODEL = "gpt-4.1-mini-2025-04-14"
44
44
  KEY_SCORE = "score"
45
45
  KEY_JUSTIFICATION = "justification"
46
46
  KEY_EXTRA_PARAMETERS = "extra_parameters"
@@ -35,7 +35,7 @@ DEFAULT_REPHRASING_PROMPT_TEMPLATE = importlib.resources.read_text(
35
35
 
36
36
  DEFAULT_LLM_CONFIG = {
37
37
  PROVIDER_CONFIG_KEY: OPENAI_PROVIDER,
38
- MODEL_CONFIG_KEY: "gpt-4o-mini",
38
+ MODEL_CONFIG_KEY: "gpt-4.1-mini-2025-04-14",
39
39
  TIMEOUT_CONFIG_KEY: 7,
40
40
  TEMPERATURE_CONFIG_KEY: 0.0,
41
41
  MAX_COMPLETION_TOKENS_CONFIG_KEY: 4096,
@@ -2,7 +2,8 @@ import os
2
2
  import shutil
3
3
  import subprocess
4
4
  from enum import Enum
5
- from typing import Dict, Optional
5
+ from pathlib import Path
6
+ from typing import Dict, Optional, Union
6
7
 
7
8
  import aiohttp
8
9
  import structlog
@@ -18,6 +19,7 @@ from rasa.model_manager.utils import (
18
19
  write_encoded_data_to_file,
19
20
  )
20
21
  from rasa.model_manager.warm_rasa_process import start_rasa_process
22
+ from rasa.studio.prompts import handle_prompts
21
23
 
22
24
  structlogger = structlog.get_logger()
23
25
 
@@ -121,11 +123,25 @@ def get_open_port() -> int:
121
123
 
122
124
 
123
125
  def write_encoded_config_data_to_files(
124
- encoded_configs: Dict[str, bytes], base_path: str
126
+ encoded_configs: Dict[str, Union[bytes, Dict[str, str]]], base_path: str
125
127
  ) -> None:
126
128
  """Write the encoded config data to files."""
127
- for key, value in encoded_configs.items():
128
- write_encoded_data_to_file(value, subpath(base_path, f"{key}.yml"))
129
+ endpoints_encoded = encoded_configs.get("endpoints")
130
+ if endpoints_encoded:
131
+ write_encoded_data_to_file(
132
+ endpoints_encoded, subpath(base_path, "endpoints.yml")
133
+ )
134
+ config_encoded = encoded_configs.get("config")
135
+ if config_encoded:
136
+ write_encoded_data_to_file(config_encoded, subpath(base_path, "config.yml"))
137
+ credentials_encoded = encoded_configs.get("credentials")
138
+ if credentials_encoded:
139
+ write_encoded_data_to_file(
140
+ credentials_encoded, subpath(base_path, "credentials.yml")
141
+ )
142
+
143
+ if prompts := encoded_configs.get("prompts"):
144
+ handle_prompts(prompts, Path(base_path))
129
145
 
130
146
 
131
147
  def prepare_bot_directory(
@@ -2,6 +2,7 @@ import os
2
2
  import shutil
3
3
  import subprocess
4
4
  from enum import Enum
5
+ from pathlib import Path
5
6
  from typing import Any, Dict, Optional
6
7
 
7
8
  import structlog
@@ -20,6 +21,7 @@ from rasa.model_manager.warm_rasa_process import (
20
21
  start_rasa_process,
21
22
  )
22
23
  from rasa.model_training import generate_random_model_name
24
+ from rasa.studio.prompts import handle_prompts
23
25
 
24
26
  structlogger = structlog.get_logger()
25
27
 
@@ -208,6 +210,7 @@ def write_training_data_to_files(
208
210
  "stories": "base64 encoded stories.yml",
209
211
  "rules": "base64 encoded rules.yml",
210
212
  "nlu": "base64 encoded nlu.yml"
213
+ "prompts": "dictionary with the prompts",
211
214
  }
212
215
  ```
213
216
  """
@@ -230,6 +233,9 @@ def write_training_data_to_files(
230
233
  subpath(training_base_path + "/" + parent_path, file_name),
231
234
  )
232
235
 
236
+ if prompts := encoded_training_data.get("prompts"):
237
+ handle_prompts(prompts, Path(training_base_path))
238
+
233
239
 
234
240
  def prepare_training_directory(
235
241
  training_base_path: str, assistant_id: str, encoded_training_data: Dict[str, Any]
@@ -12,7 +12,7 @@ import structlog
12
12
  from apscheduler.schedulers.background import BackgroundScheduler
13
13
 
14
14
  import rasa.shared.core.trackers
15
- from rasa.core.tracker_stores.tracker_store import TrackerStore
15
+ from rasa.core.tracker_stores.tracker_store import FailSafeTrackerStore, TrackerStore
16
16
  from rasa.privacy.constants import (
17
17
  TEXT_KEY,
18
18
  USER_CHAT_INACTIVITY_IN_MINUTES_ENV_VAR_NAME,
@@ -63,6 +63,7 @@ class BackgroundPrivacyManager:
63
63
  self,
64
64
  endpoints: Optional["AvailableEndpoints"],
65
65
  event_loop: Optional["AbstractEventLoop"] = None,
66
+ in_memory_tracker_store: Optional[TrackerStore] = None,
66
67
  ):
67
68
  self.config = (
68
69
  PrivacyConfig.from_dict(endpoints.privacy)
@@ -76,15 +77,28 @@ class BackgroundPrivacyManager:
76
77
  os.getenv(USER_CHAT_INACTIVITY_IN_MINUTES_ENV_VAR_NAME, 30)
77
78
  )
78
79
 
79
- # we recreate the tracker store here to ensure
80
- # that this instance has no event brokers
81
- # that could publish events during the tracker store
82
- # background jobs
83
- self.tracker_store = (
84
- TrackerStore.create(endpoints.tracker_store)
85
- if endpoints
86
- else TrackerStore.create(None)
87
- )
80
+ if in_memory_tracker_store is not None:
81
+ # if an in-memory tracker store is provided,
82
+ # we need to keep the reference to it
83
+ # so that the background jobs can access it.
84
+ # We also set the event broker to None
85
+ # to prevent it from publishing events
86
+ # during the tracker store background jobs
87
+ in_memory_tracker_store.event_broker = None
88
+ tracker_store = in_memory_tracker_store
89
+ else:
90
+ # we recreate the tracker store here to ensure
91
+ # that this instance has no event brokers
92
+ # that could publish events during the tracker store
93
+ # background jobs
94
+ tracker_store = (
95
+ TrackerStore.create(endpoints.tracker_store)
96
+ if endpoints
97
+ else TrackerStore.create(None)
98
+ )
99
+
100
+ self.tracker_store = FailSafeTrackerStore(tracker_store)
101
+
88
102
  self.event_brokers: List["EventBroker"] = []
89
103
  self.event_loop = event_loop
90
104
 
@@ -124,9 +138,10 @@ class BackgroundPrivacyManager:
124
138
  cls,
125
139
  endpoints: Optional["AvailableEndpoints"],
126
140
  event_loop: Optional["AbstractEventLoop"] = None,
141
+ in_memory_tracker_store: Optional[TrackerStore] = None,
127
142
  ) -> BackgroundPrivacyManager:
128
143
  """Create an instance of BackgroundPrivacyManager."""
129
- instance = cls(endpoints, event_loop)
144
+ instance = cls(endpoints, event_loop, in_memory_tracker_store)
130
145
  return await instance.initialize(endpoints)
131
146
 
132
147
  def stop(self) -> None:
rasa/shared/constants.py CHANGED
@@ -104,6 +104,8 @@ UTTER_FREE_CHITCHAT_RESPONSE = "utter_free_chitchat_response"
104
104
  ASSISTANT_ID_KEY = "assistant_id"
105
105
  ASSISTANT_ID_DEFAULT_VALUE = "placeholder_default"
106
106
 
107
+ ENDPOINTS_NLG_KEY = "nlg"
108
+
107
109
  CONFIG_MANDATORY_COMMON_KEYS = [ASSISTANT_ID_KEY]
108
110
  CONFIG_NAME_KEY = "name"
109
111
  CONFIG_POLICIES_KEY = "policies"
rasa/shared/utils/llm.py CHANGED
@@ -6,6 +6,7 @@ import logging
6
6
  from copy import deepcopy
7
7
  from datetime import datetime
8
8
  from functools import wraps
9
+ from pathlib import Path
9
10
  from typing import (
10
11
  TYPE_CHECKING,
11
12
  Any,
@@ -24,6 +25,9 @@ from typing import (
24
25
  import structlog
25
26
  from pydantic import BaseModel, Field
26
27
 
28
+ import rasa.cli.telemetry
29
+ import rasa.cli.utils
30
+ import rasa.shared.utils.cli
27
31
  import rasa.shared.utils.io
28
32
  from rasa.core.available_endpoints import AvailableEndpoints
29
33
  from rasa.shared.constants import (
@@ -31,6 +35,7 @@ from rasa.shared.constants import (
31
35
  CONFIG_PIPELINE_KEY,
32
36
  CONFIG_POLICIES_KEY,
33
37
  DEFAULT_PROMPT_PACKAGE_NAME,
38
+ ENDPOINTS_NLG_KEY,
34
39
  LLM_CONFIG_KEY,
35
40
  MODEL_CONFIG_KEY,
36
41
  MODEL_GROUP_CONFIG_KEY,
@@ -578,7 +583,7 @@ def embedder_factory(
578
583
  ```
579
584
  {
580
585
  "provider": "openai",
581
- "model": "text-embedding-3-small",
586
+ "model": "text-embedding-3-large",
582
587
  "timeout": 10,
583
588
  "num_retries": 3,
584
589
  }
@@ -591,7 +596,7 @@ def embedder_factory(
591
596
  "models": [
592
597
  {
593
598
  "provider": "openai",
594
- "model": "test-embedding-3-small",
599
+ "model": "test-embedding-3-large",
595
600
  "api_key": "test"
596
601
  },
597
602
  ],
@@ -1072,3 +1077,82 @@ def get_system_default_prompts(
1072
1077
  enterprise_search=_get_enterprise_search_prompt(config),
1073
1078
  contextual_response_rephraser=DEFAULT_RESPONSE_VARIATION_PROMPT_TEMPLATE,
1074
1079
  )
1080
+
1081
+
1082
+ def collect_custom_prompts(
1083
+ config: Dict[Text, Any],
1084
+ endpoints: Dict[Text, Any],
1085
+ project_root: Optional[Path] = None,
1086
+ ) -> Dict[Text, Text]:
1087
+ """Collects custom prompts from the project configuration and endpoints.
1088
+
1089
+ Args:
1090
+ config: The configuration dictionary of the project.
1091
+ endpoints: The endpoints configuration dictionary.
1092
+ project_root: The root directory of the project.
1093
+
1094
+ Returns:
1095
+ A dictionary containing custom prompts.
1096
+ The keys are:
1097
+ - 'contextual_response_rephraser'
1098
+ - 'command_generator'
1099
+ - 'enterprise_search'
1100
+ """
1101
+ from rasa.core.policies.enterprise_search_policy import EnterpriseSearchPolicy
1102
+ from rasa.dialogue_understanding.generator.llm_based_command_generator import (
1103
+ LLMBasedCommandGenerator,
1104
+ )
1105
+ from rasa.studio.prompts import (
1106
+ COMMAND_GENERATOR_NAME,
1107
+ CONTEXTUAL_RESPONSE_REPHRASER_NAME,
1108
+ ENTERPRISE_SEARCH_NAME,
1109
+ )
1110
+
1111
+ prompts: Dict[Text, Text] = {}
1112
+ project_root = project_root or Path(".").resolve()
1113
+
1114
+ def _read_prompt(root: Path, path_in_yaml: Text) -> Optional[Text]:
1115
+ if not path_in_yaml:
1116
+ return None
1117
+
1118
+ prompt_path = (
1119
+ (root / path_in_yaml).resolve()
1120
+ if not Path(path_in_yaml).is_absolute()
1121
+ else Path(path_in_yaml)
1122
+ )
1123
+ if prompt_path.exists():
1124
+ return prompt_path.read_text(encoding="utf-8")
1125
+
1126
+ structlogger.warning(
1127
+ "utils.llm.collect_custom_prompts.prompt_not_found",
1128
+ event_info=(f"Prompt file '{prompt_path}' not found. "),
1129
+ prompt_path=prompt_path,
1130
+ project_root=root,
1131
+ )
1132
+ return None
1133
+
1134
+ # contextual_response_rephraser
1135
+ nlg_conf = endpoints.get(ENDPOINTS_NLG_KEY) or {}
1136
+ if prompt_text := _read_prompt(project_root, nlg_conf.get(PROMPT_CONFIG_KEY)):
1137
+ prompts[CONTEXTUAL_RESPONSE_REPHRASER_NAME] = prompt_text
1138
+
1139
+ # command_generator
1140
+ command_generator_classes = {
1141
+ cls.__name__ for cls in all_subclasses(LLMBasedCommandGenerator)
1142
+ }
1143
+ for component in config.get(CONFIG_PIPELINE_KEY, []):
1144
+ if component.get(CONFIG_NAME_KEY) in command_generator_classes:
1145
+ if prompt_text := _read_prompt(
1146
+ project_root, component.get(PROMPT_TEMPLATE_CONFIG_KEY)
1147
+ ):
1148
+ prompts[COMMAND_GENERATOR_NAME] = prompt_text
1149
+ break
1150
+
1151
+ # enterprise_search
1152
+ for policy in config.get(CONFIG_POLICIES_KEY, []):
1153
+ if policy.get(CONFIG_NAME_KEY) == EnterpriseSearchPolicy.__name__:
1154
+ if prompt_text := _read_prompt(project_root, policy.get(PROMPT_CONFIG_KEY)):
1155
+ prompts[ENTERPRISE_SEARCH_NAME] = prompt_text
1156
+ break
1157
+
1158
+ return prompts
@@ -1,5 +1,4 @@
1
1
  import base64
2
- import json
3
2
  import logging
4
3
  from pathlib import Path
5
4
  from typing import Any, Dict, List, Optional, Tuple
@@ -46,15 +45,33 @@ class StudioDataHandler:
46
45
  intent_names: Optional[List[str]] = None,
47
46
  entity_names: Optional[List[str]] = None,
48
47
  ) -> dict:
48
+ from rasa.studio.prompts import (
49
+ COMMAND_GENERATOR_NAME,
50
+ CONTEXTUAL_RESPONSE_REPHRASER_NAME,
51
+ ENTERPRISE_SEARCH_NAME,
52
+ )
53
+
49
54
  request = {
50
- "query": (
51
- "query ExportAsEncodedYaml($input: ExportAsEncodedYamlInput!) "
52
- "{ exportAsEncodedYaml(input: $input) "
53
- "{ ... on ExportModernAsEncodedYamlOutput "
54
- "{ nlu flows domain endpoints config prompts } "
55
- "... on ExportClassicAsEncodedYamlOutput "
56
- "{ nlu domain }}}"
57
- ),
55
+ "query": "query ExportAsEncodedYaml($input: ExportAsEncodedYamlInput!) {\n"
56
+ " exportAsEncodedYaml(input: $input) {\n"
57
+ " ... on ExportModernAsEncodedYamlOutput {\n"
58
+ " nlu\n"
59
+ " flows\n"
60
+ " domain\n"
61
+ " endpoints\n"
62
+ " config\n"
63
+ " prompts {\n"
64
+ f" {COMMAND_GENERATOR_NAME}\n"
65
+ f" {CONTEXTUAL_RESPONSE_REPHRASER_NAME}\n"
66
+ f" {ENTERPRISE_SEARCH_NAME}\n"
67
+ " }\n"
68
+ " }\n"
69
+ " ... on ExportClassicAsEncodedYamlOutput {\n"
70
+ " nlu\n"
71
+ " domain\n"
72
+ " }\n"
73
+ " }\n"
74
+ "}\n",
58
75
  "variables": {"input": {"assistantName": self.assistant_name}},
59
76
  }
60
77
  if intent_names or entity_names:
@@ -98,7 +115,6 @@ class StudioDataHandler:
98
115
  },
99
116
  verify=verify,
100
117
  )
101
-
102
118
  if res.status_code != 200:
103
119
  raise RasaException(
104
120
  f"Download from Studio with URL: "
@@ -203,9 +219,7 @@ class StudioDataHandler:
203
219
  self.flows = self._decode_response(return_data.get("flows"))
204
220
  self.config = self._decode_response(return_data.get("config"))
205
221
  self.endpoints = self._decode_response(return_data.get("endpoints"))
206
-
207
- prompts_string = self._decode_response(return_data.get("prompts"))
208
- self.prompts = json.loads(prompts_string) if prompts_string else None
222
+ self.prompts = return_data.get("prompts")
209
223
 
210
224
  if not self.has_nlu() and not self.has_flows():
211
225
  raise RasaException("No nlu or flows data in Studio response.")
rasa/studio/download.py CHANGED
@@ -25,6 +25,7 @@ from rasa.studio.constants import DOMAIN_FILENAME
25
25
  from rasa.studio.data_handler import StudioDataHandler
26
26
  from rasa.studio.prompts import handle_prompts
27
27
  from rasa.studio.pull.data import _dump_flows_as_separate_files
28
+ from rasa.studio.utils import validate_argument_paths
28
29
 
29
30
  structlogger = structlog.get_logger()
30
31
 
@@ -35,6 +36,7 @@ def handle_download(args: argparse.Namespace) -> None:
35
36
  Args:
36
37
  args: The command line arguments.
37
38
  """
39
+ validate_argument_paths(args)
38
40
  assistant_name = args.assistant_name
39
41
  target_root = _prepare_target_directory(assistant_name)
40
42
 
@@ -47,7 +49,9 @@ def handle_download(args: argparse.Namespace) -> None:
47
49
  _handle_endpoints(handler, target_root)
48
50
  _handle_domain(handler, target_root)
49
51
  _handle_data(handler, target_root)
50
- handle_prompts(handler, target_root)
52
+
53
+ if prompts := handler.get_prompts():
54
+ handle_prompts(prompts, target_root)
51
55
 
52
56
  structlogger.info(
53
57
  "studio.download.success",
rasa/studio/link.py CHANGED
@@ -179,8 +179,19 @@ def handle_link(args: argparse.Namespace) -> None:
179
179
  link_file = _link_file(project_root)
180
180
 
181
181
  if link_file.exists():
182
+ linked_assistant_name = read_assistant_name(project_root)
183
+ if linked_assistant_name == assistant_name:
184
+ rasa.shared.utils.cli.print_info(
185
+ f"Project is already linked to assistant '{assistant_name}'."
186
+ )
187
+ sys.exit(0)
188
+
182
189
  overwrite = questionary.confirm(
183
- f"This project is already linked " f"(link file '{link_file}').\nOverwrite?"
190
+ f"Project is currently linked to the following Rasa Studio assistant:\n\n"
191
+ f" Assistant name: {linked_assistant_name}\n"
192
+ f" Studio URL: {studio_cfg.studio_url}\n"
193
+ f" Keycloak Auth URL: {studio_cfg.authentication_server_url}\n\n"
194
+ f"Do you want to overwrite it with the new assistant '{assistant_name}'?"
184
195
  ).ask()
185
196
  if not overwrite:
186
197
  rasa.shared.utils.cli.print_info(
rasa/studio/prompts.py CHANGED
@@ -20,7 +20,6 @@ from rasa.shared.constants import (
20
20
  from rasa.shared.utils.common import all_subclasses
21
21
  from rasa.shared.utils.llm import get_system_default_prompts
22
22
  from rasa.shared.utils.yaml import read_yaml, write_yaml
23
- from rasa.studio.data_handler import StudioDataHandler
24
23
 
25
24
  structlogger = structlog.get_logger()
26
25
 
@@ -29,14 +28,13 @@ COMMAND_GENERATOR_NAME = "command_generator"
29
28
  ENTERPRISE_SEARCH_NAME = "enterprise_search"
30
29
 
31
30
 
32
- def handle_prompts(handler: StudioDataHandler, root: Path) -> None:
31
+ def handle_prompts(prompts: Dict[Text, Text], root: Path) -> None:
33
32
  """Handle prompts for the assistant.
34
33
 
35
34
  Args:
36
- handler: The data handler to retrieve prompts from.
35
+ prompts: A dict containing prompt names as keys and their content as values.
37
36
  root: The root directory where the prompts should be saved.
38
37
  """
39
- prompts = handler.get_prompts()
40
38
  if not prompts:
41
39
  return
42
40
 
@@ -85,7 +83,7 @@ def _handle_contextual_response_rephraser(
85
83
  return
86
84
 
87
85
  prompt_path = _save_prompt_file(
88
- root, f"{CONTEXTUAL_RESPONSE_REPHRASER_NAME}.jinja", prompt_content
86
+ root, f"{CONTEXTUAL_RESPONSE_REPHRASER_NAME}.jinja2", prompt_content
89
87
  )
90
88
 
91
89
  endpoints["nlg"] = endpoints.get("nlg") or {}
@@ -113,7 +111,7 @@ def _handle_command_generator(
113
111
  return
114
112
 
115
113
  prompt_path = _save_prompt_file(
116
- root, f"{COMMAND_GENERATOR_NAME}.jinja", prompt_content
114
+ root, f"{COMMAND_GENERATOR_NAME}.jinja2", prompt_content
117
115
  )
118
116
 
119
117
  command_generator_names: List[str] = [
@@ -149,7 +147,7 @@ def _handle_enterprise_search(
149
147
  return
150
148
 
151
149
  prompt_path = _save_prompt_file(
152
- root, f"{ENTERPRISE_SEARCH_NAME}.jinja", prompt_content
150
+ root, f"{ENTERPRISE_SEARCH_NAME}.jinja2", prompt_content
153
151
  )
154
152
 
155
153
  _add_prompt_to_config(
rasa/studio/pull/pull.py CHANGED
@@ -22,6 +22,7 @@ from rasa.studio.data_handler import StudioDataHandler, import_data_from_studio
22
22
  from rasa.studio.link import read_assistant_name
23
23
  from rasa.studio.pull.data import merge_flows_in_directory, merge_nlu_in_directory
24
24
  from rasa.studio.pull.domains import merge_domain
25
+ from rasa.studio.utils import validate_argument_paths
25
26
  from rasa.utils.mapper import RasaPrimitiveStorageMapper
26
27
 
27
28
  structlogger = structlog.get_logger(__name__)
@@ -33,6 +34,7 @@ def handle_pull(args: argparse.Namespace) -> None:
33
34
  Args:
34
35
  args: The command line arguments.
35
36
  """
37
+ validate_argument_paths(args)
36
38
  handler = _create_studio_handler()
37
39
  handler.request_all_data()
38
40
 
@@ -55,6 +57,7 @@ def handle_pull_config(args: argparse.Namespace) -> None:
55
57
  Args:
56
58
  args: The command line arguments.
57
59
  """
60
+ validate_argument_paths(args)
58
61
  handler = _create_studio_handler()
59
62
  handler.request_all_data()
60
63
 
@@ -73,6 +76,7 @@ def handle_pull_endpoints(args: argparse.Namespace) -> None:
73
76
  Args:
74
77
  args: The command line arguments.
75
78
  """
79
+ validate_argument_paths(args)
76
80
  handler = _create_studio_handler()
77
81
  handler.request_all_data()
78
82
 
@@ -149,10 +153,10 @@ def _prepare_data_and_domain_paths(args: argparse.Namespace) -> Tuple[Path, Path
149
153
  domain_path = Path(domain_path)
150
154
 
151
155
  data_path = rasa.cli.utils.get_validated_path(
152
- args.data[0], "data", DEFAULT_DATA_PATH, none_is_valid=True
156
+ args.data, "data", DEFAULT_DATA_PATH, none_is_valid=True
153
157
  )
154
158
 
155
- data_path = Path(data_path or args.data[0])
159
+ data_path = Path(data_path or args.data)
156
160
  if not (data_path.is_file() or data_path.is_dir()):
157
161
  data_path.mkdir(parents=True, exist_ok=True)
158
162
 
rasa/studio/push.py CHANGED
@@ -19,6 +19,7 @@ from rasa.studio.upload import (
19
19
  make_request,
20
20
  run_validation,
21
21
  )
22
+ from rasa.studio.utils import validate_argument_paths
22
23
 
23
24
  structlogger = structlog.get_logger(__name__)
24
25
 
@@ -62,6 +63,7 @@ def handle_push(args: argparse.Namespace) -> None:
62
63
  Args:
63
64
  args: The command line arguments.
64
65
  """
66
+ validate_argument_paths(args)
65
67
  studio_cfg = get_studio_config()
66
68
 
67
69
  run_validation(args)