rasa-pro 3.8.17__py3-none-any.whl → 3.9.14__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 (272) hide show
  1. README.md +5 -5
  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/core/actions/action.py +90 -315
  43. rasa/core/actions/action_exceptions.py +24 -0
  44. rasa/core/actions/constants.py +3 -0
  45. rasa/core/actions/custom_action_executor.py +188 -0
  46. rasa/core/actions/forms.py +11 -7
  47. rasa/core/actions/grpc_custom_action_executor.py +251 -0
  48. rasa/core/actions/http_custom_action_executor.py +140 -0
  49. rasa/core/actions/loops.py +3 -0
  50. rasa/core/actions/two_stage_fallback.py +1 -1
  51. rasa/core/agent.py +2 -4
  52. rasa/core/brokers/pika.py +1 -2
  53. rasa/core/channels/audiocodes.py +1 -1
  54. rasa/core/channels/botframework.py +0 -1
  55. rasa/core/channels/callback.py +0 -1
  56. rasa/core/channels/console.py +6 -8
  57. rasa/core/channels/development_inspector.py +1 -1
  58. rasa/core/channels/facebook.py +0 -3
  59. rasa/core/channels/hangouts.py +0 -6
  60. rasa/core/channels/inspector/dist/assets/{arc-5623b6dc.js → arc-b6e548fe.js} +1 -1
  61. rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-685c106a.js → c4Diagram-d0fbc5ce-fa03ac9e.js} +1 -1
  62. rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-8cbed007.js → classDiagram-936ed81e-ee67392a.js} +1 -1
  63. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-5889cf12.js → classDiagram-v2-c3cb15f1-9b283fae.js} +1 -1
  64. rasa/core/channels/inspector/dist/assets/{createText-62fc7601-24c249d7.js → createText-62fc7601-8b6fcc2a.js} +1 -1
  65. rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-7dd06a75.js → edges-f2ad444c-22e77f4f.js} +1 -1
  66. rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-62c1e54c.js → erDiagram-9d236eb7-60ffc87f.js} +1 -1
  67. rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-ce49b86f.js → flowDb-1972c806-9dd802e4.js} +1 -1
  68. rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-4067e48f.js → flowDiagram-7ea5b25a-5fa1912f.js} +1 -1
  69. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-1844e5a5.js +1 -0
  70. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-59fe4051.js → flowchart-elk-definition-abe16c3d-622a1fd2.js} +1 -1
  71. rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-47e3a43b.js → ganttDiagram-9b5ea136-e285a63a.js} +1 -1
  72. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-5a2ac0d9.js → gitGraphDiagram-99d0ae7c-f237bdca.js} +1 -1
  73. rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-dfb8efc4.js → index-2c4b9a3b-4b03d70e.js} +1 -1
  74. rasa/core/channels/inspector/dist/assets/{index-268a75c0.js → index-a5d3e69d.js} +4 -4
  75. rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-b0c470f2.js → infoDiagram-736b4530-72a0fa5f.js} +1 -1
  76. rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-2edb829a.js → journeyDiagram-df861f2b-82218c41.js} +1 -1
  77. rasa/core/channels/inspector/dist/assets/{layout-b6873d69.js → layout-78cff630.js} +1 -1
  78. rasa/core/channels/inspector/dist/assets/{line-1efc5781.js → line-5038b469.js} +1 -1
  79. rasa/core/channels/inspector/dist/assets/{linear-661e9b94.js → linear-c4fc4098.js} +1 -1
  80. rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-2d2e727f.js → mindmap-definition-beec6740-c33c8ea6.js} +1 -1
  81. rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-9d3ea93d.js → pieDiagram-dbbf0591-a8d03059.js} +1 -1
  82. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-06a178a2.js → quadrantDiagram-4d7f4fd6-6a0e56b2.js} +1 -1
  83. rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-0bfedffc.js → requirementDiagram-6fc4c22a-2dc7c7bd.js} +1 -1
  84. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-d76d0a04.js → sankeyDiagram-8f13d901-2360fe39.js} +1 -1
  85. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-37bb4341.js → sequenceDiagram-b655622a-41b9f9ad.js} +1 -1
  86. rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-f52f7f57.js → stateDiagram-59f0c015-0aad326f.js} +1 -1
  87. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-4a986a20.js → stateDiagram-v2-2b26beab-9847d984.js} +1 -1
  88. rasa/core/channels/inspector/dist/assets/{styles-080da4f6-7dd9ae12.js → styles-080da4f6-564d890e.js} +1 -1
  89. rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-46e1ca14.js → styles-3dcbcfbf-38957613.js} +1 -1
  90. rasa/core/channels/inspector/dist/assets/{styles-9c745c82-4a97439a.js → styles-9c745c82-f0fc6921.js} +1 -1
  91. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-823917a3.js → svgDrawCommon-4835440b-ef3c5a77.js} +1 -1
  92. rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-9ea72896.js → timeline-definition-5b62e21b-bf3e91c1.js} +1 -1
  93. rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-b631a8b6.js → xychartDiagram-2b33534f-4d4026c0.js} +1 -1
  94. rasa/core/channels/inspector/dist/index.html +1 -1
  95. rasa/core/channels/inspector/src/components/DiagramFlow.tsx +10 -0
  96. rasa/core/channels/inspector/src/helpers/formatters.test.ts +4 -7
  97. rasa/core/channels/inspector/src/helpers/formatters.ts +3 -2
  98. rasa/core/channels/rest.py +36 -21
  99. rasa/core/channels/rocketchat.py +0 -1
  100. rasa/core/channels/socketio.py +1 -1
  101. rasa/core/channels/telegram.py +3 -3
  102. rasa/core/channels/webexteams.py +0 -1
  103. rasa/core/concurrent_lock_store.py +1 -1
  104. rasa/core/evaluation/marker_base.py +1 -3
  105. rasa/core/evaluation/marker_stats.py +1 -2
  106. rasa/core/featurizers/single_state_featurizer.py +2 -4
  107. rasa/core/featurizers/tracker_featurizers.py +0 -7
  108. rasa/core/information_retrieval/__init__.py +7 -0
  109. rasa/core/information_retrieval/faiss.py +9 -4
  110. rasa/core/information_retrieval/information_retrieval.py +64 -7
  111. rasa/core/information_retrieval/milvus.py +7 -14
  112. rasa/core/information_retrieval/qdrant.py +8 -15
  113. rasa/core/lock_store.py +0 -1
  114. rasa/core/migrate.py +1 -2
  115. rasa/core/nlg/callback.py +3 -4
  116. rasa/core/policies/enterprise_search_policy.py +86 -22
  117. rasa/core/policies/enterprise_search_prompt_template.jinja2 +4 -41
  118. rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +60 -0
  119. rasa/core/policies/flows/flow_executor.py +104 -2
  120. rasa/core/policies/intentless_policy.py +7 -9
  121. rasa/core/policies/memoization.py +3 -3
  122. rasa/core/policies/policy.py +18 -9
  123. rasa/core/policies/rule_policy.py +8 -11
  124. rasa/core/policies/ted_policy.py +28 -30
  125. rasa/core/policies/unexpected_intent_policy.py +1 -2
  126. rasa/core/processor.py +136 -47
  127. rasa/core/run.py +41 -25
  128. rasa/core/secrets_manager/endpoints.py +2 -2
  129. rasa/core/secrets_manager/vault.py +6 -8
  130. rasa/core/test.py +3 -5
  131. rasa/core/tracker_store.py +49 -14
  132. rasa/core/train.py +1 -3
  133. rasa/core/training/interactive.py +9 -6
  134. rasa/core/utils.py +5 -10
  135. rasa/dialogue_understanding/coexistence/intent_based_router.py +11 -4
  136. rasa/dialogue_understanding/coexistence/llm_based_router.py +2 -3
  137. rasa/dialogue_understanding/commands/__init__.py +4 -0
  138. rasa/dialogue_understanding/commands/can_not_handle_command.py +9 -0
  139. rasa/dialogue_understanding/commands/cancel_flow_command.py +9 -0
  140. rasa/dialogue_understanding/commands/change_flow_command.py +38 -0
  141. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +9 -0
  142. rasa/dialogue_understanding/commands/clarify_command.py +9 -0
  143. rasa/dialogue_understanding/commands/correct_slots_command.py +9 -0
  144. rasa/dialogue_understanding/commands/error_command.py +12 -0
  145. rasa/dialogue_understanding/commands/handle_code_change_command.py +9 -0
  146. rasa/dialogue_understanding/commands/human_handoff_command.py +9 -0
  147. rasa/dialogue_understanding/commands/knowledge_answer_command.py +9 -0
  148. rasa/dialogue_understanding/commands/noop_command.py +9 -0
  149. rasa/dialogue_understanding/commands/set_slot_command.py +34 -3
  150. rasa/dialogue_understanding/commands/skip_question_command.py +9 -0
  151. rasa/dialogue_understanding/commands/start_flow_command.py +9 -0
  152. rasa/dialogue_understanding/generator/__init__.py +16 -1
  153. rasa/dialogue_understanding/generator/command_generator.py +92 -6
  154. rasa/dialogue_understanding/generator/constants.py +18 -0
  155. rasa/dialogue_understanding/generator/flow_retrieval.py +7 -5
  156. rasa/dialogue_understanding/generator/llm_based_command_generator.py +467 -0
  157. rasa/dialogue_understanding/generator/llm_command_generator.py +39 -609
  158. rasa/dialogue_understanding/generator/multi_step/__init__.py +0 -0
  159. rasa/dialogue_understanding/generator/multi_step/fill_slots_prompt.jinja2 +62 -0
  160. rasa/dialogue_understanding/generator/multi_step/handle_flows_prompt.jinja2 +38 -0
  161. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +827 -0
  162. rasa/dialogue_understanding/generator/nlu_command_adapter.py +69 -8
  163. rasa/dialogue_understanding/generator/single_step/__init__.py +0 -0
  164. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +345 -0
  165. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +44 -39
  166. rasa/dialogue_understanding/processor/command_processor.py +111 -3
  167. rasa/e2e_test/constants.py +1 -0
  168. rasa/e2e_test/e2e_test_case.py +44 -0
  169. rasa/e2e_test/e2e_test_runner.py +114 -11
  170. rasa/e2e_test/e2e_test_schema.yml +18 -0
  171. rasa/engine/caching.py +0 -1
  172. rasa/engine/graph.py +18 -6
  173. rasa/engine/recipes/config_files/default_config.yml +3 -3
  174. rasa/engine/recipes/default_components.py +1 -1
  175. rasa/engine/recipes/default_recipe.py +4 -5
  176. rasa/engine/recipes/recipe.py +1 -1
  177. rasa/engine/runner/dask.py +3 -9
  178. rasa/engine/storage/local_model_storage.py +0 -2
  179. rasa/engine/validation.py +179 -145
  180. rasa/exceptions.py +2 -2
  181. rasa/graph_components/validators/default_recipe_validator.py +3 -5
  182. rasa/hooks.py +0 -1
  183. rasa/model.py +1 -1
  184. rasa/model_training.py +1 -0
  185. rasa/nlu/classifiers/diet_classifier.py +8 -14
  186. rasa/nlu/extractors/crf_entity_extractor.py +4 -4
  187. rasa/nlu/extractors/duckling_entity_extractor.py +1 -1
  188. rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +1 -5
  189. rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +0 -4
  190. rasa/nlu/featurizers/featurizer.py +1 -1
  191. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +2 -4
  192. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +9 -12
  193. rasa/nlu/persistor.py +68 -26
  194. rasa/nlu/selectors/response_selector.py +7 -10
  195. rasa/nlu/test.py +0 -3
  196. rasa/nlu/utils/hugging_face/registry.py +1 -1
  197. rasa/nlu/utils/spacy_utils.py +1 -3
  198. rasa/server.py +22 -7
  199. rasa/shared/constants.py +12 -1
  200. rasa/shared/core/command_payload_reader.py +109 -0
  201. rasa/shared/core/constants.py +4 -5
  202. rasa/shared/core/domain.py +57 -56
  203. rasa/shared/core/events.py +4 -7
  204. rasa/shared/core/flows/flow.py +9 -0
  205. rasa/shared/core/flows/flows_list.py +12 -0
  206. rasa/shared/core/flows/steps/action.py +7 -2
  207. rasa/shared/core/generator.py +12 -11
  208. rasa/shared/core/slot_mappings.py +315 -24
  209. rasa/shared/core/slots.py +4 -2
  210. rasa/shared/core/trackers.py +32 -14
  211. rasa/shared/core/training_data/loading.py +0 -1
  212. rasa/shared/core/training_data/story_reader/story_reader.py +3 -3
  213. rasa/shared/core/training_data/story_reader/yaml_story_reader.py +11 -11
  214. rasa/shared/core/training_data/story_writer/yaml_story_writer.py +5 -3
  215. rasa/shared/core/training_data/structures.py +1 -1
  216. rasa/shared/core/training_data/visualization.py +1 -1
  217. rasa/shared/data.py +58 -1
  218. rasa/shared/exceptions.py +36 -2
  219. rasa/shared/importers/importer.py +1 -2
  220. rasa/shared/importers/rasa.py +0 -1
  221. rasa/shared/nlu/constants.py +2 -0
  222. rasa/shared/nlu/training_data/entities_parser.py +1 -2
  223. rasa/shared/nlu/training_data/formats/dialogflow.py +3 -2
  224. rasa/shared/nlu/training_data/formats/rasa_yaml.py +3 -5
  225. rasa/shared/nlu/training_data/formats/readerwriter.py +0 -1
  226. rasa/shared/nlu/training_data/message.py +13 -0
  227. rasa/shared/nlu/training_data/training_data.py +0 -2
  228. rasa/shared/providers/openai/session_handler.py +2 -2
  229. rasa/shared/utils/constants.py +3 -0
  230. rasa/shared/utils/io.py +11 -0
  231. rasa/shared/utils/llm.py +1 -2
  232. rasa/shared/utils/pykwalify_extensions.py +1 -0
  233. rasa/shared/utils/schemas/domain.yml +3 -0
  234. rasa/shared/utils/yaml.py +44 -35
  235. rasa/studio/auth.py +26 -10
  236. rasa/studio/constants.py +2 -0
  237. rasa/studio/data_handler.py +114 -107
  238. rasa/studio/download.py +160 -27
  239. rasa/studio/results_logger.py +137 -0
  240. rasa/studio/train.py +6 -7
  241. rasa/studio/upload.py +159 -134
  242. rasa/telemetry.py +188 -34
  243. rasa/tracing/config.py +18 -3
  244. rasa/tracing/constants.py +26 -2
  245. rasa/tracing/instrumentation/attribute_extractors.py +50 -41
  246. rasa/tracing/instrumentation/instrumentation.py +290 -44
  247. rasa/tracing/instrumentation/intentless_policy_instrumentation.py +7 -5
  248. rasa/tracing/instrumentation/metrics.py +109 -21
  249. rasa/tracing/metric_instrument_provider.py +83 -3
  250. rasa/utils/cli.py +2 -1
  251. rasa/utils/common.py +1 -1
  252. rasa/utils/endpoints.py +1 -2
  253. rasa/utils/io.py +6 -6
  254. rasa/utils/licensing.py +246 -31
  255. rasa/utils/ml_utils.py +1 -1
  256. rasa/utils/tensorflow/data_generator.py +1 -1
  257. rasa/utils/tensorflow/environment.py +1 -1
  258. rasa/utils/tensorflow/model_data.py +9 -11
  259. rasa/utils/tensorflow/model_data_utils.py +499 -500
  260. rasa/utils/tensorflow/models.py +5 -6
  261. rasa/utils/tensorflow/rasa_layers.py +15 -15
  262. rasa/utils/train_utils.py +1 -1
  263. rasa/utils/url_tools.py +53 -0
  264. rasa/validator.py +305 -3
  265. rasa/version.py +1 -1
  266. {rasa_pro-3.8.17.dist-info → rasa_pro-3.9.14.dist-info}/METADATA +22 -22
  267. {rasa_pro-3.8.17.dist-info → rasa_pro-3.9.14.dist-info}/RECORD +271 -253
  268. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-85583a23.js +0 -1
  269. /rasa/dialogue_understanding/generator/{command_prompt_template.jinja2 → single_step/command_prompt_template.jinja2} +0 -0
  270. {rasa_pro-3.8.17.dist-info → rasa_pro-3.9.14.dist-info}/NOTICE +0 -0
  271. {rasa_pro-3.8.17.dist-info → rasa_pro-3.9.14.dist-info}/WHEEL +0 -0
  272. {rasa_pro-3.8.17.dist-info → rasa_pro-3.9.14.dist-info}/entry_points.txt +0 -0
rasa/shared/data.py CHANGED
@@ -4,12 +4,33 @@ import tempfile
4
4
  import uuid
5
5
  from enum import Enum
6
6
  from pathlib import Path
7
- from typing import Text, Optional, Union, List, Callable, Set, Iterable
7
+ from typing import (
8
+ Any,
9
+ Protocol,
10
+ TYPE_CHECKING,
11
+ Text,
12
+ Optional,
13
+ Union,
14
+ List,
15
+ Callable,
16
+ Set,
17
+ Iterable,
18
+ runtime_checkable,
19
+ )
20
+
21
+ import structlog
22
+
23
+ if TYPE_CHECKING:
24
+ from rasa.core.channels import UserMessage
25
+ from rasa.shared.core.domain import Domain
26
+ from rasa.shared.nlu.training_data.message import Message
8
27
 
9
28
  YAML_FILE_EXTENSIONS = [".yml", ".yaml"]
10
29
  JSON_FILE_EXTENSIONS = [".json"]
11
30
  TRAINING_DATA_EXTENSIONS = set(JSON_FILE_EXTENSIONS + YAML_FILE_EXTENSIONS)
12
31
 
32
+ structlogger = structlog.get_logger()
33
+
13
34
 
14
35
  def yaml_file_extension() -> Text:
15
36
  """Return YAML file extension."""
@@ -190,3 +211,39 @@ class TrainingType(Enum):
190
211
  if self == TrainingType.CORE:
191
212
  return "core"
192
213
  return "rasa"
214
+
215
+
216
+ @runtime_checkable
217
+ class RegexReader(Protocol):
218
+ def unpack_regex_message(self, message: "Message", **kwargs: Any) -> "Message": ...
219
+
220
+
221
+ def create_regex_pattern_reader(
222
+ message: "UserMessage", domain: "Domain"
223
+ ) -> Optional[RegexReader]:
224
+ """Create a new instance of a class to unpack regex patterns.
225
+
226
+ Args:
227
+ message: The user message to unpack.
228
+ domain: The domain of the assistant.
229
+ """
230
+ from rasa.shared.core.command_payload_reader import CommandPayloadReader
231
+ from rasa.shared.core.training_data.story_reader.yaml_story_reader import (
232
+ YAMLStoryReader,
233
+ )
234
+
235
+ if message.text is None:
236
+ structlogger.warning(
237
+ "empty.user.message",
238
+ user_text="None",
239
+ )
240
+ return None
241
+
242
+ reader: Union[CommandPayloadReader, YAMLStoryReader, None] = None
243
+
244
+ if message.text.startswith("/SetSlots"):
245
+ reader = CommandPayloadReader()
246
+ elif message.text.startswith("/"):
247
+ reader = YAMLStoryReader(domain)
248
+
249
+ return reader if isinstance(reader, RegexReader) else None
rasa/shared/exceptions.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import json
2
- from typing import Optional, Text
2
+ from typing import Optional, Text, Dict, Any
3
3
 
4
4
  import jsonschema
5
5
  from ruamel.yaml.error import (
@@ -10,7 +10,7 @@ from ruamel.yaml.error import (
10
10
 
11
11
 
12
12
  class RasaException(Exception):
13
- """Base exception class for all errors raised by Rasa Open Source.
13
+ """Base exception class for all errors raised by Rasa Pro.
14
14
 
15
15
  These exceptions result from invalid use cases and will be reported
16
16
  to the users, but will be ignored in telemetry.
@@ -127,3 +127,37 @@ class ConnectionException(RasaException):
127
127
  It's used by our broker and tracker store classes, when
128
128
  they can't connect to services like postgres, dynamoDB, mongo.
129
129
  """
130
+
131
+
132
+ class ProviderClientAPIException(RasaException):
133
+ """Raised for errors that occur during API interactions
134
+ with LLM / embedding providers.
135
+
136
+ Attributes:
137
+ original_exception (Exception): The original exception that was
138
+ caught and led to this custom exception.
139
+ message: (Optional[str]): Optional explanation of the error.
140
+ """
141
+
142
+ def __init__(
143
+ self,
144
+ original_exception: Exception,
145
+ message: Optional[str] = None,
146
+ info: Optional[Dict[Text, Any]] = None,
147
+ ):
148
+ super().__init__(
149
+ f"{message if message is not None else ''}"
150
+ f"\nOriginal error: {original_exception})"
151
+ )
152
+ self.message = message
153
+ self.original_exception = original_exception
154
+ self.info = info
155
+
156
+ def __str__(self) -> Text:
157
+ s = f"{self.__class__.__name__}:"
158
+ if self.message is not None:
159
+ s += f"\n{self.message}"
160
+ s += f"\nOriginal error: {self.original_exception}\n"
161
+ if self.info:
162
+ s += f"\nInfo: \n{self.info}\n"
163
+ return s
@@ -581,7 +581,7 @@ class ResponsesSyncImporter(PassThroughImporter):
581
581
 
582
582
  @staticmethod
583
583
  def _get_nlu_data_with_responses(
584
- responses: Dict[Text, List[Dict[Text, Any]]]
584
+ responses: Dict[Text, List[Dict[Text, Any]]],
585
585
  ) -> TrainingData:
586
586
  """Construct training data object with only the responses supplied.
587
587
 
@@ -611,7 +611,6 @@ class E2EImporter(PassThroughImporter):
611
611
  return original.merge(e2e_domain)
612
612
 
613
613
  def _get_domain_with_e2e_actions(self) -> Domain:
614
-
615
614
  stories = self.get_stories()
616
615
 
617
616
  additional_e2e_action_names = set()
@@ -30,7 +30,6 @@ class RasaFileImporter(TrainingDataImporter):
30
30
  domain_path: Optional[Text] = None,
31
31
  training_data_paths: Optional[Union[List[Text], Text]] = None,
32
32
  ):
33
-
34
33
  self._domain_path = domain_path
35
34
 
36
35
  self._nlu_files = rasa.shared.data.get_data_files(
@@ -43,3 +43,5 @@ NO_ENTITY_TAG = "O"
43
43
  SPLIT_ENTITIES_BY_COMMA = "split_entities_by_comma"
44
44
  SPLIT_ENTITIES_BY_COMMA_DEFAULT_VALUE = True
45
45
  SINGLE_ENTITY_ALLOWED_INTERLEAVING_CHARSET = {".", ",", " ", ";"}
46
+
47
+ SET_SLOT_COMMAND = "set slot"
@@ -24,7 +24,7 @@ GROUP_COMPLETE_MATCH = 0
24
24
 
25
25
  # regex for: `[entity_text]((entity_type(:entity_synonym)?)|{entity_dict}|[list_entity_dicts])` # noqa: E501
26
26
  ENTITY_REGEX = re.compile(
27
- r"\[(?P<entity_text>[^\]]+?)\](\((?P<entity>[^:)]+?)(?:\:(?P<value>[^)]+))?\)|\{(?P<entity_dict>[^}]+?)\}|\[(?P<list_entity_dicts>.*?)\])" # noqa: E501
27
+ r"\[(?P<entity_text>[^\]]+?)\](\((?P<entity>[^:)]+?)(?:\:(?P<value>[^)]+))?\)|\{(?P<entity_dict>[^}]+?)\}|\[(?P<list_entity_dicts>.*?)\])"
28
28
  )
29
29
 
30
30
  SINGLE_ENTITY_DICT = re.compile(r"{(?P<entity_dict>[^}]+?)\}")
@@ -84,7 +84,6 @@ def find_entities_in_training_example(example: Text) -> List[Dict[Text, Any]]:
84
84
  for match_inner in re.finditer(
85
85
  SINGLE_ENTITY_DICT, match.groupdict()[GROUP_ENTITY_DICT_LIST]
86
86
  ):
87
-
88
87
  entity_attributes = extract_entity_attributes_from_dict(
89
88
  entity_text=entity_text, match=match_inner
90
89
  )
@@ -34,8 +34,9 @@ class DialogflowReader(TrainingDataReader):
34
34
 
35
35
  if fformat not in {DIALOGFLOW_INTENT, DIALOGFLOW_ENTITIES}:
36
36
  raise ValueError(
37
- "fformat must be either {}, or {}"
38
- "".format(DIALOGFLOW_INTENT, DIALOGFLOW_ENTITIES)
37
+ "fformat must be either {}, or {}".format(
38
+ DIALOGFLOW_INTENT, DIALOGFLOW_ENTITIES
39
+ )
39
40
  )
40
41
 
41
42
  root_js = rasa.shared.utils.io.read_json_file(filename)
@@ -108,7 +108,6 @@ class RasaYAMLReader(TrainingDataReader):
108
108
  )
109
109
 
110
110
  def _parse_nlu(self, nlu_data: Optional[List[Dict[Text, Any]]]) -> None:
111
-
112
111
  if not nlu_data:
113
112
  return
114
113
 
@@ -162,7 +161,6 @@ class RasaYAMLReader(TrainingDataReader):
162
161
  for example, entities, metadata in self._parse_training_examples(
163
162
  examples, intent
164
163
  ):
165
-
166
164
  plain_text = entities_parser.replace_entities(example)
167
165
 
168
166
  synonyms_parser.add_synonyms_from_entities(
@@ -534,9 +532,9 @@ class RasaYAMLWriter(TrainingDataWriter):
534
532
  )
535
533
 
536
534
  if examples_have_metadata or example_texts_have_escape_chars:
537
- intent[
538
- key_examples
539
- ] = RasaYAMLWriter._render_training_examples_as_objects(converted)
535
+ intent[key_examples] = (
536
+ RasaYAMLWriter._render_training_examples_as_objects(converted)
537
+ )
540
538
  else:
541
539
  intent[key_examples] = RasaYAMLWriter._render_training_examples_as_text(
542
540
  converted
@@ -122,7 +122,6 @@ class TrainingDataWriter:
122
122
  # format (e.g. `/greet{"name": "Rasa"}) and we don't have to add the NLU
123
123
  # entity annotation
124
124
  if not text.startswith(INTENT_MESSAGE_PREFIX):
125
-
126
125
  entities = message.get("entities", [])
127
126
  entities_with_start_and_end = [
128
127
  e for e in entities if "start" in e and "end" in e
@@ -6,6 +6,7 @@ import copy
6
6
  import rasa.shared.utils.io
7
7
  from rasa.shared.exceptions import RasaException
8
8
  from rasa.shared.nlu.constants import (
9
+ COMMANDS,
9
10
  TEXT,
10
11
  INTENT,
11
12
  RESPONSE,
@@ -475,3 +476,15 @@ class Message:
475
476
  else:
476
477
  break
477
478
  return overlapping_pairs
479
+
480
+ def has_intent(self) -> bool:
481
+ """Checks if the message has an intent."""
482
+ return self.data.get(INTENT) is not None
483
+
484
+ def has_commands(self) -> bool:
485
+ """Checks if the message has any commands."""
486
+ return self.data.get(COMMANDS) is not None
487
+
488
+ def starts_with_slash_syntax(self) -> bool:
489
+ """Checks if the message text starts with a slash syntax."""
490
+ return self.data.get(TEXT, "").strip().startswith("/")
@@ -47,7 +47,6 @@ class TrainingData:
47
47
  lookup_tables: Optional[List[Dict[Text, Any]]] = None,
48
48
  responses: Optional[Dict[Text, List[Dict[Text, Any]]]] = None,
49
49
  ) -> None:
50
-
51
50
  if training_examples:
52
51
  self.training_examples = self.sanitize_examples(training_examples)
53
52
  else:
@@ -339,7 +338,6 @@ class TrainingData:
339
338
  )
340
339
  assistant_utterances = self.responses.get(story_lookup_key, [])
341
340
  if assistant_utterances:
342
-
343
341
  # Use the first response text as training label if needed downstream
344
342
  for assistant_utterance in assistant_utterances:
345
343
  if assistant_utterance.get(TEXT):
@@ -6,7 +6,7 @@ from typing import Text
6
6
  import certifi
7
7
  import openai
8
8
  import structlog
9
- from aiohttp import TCPConnector, ClientSession
9
+ from aiohttp import ClientSession, TCPConnector
10
10
 
11
11
  structlogger = structlog.get_logger()
12
12
 
@@ -58,7 +58,7 @@ class OpenAISessionHandler:
58
58
  def _create_session(self) -> ClientSession:
59
59
  """
60
60
  Create client session with an SSL context
61
- created from the certificate path.
61
+ created from the certificate path
62
62
  """
63
63
  ssl_context = self._create_ssl_context()
64
64
  conn = TCPConnector(ssl=ssl_context)
@@ -1 +1,4 @@
1
1
  DEFAULT_ENCODING = "utf-8"
2
+
3
+ READ_YAML_FILE_CACHE_MAXSIZE_ENV_VAR = "READ_YAML_FILE_CACHE_MAXSIZE"
4
+ DEFAULT_READ_YAML_FILE_CACHE_MAXSIZE = 256
rasa/shared/utils/io.py CHANGED
@@ -401,3 +401,14 @@ def handle_print_blocking(output: Text) -> None:
401
401
  lock = AnsiToWin32(lock).stream
402
402
 
403
403
  print(output, file=lock, flush=True)
404
+
405
+
406
+ def file_as_bytes(file_path: Text) -> bytes:
407
+ """Read in a file as a byte array."""
408
+ try:
409
+ with open(file_path, "rb") as f:
410
+ return f.read()
411
+ except FileNotFoundError:
412
+ raise FileNotFoundException(
413
+ f"Failed to read file, " f"'{os.path.abspath(file_path)}' does not exist."
414
+ )
rasa/shared/utils/llm.py CHANGED
@@ -106,7 +106,6 @@ def tracker_as_readable_transcript(
106
106
  # using `applied_events` rather than `events` means that only events after the
107
107
  # most recent `Restart` or `SessionStarted` are included in the transcript
108
108
  for event in tracker.applied_events():
109
-
110
109
  if isinstance(event, UserUttered):
111
110
  if event.has_triggered_error:
112
111
  first_error = event.error_commands[0]
@@ -273,7 +272,7 @@ def llm_factory(
273
272
  # packages/langchain/llms/openai.py:189: UserWarning: You are trying to
274
273
  # use a chat model. This way of initializing it is no longer supported.
275
274
  # Instead, please use: `from langchain.chat_models import ChatOpenAI
276
- with (warnings.catch_warnings()):
275
+ with warnings.catch_warnings():
277
276
  warnings.simplefilter("ignore", category=UserWarning)
278
277
  if is_azure_config(config):
279
278
  # Azure deployments are treated differently. This is done as the
@@ -3,6 +3,7 @@ loaded as an extension of the pykwalify library:
3
3
 
4
4
  https://pykwalify.readthedocs.io/en/latest/extensions.html#extensions
5
5
  """
6
+
6
7
  from typing import Any, List, Dict, Text, Union
7
8
 
8
9
  from pykwalify.errors import SchemaError
@@ -109,6 +109,9 @@ mapping:
109
109
  nullable: True
110
110
  requested_slot:
111
111
  type: "str"
112
+ active_flow:
113
+ type: "str"
114
+ nullable: True
112
115
  forms:
113
116
  type: "map"
114
117
  required: False
rasa/shared/utils/yaml.py CHANGED
@@ -1,40 +1,25 @@
1
- from io import StringIO
2
- from pathlib import Path
3
- import re
4
- from collections import OrderedDict
5
1
  import logging
6
2
  import os
3
+ import re
4
+ from collections import OrderedDict
5
+ from dataclasses import dataclass
6
+ from dataclasses import field
7
+ from functools import lru_cache
8
+ from io import StringIO
9
+ from pathlib import Path
7
10
  from typing import Dict, List, Optional, Any, Callable, Tuple, Union
8
11
 
9
-
12
+ import jsonschema
10
13
  from importlib_resources import files
11
14
  from packaging import version
12
15
  from packaging.version import LegacyVersion
13
16
  from pykwalify.core import Core
14
17
  from pykwalify.errors import SchemaError
15
- from dataclasses import dataclass
16
- import jsonschema
17
- from dataclasses import field
18
+ from ruamel import yaml as yaml
18
19
  from ruamel.yaml import RoundTripRepresenter, YAMLError
19
20
  from ruamel.yaml.constructor import DuplicateKeyError, BaseConstructor, ScalarNode
20
- from ruamel import yaml as yaml
21
21
  from ruamel.yaml.comments import CommentedSeq, CommentedMap
22
22
 
23
- from rasa.shared.utils.constants import DEFAULT_ENCODING
24
- from rasa.shared.utils.io import (
25
- read_file,
26
- convert_to_ordered_dict,
27
- raise_warning,
28
- read_json_file,
29
- )
30
-
31
- from rasa.shared.exceptions import (
32
- YamlException,
33
- YamlSyntaxException,
34
- SchemaValidationError,
35
- RasaException,
36
- FileNotFoundException,
37
- )
38
23
  from rasa.shared.constants import (
39
24
  MODEL_CONFIG_SCHEMA_FILE,
40
25
  CONFIG_SCHEMA_FILE,
@@ -44,11 +29,32 @@ from rasa.shared.constants import (
44
29
  SCHEMA_EXTENSIONS_FILE,
45
30
  RESPONSES_SCHEMA_FILE,
46
31
  )
32
+ from rasa.shared.exceptions import (
33
+ YamlException,
34
+ YamlSyntaxException,
35
+ SchemaValidationError,
36
+ RasaException,
37
+ FileNotFoundException,
38
+ )
39
+ from rasa.shared.utils.constants import (
40
+ DEFAULT_ENCODING,
41
+ READ_YAML_FILE_CACHE_MAXSIZE_ENV_VAR,
42
+ DEFAULT_READ_YAML_FILE_CACHE_MAXSIZE,
43
+ )
44
+ from rasa.shared.utils.io import (
45
+ read_file,
46
+ convert_to_ordered_dict,
47
+ raise_warning,
48
+ read_json_file,
49
+ )
47
50
 
48
51
  logger = logging.getLogger(__name__)
49
52
 
50
53
  KEY_TRAINING_DATA_FORMAT_VERSION = "version"
51
54
  YAML_VERSION = (1, 2)
55
+ READ_YAML_FILE_CACHE_MAXSIZE = os.environ.get(
56
+ READ_YAML_FILE_CACHE_MAXSIZE_ENV_VAR, DEFAULT_READ_YAML_FILE_CACHE_MAXSIZE
57
+ )
52
58
 
53
59
 
54
60
  @dataclass
@@ -437,8 +443,9 @@ def _is_ascii(text: str) -> bool:
437
443
  return all(ord(character) < 128 for character in text)
438
444
 
439
445
 
446
+ @lru_cache(maxsize=READ_YAML_FILE_CACHE_MAXSIZE)
440
447
  def read_yaml_file(
441
- filename: Union[str, Path], reader_type: Union[str, List[str]] = "safe"
448
+ filename: Union[str, Path], reader_type: Union[str, Tuple[str]] = "safe"
442
449
  ) -> Union[List[Any], Dict[str, Any]]:
443
450
  """Parses a yaml file.
444
451
 
@@ -452,7 +459,10 @@ def read_yaml_file(
452
459
  Parsed content of the file.
453
460
  """
454
461
  try:
455
- return read_yaml(read_file(filename, DEFAULT_ENCODING), reader_type)
462
+ fixed_reader_type = (
463
+ list(reader_type) if isinstance(reader_type, tuple) else reader_type
464
+ )
465
+ return read_yaml(read_file(filename, DEFAULT_ENCODING), fixed_reader_type)
456
466
  except (YAMLError, DuplicateKeyError) as e:
457
467
  raise YamlSyntaxException(filename, e)
458
468
 
@@ -635,14 +645,14 @@ def validate_training_data_format_version(
635
645
  """Validates version on the training data content using `version` field.
636
646
 
637
647
  Warns users if the file is not compatible with the current version of
638
- Rasa Open Source.
648
+ Rasa Pro.
639
649
 
640
650
  Args:
641
651
  yaml_file_content: Raw content of training data file as a dictionary.
642
652
  filename: Name of the validated file.
643
653
 
644
654
  Returns:
645
- `True` if the file can be processed by current version of Rasa Open Source,
655
+ `True` if the file can be processed by current version of Rasa Pro,
646
656
  `False` otherwise.
647
657
  """
648
658
  if filename:
@@ -662,7 +672,7 @@ def validate_training_data_format_version(
662
672
  logger.info(
663
673
  f"The '{KEY_TRAINING_DATA_FORMAT_VERSION}' key is missing in "
664
674
  f"the training data file {filename}. "
665
- f"Rasa Open Source will read the file as a "
675
+ f"Rasa Pro will read the file as a "
666
676
  f"version '{LATEST_TRAINING_DATA_FORMAT_VERSION}' file. "
667
677
  f"See {DOCS_URL_TRAINING_DATA}."
668
678
  )
@@ -680,9 +690,9 @@ def validate_training_data_format_version(
680
690
  if parsed_version < latest_version:
681
691
  raise_warning(
682
692
  f"Training data file {filename} has a lower "
683
- f"format version than your Rasa Open Source installation: "
693
+ f"format version than your Rasa Pro installation: "
684
694
  f"{version_value} < {LATEST_TRAINING_DATA_FORMAT_VERSION}. "
685
- f"Rasa Open Source will read the file as a version "
695
+ f"Rasa Pro will read the file as a version "
686
696
  f"{LATEST_TRAINING_DATA_FORMAT_VERSION} file. "
687
697
  f"Please update your version key to "
688
698
  f"{LATEST_TRAINING_DATA_FORMAT_VERSION}. "
@@ -690,7 +700,6 @@ def validate_training_data_format_version(
690
700
  )
691
701
 
692
702
  if latest_version >= parsed_version:
693
-
694
703
  return True
695
704
 
696
705
  except TypeError:
@@ -699,7 +708,7 @@ def validate_training_data_format_version(
699
708
  f"'{KEY_TRAINING_DATA_FORMAT_VERSION}' as string, for example:\n"
700
709
  f"{KEY_TRAINING_DATA_FORMAT_VERSION}: "
701
710
  f"'{LATEST_TRAINING_DATA_FORMAT_VERSION}'\n"
702
- f"Rasa Open Source will read the file as a "
711
+ f"Rasa Pro will read the file as a "
703
712
  f"version '{LATEST_TRAINING_DATA_FORMAT_VERSION}' file.",
704
713
  docs=DOCS_URL_TRAINING_DATA,
705
714
  )
@@ -707,9 +716,9 @@ def validate_training_data_format_version(
707
716
 
708
717
  raise_warning(
709
718
  f"Training data file {filename} has a greater "
710
- f"format version than your Rasa Open Source installation: "
719
+ f"format version than your Rasa Pro installation: "
711
720
  f"{version_value} > {LATEST_TRAINING_DATA_FORMAT_VERSION}. "
712
- f"Please consider updating to the latest version of Rasa Open Source."
721
+ f"Please consider updating to the latest version of Rasa Pro."
713
722
  f"This file will be skipped.",
714
723
  docs=DOCS_URL_TRAINING_DATA,
715
724
  )
rasa/studio/auth.py CHANGED
@@ -6,7 +6,7 @@ from pathlib import Path
6
6
  from typing import Any, Dict, List, Optional, Text, Union
7
7
 
8
8
  import jwt
9
- from keycloak import KeycloakOpenID
9
+ from keycloak import KeycloakOpenID, KeycloakError
10
10
  from rasa.shared.exceptions import RasaException
11
11
  from rasa.shared.utils.yaml import read_yaml_file, write_yaml
12
12
 
@@ -17,6 +17,7 @@ from rasa.studio.constants import (
17
17
  KEYCLOAK_REFRESH_EXPIRES_IN_KEY,
18
18
  KEYCLOAK_REFRESH_TOKEN,
19
19
  )
20
+ from rasa.studio.results_logger import with_studio_error_handler, StudioResult
20
21
 
21
22
 
22
23
  class StudioAuth:
@@ -31,26 +32,39 @@ class StudioAuth:
31
32
  realm_name=studio_config.realm_name,
32
33
  )
33
34
 
34
- def login(self, username: Text, password: Text, totp: Optional[int] = None) -> None:
35
+ def health_check(self) -> bool:
36
+ """Check if the Keycloak server is reachable.
35
37
 
38
+ Returns:
39
+ True if the server is reachable, False otherwise.
40
+ """
36
41
  try:
37
- token_dict = self.keycloak_openid.token(
38
- username=username, password=password, totp=totp
39
- )
40
- except Exception as e:
41
- raise RasaException(f"Could not login. Error: {e}")
42
-
42
+ self.keycloak_openid.well_known()
43
+ return True
44
+ except Exception:
45
+ return False
46
+
47
+ @with_studio_error_handler
48
+ def login(
49
+ self, username: Text, password: Text, totp: Optional[int] = None
50
+ ) -> StudioResult:
51
+ token_dict = self.keycloak_openid.token(
52
+ username=username, password=password, totp=totp
53
+ )
43
54
  keycloak_token = self._resolve_token(token_dict)
44
55
 
45
56
  KeycloakTokenWriter.write_token_to_file(
46
57
  keycloak_token, token_file_location=DEFAULT_TOKEN_FILE_PATH
47
58
  )
48
59
 
49
- def refresh_token(self, refresh_token: Text) -> None:
60
+ return StudioResult.success("Login successful.")
61
+
62
+ @with_studio_error_handler
63
+ def refresh_token(self, refresh_token: Text) -> StudioResult:
50
64
  try:
51
65
  token_dict = self.keycloak_openid.refresh_token(refresh_token)
52
66
  except Exception as e:
53
- raise RasaException(f"Could not refresh token. Error: {e}")
67
+ raise KeycloakError(f"Could not refresh token. Error: {e}")
54
68
 
55
69
  keycloak_token = self._resolve_token(token_dict)
56
70
 
@@ -58,6 +72,8 @@ class StudioAuth:
58
72
  keycloak_token, token_file_location=DEFAULT_TOKEN_FILE_PATH
59
73
  )
60
74
 
75
+ return StudioResult.success("Token refreshed successfully.")
76
+
61
77
  @staticmethod
62
78
  def _resolve_token(token_dict: Dict[Text, Any]) -> KeycloakToken:
63
79
  return KeycloakToken(
rasa/studio/constants.py CHANGED
@@ -14,3 +14,5 @@ RASA_STUDIO_CLI_CLIENT_ID_KEY_ENV = "RASA_STUDIO_CLI_CLIENT_ID_KEY"
14
14
  STUDIO_NLU_FILENAME = "studio_nlu.yml"
15
15
  STUDIO_DOMAIN_FILENAME = "studio_domain.yml"
16
16
  STUDIO_FLOWS_FILENAME = "studio_flows.yml"
17
+ STUDIO_CONFIG_FILENAME = "studio_config.yml"
18
+ STUDIO_ENDPOINTS_FILENAME = "studio_endpoints.yml"