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
@@ -99,7 +99,6 @@ class CountVectorsFeaturizer(SparseFeaturizer, GraphComponent):
99
99
  return ["sklearn"]
100
100
 
101
101
  def _load_count_vect_params(self) -> None:
102
-
103
102
  # Use shared vocabulary between text and all other attributes of Message
104
103
  self.use_shared_vocab = self._config["use_shared_vocab"]
105
104
 
@@ -340,7 +339,7 @@ class CountVectorsFeaturizer(SparseFeaturizer, GraphComponent):
340
339
 
341
340
  @staticmethod
342
341
  def _convert_attribute_tokens_to_texts(
343
- attribute_tokens: Dict[Text, List[List[Text]]]
342
+ attribute_tokens: Dict[Text, List[List[Text]]],
344
343
  ) -> Dict[Text, List[Text]]:
345
344
  attribute_texts = {}
346
345
 
@@ -659,7 +658,6 @@ class CountVectorsFeaturizer(SparseFeaturizer, GraphComponent):
659
658
 
660
659
  for message in messages:
661
660
  for attribute in self._attributes:
662
-
663
661
  message_tokens = self._get_processed_message_tokens_by_attribute(
664
662
  message, attribute
665
663
  )
@@ -685,7 +683,7 @@ class CountVectorsFeaturizer(SparseFeaturizer, GraphComponent):
685
683
 
686
684
  @staticmethod
687
685
  def _is_any_model_trained(
688
- attribute_vocabularies: Dict[Text, Optional[Dict[Text, int]]]
686
+ attribute_vocabularies: Dict[Text, Optional[Dict[Text, int]]],
689
687
  ) -> bool:
690
688
  """Check if any model got trained."""
691
689
  return any(value is not None for value in attribute_vocabularies.values())
@@ -76,9 +76,7 @@ class LexicalSyntacticFeaturizer(SparseFeaturizer, GraphComponent):
76
76
 
77
77
  # NOTE: "suffix5" of the token "is" will be "is". Hence, when combining multiple
78
78
  # prefixes, short words will be represented/encoded repeatedly.
79
- _FUNCTION_DICT: Dict[
80
- Text, Callable[[Token], Union[Text, bool, None]]
81
- ] = { # noqa: RUF012
79
+ _FUNCTION_DICT: Dict[Text, Callable[[Token], Union[Text, bool, None]]] = { # noqa: RUF012
82
80
  "low": lambda token: token.text.islower(),
83
81
  "title": lambda token: token.text.istitle(),
84
82
  "prefix5": lambda token: token.text[:5],
@@ -329,7 +327,6 @@ class LexicalSyntacticFeaturizer(SparseFeaturizer, GraphComponent):
329
327
  assert len(window_range) == window_size
330
328
 
331
329
  for anchor in range(len(tokens)):
332
-
333
330
  token_features: Dict[Tuple[int, Text], Text] = {}
334
331
 
335
332
  for window_position, relative_position in enumerate(window_range):
@@ -341,13 +338,13 @@ class LexicalSyntacticFeaturizer(SparseFeaturizer, GraphComponent):
341
338
 
342
339
  token = tokens[absolute_position]
343
340
  for feature_name in self._feature_config[window_position]:
344
- token_features[
345
- (window_position, feature_name)
346
- ] = self._extract_raw_features_from_token(
347
- token=token,
348
- feature_name=feature_name,
349
- token_position=absolute_position,
350
- num_tokens=len(tokens),
341
+ token_features[(window_position, feature_name)] = (
342
+ self._extract_raw_features_from_token(
343
+ token=token,
344
+ feature_name=feature_name,
345
+ token_position=absolute_position,
346
+ num_tokens=len(tokens),
347
+ )
351
348
  )
352
349
 
353
350
  sentence_features.append(token_features)
@@ -356,7 +353,7 @@ class LexicalSyntacticFeaturizer(SparseFeaturizer, GraphComponent):
356
353
 
357
354
  @staticmethod
358
355
  def _build_feature_to_index_map(
359
- feature_vocabulary: Dict[Tuple[int, Text], Set[Text]]
356
+ feature_vocabulary: Dict[Tuple[int, Text], Set[Text]],
360
357
  ) -> Dict[Tuple[int, Text], Dict[Text, int]]:
361
358
  """Creates a nested dictionary for mapping raw features to indices.
362
359
 
rasa/nlu/persistor.py CHANGED
@@ -1,16 +1,18 @@
1
1
  import abc
2
- import logging
2
+ import structlog
3
3
  import os
4
4
  import shutil
5
5
  from typing import Optional, Text, Tuple, TYPE_CHECKING
6
6
 
7
+ from rasa.shared.exceptions import RasaException
8
+
7
9
  import rasa.shared.utils.common
8
10
  import rasa.utils.common
9
11
 
10
12
  if TYPE_CHECKING:
11
13
  from azure.storage.blob import ContainerClient
12
14
 
13
- logger = logging.getLogger(__name__)
15
+ structlogger = structlog.get_logger()
14
16
 
15
17
 
16
18
  def get_persistor(name: Text) -> Optional["Persistor"]:
@@ -95,7 +97,6 @@ class Persistor(abc.ABC):
95
97
 
96
98
  @staticmethod
97
99
  def _tar_name(model_name: Text, include_extension: bool = True) -> Text:
98
-
99
100
  ext = ".tar.gz" if include_extension else ""
100
101
  return f"{model_name}{ext}"
101
102
 
@@ -129,20 +130,36 @@ class AWSPersistor(Persistor):
129
130
  def _ensure_bucket_exists(
130
131
  self, bucket_name: Text, region_name: Optional[Text] = None
131
132
  ) -> None:
132
- import boto3
133
133
  import botocore
134
134
 
135
- if not region_name:
136
- region_name = boto3.DEFAULT_SESSION.region_name
137
-
138
- bucket_config = {"LocationConstraint": region_name}
139
135
  # noinspection PyUnresolvedReferences
140
136
  try:
141
- self.s3.create_bucket(
142
- Bucket=bucket_name, CreateBucketConfiguration=bucket_config
143
- )
144
- except botocore.exceptions.ClientError:
145
- pass # bucket already exists
137
+ self.s3.meta.client.head_bucket(Bucket=bucket_name)
138
+ except botocore.exceptions.ClientError as e:
139
+ error_code = int(e.response["Error"]["Code"])
140
+ if error_code == 403:
141
+ log = (
142
+ f"Access to the specified bucket '{bucket_name}' is forbidden. "
143
+ "Please make sure you have the necessary "
144
+ "permission to access the bucket."
145
+ )
146
+ structlogger.error(
147
+ "aws_persistor.ensure_bucket_exists.bucket_access_forbidden",
148
+ bucket_name=bucket_name,
149
+ event_info=log,
150
+ )
151
+ raise RasaException(log)
152
+ elif error_code == 404:
153
+ log = (
154
+ f"The specified bucket '{bucket_name}' does not exist. "
155
+ "Please make sure to create the bucket first."
156
+ )
157
+ structlogger.error(
158
+ "aws_persistor.ensure_bucket_exists.bucket_not_found",
159
+ bucket_name=bucket_name,
160
+ event_info=log,
161
+ )
162
+ raise RasaException(log)
146
163
 
147
164
  def _persist_tar(self, file_key: Text, tar_path: Text) -> None:
148
165
  """Uploads a model persisted in the `target_dir` to s3."""
@@ -180,10 +197,30 @@ class GCSPersistor(Persistor):
180
197
  from google.cloud import exceptions
181
198
 
182
199
  try:
183
- self.storage_client.create_bucket(bucket_name)
184
- except exceptions.Conflict:
185
- # bucket exists
186
- pass
200
+ self.storage_client.get_bucket(bucket_name)
201
+ except exceptions.NotFound:
202
+ log = (
203
+ f"The specified bucket '{bucket_name}' does not exist. "
204
+ "Please make sure to create the bucket first."
205
+ )
206
+ structlogger.error(
207
+ "gcp_persistor.ensure_bucket_exists.bucket_not_found",
208
+ bucket_name=bucket_name,
209
+ event_info=log,
210
+ )
211
+ raise RasaException(log)
212
+ except exceptions.Forbidden:
213
+ log = (
214
+ f"Access to the specified bucket '{bucket_name}' is forbidden. "
215
+ "Please make sure you have the necessary "
216
+ "permission to access the bucket. "
217
+ )
218
+ structlogger.error(
219
+ "gcp_persistor.ensure_bucket_exists.bucket_access_forbidden",
220
+ bucket_name=bucket_name,
221
+ event_info=log,
222
+ )
223
+ raise RasaException(log)
187
224
 
188
225
  def _persist_tar(self, file_key: Text, tar_path: Text) -> None:
189
226
  """Uploads a model persisted in the `target_dir` to GCS."""
@@ -210,18 +247,23 @@ class AzurePersistor(Persistor):
210
247
  account_url=f"https://{azure_account_name}.blob.core.windows.net/",
211
248
  credential=azure_account_key,
212
249
  )
213
-
214
- self._ensure_container_exists(azure_container)
215
250
  self.container_name = azure_container
251
+ self._ensure_container_exists()
216
252
 
217
- def _ensure_container_exists(self, container_name: Text) -> None:
218
- from azure.core.exceptions import ResourceExistsError
219
-
220
- try:
221
- self.blob_service.create_container(container_name)
222
- except ResourceExistsError:
223
- # no need to create the container, it already exists
253
+ def _ensure_container_exists(self) -> None:
254
+ if self._container_client().exists():
224
255
  pass
256
+ else:
257
+ log = (
258
+ f"The specified container '{self.container_name}' does not exist."
259
+ "Please make sure to create the container first."
260
+ )
261
+ structlogger.error(
262
+ "azure_persistor.ensure_container_exists.container_not_found",
263
+ container_name=self.container_name,
264
+ event_info=log,
265
+ )
266
+ raise RasaException(log)
225
267
 
226
268
  def _container_client(self) -> "ContainerClient":
227
269
  return self.blob_service.get_container_client(self.container_name)
@@ -430,9 +430,9 @@ class ResponseSelector(DIETClassifier):
430
430
  self, message: Message, prediction_dict: Dict[Text, Any], selector_key: Text
431
431
  ) -> None:
432
432
  message_selector_properties = message.get(RESPONSE_SELECTOR_PROPERTY_NAME, {})
433
- message_selector_properties[
434
- RESPONSE_SELECTOR_RETRIEVAL_INTENTS
435
- ] = self.all_retrieval_intents
433
+ message_selector_properties[RESPONSE_SELECTOR_RETRIEVAL_INTENTS] = (
434
+ self.all_retrieval_intents
435
+ )
436
436
  message_selector_properties[selector_key] = prediction_dict
437
437
  message.set(
438
438
  RESPONSE_SELECTOR_PROPERTY_NAME,
@@ -505,7 +505,6 @@ class ResponseSelector(DIETClassifier):
505
505
  been caught earlier and a warning should have been raised.
506
506
  """
507
507
  for key, responses in self.responses.items():
508
-
509
508
  # First check if the predicted label was the key itself
510
509
  search_key = util.template_key_to_intent_response_key(key)
511
510
  if search_key == label.get("name"):
@@ -626,7 +625,6 @@ class ResponseSelector(DIETClassifier):
626
625
  config: Dict[Text, Any],
627
626
  finetune_mode: bool = False,
628
627
  ) -> "RasaModel":
629
-
630
628
  predict_data_example = RasaModelData(
631
629
  label_key=model_data_example.label_key,
632
630
  data={
@@ -723,7 +721,6 @@ class DIET2BOW(DIET):
723
721
  logger.debug(f" {metric} ({name})")
724
722
 
725
723
  def _update_label_metrics(self, loss: tf.Tensor, acc: tf.Tensor) -> None:
726
-
727
724
  self.response_loss.update_state(loss)
728
725
  self.response_acc.update_state(acc)
729
726
 
@@ -796,10 +793,10 @@ class DIET2DIET(DIET):
796
793
  (self.text_name, self.config),
797
794
  (self.label_name, label_config),
798
795
  ]:
799
- self._tf_layers[
800
- f"sequence_layer.{attribute}"
801
- ] = rasa_layers.RasaSequenceLayer(
802
- attribute, self.data_signature[attribute], config
796
+ self._tf_layers[f"sequence_layer.{attribute}"] = (
797
+ rasa_layers.RasaSequenceLayer(
798
+ attribute, self.data_signature[attribute], config
799
+ )
803
800
  )
804
801
 
805
802
  if self.config[MASKED_LM]:
rasa/nlu/test.py CHANGED
@@ -886,7 +886,6 @@ def evaluate_entities(
886
886
  exclude_label=NO_ENTITY,
887
887
  )
888
888
  if output_directory:
889
-
890
889
  _dump_report(output_directory, f"{extractor}_report.json", report)
891
890
 
892
891
  if successes:
@@ -1550,7 +1549,6 @@ async def combine_result(
1550
1549
 
1551
1550
 
1552
1551
  def _contains_entity_labels(entity_results: List[EntityEvaluationResult]) -> bool:
1553
-
1554
1552
  for result in entity_results:
1555
1553
  if result.entity_targets or result.entity_predictions:
1556
1554
  return True
@@ -1791,7 +1789,6 @@ async def compare_nlu(
1791
1789
  training_examples_per_run = []
1792
1790
 
1793
1791
  for run in range(runs):
1794
-
1795
1792
  logger.info("Beginning comparison run {}/{}".format(run + 1, runs))
1796
1793
 
1797
1794
  run_path = os.path.join(output, "run_{}".format(run + 1))
@@ -25,7 +25,7 @@ from transformers import ( # noqa: E402
25
25
  RobertaTokenizer,
26
26
  CamembertTokenizer,
27
27
  )
28
- from rasa.nlu.utils.hugging_face.transformers_pre_post_processors import ( # noqa: E402, E501
28
+ from rasa.nlu.utils.hugging_face.transformers_pre_post_processors import ( # noqa: E402
29
29
  bert_tokens_pre_processor,
30
30
  gpt_tokens_pre_processor,
31
31
  xlnet_tokens_pre_processor,
@@ -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)