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
@@ -195,7 +195,7 @@ class SpacyNLP(GraphComponent):
195
195
 
196
196
  @staticmethod
197
197
  def _filter_training_samples_by_content(
198
- indexed_training_samples: List[Tuple[int, Text]]
198
+ indexed_training_samples: List[Tuple[int, Text]],
199
199
  ) -> Tuple[List[Tuple[int, Text]], List[Tuple[int, Text]]]:
200
200
  """Separates empty training samples from content bearing ones."""
201
201
  docs_to_pipe = list(
@@ -251,7 +251,6 @@ class SpacyNLP(GraphComponent):
251
251
  ) -> Dict[Text, List[Any]]:
252
252
  attribute_docs = {}
253
253
  for attribute in DENSE_FEATURIZABLE_ATTRIBUTES:
254
-
255
254
  texts = [
256
255
  self._get_text(e, attribute) for e in training_data.training_examples
257
256
  ]
@@ -288,7 +287,6 @@ class SpacyNLP(GraphComponent):
288
287
  attribute_docs = self._docs_for_training_data(model.model, training_data)
289
288
 
290
289
  for attribute in DENSE_FEATURIZABLE_ATTRIBUTES:
291
-
292
290
  for idx, example in enumerate(training_data.training_examples):
293
291
  example_attribute_doc = attribute_docs[attribute][idx]
294
292
  if len(example_attribute_doc):
rasa/server.py CHANGED
@@ -4,6 +4,7 @@ import logging
4
4
  import multiprocessing
5
5
  import os
6
6
  import traceback
7
+ import warnings
7
8
  from collections import defaultdict
8
9
  from functools import reduce, wraps
9
10
  from http import HTTPStatus
@@ -25,6 +26,12 @@ from typing import (
25
26
 
26
27
  import aiohttp
27
28
  import jsonschema
29
+ from sanic import Sanic, response
30
+ from sanic.request import Request
31
+ from sanic.response import HTTPResponse
32
+ from sanic_cors import CORS
33
+ from sanic_jwt import Initialize, exceptions
34
+
28
35
  import rasa
29
36
  import rasa.core.utils
30
37
  import rasa.nlu.test
@@ -70,11 +77,6 @@ from rasa.shared.utils.schemas.events import EVENTS_SCHEMA
70
77
  from rasa.shared.utils.yaml import validate_training_data
71
78
  from rasa.utils.common import TempDirectoryPath, get_temp_dir_name
72
79
  from rasa.utils.endpoints import EndpointConfig
73
- from sanic import Sanic, response
74
- from sanic.request import Request
75
- from sanic.response import HTTPResponse
76
- from sanic_cors import CORS
77
- from sanic_jwt import Initialize, exceptions
78
80
 
79
81
  if TYPE_CHECKING:
80
82
  from ssl import SSLContext
@@ -233,7 +235,6 @@ def requires_auth(
233
235
  async def decorated(
234
236
  request: Request, *args: Any, **kwargs: Any
235
237
  ) -> response.HTTPResponse:
236
-
237
238
  provided = request.args.get("token", None)
238
239
 
239
240
  # noinspection PyProtectedMember
@@ -518,7 +519,18 @@ def add_root_route(app: Sanic) -> None:
518
519
  @app.get("/")
519
520
  async def hello(request: Request) -> HTTPResponse:
520
521
  """Check if the server is running and responds with the version."""
521
- return response.text("Hello from Rasa: " + rasa.__version__)
522
+ html_content = f"""
523
+ <html>
524
+ <body>
525
+ <p>Hello from Rasa: {rasa.__version__}</p>
526
+ <a href="./webhooks/inspector/inspect.html">Go to the inspector</a>
527
+ <script>
528
+ window.location.replace("./webhooks/inspector/inspect.html");
529
+ </script>
530
+ </body>
531
+ </html>
532
+ """
533
+ return response.html(html_content)
522
534
 
523
535
 
524
536
  def async_if_callback_url(f: Callable[..., Coroutine]) -> Callable:
@@ -647,6 +659,9 @@ def create_app(
647
659
  app.config.RESPONSE_TIMEOUT = response_timeout
648
660
  configure_cors(app, cors_origins)
649
661
 
662
+ # Reset Sanic warnings filter that allows the triggering of Sanic warnings
663
+ warnings.filterwarnings("ignore", category=DeprecationWarning, module=r"sanic.*")
664
+
650
665
  # Set up the Sanic-JWT extension
651
666
  if jwt_secret and jwt_method:
652
667
  # `sanic-jwt` depends on having an available event loop when making the call to
rasa/shared/constants.py CHANGED
@@ -17,6 +17,7 @@ DOCS_URL_COMPONENTS = DOCS_URL_CONCEPTS + "/components/overview"
17
17
  DOCS_URL_GRAPH_COMPONENTS = DOCS_URL_CONCEPTS + "/components/custom-graph-components"
18
18
  DOCS_URL_GRAPH_RECIPE = DOCS_URL_CONCEPTS + "/components/graph-recipe"
19
19
  DOCS_URL_CATEGORICAL_SLOTS = DOCS_URL_CONCEPTS + "/domain#categorical-slot"
20
+ DOCS_URL_DOMAIN = DOCS_URL_CONCEPTS + "/domain"
20
21
 
21
22
  # Docs URLs for NLU-based assistants
22
23
  DOCS_URL_TRAINING_DATA = DOCS_URL_NLU_BASED + "/training-data-format"
@@ -77,6 +78,8 @@ DEFAULT_LOG_LEVEL_LLM = "DEBUG"
77
78
  ENV_LOG_LEVEL_LLM = "LOG_LEVEL_LLM"
78
79
  ENV_LOG_LEVEL_LLM_MODULE_NAMES = {
79
80
  "LLMCommandGenerator": "LOG_LEVEL_LLM_COMMAND_GENERATOR",
81
+ "SingleStepLLMCommandGenerator": "LOG_LEVEL_LLM_COMMAND_GENERATOR",
82
+ "MultiStepLLMCommandGenerator": "LOG_LEVEL_LLM_COMMAND_GENERATOR",
80
83
  "EnterpriseSearchPolicy": "LOG_LEVEL_LLM_ENTERPRISE_SEARCH",
81
84
  "IntentlessPolicy": "LOG_LEVEL_LLM_INTENTLESS_POLICY",
82
85
  "ContextualResponseRephraser": "LOG_LEVEL_LLM_REPHRASER",
@@ -109,7 +112,7 @@ CONFIG_MANDATORY_KEYS = CONFIG_MANDATORY_KEYS_CORE + CONFIG_MANDATORY_KEYS_NLU
109
112
  REQUIRED_SLOTS_KEY = "required_slots"
110
113
  IGNORED_INTENTS = "ignored_intents"
111
114
 
112
- # Constants for default Rasa Open Source project layout
115
+ # Constants for default Rasa Pro project layout
113
116
  DEFAULT_ENDPOINTS_PATH = "endpoints.yml"
114
117
  DEFAULT_CREDENTIALS_PATH = "credentials.yml"
115
118
  DEFAULT_CONFIG_PATH = "config.yml"
@@ -174,8 +177,16 @@ RASA_PATTERN_INTERNAL_ERROR_USER_INPUT_EMPTY = (
174
177
  RASA_PATTERN_CANNOT_HANDLE_PREFIX = "cannot_handle_"
175
178
  RASA_PATTERN_CANNOT_HANDLE_DEFAULT = RASA_PATTERN_CANNOT_HANDLE_PREFIX + "default"
176
179
  RASA_PATTERN_CANNOT_HANDLE_CHITCHAT = RASA_PATTERN_CANNOT_HANDLE_PREFIX + "chitchat"
180
+ RASA_PATTERN_CANNOT_HANDLE_NOT_SUPPORTED = (
181
+ RASA_PATTERN_CANNOT_HANDLE_PREFIX + "not_supported"
182
+ )
177
183
  RASA_PATTERN_CANNOT_HANDLE_INVALID_INTENT = (
178
184
  RASA_PATTERN_CANNOT_HANDLE_PREFIX + "invalid_intent"
179
185
  )
180
186
 
181
187
  ROUTE_TO_CALM_SLOT = "route_session_to_calm"
188
+ EMBEDDINGS_CONFIG_KEY = "embeddings"
189
+ MODEL_CONFIG_KEY = "model"
190
+ MODEL_NAME_CONFIG_KEY = "model_name"
191
+ PROMPT_CONFIG_KEY = "prompt"
192
+ PROMPT_TEMPLATE_CONFIG_KEY = "prompt_template"
@@ -0,0 +1,109 @@
1
+ import copy
2
+ import re
3
+ from typing import List, Optional
4
+
5
+ import structlog
6
+
7
+ from rasa.dialogue_understanding.commands.set_slot_command import SetSlotExtractor
8
+ from rasa.shared.core.domain import Domain
9
+ from rasa.shared.nlu.constants import COMMANDS, SET_SLOT_COMMAND, TEXT
10
+ from rasa.shared.nlu.training_data.message import Message
11
+
12
+ structlogger = structlog.get_logger()
13
+
14
+ SET_SLOTS_PATTERN = r"(?P<slot_name>[^(),=]+)=(?P<slot_value>[^(),]+)"
15
+ MAX_NUMBER_OF_SLOTS = 10
16
+
17
+
18
+ class CommandPayloadReader:
19
+ @staticmethod
20
+ def unpack_regex_message(
21
+ message: Message,
22
+ domain: Optional[Domain] = None,
23
+ entity_extractor_name: Optional[
24
+ str
25
+ ] = SetSlotExtractor.COMMAND_PAYLOAD_READER.value,
26
+ ) -> Message:
27
+ """Extracts commands from user text and adds them to the message."""
28
+ user_text = message.get(TEXT).strip()
29
+
30
+ # prevent ReDos attacks by placing a limit on the number of slots
31
+ if CommandPayloadReader.is_above_slot_limit(user_text):
32
+ return message
33
+
34
+ matches = CommandPayloadReader.find_matches(user_text)
35
+ if not matches:
36
+ structlogger.warning(
37
+ "message.parsing.failed", user_text=copy.deepcopy(user_text)
38
+ )
39
+ return message
40
+
41
+ return CommandPayloadReader.extract_commands_from_pattern_matches(
42
+ message, matches, domain, entity_extractor_name
43
+ )
44
+
45
+ @staticmethod
46
+ def find_matches(user_text: str) -> List[re.Match]:
47
+ return re.findall(SET_SLOTS_PATTERN, user_text)
48
+
49
+ @staticmethod
50
+ def extract_commands_from_pattern_matches(
51
+ message: Message,
52
+ matches: List[re.Match],
53
+ domain: Optional[Domain] = None,
54
+ entity_extractor_name: Optional[
55
+ str
56
+ ] = SetSlotExtractor.COMMAND_PAYLOAD_READER.value,
57
+ ) -> Message:
58
+ """Extract attributes from the matches and validate them via the domain."""
59
+ commands = []
60
+
61
+ for match in matches:
62
+ slot_name = match[0].strip()
63
+ slot_value = match[1].strip()
64
+
65
+ domain_slot_names = [slot.name for slot in domain.slots] if domain else []
66
+
67
+ if domain and slot_name not in domain_slot_names:
68
+ structlogger.warning(
69
+ "slot.not.found",
70
+ slot_name=slot_name,
71
+ )
72
+ return message
73
+
74
+ slot_value = (
75
+ slot_value
76
+ if slot_value.lower() not in {"none", "null", "undefined"}
77
+ else None
78
+ )
79
+
80
+ # Create new SetSlot commands from the extracted attributes.
81
+ commands.append(
82
+ {
83
+ "command": SET_SLOT_COMMAND,
84
+ "name": slot_name,
85
+ "value": slot_value,
86
+ "extractor": entity_extractor_name,
87
+ }
88
+ )
89
+
90
+ structlogger.debug(
91
+ "slot.set.command.added",
92
+ slot_name=slot_name,
93
+ )
94
+
95
+ # set the command(s) on the Message object
96
+ message.set(COMMANDS, commands, add_to_output=True)
97
+ return message
98
+
99
+ @staticmethod
100
+ def is_above_slot_limit(user_text: str) -> bool:
101
+ """Prevent ReDoS attacks by limiting the number of slots."""
102
+ if user_text.count("=") > MAX_NUMBER_OF_SLOTS:
103
+ structlogger.warning(
104
+ "too.many.slots",
105
+ user_text=copy.deepcopy(user_text),
106
+ slot_limit=10,
107
+ )
108
+ return True
109
+ return False
@@ -85,6 +85,7 @@ LOOP_INTERRUPTED = "is_interrupted"
85
85
  LOOP_REJECTED = "rejected"
86
86
  TRIGGER_MESSAGE = "trigger_message"
87
87
  FOLLOWUP_ACTION = "followup_action"
88
+ ACTIVE_FLOW = "active_flow"
88
89
 
89
90
  # start of special user message section
90
91
  EXTERNAL_MESSAGE_PREFIX = "EXTERNAL: "
@@ -130,6 +131,7 @@ class SlotMappingType(Enum):
130
131
  FROM_INTENT = "from_intent"
131
132
  FROM_TRIGGER_INTENT = "from_trigger_intent"
132
133
  FROM_TEXT = "from_text"
134
+ FROM_LLM = "from_llm"
133
135
  CUSTOM = "custom"
134
136
 
135
137
  def __str__(self) -> str:
@@ -137,11 +139,8 @@ class SlotMappingType(Enum):
137
139
  return self.value
138
140
 
139
141
  def is_predefined_type(self) -> bool:
140
- """Returns True iff the mapping type is predefined.
141
-
142
- That is, to evaluate the mapping no custom action execution is needed.
143
- """
144
- return self != SlotMappingType.CUSTOM
142
+ """Returns True if the mapping type is NLU-predefined."""
143
+ return not (self == SlotMappingType.CUSTOM or self == SlotMappingType.FROM_LLM)
145
144
 
146
145
 
147
146
  # the keys for `State` (USER, PREVIOUS_ACTION, SLOTS, ACTIVE_LOOP)
@@ -1,85 +1,84 @@
1
- import copy
2
1
  import collections
2
+ import copy
3
3
  import json
4
- import structlog
5
4
  import os
5
+ from dataclasses import dataclass
6
6
  from pathlib import Path
7
7
  from typing import (
8
+ TYPE_CHECKING,
8
9
  Any,
10
+ Callable,
9
11
  Dict,
12
+ Iterable,
10
13
  List,
14
+ MutableMapping,
15
+ NamedTuple,
11
16
  NoReturn,
12
17
  Optional,
13
18
  Set,
14
19
  Text,
15
20
  Tuple,
16
21
  Union,
17
- TYPE_CHECKING,
18
- Iterable,
19
- MutableMapping,
20
- NamedTuple,
21
- Callable,
22
22
  cast,
23
23
  )
24
- from dataclasses import dataclass
25
24
 
25
+ import structlog
26
26
  from ruamel.yaml.scalarstring import DoubleQuotedScalarString
27
27
 
28
+ import rasa.shared.core.slot_mappings
29
+ import rasa.shared.utils.common
30
+ import rasa.shared.utils.io
28
31
  from rasa.shared.constants import (
29
- DEFAULT_SESSION_EXPIRATION_TIME_IN_MINUTES,
30
32
  DEFAULT_CARRY_OVER_SLOTS_TO_NEW_SESSION,
31
- DOMAIN_SCHEMA_FILE,
33
+ DEFAULT_SESSION_EXPIRATION_TIME_IN_MINUTES,
32
34
  DOCS_URL_DOMAINS,
33
35
  DOCS_URL_FORMS,
34
- LATEST_TRAINING_DATA_FORMAT_VERSION,
35
36
  DOCS_URL_RESPONSES,
36
- REQUIRED_SLOTS_KEY,
37
+ DOMAIN_SCHEMA_FILE,
37
38
  IGNORED_INTENTS,
39
+ LATEST_TRAINING_DATA_FORMAT_VERSION,
40
+ REQUIRED_SLOTS_KEY,
38
41
  RESPONSE_CONDITION,
39
42
  )
40
43
  from rasa.shared.core.constants import (
41
44
  ACTION_SHOULD_SEND_DOMAIN,
45
+ ACTIVE_LOOP,
46
+ KNOWLEDGE_BASE_SLOT_NAMES,
47
+ MAPPING_CONDITIONS,
48
+ MAPPING_TYPE,
42
49
  SLOT_MAPPINGS,
43
50
  SlotMappingType,
44
- MAPPING_TYPE,
45
- MAPPING_CONDITIONS,
46
- KNOWLEDGE_BASE_SLOT_NAMES,
47
- ACTIVE_LOOP,
51
+ )
52
+ from rasa.shared.core.events import SlotSet, UserUttered
53
+ from rasa.shared.core.slots import (
54
+ AnySlot,
55
+ CategoricalSlot,
56
+ ListSlot,
57
+ Slot,
58
+ TextSlot,
48
59
  )
49
60
  from rasa.shared.exceptions import (
50
61
  RasaException,
51
62
  YamlException,
52
63
  YamlSyntaxException,
53
64
  )
54
- from rasa.shared.utils.cli import print_error_and_exit
55
- import rasa.shared.utils.io
56
- import rasa.shared.utils.common
57
- import rasa.shared.core.slot_mappings
58
- from rasa.shared.core.events import SlotSet, UserUttered
59
- from rasa.shared.core.slots import (
60
- Slot,
61
- CategoricalSlot,
62
- TextSlot,
63
- AnySlot,
64
- ListSlot,
65
+ from rasa.shared.nlu.constants import (
66
+ ENTITIES,
67
+ ENTITY_ATTRIBUTE_GROUP,
68
+ ENTITY_ATTRIBUTE_ROLE,
69
+ ENTITY_ATTRIBUTE_TYPE,
70
+ INTENT_NAME_KEY,
71
+ RESPONSE_IDENTIFIER_DELIMITER,
65
72
  )
73
+ from rasa.shared.utils.cli import print_error_and_exit
66
74
  from rasa.shared.utils.yaml import (
67
75
  KEY_TRAINING_DATA_FORMAT_VERSION,
76
+ dump_obj_as_yaml_to_string,
68
77
  read_yaml,
69
- validate_training_data_format_version,
70
78
  read_yaml_file,
71
- dump_obj_as_yaml_to_string,
72
79
  validate_raw_yaml_using_schema_file_with_responses,
80
+ validate_training_data_format_version,
73
81
  )
74
- from rasa.shared.nlu.constants import (
75
- ENTITY_ATTRIBUTE_TYPE,
76
- ENTITY_ATTRIBUTE_ROLE,
77
- ENTITY_ATTRIBUTE_GROUP,
78
- RESPONSE_IDENTIFIER_DELIMITER,
79
- INTENT_NAME_KEY,
80
- ENTITIES,
81
- )
82
-
83
82
 
84
83
  if TYPE_CHECKING:
85
84
  from rasa.shared.core.trackers import DialogueStateTracker
@@ -316,7 +315,6 @@ class Domain:
316
315
 
317
316
  for root, _, files in os.walk(path, followlinks=True):
318
317
  for file in files:
319
-
320
318
  full_path = os.path.join(root, file)
321
319
  if not Domain.is_domain_file(full_path):
322
320
  continue
@@ -335,7 +333,7 @@ class Domain:
335
333
 
336
334
  @staticmethod
337
335
  def _handle_duplicates_from_multiple_files(
338
- duplicates_from_multiple_files: List[Dict[Text, List[Text]]]
336
+ duplicates_from_multiple_files: List[Dict[Text, List[Text]]],
339
337
  ) -> None:
340
338
  combined_duplicates: Dict[Text, List[Text]] = collections.defaultdict(list)
341
339
 
@@ -560,10 +558,12 @@ class Domain:
560
558
  "domain.collect_slots.no_mappings_defined",
561
559
  event_info=(
562
560
  f"Slot '{slot_name}' has no mappings defined. "
563
- f"We will continue with an empty list of mappings."
561
+ f"Assigning the default FROM_LLM slot mapping."
564
562
  ),
565
563
  )
566
- slot_dict[slot_name][SLOT_MAPPINGS] = []
564
+ slot_dict[slot_name][SLOT_MAPPINGS] = [
565
+ {MAPPING_TYPE: SlotMappingType.FROM_LLM.value}
566
+ ]
567
567
 
568
568
  slot = slot_class(slot_name, **slot_dict[slot_name])
569
569
  slots.append(slot)
@@ -922,7 +922,7 @@ class Domain:
922
922
 
923
923
  @staticmethod
924
924
  def _collect_overridden_default_intents(
925
- intents: Union[Set[Text], List[Text], List[Dict[Text, Any]]]
925
+ intents: Union[Set[Text], List[Text], List[Dict[Text, Any]]],
926
926
  ) -> List[Text]:
927
927
  """Collects the default intents overridden by the user.
928
928
 
@@ -942,7 +942,7 @@ class Domain:
942
942
 
943
943
  @staticmethod
944
944
  def _initialize_forms(
945
- forms: Dict[Text, Any]
945
+ forms: Dict[Text, Any],
946
946
  ) -> Tuple[List[Text], Dict[Text, Any], List[Text]]:
947
947
  """Retrieves the initial values for the Domain's form fields.
948
948
 
@@ -952,7 +952,7 @@ class Domain:
952
952
  Returns:
953
953
  The form names, a mapping of form names and required slots, and custom
954
954
  actions.
955
- Returning custom actions for each forms means that Rasa Open Source should
955
+ Returning custom actions for each forms means that Rasa Pro should
956
956
  not use the default `FormAction` for the forms, but rather a custom action
957
957
  for it. This can e.g. be used to run the deprecated Rasa Open Source 1
958
958
  `FormAction` which is implemented in the Rasa SDK.
@@ -966,6 +966,7 @@ class Domain:
966
966
  """Returns a unique hash for the domain."""
967
967
  return int(self.fingerprint(), 16)
968
968
 
969
+ @rasa.shared.utils.common.cached_method
969
970
  def fingerprint(self) -> Text:
970
971
  """Returns a unique hash for the domain which is stable across python runs.
971
972
 
@@ -986,7 +987,7 @@ class Domain:
986
987
 
987
988
  @staticmethod
988
989
  def _sort_intent_names_alphabetical_order(
989
- intents: List[Union[Text, Dict]]
990
+ intents: List[Union[Text, Dict]],
990
991
  ) -> List[Union[Text, Dict]]:
991
992
  def sort(elem: Union[Text, Dict]) -> Union[Text, Dict]:
992
993
  if isinstance(elem, dict):
@@ -1027,7 +1028,7 @@ class Domain:
1027
1028
 
1028
1029
  @staticmethod
1029
1030
  def is_retrieval_intent_response(
1030
- response: Tuple[Text, List[Dict[Text, Any]]]
1031
+ response: Tuple[Text, List[Dict[Text, Any]]],
1031
1032
  ) -> bool:
1032
1033
  """Check if the response is for a retrieval intent.
1033
1034
 
@@ -1603,7 +1604,7 @@ class Domain:
1603
1604
 
1604
1605
  @staticmethod
1605
1606
  def get_responses_with_multilines(
1606
- responses: Dict[Text, List[Dict[Text, Any]]]
1607
+ responses: Dict[Text, List[Dict[Text, Any]]],
1607
1608
  ) -> Dict[Text, List[Dict[Text, Any]]]:
1608
1609
  """Returns `responses` with preserved multilines in the `text` key.
1609
1610
 
@@ -1622,9 +1623,9 @@ class Domain:
1622
1623
  if not response_text or "\n" not in response_text:
1623
1624
  continue
1624
1625
  # Has new lines, use `LiteralScalarString`
1625
- final_responses[utter_action][i][
1626
- KEY_RESPONSES_TEXT
1627
- ] = LiteralScalarString(response_text)
1626
+ final_responses[utter_action][i][KEY_RESPONSES_TEXT] = (
1627
+ LiteralScalarString(response_text)
1628
+ )
1628
1629
 
1629
1630
  return final_responses
1630
1631
 
@@ -1802,7 +1803,7 @@ class Domain:
1802
1803
  ]
1803
1804
 
1804
1805
  def check_mappings(
1805
- intent_properties: Dict[Text, Dict[Text, Union[bool, List]]]
1806
+ intent_properties: Dict[Text, Dict[Text, Union[bool, List]]],
1806
1807
  ) -> List[Tuple[Text, Text]]:
1807
1808
  """Checks whether intent-action mappings use valid action names or texts."""
1808
1809
  incorrect = []
@@ -1840,7 +1841,7 @@ class Domain:
1840
1841
  return message
1841
1842
 
1842
1843
  def get_duplicate_exception_message(
1843
- duplicates: List[Tuple[List[Text], Text]]
1844
+ duplicates: List[Tuple[List[Text], Text]],
1844
1845
  ) -> Text:
1845
1846
  """Return a message given a list of duplicates."""
1846
1847
  message = ""
@@ -2014,7 +2015,7 @@ class Domain:
2014
2015
 
2015
2016
  @staticmethod
2016
2017
  def _collect_action_names(
2017
- actions: List[Union[Text, Dict[Text, Any]]]
2018
+ actions: List[Union[Text, Dict[Text, Any]]],
2018
2019
  ) -> List[Text]:
2019
2020
  action_names: List[Text] = []
2020
2021
 
@@ -2028,7 +2029,7 @@ class Domain:
2028
2029
 
2029
2030
  @staticmethod
2030
2031
  def _collect_actions_which_explicitly_need_domain(
2031
- actions: List[Union[Text, Dict[Text, Any]]]
2032
+ actions: List[Union[Text, Dict[Text, Any]]],
2032
2033
  ) -> List[Text]:
2033
2034
  action_names: List[Text] = []
2034
2035
 
@@ -2048,7 +2049,7 @@ class Domain:
2048
2049
 
2049
2050
 
2050
2051
  def warn_about_duplicates_found_during_domain_merging(
2051
- duplicates: Dict[str, List[str]]
2052
+ duplicates: Dict[Text, List[Text]],
2052
2053
  ) -> None:
2053
2054
  """Emits a warning about found duplicates while loading multiple domain paths."""
2054
2055
  domain_keys = [
@@ -86,7 +86,8 @@ if TYPE_CHECKING:
86
86
  )
87
87
 
88
88
  IntentPrediction = TypedDict(
89
- "IntentPrediction", {INTENT_NAME_KEY: Text, PREDICTED_CONFIDENCE_KEY: float} # type: ignore[misc] # noqa: E501
89
+ "IntentPrediction",
90
+ {INTENT_NAME_KEY: Text, PREDICTED_CONFIDENCE_KEY: float}, # type: ignore[misc]
90
91
  )
91
92
  NLUPredictionData = TypedDict(
92
93
  "NLUPredictionData",
@@ -317,7 +318,6 @@ class Event(ABC):
317
318
  def from_parameters(
318
319
  parameters: Dict[Text, Any], default: Optional[Type["Event"]] = None
319
320
  ) -> Optional["Event"]:
320
-
321
321
  event_name = parameters.get("event")
322
322
  if event_name is None:
323
323
  return None
@@ -533,7 +533,8 @@ class UserUttered(Event):
533
533
  def commands(self) -> List[Dict[str, Any]]:
534
534
  """Returns commands included in the message."""
535
535
  if COMMANDS in self.parse_data and isinstance(
536
- self.parse_data[COMMANDS], list # type: ignore[literal-required]
536
+ self.parse_data[COMMANDS], # type: ignore[literal-required]
537
+ list,
537
538
  ):
538
539
  return self.parse_data[COMMANDS] # type: ignore[literal-required]
539
540
  return []
@@ -1040,7 +1041,6 @@ class SlotSet(Event):
1040
1041
  def _from_story_string(
1041
1042
  cls, parameters: Dict[Text, Any]
1042
1043
  ) -> Optional[List["SlotSet"]]:
1043
-
1044
1044
  slots = []
1045
1045
  for slot_key, slot_val in parameters.items():
1046
1046
  slots.append(SlotSet(slot_key, slot_val))
@@ -1193,7 +1193,6 @@ class DialogueStackUpdated(Event):
1193
1193
  def _from_story_string(
1194
1194
  cls, parameters: Dict[Text, Any]
1195
1195
  ) -> Optional[List["DialogueStackUpdated"]]:
1196
-
1197
1196
  return [
1198
1197
  DialogueStackUpdated(
1199
1198
  parameters.get("update"),
@@ -1315,7 +1314,6 @@ class ReminderScheduled(Event):
1315
1314
  def _from_story_string(
1316
1315
  cls, parameters: Dict[Text, Any]
1317
1316
  ) -> Optional[List["ReminderScheduled"]]:
1318
-
1319
1317
  trigger_date_time = parser.parse(parameters.get("date_time"))
1320
1318
 
1321
1319
  return [
@@ -1567,7 +1565,6 @@ class FollowupAction(Event):
1567
1565
  def _from_story_string(
1568
1566
  cls, parameters: Dict[Text, Any]
1569
1567
  ) -> Optional[List["FollowupAction"]]:
1570
-
1571
1568
  return [
1572
1569
  FollowupAction(
1573
1570
  parameters.get("name"),
@@ -222,6 +222,15 @@ class Flow:
222
222
  *[step.utterances for step in self.step_sequence.steps_with_calls_resolved]
223
223
  )
224
224
 
225
+ @property
226
+ def custom_actions(self) -> Set[str]:
227
+ """Retrieve all custom actions of this flow."""
228
+ return {
229
+ step.custom_action
230
+ for step in self.step_sequence.steps_with_calls_resolved
231
+ if isinstance(step, ActionFlowStep) and step.custom_action is not None
232
+ }
233
+
225
234
  @property
226
235
  def name(self) -> str:
227
236
  """Create a default name if none is present."""
@@ -209,3 +209,15 @@ class FlowsList:
209
209
  return FlowsList(
210
210
  [f for f in self.underlying_flows if not f.is_startable_only_via_link()]
211
211
  )
212
+
213
+ def available_slot_names(self) -> Set[str]:
214
+ """Get all slot names collected by flows."""
215
+ return {
216
+ step.collect
217
+ for flow in self.underlying_flows
218
+ for step in flow.get_collect_steps()
219
+ }
220
+
221
+ def available_custom_actions(self) -> Set[str]:
222
+ """Get all custom actions collected by flows."""
223
+ return set().union(*[flow.custom_actions for flow in self.underlying_flows])
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
- from typing import Text, Dict, Any, Set
4
+ from typing import Optional, Text, Dict, Any, Set
5
5
 
6
6
  from rasa.shared.constants import UTTER_PREFIX
7
7
  from rasa.shared.core.flows.flow_step import FlowStep
@@ -47,5 +47,10 @@ class ActionFlowStep(FlowStep):
47
47
 
48
48
  @property
49
49
  def utterances(self) -> Set[str]:
50
- """Return all the utterances used in this step"""
50
+ """Return all the utterances used in this step."""
51
51
  return {self.action} if self.action.startswith(UTTER_PREFIX) else set()
52
+
53
+ @property
54
+ def custom_action(self) -> Optional[str]:
55
+ """Return all the custom actions used in this step."""
56
+ return self.action if not self.action.startswith(UTTER_PREFIX) else None