rasa-pro 3.8.18__py3-none-any.whl → 3.9.15__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 (278) hide show
  1. README.md +6 -42
  2. rasa/__main__.py +14 -9
  3. rasa/anonymization/anonymization_pipeline.py +0 -1
  4. rasa/anonymization/anonymization_rule_executor.py +3 -3
  5. rasa/anonymization/utils.py +4 -3
  6. rasa/api.py +2 -2
  7. rasa/cli/arguments/default_arguments.py +1 -1
  8. rasa/cli/arguments/run.py +2 -2
  9. rasa/cli/arguments/test.py +1 -1
  10. rasa/cli/arguments/train.py +10 -10
  11. rasa/cli/e2e_test.py +27 -7
  12. rasa/cli/export.py +0 -1
  13. rasa/cli/license.py +3 -3
  14. rasa/cli/project_templates/calm/actions/action_template.py +1 -1
  15. rasa/cli/project_templates/calm/config.yml +1 -1
  16. rasa/cli/project_templates/calm/credentials.yml +1 -1
  17. rasa/cli/project_templates/calm/data/flows/add_contact.yml +1 -1
  18. rasa/cli/project_templates/calm/data/flows/remove_contact.yml +1 -1
  19. rasa/cli/project_templates/calm/domain/add_contact.yml +8 -2
  20. rasa/cli/project_templates/calm/domain/list_contacts.yml +3 -0
  21. rasa/cli/project_templates/calm/domain/remove_contact.yml +9 -2
  22. rasa/cli/project_templates/calm/domain/shared.yml +5 -0
  23. rasa/cli/project_templates/calm/endpoints.yml +4 -4
  24. rasa/cli/project_templates/default/actions/actions.py +1 -1
  25. rasa/cli/project_templates/default/config.yml +5 -5
  26. rasa/cli/project_templates/default/credentials.yml +1 -1
  27. rasa/cli/project_templates/default/endpoints.yml +4 -4
  28. rasa/cli/project_templates/default/tests/test_stories.yml +1 -1
  29. rasa/cli/project_templates/tutorial/config.yml +1 -1
  30. rasa/cli/project_templates/tutorial/credentials.yml +1 -1
  31. rasa/cli/project_templates/tutorial/data/patterns.yml +6 -0
  32. rasa/cli/project_templates/tutorial/domain.yml +4 -0
  33. rasa/cli/project_templates/tutorial/endpoints.yml +6 -6
  34. rasa/cli/run.py +0 -1
  35. rasa/cli/scaffold.py +3 -2
  36. rasa/cli/studio/download.py +11 -0
  37. rasa/cli/studio/studio.py +180 -24
  38. rasa/cli/studio/upload.py +0 -8
  39. rasa/cli/telemetry.py +18 -6
  40. rasa/cli/utils.py +21 -10
  41. rasa/cli/x.py +3 -2
  42. rasa/constants.py +1 -1
  43. rasa/core/actions/action.py +90 -315
  44. rasa/core/actions/action_exceptions.py +24 -0
  45. rasa/core/actions/constants.py +3 -0
  46. rasa/core/actions/custom_action_executor.py +188 -0
  47. rasa/core/actions/forms.py +11 -7
  48. rasa/core/actions/grpc_custom_action_executor.py +251 -0
  49. rasa/core/actions/http_custom_action_executor.py +140 -0
  50. rasa/core/actions/loops.py +3 -0
  51. rasa/core/actions/two_stage_fallback.py +1 -1
  52. rasa/core/agent.py +2 -4
  53. rasa/core/brokers/pika.py +1 -2
  54. rasa/core/channels/audiocodes.py +1 -1
  55. rasa/core/channels/botframework.py +0 -1
  56. rasa/core/channels/callback.py +0 -1
  57. rasa/core/channels/console.py +6 -8
  58. rasa/core/channels/development_inspector.py +1 -1
  59. rasa/core/channels/facebook.py +0 -3
  60. rasa/core/channels/hangouts.py +0 -6
  61. rasa/core/channels/inspector/dist/assets/{arc-5623b6dc.js → arc-b6e548fe.js} +1 -1
  62. rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-685c106a.js → c4Diagram-d0fbc5ce-fa03ac9e.js} +1 -1
  63. rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-8cbed007.js → classDiagram-936ed81e-ee67392a.js} +1 -1
  64. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-5889cf12.js → classDiagram-v2-c3cb15f1-9b283fae.js} +1 -1
  65. rasa/core/channels/inspector/dist/assets/{createText-62fc7601-24c249d7.js → createText-62fc7601-8b6fcc2a.js} +1 -1
  66. rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-7dd06a75.js → edges-f2ad444c-22e77f4f.js} +1 -1
  67. rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-62c1e54c.js → erDiagram-9d236eb7-60ffc87f.js} +1 -1
  68. rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-ce49b86f.js → flowDb-1972c806-9dd802e4.js} +1 -1
  69. rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-4067e48f.js → flowDiagram-7ea5b25a-5fa1912f.js} +1 -1
  70. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-1844e5a5.js +1 -0
  71. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-59fe4051.js → flowchart-elk-definition-abe16c3d-622a1fd2.js} +1 -1
  72. rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-47e3a43b.js → ganttDiagram-9b5ea136-e285a63a.js} +1 -1
  73. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-5a2ac0d9.js → gitGraphDiagram-99d0ae7c-f237bdca.js} +1 -1
  74. rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-dfb8efc4.js → index-2c4b9a3b-4b03d70e.js} +1 -1
  75. rasa/core/channels/inspector/dist/assets/{index-268a75c0.js → index-a5d3e69d.js} +4 -4
  76. rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-b0c470f2.js → infoDiagram-736b4530-72a0fa5f.js} +1 -1
  77. rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-2edb829a.js → journeyDiagram-df861f2b-82218c41.js} +1 -1
  78. rasa/core/channels/inspector/dist/assets/{layout-b6873d69.js → layout-78cff630.js} +1 -1
  79. rasa/core/channels/inspector/dist/assets/{line-1efc5781.js → line-5038b469.js} +1 -1
  80. rasa/core/channels/inspector/dist/assets/{linear-661e9b94.js → linear-c4fc4098.js} +1 -1
  81. rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-2d2e727f.js → mindmap-definition-beec6740-c33c8ea6.js} +1 -1
  82. rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-9d3ea93d.js → pieDiagram-dbbf0591-a8d03059.js} +1 -1
  83. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-06a178a2.js → quadrantDiagram-4d7f4fd6-6a0e56b2.js} +1 -1
  84. rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-0bfedffc.js → requirementDiagram-6fc4c22a-2dc7c7bd.js} +1 -1
  85. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-d76d0a04.js → sankeyDiagram-8f13d901-2360fe39.js} +1 -1
  86. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-37bb4341.js → sequenceDiagram-b655622a-41b9f9ad.js} +1 -1
  87. rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-f52f7f57.js → stateDiagram-59f0c015-0aad326f.js} +1 -1
  88. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-4a986a20.js → stateDiagram-v2-2b26beab-9847d984.js} +1 -1
  89. rasa/core/channels/inspector/dist/assets/{styles-080da4f6-7dd9ae12.js → styles-080da4f6-564d890e.js} +1 -1
  90. rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-46e1ca14.js → styles-3dcbcfbf-38957613.js} +1 -1
  91. rasa/core/channels/inspector/dist/assets/{styles-9c745c82-4a97439a.js → styles-9c745c82-f0fc6921.js} +1 -1
  92. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-823917a3.js → svgDrawCommon-4835440b-ef3c5a77.js} +1 -1
  93. rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-9ea72896.js → timeline-definition-5b62e21b-bf3e91c1.js} +1 -1
  94. rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-b631a8b6.js → xychartDiagram-2b33534f-4d4026c0.js} +1 -1
  95. rasa/core/channels/inspector/dist/index.html +1 -1
  96. rasa/core/channels/inspector/src/components/DiagramFlow.tsx +10 -0
  97. rasa/core/channels/inspector/src/helpers/formatters.test.ts +4 -7
  98. rasa/core/channels/inspector/src/helpers/formatters.ts +3 -2
  99. rasa/core/channels/rest.py +36 -21
  100. rasa/core/channels/rocketchat.py +0 -1
  101. rasa/core/channels/socketio.py +1 -1
  102. rasa/core/channels/telegram.py +3 -3
  103. rasa/core/channels/webexteams.py +0 -1
  104. rasa/core/concurrent_lock_store.py +1 -1
  105. rasa/core/evaluation/marker_base.py +1 -3
  106. rasa/core/evaluation/marker_stats.py +1 -2
  107. rasa/core/featurizers/single_state_featurizer.py +3 -26
  108. rasa/core/featurizers/tracker_featurizers.py +18 -122
  109. rasa/core/information_retrieval/__init__.py +7 -0
  110. rasa/core/information_retrieval/faiss.py +9 -4
  111. rasa/core/information_retrieval/information_retrieval.py +64 -7
  112. rasa/core/information_retrieval/milvus.py +7 -14
  113. rasa/core/information_retrieval/qdrant.py +8 -15
  114. rasa/core/lock_store.py +0 -1
  115. rasa/core/migrate.py +1 -2
  116. rasa/core/nlg/callback.py +3 -4
  117. rasa/core/policies/enterprise_search_policy.py +86 -22
  118. rasa/core/policies/enterprise_search_prompt_template.jinja2 +4 -41
  119. rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +60 -0
  120. rasa/core/policies/flows/flow_executor.py +104 -2
  121. rasa/core/policies/intentless_policy.py +7 -9
  122. rasa/core/policies/memoization.py +3 -3
  123. rasa/core/policies/policy.py +18 -9
  124. rasa/core/policies/rule_policy.py +8 -11
  125. rasa/core/policies/ted_policy.py +61 -88
  126. rasa/core/policies/unexpected_intent_policy.py +8 -17
  127. rasa/core/processor.py +136 -47
  128. rasa/core/run.py +41 -25
  129. rasa/core/secrets_manager/endpoints.py +2 -2
  130. rasa/core/secrets_manager/vault.py +6 -8
  131. rasa/core/test.py +3 -5
  132. rasa/core/tracker_store.py +49 -14
  133. rasa/core/train.py +1 -3
  134. rasa/core/training/interactive.py +9 -6
  135. rasa/core/utils.py +5 -10
  136. rasa/dialogue_understanding/coexistence/intent_based_router.py +11 -4
  137. rasa/dialogue_understanding/coexistence/llm_based_router.py +2 -3
  138. rasa/dialogue_understanding/commands/__init__.py +4 -0
  139. rasa/dialogue_understanding/commands/can_not_handle_command.py +9 -0
  140. rasa/dialogue_understanding/commands/cancel_flow_command.py +9 -0
  141. rasa/dialogue_understanding/commands/change_flow_command.py +38 -0
  142. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +9 -0
  143. rasa/dialogue_understanding/commands/clarify_command.py +9 -0
  144. rasa/dialogue_understanding/commands/correct_slots_command.py +9 -0
  145. rasa/dialogue_understanding/commands/error_command.py +12 -0
  146. rasa/dialogue_understanding/commands/handle_code_change_command.py +9 -0
  147. rasa/dialogue_understanding/commands/human_handoff_command.py +9 -0
  148. rasa/dialogue_understanding/commands/knowledge_answer_command.py +9 -0
  149. rasa/dialogue_understanding/commands/noop_command.py +9 -0
  150. rasa/dialogue_understanding/commands/set_slot_command.py +38 -3
  151. rasa/dialogue_understanding/commands/skip_question_command.py +9 -0
  152. rasa/dialogue_understanding/commands/start_flow_command.py +9 -0
  153. rasa/dialogue_understanding/generator/__init__.py +16 -1
  154. rasa/dialogue_understanding/generator/command_generator.py +92 -6
  155. rasa/dialogue_understanding/generator/constants.py +18 -0
  156. rasa/dialogue_understanding/generator/flow_retrieval.py +7 -5
  157. rasa/dialogue_understanding/generator/llm_based_command_generator.py +467 -0
  158. rasa/dialogue_understanding/generator/llm_command_generator.py +39 -609
  159. rasa/dialogue_understanding/generator/multi_step/__init__.py +0 -0
  160. rasa/dialogue_understanding/generator/multi_step/fill_slots_prompt.jinja2 +62 -0
  161. rasa/dialogue_understanding/generator/multi_step/handle_flows_prompt.jinja2 +38 -0
  162. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +827 -0
  163. rasa/dialogue_understanding/generator/nlu_command_adapter.py +69 -8
  164. rasa/dialogue_understanding/generator/single_step/__init__.py +0 -0
  165. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +345 -0
  166. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +36 -31
  167. rasa/dialogue_understanding/processor/command_processor.py +112 -3
  168. rasa/e2e_test/constants.py +1 -0
  169. rasa/e2e_test/e2e_test_case.py +44 -0
  170. rasa/e2e_test/e2e_test_runner.py +114 -11
  171. rasa/e2e_test/e2e_test_schema.yml +18 -0
  172. rasa/engine/caching.py +0 -1
  173. rasa/engine/graph.py +18 -6
  174. rasa/engine/recipes/config_files/default_config.yml +3 -3
  175. rasa/engine/recipes/default_components.py +1 -1
  176. rasa/engine/recipes/default_recipe.py +4 -5
  177. rasa/engine/recipes/recipe.py +1 -1
  178. rasa/engine/runner/dask.py +3 -9
  179. rasa/engine/storage/local_model_storage.py +0 -2
  180. rasa/engine/validation.py +179 -145
  181. rasa/exceptions.py +2 -2
  182. rasa/graph_components/validators/default_recipe_validator.py +3 -5
  183. rasa/hooks.py +0 -1
  184. rasa/model.py +1 -1
  185. rasa/model_training.py +1 -0
  186. rasa/nlu/classifiers/diet_classifier.py +33 -52
  187. rasa/nlu/classifiers/logistic_regression_classifier.py +9 -22
  188. rasa/nlu/classifiers/sklearn_intent_classifier.py +16 -37
  189. rasa/nlu/extractors/crf_entity_extractor.py +54 -97
  190. rasa/nlu/extractors/duckling_entity_extractor.py +1 -1
  191. rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +1 -5
  192. rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +0 -4
  193. rasa/nlu/featurizers/featurizer.py +1 -1
  194. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +18 -49
  195. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +26 -64
  196. rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +3 -5
  197. rasa/nlu/persistor.py +68 -26
  198. rasa/nlu/selectors/response_selector.py +7 -10
  199. rasa/nlu/test.py +0 -3
  200. rasa/nlu/utils/hugging_face/registry.py +1 -1
  201. rasa/nlu/utils/spacy_utils.py +1 -3
  202. rasa/server.py +22 -7
  203. rasa/shared/constants.py +12 -1
  204. rasa/shared/core/command_payload_reader.py +109 -0
  205. rasa/shared/core/constants.py +4 -5
  206. rasa/shared/core/domain.py +57 -56
  207. rasa/shared/core/events.py +4 -7
  208. rasa/shared/core/flows/flow.py +9 -0
  209. rasa/shared/core/flows/flows_list.py +12 -0
  210. rasa/shared/core/flows/steps/action.py +7 -2
  211. rasa/shared/core/generator.py +12 -11
  212. rasa/shared/core/slot_mappings.py +315 -24
  213. rasa/shared/core/slots.py +4 -2
  214. rasa/shared/core/trackers.py +32 -14
  215. rasa/shared/core/training_data/loading.py +0 -1
  216. rasa/shared/core/training_data/story_reader/story_reader.py +3 -3
  217. rasa/shared/core/training_data/story_reader/yaml_story_reader.py +11 -11
  218. rasa/shared/core/training_data/story_writer/yaml_story_writer.py +5 -3
  219. rasa/shared/core/training_data/structures.py +1 -1
  220. rasa/shared/core/training_data/visualization.py +1 -1
  221. rasa/shared/data.py +58 -1
  222. rasa/shared/exceptions.py +36 -2
  223. rasa/shared/importers/importer.py +1 -2
  224. rasa/shared/importers/rasa.py +0 -1
  225. rasa/shared/nlu/constants.py +2 -0
  226. rasa/shared/nlu/training_data/entities_parser.py +1 -2
  227. rasa/shared/nlu/training_data/features.py +2 -120
  228. rasa/shared/nlu/training_data/formats/dialogflow.py +3 -2
  229. rasa/shared/nlu/training_data/formats/rasa_yaml.py +3 -5
  230. rasa/shared/nlu/training_data/formats/readerwriter.py +0 -1
  231. rasa/shared/nlu/training_data/message.py +13 -0
  232. rasa/shared/nlu/training_data/training_data.py +0 -2
  233. rasa/shared/providers/openai/session_handler.py +2 -2
  234. rasa/shared/utils/constants.py +3 -0
  235. rasa/shared/utils/io.py +11 -1
  236. rasa/shared/utils/llm.py +1 -2
  237. rasa/shared/utils/pykwalify_extensions.py +1 -0
  238. rasa/shared/utils/schemas/domain.yml +3 -0
  239. rasa/shared/utils/yaml.py +44 -35
  240. rasa/studio/auth.py +26 -10
  241. rasa/studio/constants.py +2 -0
  242. rasa/studio/data_handler.py +114 -107
  243. rasa/studio/download.py +160 -27
  244. rasa/studio/results_logger.py +137 -0
  245. rasa/studio/train.py +6 -7
  246. rasa/studio/upload.py +159 -134
  247. rasa/telemetry.py +188 -34
  248. rasa/tracing/config.py +18 -3
  249. rasa/tracing/constants.py +26 -2
  250. rasa/tracing/instrumentation/attribute_extractors.py +50 -41
  251. rasa/tracing/instrumentation/instrumentation.py +290 -44
  252. rasa/tracing/instrumentation/intentless_policy_instrumentation.py +7 -5
  253. rasa/tracing/instrumentation/metrics.py +109 -21
  254. rasa/tracing/metric_instrument_provider.py +83 -3
  255. rasa/utils/cli.py +2 -1
  256. rasa/utils/common.py +1 -1
  257. rasa/utils/endpoints.py +1 -2
  258. rasa/utils/io.py +72 -6
  259. rasa/utils/licensing.py +246 -31
  260. rasa/utils/ml_utils.py +1 -1
  261. rasa/utils/tensorflow/data_generator.py +1 -1
  262. rasa/utils/tensorflow/environment.py +1 -1
  263. rasa/utils/tensorflow/model_data.py +201 -12
  264. rasa/utils/tensorflow/model_data_utils.py +499 -500
  265. rasa/utils/tensorflow/models.py +5 -6
  266. rasa/utils/tensorflow/rasa_layers.py +15 -15
  267. rasa/utils/train_utils.py +1 -1
  268. rasa/utils/url_tools.py +53 -0
  269. rasa/validator.py +305 -3
  270. rasa/version.py +1 -1
  271. {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.15.dist-info}/METADATA +25 -61
  272. {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.15.dist-info}/RECORD +276 -259
  273. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-85583a23.js +0 -1
  274. rasa/utils/tensorflow/feature_array.py +0 -370
  275. /rasa/dialogue_understanding/generator/{command_prompt_template.jinja2 → single_step/command_prompt_template.jinja2} +0 -0
  276. {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.15.dist-info}/NOTICE +0 -0
  277. {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.15.dist-info}/WHEEL +0 -0
  278. {rasa_pro-3.8.18.dist-info → rasa_pro-3.9.15.dist-info}/entry_points.txt +0 -0
rasa/studio/upload.py CHANGED
@@ -1,9 +1,11 @@
1
1
  import argparse
2
2
  import base64
3
- import logging
4
- from typing import Dict, Iterable, List, Set, Text, Tuple, Union
3
+ import sys
4
+ from typing import Dict, Iterable, List, Set, Text, Tuple, Union, Any
5
5
 
6
+ import questionary
6
7
  import requests
8
+ import structlog
7
9
 
8
10
  import rasa.cli.telemetry
9
11
  import rasa.cli.utils
@@ -11,16 +13,19 @@ import rasa.shared.utils.cli
11
13
  import rasa.shared.utils.io
12
14
  from rasa.shared.constants import (
13
15
  DEFAULT_DOMAIN_PATHS,
16
+ DEFAULT_CONFIG_PATH,
14
17
  )
15
18
  from rasa.shared.core.flows.yaml_flows_io import YamlFlowsWriter
16
19
  from rasa.shared.exceptions import RasaException
17
20
  from rasa.shared.importers.importer import TrainingDataImporter, FlowSyncImporter
18
21
  from rasa.shared.nlu.training_data.formats.rasa_yaml import RasaYAMLWriter
19
- from rasa.shared.utils.yaml import dump_obj_as_yaml_to_string
22
+ from rasa.shared.utils.yaml import dump_obj_as_yaml_to_string, read_yaml_file
23
+ from rasa.studio import results_logger
20
24
  from rasa.studio.auth import KeycloakTokenReader
21
25
  from rasa.studio.config import StudioConfig
26
+ from rasa.studio.results_logger import StudioResult, with_studio_error_handler
22
27
 
23
- logger = logging.getLogger(__name__)
28
+ structlogger = structlog.get_logger()
24
29
 
25
30
 
26
31
  def _get_selected_entities_and_intents(
@@ -32,37 +37,59 @@ def _get_selected_entities_and_intents(
32
37
 
33
38
  if entities is None or len(entities) == 0:
34
39
  entities = entities_from_files
35
- logger.info("No entities specified. Using all entities from files.")
40
+ structlogger.info(
41
+ "rasa.studio.upload.entities_empty",
42
+ event_info="No entities specified. Using all entities from files.",
43
+ )
36
44
 
37
45
  intents = args.intents
38
46
 
39
47
  if intents is None or len(intents) == 0:
40
48
  intents = intents_from_files
41
- logger.info("No intents specified. Using all intents from files.")
49
+ structlogger.info(
50
+ "rasa.studio.upload.intents_empty",
51
+ event_info="No intents specified. Using all intents from files.",
52
+ )
42
53
 
43
54
  return list(entities), list(intents)
44
55
 
45
56
 
46
57
  def handle_upload(args: argparse.Namespace) -> None:
47
58
  """Uploads primitives to rasa studio."""
48
- assistant_name = args.assistant_name[0]
49
59
  endpoint = StudioConfig.read_config().studio_url
50
60
  if not endpoint:
51
61
  rasa.shared.utils.cli.print_error_and_exit(
52
62
  "No GraphQL endpoint found in config. Please run `rasa studio config`."
53
63
  )
54
64
  else:
55
- logger.info("Loading data...")
65
+ structlogger.info(
66
+ "rasa.studio.upload.loading_data", event_info="Loading data..."
67
+ )
56
68
 
57
69
  args.domain = rasa.cli.utils.get_validated_path(
58
70
  args.domain, "domain", DEFAULT_DOMAIN_PATHS
59
71
  )
60
72
 
73
+ args.config = rasa.cli.utils.get_validated_path(
74
+ args.config, "config", DEFAULT_CONFIG_PATH
75
+ )
76
+
61
77
  # check safely if args.calm is set and not fail if not
62
78
  if hasattr(args, "calm") and args.calm:
63
- upload_calm_assistant(args, assistant_name, endpoint)
79
+ upload_calm_assistant(args, endpoint)
64
80
  else:
65
- upload_nlu_assistant(args, assistant_name, endpoint)
81
+ upload_nlu_assistant(args, endpoint)
82
+
83
+
84
+ config_keys = [
85
+ "recipe",
86
+ "language",
87
+ "pipeline",
88
+ "llm",
89
+ "policies",
90
+ "model_name",
91
+ "assistant_id",
92
+ ]
66
93
 
67
94
 
68
95
  def extract_values(data: Dict, keys: List[Text]) -> Dict:
@@ -70,9 +97,36 @@ def extract_values(data: Dict, keys: List[Text]) -> Dict:
70
97
  return {key: data.get(key) for key in keys if data.get(key)}
71
98
 
72
99
 
73
- def upload_calm_assistant(
74
- args: argparse.Namespace, assistant_name: str, endpoint: str
75
- ) -> None:
100
+ def _get_assistant_name(config: Dict[Text, Any]) -> str:
101
+ config_assistant_id = config.get("assistant_id", "")
102
+ assistant_name = questionary.text(
103
+ "Please provide the assistant name", default=config_assistant_id
104
+ ).ask()
105
+ if not assistant_name:
106
+ structlogger.error(
107
+ "rasa.studio.upload.assistant_name_empty",
108
+ event_info="Assistant name cannot be empty.",
109
+ )
110
+ sys.exit(1)
111
+
112
+ # if assistant_name exists and different from config assistant_id,
113
+ # notify user and upload with new assistant_name
114
+ same = assistant_name == config_assistant_id
115
+ if not same and config_assistant_id != "":
116
+ structlogger.info(
117
+ "rasa.studio.upload.assistant_name_mismatch",
118
+ event_info=(
119
+ f"Assistant name '{assistant_name}' is different"
120
+ f" from the one in the config file: '{config_assistant_id}'."
121
+ ),
122
+ )
123
+
124
+ structlogger.info(f"Uploading assistant with the name '{assistant_name}'.")
125
+ return assistant_name
126
+
127
+
128
+ @with_studio_error_handler
129
+ def upload_calm_assistant(args: argparse.Namespace, endpoint: str) -> StudioResult:
76
130
  """Uploads the CALM assistant data to Rasa Studio.
77
131
 
78
132
  Args:
@@ -82,101 +136,92 @@ def upload_calm_assistant(
82
136
  - flows: The path to the flows
83
137
  - endpoints: The path to the endpoints
84
138
  - config: The path to the config
85
- assistant_name: The name of the assistant
86
139
  endpoint: The studio endpoint
87
140
  Returns:
88
141
  None
89
142
  """
90
- logger.info("Parsing CALM assistant data...")
143
+ structlogger.info(
144
+ "rasa.studio.upload.loading_data", event_info="Parsing CALM assistant data..."
145
+ )
91
146
 
92
- try:
93
- importer = TrainingDataImporter.load_from_dict(
94
- domain_path=args.domain,
95
- config_path=args.config,
96
- )
147
+ importer = TrainingDataImporter.load_from_dict(
148
+ domain_path=args.domain,
149
+ config_path=args.config,
150
+ )
97
151
 
98
- # Prepare config and domain
99
- config_from_files = importer.get_config()
100
- domain_from_files = importer.get_domain().as_dict()
101
-
102
- # Extract domain and config values
103
- domain_keys = [
104
- "version",
105
- "actions",
106
- "responses",
107
- "slots",
108
- "intents",
109
- "entities",
110
- "forms",
111
- "session_config",
112
- ]
113
- config_keys = [
114
- "recipe",
115
- "language",
116
- "pipeline",
117
- "llm",
118
- "policies",
119
- "model_name",
120
- ]
121
-
122
- domain = extract_values(domain_from_files, domain_keys)
123
- config = extract_values(config_from_files, config_keys)
124
-
125
- training_data_paths = args.data
126
-
127
- if isinstance(training_data_paths, list):
128
- training_data_paths.append(args.flows)
129
- elif isinstance(training_data_paths, str):
152
+ # Prepare config and domain
153
+ config = importer.get_config()
154
+ domain_from_files = importer.get_domain().as_dict()
155
+ endpoints_from_files = read_yaml_file(args.endpoints)
156
+ config_from_files = read_yaml_file(args.config)
157
+
158
+ # Extract domain and config values
159
+ domain_keys = [
160
+ "version",
161
+ "actions",
162
+ "responses",
163
+ "slots",
164
+ "intents",
165
+ "entities",
166
+ "forms",
167
+ "session_config",
168
+ ]
169
+
170
+ domain = extract_values(domain_from_files, domain_keys)
171
+
172
+ assistant_name = _get_assistant_name(config)
173
+
174
+ training_data_paths = args.data
175
+
176
+ if isinstance(training_data_paths, list):
177
+ training_data_paths.append(args.flows)
178
+ elif isinstance(training_data_paths, str):
179
+ if isinstance(args.flows, list):
180
+ training_data_paths = [training_data_paths] + args.flows
181
+ elif isinstance(args.flows, str):
130
182
  training_data_paths = [training_data_paths, args.flows]
183
+ else:
184
+ raise RasaException("Invalid flows path")
131
185
 
132
- # Prepare flows
133
- flow_importer = FlowSyncImporter.load_from_dict(
134
- training_data_paths=training_data_paths
135
- )
136
-
137
- user_flows = flow_importer.get_flows().user_flows
138
- flows = list(user_flows)
139
-
140
- # We instantiate the TrainingDataImporter again on purpose to avoid
141
- # adding patterns to domain's actions. More info https://t.ly/W8uuc
142
- nlu_importer = TrainingDataImporter.load_from_dict(
143
- domain_path=args.domain, training_data_paths=args.data
144
- )
145
- nlu_data = nlu_importer.get_nlu_data()
186
+ # Prepare flows
187
+ flow_importer = FlowSyncImporter.load_from_dict(
188
+ training_data_paths=training_data_paths
189
+ )
146
190
 
147
- intents_from_files = nlu_data.intents
191
+ user_flows = flow_importer.get_flows().user_flows
192
+ flows = list(user_flows)
148
193
 
149
- nlu_examples = nlu_data.filter_training_examples(
150
- lambda ex: ex.get("intent") in intents_from_files
151
- )
194
+ # We instantiate the TrainingDataImporter again on purpose to avoid
195
+ # adding patterns to domain's actions. More info https://t.ly/W8uuc
196
+ nlu_importer = TrainingDataImporter.load_from_dict(
197
+ domain_path=args.domain, training_data_paths=args.data
198
+ )
199
+ nlu_data = nlu_importer.get_nlu_data()
152
200
 
153
- nlu_examples_yaml = RasaYAMLWriter().dumps(nlu_examples)
201
+ intents_from_files = nlu_data.intents
154
202
 
155
- # Build GraphQL request
156
- graphql_req = build_import_request(
157
- assistant_name,
158
- flows_yaml=YamlFlowsWriter().dumps(flows),
159
- domain_yaml=dump_obj_as_yaml_to_string(domain),
160
- config_yaml=dump_obj_as_yaml_to_string(config),
161
- nlu_yaml=nlu_examples_yaml,
162
- )
203
+ nlu_examples = nlu_data.filter_training_examples(
204
+ lambda ex: ex.get("intent") in intents_from_files
205
+ )
163
206
 
164
- logger.info("Uploading to Rasa Studio...")
165
- response, status = make_request(endpoint, graphql_req)
207
+ nlu_examples_yaml = RasaYAMLWriter().dumps(nlu_examples)
166
208
 
167
- if status:
168
- rasa.shared.utils.cli.print_success(response)
169
- else:
170
- logger.error(f"Failed to upload to Rasa Studio: {response}")
171
- rasa.shared.utils.cli.print_error(response)
209
+ # Build GraphQL request
210
+ graphql_req = build_import_request(
211
+ assistant_name,
212
+ flows_yaml=YamlFlowsWriter().dumps(flows),
213
+ domain_yaml=dump_obj_as_yaml_to_string(domain),
214
+ config_yaml=dump_obj_as_yaml_to_string(config_from_files),
215
+ endpoints=dump_obj_as_yaml_to_string(endpoints_from_files),
216
+ nlu_yaml=nlu_examples_yaml,
217
+ )
172
218
 
173
- except Exception as e:
174
- logger.error(f"An error occurred while uploading the CALM assistant: {e}")
219
+ structlogger.info("Uploading to Rasa Studio...")
220
+ return make_request(endpoint, graphql_req)
175
221
 
176
222
 
177
- def upload_nlu_assistant(
178
- args: argparse.Namespace, assistant_name: str, endpoint: str
179
- ) -> None:
223
+ @with_studio_error_handler
224
+ def upload_nlu_assistant(args: argparse.Namespace, endpoint: str) -> StudioResult:
180
225
  """Uploads the classic (dm1) assistant data to Rasa Studio.
181
226
 
182
227
  Args:
@@ -185,14 +230,13 @@ def upload_nlu_assistant(
185
230
  - domain: The path to the domain
186
231
  - intents: The intents to upload
187
232
  - entities: The entities to upload
188
- assistant_name: The name of the assistant
189
233
  endpoint: The studio endpoint
190
234
  Returns:
191
235
  None
192
236
  """
193
- logger.info("Found DM1 assistant data, parsing...")
237
+ structlogger.info("Found DM1 assistant data, parsing...")
194
238
  importer = TrainingDataImporter.load_from_dict(
195
- domain_path=args.domain, training_data_paths=args.data
239
+ domain_path=args.domain, training_data_paths=args.data, config_path=args.config
196
240
  )
197
241
 
198
242
  intents_from_files = importer.get_nlu_data().intents
@@ -202,7 +246,12 @@ def upload_nlu_assistant(
202
246
  args, intents_from_files, entities_from_files
203
247
  )
204
248
 
205
- logger.info("Validating data...")
249
+ config_from_files = importer.get_config()
250
+ config = extract_values(config_from_files, config_keys)
251
+
252
+ assistant_name = _get_assistant_name(config)
253
+
254
+ structlogger.info("Validating data...")
206
255
  _check_for_missing_primitives(
207
256
  intents, entities, intents_from_files, entities_from_files
208
257
  )
@@ -219,15 +268,11 @@ def upload_nlu_assistant(
219
268
 
220
269
  graphql_req = build_request(assistant_name, nlu_examples_yaml, domain_yaml)
221
270
 
222
- logger.info("Uploading to Rasa Studio...")
223
- response, status = make_request(endpoint, graphql_req)
224
- if status:
225
- rasa.shared.utils.cli.print_success(response)
226
- else:
227
- rasa.shared.utils.cli.print_error(response)
271
+ structlogger.info("Uploading to Rasa Studio...")
272
+ return make_request(endpoint, graphql_req)
228
273
 
229
274
 
230
- def make_request(endpoint: str, graphql_req: Dict) -> Tuple[str, bool]:
275
+ def make_request(endpoint: str, graphql_req: Dict) -> StudioResult:
231
276
  """Makes a request to the studio endpoint to upload data.
232
277
 
233
278
  Args:
@@ -235,7 +280,6 @@ def make_request(endpoint: str, graphql_req: Dict) -> Tuple[str, bool]:
235
280
  graphql_req: The graphql request
236
281
  """
237
282
  token = KeycloakTokenReader().get_token()
238
-
239
283
  res = requests.post(
240
284
  endpoint,
241
285
  json=graphql_req,
@@ -245,30 +289,9 @@ def make_request(endpoint: str, graphql_req: Dict) -> Tuple[str, bool]:
245
289
  },
246
290
  )
247
291
 
248
- response = res.json()
249
-
250
- if _response_has_errors(response):
251
- print_errors_from_response(response)
252
-
253
- if res.status_code != 200:
254
- return f"Upload failed with status code {res.status_code}", False
255
- elif _response_has_errors(response):
256
- return "Error while uploading data!", False
257
-
258
- return "Upload successful!", True
259
-
260
-
261
- def _response_has_errors(response: Dict) -> bool:
262
- return (
263
- "errors" in response
264
- and isinstance(response["errors"], list)
265
- and len(response["errors"]) > 0
266
- )
267
-
268
-
269
- def print_errors_from_response(response: Dict) -> None:
270
- for error in response["errors"]:
271
- logger.error(error["message"])
292
+ if results_logger.response_has_errors(res.json()):
293
+ return StudioResult.error(res.json())
294
+ return StudioResult.success("Upload successful")
272
295
 
273
296
 
274
297
  def _add_missing_entities(
@@ -278,7 +301,7 @@ def _add_missing_entities(
278
301
  all_entities.extend(entities)
279
302
  for entity in entities_from_intents:
280
303
  if entity not in entities:
281
- logger.warning(
304
+ structlogger.warning(
282
305
  f"Adding entity '{entity}' to upload since it is used in an intent."
283
306
  )
284
307
  all_entities.append(entity)
@@ -290,6 +313,7 @@ def build_import_request(
290
313
  flows_yaml: str,
291
314
  domain_yaml: str,
292
315
  config_yaml: str,
316
+ endpoints: str,
293
317
  nlu_yaml: str = "",
294
318
  ) -> Dict:
295
319
  # b64encode expects bytes and returns bytes so we need to decode to string
@@ -297,6 +321,7 @@ def build_import_request(
297
321
  base64_flows = base64.b64encode(flows_yaml.encode("utf-8")).decode("utf-8")
298
322
  base64_config = base64.b64encode(config_yaml.encode("utf-8")).decode("utf-8")
299
323
  base64_nlu = base64.b64encode(nlu_yaml.encode("utf-8")).decode("utf-8")
324
+ base64_endpoints = base64.b64encode(endpoints.encode("utf-8")).decode("utf-8")
300
325
 
301
326
  graphql_req = {
302
327
  "query": (
@@ -310,6 +335,7 @@ def build_import_request(
310
335
  "flows": base64_flows,
311
336
  "nlu": base64_nlu,
312
337
  "config": base64_config,
338
+ "endpoints": base64_endpoints,
313
339
  }
314
340
  },
315
341
  }
@@ -347,16 +373,15 @@ def _filter_domain(
347
373
  entities: List[Union[str, Dict]], intents: List[str], domain_from_files: Dict
348
374
  ) -> Dict:
349
375
  """Filters the domain to only include the selected entities and intents."""
350
- domain = {
376
+ selected_entities = _remove_not_selected_entities(
377
+ entities, domain_from_files.get("entities", [])
378
+ )
379
+ return {
351
380
  "version": domain_from_files["version"],
352
381
  "intents": intents,
353
- "entities": _remove_not_selected_entities(
354
- entities, domain_from_files["entities"]
355
- ),
382
+ "entities": selected_entities,
356
383
  }
357
384
 
358
- return domain
359
-
360
385
 
361
386
  def _check_for_missing_primitives(
362
387
  intents: Iterable[str],