rasa-pro 3.12.0.dev1__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 (790) hide show
  1. README.md +41 -0
  2. rasa/__init__.py +9 -0
  3. rasa/__main__.py +177 -0
  4. rasa/anonymization/__init__.py +2 -0
  5. rasa/anonymization/anonymisation_rule_yaml_reader.py +91 -0
  6. rasa/anonymization/anonymization_pipeline.py +286 -0
  7. rasa/anonymization/anonymization_rule_executor.py +260 -0
  8. rasa/anonymization/anonymization_rule_orchestrator.py +120 -0
  9. rasa/anonymization/schemas/config.yml +47 -0
  10. rasa/anonymization/utils.py +118 -0
  11. rasa/api.py +160 -0
  12. rasa/cli/__init__.py +5 -0
  13. rasa/cli/arguments/__init__.py +0 -0
  14. rasa/cli/arguments/data.py +106 -0
  15. rasa/cli/arguments/default_arguments.py +207 -0
  16. rasa/cli/arguments/evaluate.py +65 -0
  17. rasa/cli/arguments/export.py +51 -0
  18. rasa/cli/arguments/interactive.py +74 -0
  19. rasa/cli/arguments/run.py +219 -0
  20. rasa/cli/arguments/shell.py +17 -0
  21. rasa/cli/arguments/test.py +211 -0
  22. rasa/cli/arguments/train.py +279 -0
  23. rasa/cli/arguments/visualize.py +34 -0
  24. rasa/cli/arguments/x.py +30 -0
  25. rasa/cli/data.py +354 -0
  26. rasa/cli/dialogue_understanding_test.py +251 -0
  27. rasa/cli/e2e_test.py +259 -0
  28. rasa/cli/evaluate.py +222 -0
  29. rasa/cli/export.py +250 -0
  30. rasa/cli/inspect.py +75 -0
  31. rasa/cli/interactive.py +166 -0
  32. rasa/cli/license.py +65 -0
  33. rasa/cli/llm_fine_tuning.py +403 -0
  34. rasa/cli/markers.py +78 -0
  35. rasa/cli/project_templates/__init__.py +0 -0
  36. rasa/cli/project_templates/calm/actions/__init__.py +0 -0
  37. rasa/cli/project_templates/calm/actions/action_template.py +27 -0
  38. rasa/cli/project_templates/calm/actions/add_contact.py +30 -0
  39. rasa/cli/project_templates/calm/actions/db.py +57 -0
  40. rasa/cli/project_templates/calm/actions/list_contacts.py +22 -0
  41. rasa/cli/project_templates/calm/actions/remove_contact.py +35 -0
  42. rasa/cli/project_templates/calm/config.yml +10 -0
  43. rasa/cli/project_templates/calm/credentials.yml +33 -0
  44. rasa/cli/project_templates/calm/data/flows/add_contact.yml +31 -0
  45. rasa/cli/project_templates/calm/data/flows/list_contacts.yml +14 -0
  46. rasa/cli/project_templates/calm/data/flows/remove_contact.yml +29 -0
  47. rasa/cli/project_templates/calm/db/contacts.json +10 -0
  48. rasa/cli/project_templates/calm/domain/add_contact.yml +39 -0
  49. rasa/cli/project_templates/calm/domain/list_contacts.yml +17 -0
  50. rasa/cli/project_templates/calm/domain/remove_contact.yml +38 -0
  51. rasa/cli/project_templates/calm/domain/shared.yml +10 -0
  52. rasa/cli/project_templates/calm/e2e_tests/cancelations/user_cancels_during_a_correction.yml +16 -0
  53. rasa/cli/project_templates/calm/e2e_tests/cancelations/user_changes_mind_on_a_whim.yml +7 -0
  54. rasa/cli/project_templates/calm/e2e_tests/corrections/user_corrects_contact_handle.yml +20 -0
  55. rasa/cli/project_templates/calm/e2e_tests/corrections/user_corrects_contact_name.yml +19 -0
  56. rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_adds_contact_to_their_list.yml +15 -0
  57. rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_lists_contacts.yml +5 -0
  58. rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_removes_contact.yml +11 -0
  59. rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_removes_contact_from_list.yml +12 -0
  60. rasa/cli/project_templates/calm/endpoints.yml +58 -0
  61. rasa/cli/project_templates/default/actions/__init__.py +0 -0
  62. rasa/cli/project_templates/default/actions/actions.py +27 -0
  63. rasa/cli/project_templates/default/config.yml +44 -0
  64. rasa/cli/project_templates/default/credentials.yml +33 -0
  65. rasa/cli/project_templates/default/data/nlu.yml +91 -0
  66. rasa/cli/project_templates/default/data/rules.yml +13 -0
  67. rasa/cli/project_templates/default/data/stories.yml +30 -0
  68. rasa/cli/project_templates/default/domain.yml +34 -0
  69. rasa/cli/project_templates/default/endpoints.yml +42 -0
  70. rasa/cli/project_templates/default/tests/test_stories.yml +91 -0
  71. rasa/cli/project_templates/tutorial/actions/__init__.py +0 -0
  72. rasa/cli/project_templates/tutorial/actions/actions.py +22 -0
  73. rasa/cli/project_templates/tutorial/config.yml +12 -0
  74. rasa/cli/project_templates/tutorial/credentials.yml +33 -0
  75. rasa/cli/project_templates/tutorial/data/flows.yml +8 -0
  76. rasa/cli/project_templates/tutorial/data/patterns.yml +11 -0
  77. rasa/cli/project_templates/tutorial/domain.yml +35 -0
  78. rasa/cli/project_templates/tutorial/endpoints.yml +55 -0
  79. rasa/cli/run.py +143 -0
  80. rasa/cli/scaffold.py +273 -0
  81. rasa/cli/shell.py +141 -0
  82. rasa/cli/studio/__init__.py +0 -0
  83. rasa/cli/studio/download.py +62 -0
  84. rasa/cli/studio/studio.py +296 -0
  85. rasa/cli/studio/train.py +59 -0
  86. rasa/cli/studio/upload.py +62 -0
  87. rasa/cli/telemetry.py +102 -0
  88. rasa/cli/test.py +280 -0
  89. rasa/cli/train.py +278 -0
  90. rasa/cli/utils.py +484 -0
  91. rasa/cli/visualize.py +40 -0
  92. rasa/cli/x.py +206 -0
  93. rasa/constants.py +45 -0
  94. rasa/core/__init__.py +17 -0
  95. rasa/core/actions/__init__.py +0 -0
  96. rasa/core/actions/action.py +1318 -0
  97. rasa/core/actions/action_clean_stack.py +59 -0
  98. rasa/core/actions/action_exceptions.py +24 -0
  99. rasa/core/actions/action_hangup.py +29 -0
  100. rasa/core/actions/action_repeat_bot_messages.py +89 -0
  101. rasa/core/actions/action_run_slot_rejections.py +210 -0
  102. rasa/core/actions/action_trigger_chitchat.py +31 -0
  103. rasa/core/actions/action_trigger_flow.py +109 -0
  104. rasa/core/actions/action_trigger_search.py +31 -0
  105. rasa/core/actions/constants.py +5 -0
  106. rasa/core/actions/custom_action_executor.py +191 -0
  107. rasa/core/actions/direct_custom_actions_executor.py +109 -0
  108. rasa/core/actions/e2e_stub_custom_action_executor.py +72 -0
  109. rasa/core/actions/forms.py +741 -0
  110. rasa/core/actions/grpc_custom_action_executor.py +251 -0
  111. rasa/core/actions/http_custom_action_executor.py +145 -0
  112. rasa/core/actions/loops.py +114 -0
  113. rasa/core/actions/two_stage_fallback.py +186 -0
  114. rasa/core/agent.py +559 -0
  115. rasa/core/auth_retry_tracker_store.py +122 -0
  116. rasa/core/brokers/__init__.py +0 -0
  117. rasa/core/brokers/broker.py +126 -0
  118. rasa/core/brokers/file.py +58 -0
  119. rasa/core/brokers/kafka.py +324 -0
  120. rasa/core/brokers/pika.py +388 -0
  121. rasa/core/brokers/sql.py +86 -0
  122. rasa/core/channels/__init__.py +61 -0
  123. rasa/core/channels/botframework.py +338 -0
  124. rasa/core/channels/callback.py +84 -0
  125. rasa/core/channels/channel.py +456 -0
  126. rasa/core/channels/console.py +241 -0
  127. rasa/core/channels/development_inspector.py +197 -0
  128. rasa/core/channels/facebook.py +419 -0
  129. rasa/core/channels/hangouts.py +329 -0
  130. rasa/core/channels/inspector/.eslintrc.cjs +25 -0
  131. rasa/core/channels/inspector/.gitignore +23 -0
  132. rasa/core/channels/inspector/README.md +54 -0
  133. rasa/core/channels/inspector/assets/favicon.ico +0 -0
  134. rasa/core/channels/inspector/assets/rasa-chat.js +2 -0
  135. rasa/core/channels/inspector/custom.d.ts +3 -0
  136. rasa/core/channels/inspector/dist/assets/arc-861ddd57.js +1 -0
  137. rasa/core/channels/inspector/dist/assets/array-9f3ba611.js +1 -0
  138. rasa/core/channels/inspector/dist/assets/c4Diagram-d0fbc5ce-921f02db.js +10 -0
  139. rasa/core/channels/inspector/dist/assets/classDiagram-936ed81e-b436c4f8.js +2 -0
  140. rasa/core/channels/inspector/dist/assets/classDiagram-v2-c3cb15f1-511a23cb.js +2 -0
  141. rasa/core/channels/inspector/dist/assets/createText-62fc7601-ef476ecd.js +7 -0
  142. rasa/core/channels/inspector/dist/assets/edges-f2ad444c-f1878e0a.js +4 -0
  143. rasa/core/channels/inspector/dist/assets/erDiagram-9d236eb7-fac75185.js +51 -0
  144. rasa/core/channels/inspector/dist/assets/flowDb-1972c806-201c5bbc.js +6 -0
  145. rasa/core/channels/inspector/dist/assets/flowDiagram-7ea5b25a-f904ae41.js +4 -0
  146. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-b080d6f2.js +1 -0
  147. rasa/core/channels/inspector/dist/assets/flowchart-elk-definition-abe16c3d-1813da66.js +139 -0
  148. rasa/core/channels/inspector/dist/assets/ganttDiagram-9b5ea136-872af172.js +266 -0
  149. rasa/core/channels/inspector/dist/assets/gitGraphDiagram-99d0ae7c-34a0af5a.js +70 -0
  150. rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-128cfa44.ttf +0 -0
  151. rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-21dbcb97.woff +0 -0
  152. rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-222b5e26.svg +329 -0
  153. rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-9ad89b2a.woff2 +0 -0
  154. rasa/core/channels/inspector/dist/assets/index-2c4b9a3b-42ba3e3d.js +1 -0
  155. rasa/core/channels/inspector/dist/assets/index-37817b51.js +1317 -0
  156. rasa/core/channels/inspector/dist/assets/index-3ee28881.css +1 -0
  157. rasa/core/channels/inspector/dist/assets/infoDiagram-736b4530-6b731386.js +7 -0
  158. rasa/core/channels/inspector/dist/assets/init-77b53fdd.js +1 -0
  159. rasa/core/channels/inspector/dist/assets/journeyDiagram-df861f2b-e8579ac6.js +139 -0
  160. rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-60c05ee4.woff +0 -0
  161. rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-8335d9b8.svg +438 -0
  162. rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-9cc39c75.ttf +0 -0
  163. rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-ead13ccf.woff2 +0 -0
  164. rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-16705655.woff2 +0 -0
  165. rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-5aeb07f9.woff +0 -0
  166. rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-9c459044.ttf +0 -0
  167. rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-9e2898a4.svg +435 -0
  168. rasa/core/channels/inspector/dist/assets/layout-89e6403a.js +1 -0
  169. rasa/core/channels/inspector/dist/assets/line-dc73d3fc.js +1 -0
  170. rasa/core/channels/inspector/dist/assets/linear-f5b1d2bc.js +1 -0
  171. rasa/core/channels/inspector/dist/assets/mindmap-definition-beec6740-82cb74fa.js +109 -0
  172. rasa/core/channels/inspector/dist/assets/ordinal-ba9b4969.js +1 -0
  173. rasa/core/channels/inspector/dist/assets/path-53f90ab3.js +1 -0
  174. rasa/core/channels/inspector/dist/assets/pieDiagram-dbbf0591-bdf5f29b.js +35 -0
  175. rasa/core/channels/inspector/dist/assets/quadrantDiagram-4d7f4fd6-c7a0cbe4.js +7 -0
  176. rasa/core/channels/inspector/dist/assets/requirementDiagram-6fc4c22a-7ec5410f.js +52 -0
  177. rasa/core/channels/inspector/dist/assets/sankeyDiagram-8f13d901-caee5554.js +8 -0
  178. rasa/core/channels/inspector/dist/assets/sequenceDiagram-b655622a-2935f8db.js +122 -0
  179. rasa/core/channels/inspector/dist/assets/stateDiagram-59f0c015-8f5d9693.js +1 -0
  180. rasa/core/channels/inspector/dist/assets/stateDiagram-v2-2b26beab-d565d1de.js +1 -0
  181. rasa/core/channels/inspector/dist/assets/styles-080da4f6-75ad421d.js +110 -0
  182. rasa/core/channels/inspector/dist/assets/styles-3dcbcfbf-7e764226.js +159 -0
  183. rasa/core/channels/inspector/dist/assets/styles-9c745c82-7a4e0e61.js +207 -0
  184. rasa/core/channels/inspector/dist/assets/svgDrawCommon-4835440b-4019d1bf.js +1 -0
  185. rasa/core/channels/inspector/dist/assets/timeline-definition-5b62e21b-01ea12df.js +61 -0
  186. rasa/core/channels/inspector/dist/assets/xychartDiagram-2b33534f-89407137.js +7 -0
  187. rasa/core/channels/inspector/dist/index.html +42 -0
  188. rasa/core/channels/inspector/index.html +40 -0
  189. rasa/core/channels/inspector/jest.config.ts +13 -0
  190. rasa/core/channels/inspector/package.json +52 -0
  191. rasa/core/channels/inspector/setupTests.ts +2 -0
  192. rasa/core/channels/inspector/src/App.tsx +220 -0
  193. rasa/core/channels/inspector/src/components/Chat.tsx +95 -0
  194. rasa/core/channels/inspector/src/components/DiagramFlow.tsx +108 -0
  195. rasa/core/channels/inspector/src/components/DialogueInformation.tsx +187 -0
  196. rasa/core/channels/inspector/src/components/DialogueStack.tsx +136 -0
  197. rasa/core/channels/inspector/src/components/ExpandIcon.tsx +16 -0
  198. rasa/core/channels/inspector/src/components/FullscreenButton.tsx +45 -0
  199. rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +22 -0
  200. rasa/core/channels/inspector/src/components/NoActiveFlow.tsx +21 -0
  201. rasa/core/channels/inspector/src/components/RasaLogo.tsx +32 -0
  202. rasa/core/channels/inspector/src/components/SaraDiagrams.tsx +39 -0
  203. rasa/core/channels/inspector/src/components/Slots.tsx +91 -0
  204. rasa/core/channels/inspector/src/components/Welcome.tsx +54 -0
  205. rasa/core/channels/inspector/src/helpers/audiostream.ts +191 -0
  206. rasa/core/channels/inspector/src/helpers/formatters.test.ts +392 -0
  207. rasa/core/channels/inspector/src/helpers/formatters.ts +306 -0
  208. rasa/core/channels/inspector/src/helpers/utils.ts +127 -0
  209. rasa/core/channels/inspector/src/main.tsx +13 -0
  210. rasa/core/channels/inspector/src/theme/Button/Button.ts +29 -0
  211. rasa/core/channels/inspector/src/theme/Heading/Heading.ts +31 -0
  212. rasa/core/channels/inspector/src/theme/Input/Input.ts +27 -0
  213. rasa/core/channels/inspector/src/theme/Link/Link.ts +10 -0
  214. rasa/core/channels/inspector/src/theme/Modal/Modal.ts +47 -0
  215. rasa/core/channels/inspector/src/theme/Table/Table.tsx +38 -0
  216. rasa/core/channels/inspector/src/theme/Tooltip/Tooltip.ts +12 -0
  217. rasa/core/channels/inspector/src/theme/base/breakpoints.ts +8 -0
  218. rasa/core/channels/inspector/src/theme/base/colors.ts +88 -0
  219. rasa/core/channels/inspector/src/theme/base/fonts/fontFaces.css +29 -0
  220. rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.eot +0 -0
  221. rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.svg +329 -0
  222. rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.ttf +0 -0
  223. rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.woff +0 -0
  224. rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.woff2 +0 -0
  225. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.eot +0 -0
  226. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.svg +438 -0
  227. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.ttf +0 -0
  228. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.woff +0 -0
  229. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.woff2 +0 -0
  230. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.eot +0 -0
  231. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.svg +435 -0
  232. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.ttf +0 -0
  233. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.woff +0 -0
  234. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.woff2 +0 -0
  235. rasa/core/channels/inspector/src/theme/base/radii.ts +9 -0
  236. rasa/core/channels/inspector/src/theme/base/shadows.ts +7 -0
  237. rasa/core/channels/inspector/src/theme/base/sizes.ts +7 -0
  238. rasa/core/channels/inspector/src/theme/base/space.ts +15 -0
  239. rasa/core/channels/inspector/src/theme/base/styles.ts +13 -0
  240. rasa/core/channels/inspector/src/theme/base/typography.ts +24 -0
  241. rasa/core/channels/inspector/src/theme/base/zIndices.ts +19 -0
  242. rasa/core/channels/inspector/src/theme/index.ts +101 -0
  243. rasa/core/channels/inspector/src/types.ts +84 -0
  244. rasa/core/channels/inspector/src/vite-env.d.ts +1 -0
  245. rasa/core/channels/inspector/tests/__mocks__/fileMock.ts +1 -0
  246. rasa/core/channels/inspector/tests/__mocks__/matchMedia.ts +16 -0
  247. rasa/core/channels/inspector/tests/__mocks__/styleMock.ts +1 -0
  248. rasa/core/channels/inspector/tests/renderWithProviders.tsx +14 -0
  249. rasa/core/channels/inspector/tsconfig.json +26 -0
  250. rasa/core/channels/inspector/tsconfig.node.json +10 -0
  251. rasa/core/channels/inspector/vite.config.ts +8 -0
  252. rasa/core/channels/inspector/yarn.lock +6249 -0
  253. rasa/core/channels/mattermost.py +229 -0
  254. rasa/core/channels/rasa_chat.py +126 -0
  255. rasa/core/channels/rest.py +230 -0
  256. rasa/core/channels/rocketchat.py +174 -0
  257. rasa/core/channels/slack.py +620 -0
  258. rasa/core/channels/socketio.py +302 -0
  259. rasa/core/channels/telegram.py +298 -0
  260. rasa/core/channels/twilio.py +169 -0
  261. rasa/core/channels/vier_cvg.py +374 -0
  262. rasa/core/channels/voice_ready/__init__.py +0 -0
  263. rasa/core/channels/voice_ready/audiocodes.py +501 -0
  264. rasa/core/channels/voice_ready/jambonz.py +121 -0
  265. rasa/core/channels/voice_ready/jambonz_protocol.py +396 -0
  266. rasa/core/channels/voice_ready/twilio_voice.py +403 -0
  267. rasa/core/channels/voice_ready/utils.py +37 -0
  268. rasa/core/channels/voice_stream/__init__.py +0 -0
  269. rasa/core/channels/voice_stream/asr/__init__.py +0 -0
  270. rasa/core/channels/voice_stream/asr/asr_engine.py +89 -0
  271. rasa/core/channels/voice_stream/asr/asr_event.py +18 -0
  272. rasa/core/channels/voice_stream/asr/azure.py +130 -0
  273. rasa/core/channels/voice_stream/asr/deepgram.py +90 -0
  274. rasa/core/channels/voice_stream/audio_bytes.py +8 -0
  275. rasa/core/channels/voice_stream/browser_audio.py +107 -0
  276. rasa/core/channels/voice_stream/call_state.py +23 -0
  277. rasa/core/channels/voice_stream/tts/__init__.py +0 -0
  278. rasa/core/channels/voice_stream/tts/azure.py +106 -0
  279. rasa/core/channels/voice_stream/tts/cartesia.py +118 -0
  280. rasa/core/channels/voice_stream/tts/tts_cache.py +27 -0
  281. rasa/core/channels/voice_stream/tts/tts_engine.py +58 -0
  282. rasa/core/channels/voice_stream/twilio_media_streams.py +173 -0
  283. rasa/core/channels/voice_stream/util.py +57 -0
  284. rasa/core/channels/voice_stream/voice_channel.py +427 -0
  285. rasa/core/channels/webexteams.py +134 -0
  286. rasa/core/concurrent_lock_store.py +210 -0
  287. rasa/core/constants.py +112 -0
  288. rasa/core/evaluation/__init__.py +0 -0
  289. rasa/core/evaluation/marker.py +267 -0
  290. rasa/core/evaluation/marker_base.py +923 -0
  291. rasa/core/evaluation/marker_stats.py +293 -0
  292. rasa/core/evaluation/marker_tracker_loader.py +103 -0
  293. rasa/core/exceptions.py +29 -0
  294. rasa/core/exporter.py +284 -0
  295. rasa/core/featurizers/__init__.py +0 -0
  296. rasa/core/featurizers/precomputation.py +410 -0
  297. rasa/core/featurizers/single_state_featurizer.py +421 -0
  298. rasa/core/featurizers/tracker_featurizers.py +1262 -0
  299. rasa/core/http_interpreter.py +89 -0
  300. rasa/core/information_retrieval/__init__.py +7 -0
  301. rasa/core/information_retrieval/faiss.py +124 -0
  302. rasa/core/information_retrieval/information_retrieval.py +137 -0
  303. rasa/core/information_retrieval/milvus.py +59 -0
  304. rasa/core/information_retrieval/qdrant.py +96 -0
  305. rasa/core/jobs.py +63 -0
  306. rasa/core/lock.py +139 -0
  307. rasa/core/lock_store.py +343 -0
  308. rasa/core/migrate.py +403 -0
  309. rasa/core/nlg/__init__.py +3 -0
  310. rasa/core/nlg/callback.py +146 -0
  311. rasa/core/nlg/contextual_response_rephraser.py +320 -0
  312. rasa/core/nlg/generator.py +230 -0
  313. rasa/core/nlg/interpolator.py +143 -0
  314. rasa/core/nlg/response.py +155 -0
  315. rasa/core/nlg/summarize.py +70 -0
  316. rasa/core/persistor.py +538 -0
  317. rasa/core/policies/__init__.py +0 -0
  318. rasa/core/policies/ensemble.py +329 -0
  319. rasa/core/policies/enterprise_search_policy.py +905 -0
  320. rasa/core/policies/enterprise_search_prompt_template.jinja2 +25 -0
  321. rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +60 -0
  322. rasa/core/policies/flow_policy.py +205 -0
  323. rasa/core/policies/flows/__init__.py +0 -0
  324. rasa/core/policies/flows/flow_exceptions.py +44 -0
  325. rasa/core/policies/flows/flow_executor.py +754 -0
  326. rasa/core/policies/flows/flow_step_result.py +43 -0
  327. rasa/core/policies/intentless_policy.py +1031 -0
  328. rasa/core/policies/intentless_prompt_template.jinja2 +22 -0
  329. rasa/core/policies/memoization.py +538 -0
  330. rasa/core/policies/policy.py +725 -0
  331. rasa/core/policies/rule_policy.py +1273 -0
  332. rasa/core/policies/ted_policy.py +2169 -0
  333. rasa/core/policies/unexpected_intent_policy.py +1022 -0
  334. rasa/core/processor.py +1465 -0
  335. rasa/core/run.py +342 -0
  336. rasa/core/secrets_manager/__init__.py +0 -0
  337. rasa/core/secrets_manager/constants.py +36 -0
  338. rasa/core/secrets_manager/endpoints.py +391 -0
  339. rasa/core/secrets_manager/factory.py +241 -0
  340. rasa/core/secrets_manager/secret_manager.py +262 -0
  341. rasa/core/secrets_manager/vault.py +584 -0
  342. rasa/core/test.py +1335 -0
  343. rasa/core/tracker_store.py +1703 -0
  344. rasa/core/train.py +105 -0
  345. rasa/core/training/__init__.py +89 -0
  346. rasa/core/training/converters/__init__.py +0 -0
  347. rasa/core/training/converters/responses_prefix_converter.py +119 -0
  348. rasa/core/training/interactive.py +1744 -0
  349. rasa/core/training/story_conflict.py +381 -0
  350. rasa/core/training/training.py +93 -0
  351. rasa/core/utils.py +366 -0
  352. rasa/core/visualize.py +70 -0
  353. rasa/dialogue_understanding/__init__.py +0 -0
  354. rasa/dialogue_understanding/coexistence/__init__.py +0 -0
  355. rasa/dialogue_understanding/coexistence/constants.py +4 -0
  356. rasa/dialogue_understanding/coexistence/intent_based_router.py +196 -0
  357. rasa/dialogue_understanding/coexistence/llm_based_router.py +327 -0
  358. rasa/dialogue_understanding/coexistence/router_template.jinja2 +12 -0
  359. rasa/dialogue_understanding/commands/__init__.py +61 -0
  360. rasa/dialogue_understanding/commands/can_not_handle_command.py +70 -0
  361. rasa/dialogue_understanding/commands/cancel_flow_command.py +125 -0
  362. rasa/dialogue_understanding/commands/change_flow_command.py +44 -0
  363. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +57 -0
  364. rasa/dialogue_understanding/commands/clarify_command.py +86 -0
  365. rasa/dialogue_understanding/commands/command.py +85 -0
  366. rasa/dialogue_understanding/commands/correct_slots_command.py +297 -0
  367. rasa/dialogue_understanding/commands/error_command.py +79 -0
  368. rasa/dialogue_understanding/commands/free_form_answer_command.py +9 -0
  369. rasa/dialogue_understanding/commands/handle_code_change_command.py +73 -0
  370. rasa/dialogue_understanding/commands/human_handoff_command.py +66 -0
  371. rasa/dialogue_understanding/commands/knowledge_answer_command.py +57 -0
  372. rasa/dialogue_understanding/commands/noop_command.py +54 -0
  373. rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +60 -0
  374. rasa/dialogue_understanding/commands/restart_command.py +58 -0
  375. rasa/dialogue_understanding/commands/session_end_command.py +61 -0
  376. rasa/dialogue_understanding/commands/session_start_command.py +59 -0
  377. rasa/dialogue_understanding/commands/set_slot_command.py +160 -0
  378. rasa/dialogue_understanding/commands/skip_question_command.py +75 -0
  379. rasa/dialogue_understanding/commands/start_flow_command.py +107 -0
  380. rasa/dialogue_understanding/commands/user_silence_command.py +59 -0
  381. rasa/dialogue_understanding/commands/utils.py +45 -0
  382. rasa/dialogue_understanding/generator/__init__.py +21 -0
  383. rasa/dialogue_understanding/generator/command_generator.py +464 -0
  384. rasa/dialogue_understanding/generator/constants.py +27 -0
  385. rasa/dialogue_understanding/generator/flow_document_template.jinja2 +4 -0
  386. rasa/dialogue_understanding/generator/flow_retrieval.py +466 -0
  387. rasa/dialogue_understanding/generator/llm_based_command_generator.py +500 -0
  388. rasa/dialogue_understanding/generator/llm_command_generator.py +67 -0
  389. rasa/dialogue_understanding/generator/multi_step/__init__.py +0 -0
  390. rasa/dialogue_understanding/generator/multi_step/fill_slots_prompt.jinja2 +62 -0
  391. rasa/dialogue_understanding/generator/multi_step/handle_flows_prompt.jinja2 +38 -0
  392. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +920 -0
  393. rasa/dialogue_understanding/generator/nlu_command_adapter.py +261 -0
  394. rasa/dialogue_understanding/generator/single_step/__init__.py +0 -0
  395. rasa/dialogue_understanding/generator/single_step/command_prompt_template.jinja2 +60 -0
  396. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +486 -0
  397. rasa/dialogue_understanding/patterns/__init__.py +0 -0
  398. rasa/dialogue_understanding/patterns/cancel.py +111 -0
  399. rasa/dialogue_understanding/patterns/cannot_handle.py +43 -0
  400. rasa/dialogue_understanding/patterns/chitchat.py +37 -0
  401. rasa/dialogue_understanding/patterns/clarify.py +97 -0
  402. rasa/dialogue_understanding/patterns/code_change.py +41 -0
  403. rasa/dialogue_understanding/patterns/collect_information.py +90 -0
  404. rasa/dialogue_understanding/patterns/completed.py +40 -0
  405. rasa/dialogue_understanding/patterns/continue_interrupted.py +42 -0
  406. rasa/dialogue_understanding/patterns/correction.py +278 -0
  407. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +301 -0
  408. rasa/dialogue_understanding/patterns/human_handoff.py +37 -0
  409. rasa/dialogue_understanding/patterns/internal_error.py +47 -0
  410. rasa/dialogue_understanding/patterns/repeat.py +37 -0
  411. rasa/dialogue_understanding/patterns/restart.py +37 -0
  412. rasa/dialogue_understanding/patterns/search.py +37 -0
  413. rasa/dialogue_understanding/patterns/session_start.py +37 -0
  414. rasa/dialogue_understanding/patterns/skip_question.py +38 -0
  415. rasa/dialogue_understanding/patterns/user_silence.py +37 -0
  416. rasa/dialogue_understanding/processor/__init__.py +0 -0
  417. rasa/dialogue_understanding/processor/command_processor.py +720 -0
  418. rasa/dialogue_understanding/processor/command_processor_component.py +43 -0
  419. rasa/dialogue_understanding/stack/__init__.py +0 -0
  420. rasa/dialogue_understanding/stack/dialogue_stack.py +178 -0
  421. rasa/dialogue_understanding/stack/frames/__init__.py +19 -0
  422. rasa/dialogue_understanding/stack/frames/chit_chat_frame.py +27 -0
  423. rasa/dialogue_understanding/stack/frames/dialogue_stack_frame.py +137 -0
  424. rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +157 -0
  425. rasa/dialogue_understanding/stack/frames/pattern_frame.py +10 -0
  426. rasa/dialogue_understanding/stack/frames/search_frame.py +27 -0
  427. rasa/dialogue_understanding/stack/utils.py +211 -0
  428. rasa/dialogue_understanding/utils.py +14 -0
  429. rasa/dialogue_understanding_test/__init__.py +0 -0
  430. rasa/dialogue_understanding_test/command_metric_calculation.py +12 -0
  431. rasa/dialogue_understanding_test/constants.py +17 -0
  432. rasa/dialogue_understanding_test/du_test_case.py +118 -0
  433. rasa/dialogue_understanding_test/du_test_result.py +11 -0
  434. rasa/dialogue_understanding_test/du_test_runner.py +93 -0
  435. rasa/dialogue_understanding_test/io.py +54 -0
  436. rasa/dialogue_understanding_test/validation.py +22 -0
  437. rasa/e2e_test/__init__.py +0 -0
  438. rasa/e2e_test/aggregate_test_stats_calculator.py +134 -0
  439. rasa/e2e_test/assertions.py +1345 -0
  440. rasa/e2e_test/assertions_schema.yml +129 -0
  441. rasa/e2e_test/constants.py +31 -0
  442. rasa/e2e_test/e2e_config.py +220 -0
  443. rasa/e2e_test/e2e_config_schema.yml +26 -0
  444. rasa/e2e_test/e2e_test_case.py +569 -0
  445. rasa/e2e_test/e2e_test_converter.py +363 -0
  446. rasa/e2e_test/e2e_test_converter_prompt.jinja2 +70 -0
  447. rasa/e2e_test/e2e_test_coverage_report.py +364 -0
  448. rasa/e2e_test/e2e_test_result.py +54 -0
  449. rasa/e2e_test/e2e_test_runner.py +1192 -0
  450. rasa/e2e_test/e2e_test_schema.yml +181 -0
  451. rasa/e2e_test/pykwalify_extensions.py +39 -0
  452. rasa/e2e_test/stub_custom_action.py +70 -0
  453. rasa/e2e_test/utils/__init__.py +0 -0
  454. rasa/e2e_test/utils/e2e_yaml_utils.py +55 -0
  455. rasa/e2e_test/utils/io.py +598 -0
  456. rasa/e2e_test/utils/validation.py +178 -0
  457. rasa/engine/__init__.py +0 -0
  458. rasa/engine/caching.py +463 -0
  459. rasa/engine/constants.py +17 -0
  460. rasa/engine/exceptions.py +14 -0
  461. rasa/engine/graph.py +642 -0
  462. rasa/engine/loader.py +48 -0
  463. rasa/engine/recipes/__init__.py +0 -0
  464. rasa/engine/recipes/config_files/default_config.yml +41 -0
  465. rasa/engine/recipes/default_components.py +97 -0
  466. rasa/engine/recipes/default_recipe.py +1272 -0
  467. rasa/engine/recipes/graph_recipe.py +79 -0
  468. rasa/engine/recipes/recipe.py +93 -0
  469. rasa/engine/runner/__init__.py +0 -0
  470. rasa/engine/runner/dask.py +250 -0
  471. rasa/engine/runner/interface.py +49 -0
  472. rasa/engine/storage/__init__.py +0 -0
  473. rasa/engine/storage/local_model_storage.py +244 -0
  474. rasa/engine/storage/resource.py +110 -0
  475. rasa/engine/storage/storage.py +199 -0
  476. rasa/engine/training/__init__.py +0 -0
  477. rasa/engine/training/components.py +176 -0
  478. rasa/engine/training/fingerprinting.py +64 -0
  479. rasa/engine/training/graph_trainer.py +256 -0
  480. rasa/engine/training/hooks.py +164 -0
  481. rasa/engine/validation.py +1451 -0
  482. rasa/env.py +14 -0
  483. rasa/exceptions.py +69 -0
  484. rasa/graph_components/__init__.py +0 -0
  485. rasa/graph_components/converters/__init__.py +0 -0
  486. rasa/graph_components/converters/nlu_message_converter.py +48 -0
  487. rasa/graph_components/providers/__init__.py +0 -0
  488. rasa/graph_components/providers/domain_for_core_training_provider.py +87 -0
  489. rasa/graph_components/providers/domain_provider.py +71 -0
  490. rasa/graph_components/providers/flows_provider.py +74 -0
  491. rasa/graph_components/providers/forms_provider.py +44 -0
  492. rasa/graph_components/providers/nlu_training_data_provider.py +56 -0
  493. rasa/graph_components/providers/responses_provider.py +44 -0
  494. rasa/graph_components/providers/rule_only_provider.py +49 -0
  495. rasa/graph_components/providers/story_graph_provider.py +96 -0
  496. rasa/graph_components/providers/training_tracker_provider.py +55 -0
  497. rasa/graph_components/validators/__init__.py +0 -0
  498. rasa/graph_components/validators/default_recipe_validator.py +550 -0
  499. rasa/graph_components/validators/finetuning_validator.py +302 -0
  500. rasa/hooks.py +111 -0
  501. rasa/jupyter.py +63 -0
  502. rasa/llm_fine_tuning/__init__.py +0 -0
  503. rasa/llm_fine_tuning/annotation_module.py +241 -0
  504. rasa/llm_fine_tuning/conversations.py +144 -0
  505. rasa/llm_fine_tuning/llm_data_preparation_module.py +178 -0
  506. rasa/llm_fine_tuning/paraphrasing/__init__.py +0 -0
  507. rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +281 -0
  508. rasa/llm_fine_tuning/paraphrasing/default_rephrase_prompt_template.jina2 +44 -0
  509. rasa/llm_fine_tuning/paraphrasing/rephrase_validator.py +121 -0
  510. rasa/llm_fine_tuning/paraphrasing/rephrased_user_message.py +10 -0
  511. rasa/llm_fine_tuning/paraphrasing_module.py +128 -0
  512. rasa/llm_fine_tuning/storage.py +174 -0
  513. rasa/llm_fine_tuning/train_test_split_module.py +441 -0
  514. rasa/markers/__init__.py +0 -0
  515. rasa/markers/marker.py +269 -0
  516. rasa/markers/marker_base.py +828 -0
  517. rasa/markers/upload.py +74 -0
  518. rasa/markers/validate.py +21 -0
  519. rasa/model.py +118 -0
  520. rasa/model_manager/__init__.py +0 -0
  521. rasa/model_manager/config.py +40 -0
  522. rasa/model_manager/model_api.py +559 -0
  523. rasa/model_manager/runner_service.py +286 -0
  524. rasa/model_manager/socket_bridge.py +146 -0
  525. rasa/model_manager/studio_jwt_auth.py +86 -0
  526. rasa/model_manager/trainer_service.py +325 -0
  527. rasa/model_manager/utils.py +87 -0
  528. rasa/model_manager/warm_rasa_process.py +187 -0
  529. rasa/model_service.py +112 -0
  530. rasa/model_testing.py +457 -0
  531. rasa/model_training.py +596 -0
  532. rasa/nlu/__init__.py +7 -0
  533. rasa/nlu/classifiers/__init__.py +3 -0
  534. rasa/nlu/classifiers/classifier.py +5 -0
  535. rasa/nlu/classifiers/diet_classifier.py +1881 -0
  536. rasa/nlu/classifiers/fallback_classifier.py +192 -0
  537. rasa/nlu/classifiers/keyword_intent_classifier.py +188 -0
  538. rasa/nlu/classifiers/logistic_regression_classifier.py +253 -0
  539. rasa/nlu/classifiers/mitie_intent_classifier.py +156 -0
  540. rasa/nlu/classifiers/regex_message_handler.py +56 -0
  541. rasa/nlu/classifiers/sklearn_intent_classifier.py +330 -0
  542. rasa/nlu/constants.py +77 -0
  543. rasa/nlu/convert.py +40 -0
  544. rasa/nlu/emulators/__init__.py +0 -0
  545. rasa/nlu/emulators/dialogflow.py +55 -0
  546. rasa/nlu/emulators/emulator.py +49 -0
  547. rasa/nlu/emulators/luis.py +86 -0
  548. rasa/nlu/emulators/no_emulator.py +10 -0
  549. rasa/nlu/emulators/wit.py +56 -0
  550. rasa/nlu/extractors/__init__.py +0 -0
  551. rasa/nlu/extractors/crf_entity_extractor.py +715 -0
  552. rasa/nlu/extractors/duckling_entity_extractor.py +206 -0
  553. rasa/nlu/extractors/entity_synonyms.py +178 -0
  554. rasa/nlu/extractors/extractor.py +470 -0
  555. rasa/nlu/extractors/mitie_entity_extractor.py +293 -0
  556. rasa/nlu/extractors/regex_entity_extractor.py +220 -0
  557. rasa/nlu/extractors/spacy_entity_extractor.py +95 -0
  558. rasa/nlu/featurizers/__init__.py +0 -0
  559. rasa/nlu/featurizers/dense_featurizer/__init__.py +0 -0
  560. rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +445 -0
  561. rasa/nlu/featurizers/dense_featurizer/dense_featurizer.py +57 -0
  562. rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +768 -0
  563. rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +170 -0
  564. rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +132 -0
  565. rasa/nlu/featurizers/featurizer.py +89 -0
  566. rasa/nlu/featurizers/sparse_featurizer/__init__.py +0 -0
  567. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +867 -0
  568. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +571 -0
  569. rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +271 -0
  570. rasa/nlu/featurizers/sparse_featurizer/sparse_featurizer.py +9 -0
  571. rasa/nlu/model.py +24 -0
  572. rasa/nlu/run.py +27 -0
  573. rasa/nlu/selectors/__init__.py +0 -0
  574. rasa/nlu/selectors/response_selector.py +987 -0
  575. rasa/nlu/test.py +1940 -0
  576. rasa/nlu/tokenizers/__init__.py +0 -0
  577. rasa/nlu/tokenizers/jieba_tokenizer.py +148 -0
  578. rasa/nlu/tokenizers/mitie_tokenizer.py +75 -0
  579. rasa/nlu/tokenizers/spacy_tokenizer.py +72 -0
  580. rasa/nlu/tokenizers/tokenizer.py +239 -0
  581. rasa/nlu/tokenizers/whitespace_tokenizer.py +95 -0
  582. rasa/nlu/utils/__init__.py +35 -0
  583. rasa/nlu/utils/bilou_utils.py +462 -0
  584. rasa/nlu/utils/hugging_face/__init__.py +0 -0
  585. rasa/nlu/utils/hugging_face/registry.py +108 -0
  586. rasa/nlu/utils/hugging_face/transformers_pre_post_processors.py +311 -0
  587. rasa/nlu/utils/mitie_utils.py +113 -0
  588. rasa/nlu/utils/pattern_utils.py +168 -0
  589. rasa/nlu/utils/spacy_utils.py +310 -0
  590. rasa/plugin.py +90 -0
  591. rasa/server.py +1588 -0
  592. rasa/shared/__init__.py +0 -0
  593. rasa/shared/constants.py +311 -0
  594. rasa/shared/core/__init__.py +0 -0
  595. rasa/shared/core/command_payload_reader.py +109 -0
  596. rasa/shared/core/constants.py +180 -0
  597. rasa/shared/core/conversation.py +46 -0
  598. rasa/shared/core/domain.py +2172 -0
  599. rasa/shared/core/events.py +2559 -0
  600. rasa/shared/core/flows/__init__.py +7 -0
  601. rasa/shared/core/flows/flow.py +562 -0
  602. rasa/shared/core/flows/flow_path.py +84 -0
  603. rasa/shared/core/flows/flow_step.py +146 -0
  604. rasa/shared/core/flows/flow_step_links.py +319 -0
  605. rasa/shared/core/flows/flow_step_sequence.py +70 -0
  606. rasa/shared/core/flows/flows_list.py +258 -0
  607. rasa/shared/core/flows/flows_yaml_schema.json +303 -0
  608. rasa/shared/core/flows/nlu_trigger.py +117 -0
  609. rasa/shared/core/flows/steps/__init__.py +24 -0
  610. rasa/shared/core/flows/steps/action.py +56 -0
  611. rasa/shared/core/flows/steps/call.py +64 -0
  612. rasa/shared/core/flows/steps/collect.py +112 -0
  613. rasa/shared/core/flows/steps/constants.py +5 -0
  614. rasa/shared/core/flows/steps/continuation.py +36 -0
  615. rasa/shared/core/flows/steps/end.py +22 -0
  616. rasa/shared/core/flows/steps/internal.py +44 -0
  617. rasa/shared/core/flows/steps/link.py +51 -0
  618. rasa/shared/core/flows/steps/no_operation.py +48 -0
  619. rasa/shared/core/flows/steps/set_slots.py +50 -0
  620. rasa/shared/core/flows/steps/start.py +30 -0
  621. rasa/shared/core/flows/utils.py +39 -0
  622. rasa/shared/core/flows/validation.py +735 -0
  623. rasa/shared/core/flows/yaml_flows_io.py +405 -0
  624. rasa/shared/core/generator.py +908 -0
  625. rasa/shared/core/slot_mappings.py +526 -0
  626. rasa/shared/core/slots.py +654 -0
  627. rasa/shared/core/trackers.py +1183 -0
  628. rasa/shared/core/training_data/__init__.py +0 -0
  629. rasa/shared/core/training_data/loading.py +89 -0
  630. rasa/shared/core/training_data/story_reader/__init__.py +0 -0
  631. rasa/shared/core/training_data/story_reader/story_reader.py +129 -0
  632. rasa/shared/core/training_data/story_reader/story_step_builder.py +168 -0
  633. rasa/shared/core/training_data/story_reader/yaml_story_reader.py +888 -0
  634. rasa/shared/core/training_data/story_writer/__init__.py +0 -0
  635. rasa/shared/core/training_data/story_writer/story_writer.py +76 -0
  636. rasa/shared/core/training_data/story_writer/yaml_story_writer.py +444 -0
  637. rasa/shared/core/training_data/structures.py +858 -0
  638. rasa/shared/core/training_data/visualization.html +146 -0
  639. rasa/shared/core/training_data/visualization.py +603 -0
  640. rasa/shared/data.py +249 -0
  641. rasa/shared/engine/__init__.py +0 -0
  642. rasa/shared/engine/caching.py +26 -0
  643. rasa/shared/exceptions.py +167 -0
  644. rasa/shared/importers/__init__.py +0 -0
  645. rasa/shared/importers/importer.py +770 -0
  646. rasa/shared/importers/multi_project.py +215 -0
  647. rasa/shared/importers/rasa.py +108 -0
  648. rasa/shared/importers/remote_importer.py +196 -0
  649. rasa/shared/importers/utils.py +36 -0
  650. rasa/shared/nlu/__init__.py +0 -0
  651. rasa/shared/nlu/constants.py +53 -0
  652. rasa/shared/nlu/interpreter.py +10 -0
  653. rasa/shared/nlu/training_data/__init__.py +0 -0
  654. rasa/shared/nlu/training_data/entities_parser.py +208 -0
  655. rasa/shared/nlu/training_data/features.py +492 -0
  656. rasa/shared/nlu/training_data/formats/__init__.py +10 -0
  657. rasa/shared/nlu/training_data/formats/dialogflow.py +163 -0
  658. rasa/shared/nlu/training_data/formats/luis.py +87 -0
  659. rasa/shared/nlu/training_data/formats/rasa.py +135 -0
  660. rasa/shared/nlu/training_data/formats/rasa_yaml.py +618 -0
  661. rasa/shared/nlu/training_data/formats/readerwriter.py +244 -0
  662. rasa/shared/nlu/training_data/formats/wit.py +52 -0
  663. rasa/shared/nlu/training_data/loading.py +137 -0
  664. rasa/shared/nlu/training_data/lookup_tables_parser.py +30 -0
  665. rasa/shared/nlu/training_data/message.py +490 -0
  666. rasa/shared/nlu/training_data/schemas/__init__.py +0 -0
  667. rasa/shared/nlu/training_data/schemas/data_schema.py +85 -0
  668. rasa/shared/nlu/training_data/schemas/nlu.yml +53 -0
  669. rasa/shared/nlu/training_data/schemas/responses.yml +70 -0
  670. rasa/shared/nlu/training_data/synonyms_parser.py +42 -0
  671. rasa/shared/nlu/training_data/training_data.py +729 -0
  672. rasa/shared/nlu/training_data/util.py +223 -0
  673. rasa/shared/providers/__init__.py +0 -0
  674. rasa/shared/providers/_configs/__init__.py +0 -0
  675. rasa/shared/providers/_configs/azure_openai_client_config.py +677 -0
  676. rasa/shared/providers/_configs/client_config.py +59 -0
  677. rasa/shared/providers/_configs/default_litellm_client_config.py +132 -0
  678. rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +236 -0
  679. rasa/shared/providers/_configs/litellm_router_client_config.py +222 -0
  680. rasa/shared/providers/_configs/model_group_config.py +173 -0
  681. rasa/shared/providers/_configs/openai_client_config.py +177 -0
  682. rasa/shared/providers/_configs/rasa_llm_client_config.py +75 -0
  683. rasa/shared/providers/_configs/self_hosted_llm_client_config.py +178 -0
  684. rasa/shared/providers/_configs/utils.py +117 -0
  685. rasa/shared/providers/_ssl_verification_utils.py +124 -0
  686. rasa/shared/providers/_utils.py +79 -0
  687. rasa/shared/providers/constants.py +7 -0
  688. rasa/shared/providers/embedding/__init__.py +0 -0
  689. rasa/shared/providers/embedding/_base_litellm_embedding_client.py +243 -0
  690. rasa/shared/providers/embedding/_langchain_embedding_client_adapter.py +74 -0
  691. rasa/shared/providers/embedding/azure_openai_embedding_client.py +335 -0
  692. rasa/shared/providers/embedding/default_litellm_embedding_client.py +126 -0
  693. rasa/shared/providers/embedding/embedding_client.py +90 -0
  694. rasa/shared/providers/embedding/embedding_response.py +41 -0
  695. rasa/shared/providers/embedding/huggingface_local_embedding_client.py +191 -0
  696. rasa/shared/providers/embedding/litellm_router_embedding_client.py +138 -0
  697. rasa/shared/providers/embedding/openai_embedding_client.py +172 -0
  698. rasa/shared/providers/llm/__init__.py +0 -0
  699. rasa/shared/providers/llm/_base_litellm_client.py +265 -0
  700. rasa/shared/providers/llm/azure_openai_llm_client.py +415 -0
  701. rasa/shared/providers/llm/default_litellm_llm_client.py +110 -0
  702. rasa/shared/providers/llm/litellm_router_llm_client.py +202 -0
  703. rasa/shared/providers/llm/llm_client.py +78 -0
  704. rasa/shared/providers/llm/llm_response.py +50 -0
  705. rasa/shared/providers/llm/openai_llm_client.py +161 -0
  706. rasa/shared/providers/llm/rasa_llm_client.py +120 -0
  707. rasa/shared/providers/llm/self_hosted_llm_client.py +276 -0
  708. rasa/shared/providers/mappings.py +94 -0
  709. rasa/shared/providers/router/__init__.py +0 -0
  710. rasa/shared/providers/router/_base_litellm_router_client.py +185 -0
  711. rasa/shared/providers/router/router_client.py +75 -0
  712. rasa/shared/utils/__init__.py +0 -0
  713. rasa/shared/utils/cli.py +102 -0
  714. rasa/shared/utils/common.py +324 -0
  715. rasa/shared/utils/constants.py +4 -0
  716. rasa/shared/utils/health_check/__init__.py +0 -0
  717. rasa/shared/utils/health_check/embeddings_health_check_mixin.py +31 -0
  718. rasa/shared/utils/health_check/health_check.py +258 -0
  719. rasa/shared/utils/health_check/llm_health_check_mixin.py +31 -0
  720. rasa/shared/utils/io.py +499 -0
  721. rasa/shared/utils/llm.py +764 -0
  722. rasa/shared/utils/pykwalify_extensions.py +27 -0
  723. rasa/shared/utils/schemas/__init__.py +0 -0
  724. rasa/shared/utils/schemas/config.yml +2 -0
  725. rasa/shared/utils/schemas/domain.yml +145 -0
  726. rasa/shared/utils/schemas/events.py +214 -0
  727. rasa/shared/utils/schemas/model_config.yml +36 -0
  728. rasa/shared/utils/schemas/stories.yml +173 -0
  729. rasa/shared/utils/yaml.py +1068 -0
  730. rasa/studio/__init__.py +0 -0
  731. rasa/studio/auth.py +270 -0
  732. rasa/studio/config.py +136 -0
  733. rasa/studio/constants.py +19 -0
  734. rasa/studio/data_handler.py +368 -0
  735. rasa/studio/download.py +489 -0
  736. rasa/studio/results_logger.py +137 -0
  737. rasa/studio/train.py +134 -0
  738. rasa/studio/upload.py +563 -0
  739. rasa/telemetry.py +1876 -0
  740. rasa/tracing/__init__.py +0 -0
  741. rasa/tracing/config.py +355 -0
  742. rasa/tracing/constants.py +62 -0
  743. rasa/tracing/instrumentation/__init__.py +0 -0
  744. rasa/tracing/instrumentation/attribute_extractors.py +765 -0
  745. rasa/tracing/instrumentation/instrumentation.py +1306 -0
  746. rasa/tracing/instrumentation/intentless_policy_instrumentation.py +144 -0
  747. rasa/tracing/instrumentation/metrics.py +294 -0
  748. rasa/tracing/metric_instrument_provider.py +205 -0
  749. rasa/utils/__init__.py +0 -0
  750. rasa/utils/beta.py +83 -0
  751. rasa/utils/cli.py +28 -0
  752. rasa/utils/common.py +639 -0
  753. rasa/utils/converter.py +53 -0
  754. rasa/utils/endpoints.py +331 -0
  755. rasa/utils/io.py +252 -0
  756. rasa/utils/json_utils.py +60 -0
  757. rasa/utils/licensing.py +542 -0
  758. rasa/utils/log_utils.py +181 -0
  759. rasa/utils/mapper.py +210 -0
  760. rasa/utils/ml_utils.py +147 -0
  761. rasa/utils/plotting.py +362 -0
  762. rasa/utils/sanic_error_handler.py +32 -0
  763. rasa/utils/singleton.py +23 -0
  764. rasa/utils/tensorflow/__init__.py +0 -0
  765. rasa/utils/tensorflow/callback.py +112 -0
  766. rasa/utils/tensorflow/constants.py +116 -0
  767. rasa/utils/tensorflow/crf.py +492 -0
  768. rasa/utils/tensorflow/data_generator.py +440 -0
  769. rasa/utils/tensorflow/environment.py +161 -0
  770. rasa/utils/tensorflow/exceptions.py +5 -0
  771. rasa/utils/tensorflow/feature_array.py +366 -0
  772. rasa/utils/tensorflow/layers.py +1565 -0
  773. rasa/utils/tensorflow/layers_utils.py +113 -0
  774. rasa/utils/tensorflow/metrics.py +281 -0
  775. rasa/utils/tensorflow/model_data.py +798 -0
  776. rasa/utils/tensorflow/model_data_utils.py +499 -0
  777. rasa/utils/tensorflow/models.py +935 -0
  778. rasa/utils/tensorflow/rasa_layers.py +1094 -0
  779. rasa/utils/tensorflow/transformer.py +640 -0
  780. rasa/utils/tensorflow/types.py +6 -0
  781. rasa/utils/train_utils.py +572 -0
  782. rasa/utils/url_tools.py +53 -0
  783. rasa/utils/yaml.py +54 -0
  784. rasa/validator.py +1644 -0
  785. rasa/version.py +3 -0
  786. rasa_pro-3.12.0.dev1.dist-info/METADATA +199 -0
  787. rasa_pro-3.12.0.dev1.dist-info/NOTICE +5 -0
  788. rasa_pro-3.12.0.dev1.dist-info/RECORD +790 -0
  789. rasa_pro-3.12.0.dev1.dist-info/WHEEL +4 -0
  790. rasa_pro-3.12.0.dev1.dist-info/entry_points.txt +3 -0
rasa/validator.py ADDED
@@ -0,0 +1,1644 @@
1
+ import logging
2
+ import re
3
+ import string
4
+ import sys
5
+ from collections import defaultdict
6
+ from typing import Any, Dict, List, Optional, Set, Text, Tuple
7
+
8
+ import structlog
9
+ from jinja2 import Template
10
+ from pypred import Predicate
11
+ from pypred.ast import CompareOperator, Literal, NegateOperator
12
+
13
+ import rasa.core.training.story_conflict
14
+ import rasa.shared.nlu.constants
15
+ import rasa.shared.utils.cli
16
+ import rasa.shared.utils.io
17
+ from rasa.core.channels import UserMessage
18
+ from rasa.dialogue_understanding.stack.frames import PatternFlowStackFrame
19
+ from rasa.shared.constants import (
20
+ ASSISTANT_ID_DEFAULT_VALUE,
21
+ ASSISTANT_ID_KEY,
22
+ CONFIG_MANDATORY_KEYS,
23
+ CONFIG_PIPELINE_KEY,
24
+ DOCS_URL_ACTIONS,
25
+ DOCS_URL_DOMAIN,
26
+ DOCS_URL_DOMAINS,
27
+ DOCS_URL_FORMS,
28
+ DOCS_URL_RESPONSES,
29
+ REQUIRED_SLOTS_KEY,
30
+ UTTER_PREFIX,
31
+ )
32
+ from rasa.shared.core import constants
33
+ from rasa.shared.core.command_payload_reader import (
34
+ MAX_NUMBER_OF_SLOTS,
35
+ CommandPayloadReader,
36
+ )
37
+ from rasa.shared.core.constants import (
38
+ ACTIVE_LOOP,
39
+ MAPPING_CONDITIONS,
40
+ MAPPING_TYPE,
41
+ SlotMappingType,
42
+ )
43
+ from rasa.shared.core.domain import (
44
+ RESPONSE_KEYS_TO_INTERPOLATE,
45
+ Domain,
46
+ )
47
+ from rasa.shared.core.events import ActionExecuted, ActiveLoop, UserUttered
48
+ from rasa.shared.core.flows import FlowsList
49
+ from rasa.shared.core.flows.flow_step_links import IfFlowStepLink
50
+ from rasa.shared.core.flows.steps.action import ActionFlowStep
51
+ from rasa.shared.core.flows.steps.collect import CollectInformationFlowStep
52
+ from rasa.shared.core.flows.steps.link import LinkFlowStep
53
+ from rasa.shared.core.flows.steps.set_slots import SetSlotsFlowStep
54
+ from rasa.shared.core.flows.utils import (
55
+ get_duplicate_slot_persistence_config_error_message,
56
+ get_invalid_slot_persistence_config_error_message,
57
+ warn_deprecated_collect_step_config,
58
+ )
59
+ from rasa.shared.core.generator import TrainingDataGenerator
60
+ from rasa.shared.core.slots import BooleanSlot, CategoricalSlot, ListSlot, Slot
61
+ from rasa.shared.core.training_data.story_reader.yaml_story_reader import (
62
+ YAMLStoryReader,
63
+ )
64
+ from rasa.shared.core.training_data.structures import StoryGraph
65
+ from rasa.shared.data import create_regex_pattern_reader
66
+ from rasa.shared.importers.importer import TrainingDataImporter
67
+ from rasa.shared.nlu.constants import COMMANDS
68
+ from rasa.shared.nlu.training_data.message import Message
69
+ from rasa.shared.nlu.training_data.training_data import TrainingData
70
+
71
+ logger = logging.getLogger(__name__)
72
+ structlogger = structlog.get_logger()
73
+
74
+
75
+ class Validator:
76
+ """A class used to verify usage of intents and utterances."""
77
+
78
+ def __init__(
79
+ self,
80
+ domain: Domain,
81
+ intents: TrainingData,
82
+ story_graph: StoryGraph,
83
+ flows: FlowsList,
84
+ config: Optional[Dict[Text, Any]],
85
+ ) -> None:
86
+ """Initializes the Validator object.
87
+
88
+ Args:
89
+ domain: The domain.
90
+ intents: Training data.
91
+ story_graph: The story graph.
92
+ flows: The flows.
93
+ config: The configuration.
94
+ """
95
+ self.domain = domain
96
+ self.intents = intents
97
+ self.story_graph = story_graph
98
+ self.flows = flows
99
+ self.config = config or {}
100
+
101
+ @classmethod
102
+ def from_importer(cls, importer: TrainingDataImporter) -> "Validator":
103
+ """Create an instance from the domain, nlu and story files."""
104
+ domain = importer.get_domain()
105
+ story_graph = importer.get_stories()
106
+ intents = importer.get_nlu_data()
107
+ config = importer.get_config()
108
+ flows = importer.get_flows()
109
+
110
+ return cls(domain, intents, story_graph, flows, config)
111
+
112
+ def _non_default_intents(self) -> List[Text]:
113
+ return [
114
+ item
115
+ for item in self.domain.intents
116
+ if item not in constants.DEFAULT_INTENTS
117
+ ]
118
+
119
+ def verify_intents(self, ignore_warnings: bool = True) -> bool:
120
+ """Compares list of intents in domain with intents in NLU training data."""
121
+ everything_is_alright = True
122
+
123
+ nlu_data_intents = {e.data["intent"] for e in self.intents.intent_examples}
124
+
125
+ for intent in self._non_default_intents():
126
+ if intent not in nlu_data_intents:
127
+ structlogger.warn(
128
+ "validator.verify_intents.not_in_nlu_training_data",
129
+ intent=intent,
130
+ event_info=(
131
+ f"The intent '{intent}' is listed "
132
+ f"in the domain file, but is not found "
133
+ f"in the NLU training data."
134
+ ),
135
+ )
136
+ everything_is_alright = ignore_warnings or everything_is_alright
137
+
138
+ for intent in nlu_data_intents:
139
+ if intent not in self.domain.intents:
140
+ structlogger.warn(
141
+ "validator.verify_intents.not_in_domain",
142
+ intent=intent,
143
+ event_info=(
144
+ f"There is a message in the training data "
145
+ f"labeled with intent '{intent}'. This "
146
+ f"intent is not listed in your domain. You "
147
+ f"should need to add that intent to your domain "
148
+ f"file!"
149
+ ),
150
+ docs=DOCS_URL_DOMAINS,
151
+ )
152
+ everything_is_alright = ignore_warnings
153
+
154
+ return everything_is_alright
155
+
156
+ def verify_example_repetition_in_intents(
157
+ self, ignore_warnings: bool = True
158
+ ) -> bool:
159
+ """Checks if there is no duplicated example in different intents."""
160
+ everything_is_alright = True
161
+
162
+ duplication_hash = defaultdict(set)
163
+ for example in self.intents.intent_examples:
164
+ text = example.get(rasa.shared.nlu.constants.TEXT)
165
+ duplication_hash[text].add(example.get("intent"))
166
+
167
+ for text, intents in duplication_hash.items():
168
+ if len(duplication_hash[text]) > 1:
169
+ everything_is_alright = ignore_warnings
170
+ intents_string = ", ".join(sorted(intents))
171
+ structlogger.warn(
172
+ "validator.verify_example_repetition_in_intents"
173
+ ".one_example_multiple_intents",
174
+ example=text,
175
+ intents=intents_string,
176
+ event_info=(
177
+ f"The example '{text}' was found labeled "
178
+ f"with multiple different intents in the "
179
+ f"training data. Each annotated message "
180
+ f"should only appear with one intent. "
181
+ f"You should fix that conflict The example is "
182
+ f"labeled with: {intents_string}."
183
+ ),
184
+ )
185
+ return everything_is_alright
186
+
187
+ def verify_intents_in_stories_or_flows(self, ignore_warnings: bool = True) -> bool:
188
+ """Checks intents used in stories.
189
+
190
+ Verifies if the intents used in the stories are valid, and whether
191
+ all valid intents are used in the stories.
192
+ """
193
+ everything_is_alright = self.verify_intents(ignore_warnings=ignore_warnings)
194
+
195
+ stories_intents = {
196
+ event.intent["name"]
197
+ for story in self.story_graph.story_steps
198
+ for event in story.events
199
+ if type(event) == UserUttered and event.intent_name is not None
200
+ }
201
+ flow_intents = {
202
+ trigger.intent
203
+ for flow in self.flows.underlying_flows
204
+ if flow.nlu_triggers is not None
205
+ for trigger in flow.nlu_triggers.trigger_conditions
206
+ }
207
+ used_intents = stories_intents.union(flow_intents)
208
+
209
+ for intent in used_intents:
210
+ if intent not in self.domain.intents:
211
+ structlogger.warn(
212
+ "validator.verify_intents_in_stories_or_flows.not_in_domain",
213
+ intent=intent,
214
+ event_info=(
215
+ f"The intent '{intent}' is used in a "
216
+ f"story or flow, but it is not listed in "
217
+ f"the domain file. You should add it to your "
218
+ f"domain file!"
219
+ ),
220
+ docs=DOCS_URL_DOMAINS,
221
+ )
222
+ everything_is_alright = ignore_warnings
223
+
224
+ for intent in self._non_default_intents():
225
+ if intent not in used_intents:
226
+ structlogger.warn(
227
+ "validator.verify_intents_in_stories_or_flows.not_used",
228
+ intent=intent,
229
+ event_info=(
230
+ f"The intent '{intent}' is not used "
231
+ f"in any story, rule or flow."
232
+ ),
233
+ )
234
+ everything_is_alright = ignore_warnings or everything_is_alright
235
+
236
+ return everything_is_alright
237
+
238
+ def _gather_utterance_actions(self) -> Set[Text]:
239
+ """Return all utterances which are actions.
240
+
241
+ Returns:
242
+ A set of response names found in the domain and data files, with the
243
+ response key stripped in the case of response selector responses.
244
+ """
245
+ domain_responses = {
246
+ response.split(rasa.shared.nlu.constants.RESPONSE_IDENTIFIER_DELIMITER)[0]
247
+ for response in self.domain.responses.keys()
248
+ if response in self.domain.action_names_or_texts
249
+ }
250
+ data_responses = {
251
+ response.split(rasa.shared.nlu.constants.RESPONSE_IDENTIFIER_DELIMITER)[0]
252
+ for response in self.intents.responses.keys()
253
+ }
254
+ return domain_responses.union(data_responses)
255
+
256
+ def _does_story_only_use_valid_actions(
257
+ self, used_utterances_in_stories: Set[str], utterance_actions: List[str]
258
+ ) -> bool:
259
+ """Checks if all utterances used in stories are valid."""
260
+ has_no_warnings = True
261
+ for used_utterance in used_utterances_in_stories:
262
+ if used_utterance not in utterance_actions:
263
+ structlogger.warn(
264
+ "validator.invalid_utterance_action",
265
+ action=used_utterance,
266
+ event_info=(
267
+ f"The action '{used_utterance}' is used in the stories, "
268
+ f"but is not a valid utterance action. Please make sure "
269
+ f"the action is listed in your domain and there is a "
270
+ f"template defined with its name."
271
+ ),
272
+ docs=DOCS_URL_ACTIONS + "#utterance-actions",
273
+ )
274
+ has_no_warnings = False
275
+ return has_no_warnings
276
+
277
+ def _utterances_used_in_stories(self) -> Set[str]:
278
+ """Return all utterances which are used in stories."""
279
+ stories_utterances = set()
280
+
281
+ for story in self.story_graph.story_steps:
282
+ for event in story.events:
283
+ if not isinstance(event, ActionExecuted):
284
+ continue
285
+
286
+ if not event.action_name:
287
+ continue
288
+
289
+ if not event.action_name.startswith(UTTER_PREFIX):
290
+ # we are only interested in utter actions
291
+ continue
292
+
293
+ if event.action_name in stories_utterances:
294
+ # we already processed this one before, we only want to warn once
295
+ continue
296
+
297
+ stories_utterances.add(event.action_name)
298
+ return stories_utterances
299
+
300
+ @classmethod
301
+ def check_for_placeholder(cls, value: Any) -> bool:
302
+ """Check if a value contains a placeholder."""
303
+ if isinstance(value, str):
304
+ return bool(re.search(r"{\s*}", value))
305
+ elif isinstance(value, dict):
306
+ return any(cls.check_for_placeholder(i) for i in value.values())
307
+ elif isinstance(value, list):
308
+ return any(cls.check_for_placeholder(i) for i in value)
309
+ return False
310
+
311
+ def check_for_no_empty_parenthesis_in_responses(self) -> bool:
312
+ """Checks if there are no empty parenthesis in utterances."""
313
+ everything_is_alright = True
314
+
315
+ for response_text, response_variations in self.domain.responses.items():
316
+ for response in response_variations:
317
+ if any(
318
+ self.check_for_placeholder(response.get(key))
319
+ for key in RESPONSE_KEYS_TO_INTERPOLATE
320
+ ):
321
+ structlogger.error(
322
+ "validator.empty_parenthesis_in_utterances",
323
+ response=response_text,
324
+ event_info=(
325
+ f"The response '{response_text}' in the domain file "
326
+ f"contains empty parenthesis, which is not permitted. "
327
+ f"Please remove the empty parenthesis."
328
+ ),
329
+ )
330
+ everything_is_alright = False
331
+
332
+ return everything_is_alright
333
+
334
+ def verify_forms_in_stories_rules(self) -> bool:
335
+ """Verifies that forms referenced in active_loop directives are present."""
336
+ all_forms_exist = True
337
+ visited_loops = set()
338
+
339
+ for story in self.story_graph.story_steps:
340
+ for event in story.events:
341
+ if not isinstance(event, ActiveLoop):
342
+ continue
343
+
344
+ if event.name in visited_loops:
345
+ # We've seen this loop before, don't alert on it twice
346
+ continue
347
+
348
+ if not event.name:
349
+ # To support setting `active_loop` to `null`
350
+ continue
351
+
352
+ if event.name not in self.domain.action_names_or_texts:
353
+ structlogger.error(
354
+ "validator.verify_forms_in_stories_rules.not_in_domain",
355
+ form=event.name,
356
+ block=story.block_name,
357
+ event_info=(
358
+ f"The form '{event.name}' is used in the "
359
+ f"'{story.block_name}' block, but it "
360
+ f"is not listed in the domain file. "
361
+ f"You should add it to your "
362
+ f"domain file!"
363
+ ),
364
+ docs=DOCS_URL_FORMS,
365
+ )
366
+ all_forms_exist = False
367
+ visited_loops.add(event.name)
368
+
369
+ return all_forms_exist
370
+
371
+ def verify_actions_in_stories_rules(self) -> bool:
372
+ """Verifies that actions used in stories and rules are present in the domain."""
373
+ everything_is_alright = True
374
+ visited = set()
375
+
376
+ for story in self.story_graph.story_steps:
377
+ for event in story.events:
378
+ if not isinstance(event, ActionExecuted):
379
+ continue
380
+
381
+ if not event.action_name:
382
+ continue
383
+
384
+ if not event.action_name.startswith("action_"):
385
+ continue
386
+
387
+ if event.action_name in visited:
388
+ # we already processed this one before, we only want to warn once
389
+ continue
390
+
391
+ if event.action_name not in self.domain.action_names_or_texts:
392
+ structlogger.error(
393
+ "validator.verify_actions_in_stories_rules.not_in_domain",
394
+ action=event.action_name,
395
+ block=story.block_name,
396
+ event_info=(
397
+ f"The action '{event.action_name}' is used in the "
398
+ f"'{story.block_name}' block, but it "
399
+ f"is not listed in the domain file. You "
400
+ f"should add it to your domain file!"
401
+ ),
402
+ docs=DOCS_URL_DOMAINS,
403
+ )
404
+ everything_is_alright = False
405
+ visited.add(event.action_name)
406
+
407
+ return everything_is_alright
408
+
409
+ def verify_story_structure(
410
+ self, ignore_warnings: bool = True, max_history: Optional[int] = None
411
+ ) -> bool:
412
+ """Verifies that the bot behaviour in stories is deterministic.
413
+
414
+ Args:
415
+ ignore_warnings: When `True`, return `True` even if conflicts were found.
416
+ max_history: Maximal number of events to take into account for conflict
417
+ identification.
418
+
419
+ Returns:
420
+ `False` is a conflict was found and `ignore_warnings` is `False`.
421
+ `True` otherwise.
422
+ """
423
+ structlogger.info(
424
+ "validator.verify_story_structure.start",
425
+ event_info="Story structure validation...",
426
+ )
427
+
428
+ trackers = TrainingDataGenerator(
429
+ self.story_graph,
430
+ domain=self.domain,
431
+ remove_duplicates=False,
432
+ augmentation_factor=0,
433
+ ).generate_story_trackers()
434
+
435
+ # Create a list of `StoryConflict` objects
436
+ conflicts = rasa.core.training.story_conflict.find_story_conflicts(
437
+ trackers, self.domain, max_history
438
+ )
439
+
440
+ if not conflicts:
441
+ structlogger.info(
442
+ "validator.verify_story_structure.no_conflicts",
443
+ event_info="No story structure conflicts found.",
444
+ )
445
+ else:
446
+ for conflict in conflicts:
447
+ structlogger.warn(
448
+ "validator.verify_story_structure.conflicts",
449
+ event_info="Found story structure conflict",
450
+ conflict=str(conflict),
451
+ )
452
+
453
+ return ignore_warnings or not conflicts
454
+
455
+ def verify_nlu(self, ignore_warnings: bool = True) -> bool:
456
+ """Runs all the validations on intents and utterances."""
457
+ structlogger.info(
458
+ "validator.verify_intents_in_stories.start",
459
+ event_info="Validating intents...",
460
+ )
461
+ intents_are_valid = self.verify_intents_in_stories_or_flows(ignore_warnings)
462
+
463
+ structlogger.info(
464
+ "validator.verify_example_repetition_in_intents.start",
465
+ event_info="Validating uniqueness of intents and stories...",
466
+ )
467
+ there_is_no_duplication = self.verify_example_repetition_in_intents(
468
+ ignore_warnings
469
+ )
470
+
471
+ return intents_are_valid and there_is_no_duplication
472
+
473
+ def verify_form_slots(self) -> bool:
474
+ """Verifies that form slots match the slot mappings in domain."""
475
+ domain_slot_names = [slot.name for slot in self.domain.slots]
476
+ everything_is_alright = True
477
+
478
+ for form in self.domain.form_names:
479
+ form_slots = self.domain.required_slots_for_form(form)
480
+ for slot in form_slots:
481
+ if slot in domain_slot_names:
482
+ continue
483
+ else:
484
+ structlogger.warn(
485
+ "validator.verify_form_slots.not_in_domain",
486
+ slot=slot,
487
+ form=form,
488
+ event_info=(
489
+ f"The form slot '{slot}' in form '{form}' "
490
+ f"is not present in the domain slots."
491
+ f"Please add the correct slot or check for typos."
492
+ ),
493
+ docs=DOCS_URL_DOMAINS,
494
+ )
495
+ everything_is_alright = False
496
+
497
+ return everything_is_alright
498
+
499
+ def verify_slot_mappings(self) -> bool:
500
+ """Verifies that slot mappings match forms."""
501
+ everything_is_alright = True
502
+
503
+ for slot in self.domain.slots:
504
+ for mapping in slot.mappings:
505
+ for condition in mapping.get(MAPPING_CONDITIONS, []):
506
+ condition_active_loop = condition.get(ACTIVE_LOOP)
507
+ mapping_type = SlotMappingType(mapping.get(MAPPING_TYPE))
508
+ if (
509
+ condition_active_loop
510
+ and condition_active_loop not in self.domain.form_names
511
+ ):
512
+ structlogger.warn(
513
+ "validator.verify_slot_mappings.not_in_domain",
514
+ slot=slot.name,
515
+ form=condition_active_loop,
516
+ event_info=(
517
+ f"Slot '{slot.name}' has a mapping "
518
+ f"condition for form '{condition_active_loop}' "
519
+ f"which is not listed in domain forms. Please "
520
+ f"add this form to the forms section or check "
521
+ f"for typos."
522
+ ),
523
+ )
524
+ everything_is_alright = False
525
+
526
+ form_slots = self.domain.forms.get(condition_active_loop, {}).get(
527
+ REQUIRED_SLOTS_KEY, {}
528
+ )
529
+ if (
530
+ form_slots
531
+ and slot.name not in form_slots
532
+ and mapping_type != SlotMappingType.FROM_TRIGGER_INTENT
533
+ ):
534
+ structlogger.warn(
535
+ "validator.verify_slot_mappings.not_in_forms_key",
536
+ slot=slot.name,
537
+ form=condition_active_loop,
538
+ forms_key=REQUIRED_SLOTS_KEY,
539
+ event_info=(
540
+ f"Slot '{slot.name}' has a mapping condition "
541
+ f"for form '{condition_active_loop}', but it's "
542
+ f"not present in '{condition_active_loop}' "
543
+ f"form's '{REQUIRED_SLOTS_KEY}'. "
544
+ f"The slot needs to be added to this key."
545
+ ),
546
+ )
547
+ everything_is_alright = False
548
+
549
+ return everything_is_alright
550
+
551
+ def verify_domain_validity(self) -> bool:
552
+ """Checks whether the domain returned by the importer is empty.
553
+
554
+ An empty domain or one that uses deprecated Mapping Policy is invalid.
555
+ """
556
+ if self.domain.is_empty():
557
+ return False
558
+
559
+ for intent_key, intent_dict in self.domain.intent_properties.items():
560
+ if "triggers" in intent_dict:
561
+ structlogger.warn(
562
+ "validator.verify_domain_validity.mapping_policy_deprecation",
563
+ intent_key=intent_key,
564
+ event_info=(
565
+ f"The intent {intent_key} in the domain file "
566
+ f"is using the MappingPolicy format "
567
+ f"which has now been deprecated. "
568
+ f"Please migrate to RulePolicy."
569
+ ),
570
+ )
571
+ return False
572
+
573
+ return True
574
+
575
+ def warn_if_config_mandatory_keys_are_not_set(self) -> None:
576
+ """Raises a warning if mandatory keys are not present in the config.
577
+
578
+ Additionally, raises a UserWarning if the assistant_id key is filled with the
579
+ default placeholder value.
580
+ """
581
+ for key in set(CONFIG_MANDATORY_KEYS):
582
+ if key not in self.config:
583
+ structlogger.warn(
584
+ "validator.config_missing_mandatory_key",
585
+ key=key,
586
+ event_info=(
587
+ f"The config file is missing the " f"'{key}' mandatory key."
588
+ ),
589
+ )
590
+
591
+ assistant_id = self.config.get(ASSISTANT_ID_KEY)
592
+
593
+ if assistant_id is not None and assistant_id == ASSISTANT_ID_DEFAULT_VALUE:
594
+ structlogger.warn(
595
+ "validator.config_missing_unique_mandatory_key_value",
596
+ key=ASSISTANT_ID_KEY,
597
+ event_info=(
598
+ f"The config file is missing a unique value for the "
599
+ f"'{ASSISTANT_ID_KEY}' mandatory key. Please replace the default "
600
+ f"placeholder value with a unique identifier."
601
+ ),
602
+ )
603
+
604
+ def _log_error_if_either_action_or_utterance_are_not_defined(
605
+ self,
606
+ collect: CollectInformationFlowStep,
607
+ all_good: bool,
608
+ domain_slots: Dict[Text, Slot],
609
+ flow_id: str,
610
+ ) -> bool:
611
+ """Validates that a collect step can have either an action or an utterance.
612
+ Also logs an error if neither an action nor an utterance is defined.
613
+
614
+ Args:
615
+ collect: the name of the slot to collect
616
+ all_good: boolean value indicating the validation status
617
+
618
+ Returns:
619
+ False, if validation failed, true, otherwise
620
+ """
621
+ has_utterance_defined = any(
622
+ [u for u in self.domain.utterances_for_response if u == collect.utter]
623
+ )
624
+
625
+ has_action_defined = any(
626
+ [
627
+ a
628
+ for a in self.domain.action_names_or_texts
629
+ if a == collect.collect_action
630
+ ]
631
+ )
632
+
633
+ if has_utterance_defined and has_action_defined:
634
+ structlogger.error(
635
+ "validator.verify_flows_steps_against_domain.collect_step",
636
+ collect=collect.collect,
637
+ has_utterance_defined=has_utterance_defined,
638
+ has_action_defined=has_action_defined,
639
+ flow=flow_id,
640
+ event_info=(
641
+ f"The collect step '{collect.collect}' has an utterance "
642
+ f"'{collect.utter}' as well as an action "
643
+ f"'{collect.collect_action}' defined. "
644
+ f"You can just have one of them! "
645
+ f"Please remove either the utterance or the action."
646
+ ),
647
+ )
648
+ all_good = False
649
+
650
+ slot = domain_slots.get(collect.collect)
651
+ slot_has_initial_value_defind = slot and slot.initial_value is not None
652
+
653
+ if (
654
+ not slot_has_initial_value_defind
655
+ and not has_utterance_defined
656
+ and not has_action_defined
657
+ ):
658
+ structlogger.error(
659
+ "validator.verify_flows_steps_against_domain.collect_step",
660
+ collect=collect.collect,
661
+ has_utterance_defined=has_utterance_defined,
662
+ has_action_defined=has_action_defined,
663
+ flow=flow_id,
664
+ event_info=(
665
+ f"The collect step '{collect.collect}' has neither an utterance "
666
+ f"nor an action defined, or an initial value defined in the domain."
667
+ f"You need to define either an utterance or an action."
668
+ ),
669
+ )
670
+ all_good = False
671
+
672
+ return all_good
673
+
674
+ @staticmethod
675
+ def _log_error_if_slot_not_in_domain(
676
+ slot_name: str,
677
+ domain_slots: Dict[Text, Slot],
678
+ step_id: str,
679
+ flow_id: str,
680
+ all_good: bool,
681
+ ) -> bool:
682
+ if slot_name not in domain_slots:
683
+ structlogger.error(
684
+ "validator.verify_flows_steps_against_domain.slot_not_in_domain",
685
+ slot=slot_name,
686
+ step=step_id,
687
+ flow=flow_id,
688
+ event_info=(
689
+ f"The slot '{slot_name}' is used in the "
690
+ f"step '{step_id}' of flow id '{flow_id}', but it "
691
+ f"is not listed in the domain slots. "
692
+ f"You should add it to your domain file!"
693
+ ),
694
+ )
695
+ all_good = False
696
+
697
+ return all_good
698
+
699
+ @staticmethod
700
+ def _log_error_if_list_slot(
701
+ slot: Slot, step_id: str, flow_id: str, all_good: bool
702
+ ) -> bool:
703
+ if isinstance(slot, ListSlot):
704
+ structlogger.error(
705
+ "validator.verify_flows_steps_against_domain.use_of_list_slot_in_flow",
706
+ slot=slot.name,
707
+ step=step_id,
708
+ flow=flow_id,
709
+ event_info=(
710
+ f"The slot '{slot.name}' is used in the "
711
+ f"step '{step_id}' of flow id '{flow_id}', but it "
712
+ f"is a list slot. List slots are currently not "
713
+ f"supported in flows. You should change it to a "
714
+ f"text, boolean or float slot in your domain file!"
715
+ ),
716
+ )
717
+ all_good = False
718
+
719
+ return all_good
720
+
721
+ def verify_flows_steps_against_domain(self) -> bool:
722
+ """Checks flows steps' references against the domain file."""
723
+ all_good = True
724
+ domain_slots = {slot.name: slot for slot in self.domain.slots}
725
+ flow_ids = [flow.id for flow in self.flows.underlying_flows]
726
+
727
+ for flow in self.flows.underlying_flows:
728
+ for step in flow.steps_with_calls_resolved:
729
+ if isinstance(step, CollectInformationFlowStep):
730
+ all_good = (
731
+ self._log_error_if_either_action_or_utterance_are_not_defined(
732
+ step, all_good, domain_slots, flow.id
733
+ )
734
+ )
735
+
736
+ all_good = self._log_error_if_slot_not_in_domain(
737
+ step.collect, domain_slots, step.id, flow.id, all_good
738
+ )
739
+
740
+ current_slot = domain_slots.get(step.collect)
741
+ if not current_slot:
742
+ continue
743
+
744
+ all_good = self._log_error_if_list_slot(
745
+ current_slot, step.id, flow.id, all_good
746
+ )
747
+
748
+ elif isinstance(step, SetSlotsFlowStep):
749
+ for slot in step.slots:
750
+ slot_name = slot["key"]
751
+ all_good = self._log_error_if_slot_not_in_domain(
752
+ slot_name, domain_slots, step.id, flow.id, all_good
753
+ )
754
+ current_slot = domain_slots.get(slot_name)
755
+ if not current_slot:
756
+ continue
757
+
758
+ all_good = self._log_error_if_list_slot(
759
+ current_slot, step.id, flow.id, all_good
760
+ )
761
+
762
+ elif isinstance(step, ActionFlowStep):
763
+ regex = r"{context\..+?}"
764
+ matches = re.findall(regex, step.action)
765
+ if matches:
766
+ structlogger.debug(
767
+ "validator.verify_flows_steps_against_domain"
768
+ ".interpolated_action",
769
+ action=step.action,
770
+ step=step.id,
771
+ flow=flow.id,
772
+ event_info=(
773
+ f"An interpolated action name '{step.action}' was "
774
+ f"found at step '{step.id}' of flow id '{flow.id}'. "
775
+ f"Skipping validation for this step. "
776
+ f"Please make sure that the action name is "
777
+ f"listed in your domain responses or actions."
778
+ ),
779
+ )
780
+ elif step.action not in self.domain.action_names_or_texts:
781
+ structlogger.error(
782
+ "validator.verify_flows_steps_against_domain"
783
+ ".action_not_in_domain",
784
+ action=step.action,
785
+ step=step.id,
786
+ flow=flow.id,
787
+ event_info=(
788
+ f"The action '{step.action}' is used in the "
789
+ f"step '{step.id}' of flow id '{flow.id}', "
790
+ f"but it is not listed in the domain file. "
791
+ f"You should add it to your domain file!"
792
+ ),
793
+ )
794
+ all_good = False
795
+
796
+ elif isinstance(step, LinkFlowStep):
797
+ if step.link not in flow_ids:
798
+ logger.error(
799
+ f"The flow '{step.link}' is used in the step "
800
+ f"'{step.id}' of flow id '{flow.id}', but it "
801
+ f"is not listed in the flows file. "
802
+ f"Did you make a typo?",
803
+ )
804
+ all_good = False
805
+ return all_good
806
+
807
+ def verify_unique_flows(self) -> bool:
808
+ """Checks if all flows have unique names and descriptions."""
809
+ all_good = True
810
+ flow_names = set()
811
+ flow_descriptions = set()
812
+ punctuation_table = str.maketrans({i: "" for i in string.punctuation})
813
+
814
+ for flow in self.flows.underlying_flows:
815
+ flow_description = flow.description
816
+ cleaned_description = flow_description.translate(punctuation_table) # type: ignore[union-attr]
817
+ if cleaned_description in flow_descriptions:
818
+ structlogger.error(
819
+ "validator.verify_unique_flows.duplicate_description",
820
+ flow=flow.id,
821
+ event_info=(
822
+ f"Detected duplicate flow description for "
823
+ f"flow id '{flow.id}'. Flow descriptions must be "
824
+ f"unique. Please make sure that all flows have "
825
+ f"different descriptions."
826
+ ),
827
+ )
828
+ all_good = False
829
+
830
+ if flow.name in flow_names:
831
+ structlogger.error(
832
+ "validator.verify_unique_flows.duplicate_name",
833
+ flow=flow.id,
834
+ name=flow.name,
835
+ event_info=(
836
+ f"Detected duplicate flow name '{flow.name}' for flow "
837
+ f"id '{flow.id}'. Flow names must be unique. "
838
+ f"Please make sure that all flows have different names."
839
+ ),
840
+ )
841
+ all_good = False
842
+
843
+ flow_names.add(flow.name)
844
+ flow_descriptions.add(cleaned_description)
845
+
846
+ return all_good
847
+
848
+ def _build_context(self) -> Dict[str, Any]:
849
+ """Build context for jinja template rendering.
850
+
851
+ Returns:
852
+ A dictionary containing the allowed namespaces for jinja template rendering:
853
+ - `context`: The context mapping the attributes of every flow stack frame
854
+ to None values because this is only used for rendering the template
855
+ during validation.
856
+ - `slots`: The slots of the domain mapped to None values because this is
857
+ only used for rendering the template during validation and not for
858
+ evaluating the predicate at runtime.
859
+ """
860
+ subclasses = [subclass for subclass in PatternFlowStackFrame.__subclasses__()]
861
+ subclass_attrs = []
862
+ for subclass in subclasses:
863
+ subclass_attrs.extend(
864
+ [attr for attr in dir(subclass) if not attr.startswith("__")]
865
+ )
866
+
867
+ context = {
868
+ "context": {attr: None for attr in subclass_attrs},
869
+ "slots": {slot.name: None for slot in self.domain.slots},
870
+ }
871
+ return context
872
+
873
+ @staticmethod
874
+ def _construct_predicate(
875
+ predicate: Optional[str],
876
+ object_id: str,
877
+ context: Dict[str, Any],
878
+ is_step: bool,
879
+ all_good: bool = True,
880
+ ) -> Tuple[Optional[Predicate], bool]:
881
+ rendered_template = Template(predicate).render(context)
882
+ try:
883
+ pred = Predicate(rendered_template)
884
+ except (TypeError, Exception) as exception:
885
+ if is_step:
886
+ structlogger.error(
887
+ "validator.verify_predicates.step_predicate.error",
888
+ step=object_id,
889
+ exception=exception,
890
+ event_info=(
891
+ f"Could not initialize the predicate found under step "
892
+ f"'{object_id}': {exception}"
893
+ ),
894
+ )
895
+ else:
896
+ structlogger.error(
897
+ "validator.verify_predicates.flow_guard_predicate.error",
898
+ flow=object_id,
899
+ exception=exception,
900
+ event_info=(
901
+ f"Could not initialize the predicate found in flow guard "
902
+ f"for flow: '{object_id}': {exception}."
903
+ ),
904
+ )
905
+ pred = None
906
+ all_good = False
907
+
908
+ return pred, all_good
909
+
910
+ def _extract_predicate_syntax_tree(self, predicate: Predicate) -> Any:
911
+ """Extract the predicate syntax tree from the given predicate.
912
+
913
+ Args:
914
+ predicate: The predicate from which to extract the syntax tree.
915
+
916
+ Returns:
917
+ The extracted syntax tree.
918
+ """
919
+ if isinstance(predicate.ast, NegateOperator):
920
+ return predicate.ast.left
921
+ return predicate.ast
922
+
923
+ def _extract_slot_name_and_slot_value(
924
+ self,
925
+ predicate_syntax_tree: Any,
926
+ ) -> tuple:
927
+ """Extract the slot name and slot value from the predicate syntax tree.
928
+
929
+ Args:
930
+ predicate_syntax_tree: The predicate syntax tree.
931
+
932
+ Returns:
933
+ A tuple containing the slot name and slot value.
934
+ """
935
+ try:
936
+ if isinstance(predicate_syntax_tree.left, Literal):
937
+ slot_name = predicate_syntax_tree.left.value.split(".")
938
+ slot_value = predicate_syntax_tree.right.value
939
+ else:
940
+ slot_name = predicate_syntax_tree.right.value.split(".")
941
+ slot_value = predicate_syntax_tree.left.value
942
+ except AttributeError:
943
+ # predicate only has negation and doesn't need to be checked further
944
+ return None, None
945
+ return slot_name, slot_value
946
+
947
+ def _validate_categorical_value_check(
948
+ self,
949
+ slot_name: str,
950
+ slot_value: Any,
951
+ valid_slot_values: List[str],
952
+ all_good: bool,
953
+ step_id: str,
954
+ link_condition: str,
955
+ flow_id: str,
956
+ ) -> bool:
957
+ """Validates the categorical slot check.
958
+
959
+ Validates that the categorical slot is checked against valid values.
960
+
961
+ Args:
962
+ slot_name: name of the slot to be checked
963
+ slot_value: value of the slot to be checked
964
+ valid_slot_values: valid values for the given slot
965
+ all_good: flag whether all the validations have passed so far
966
+ step_id: id of the step in which the values are being checked
967
+ link_condition: condition where the values are being checked
968
+ flow_id: id of the flow where the values are being checked
969
+
970
+ Returns:
971
+ False, if validation failed, previous value of all_good, otherwise
972
+ """
973
+ valid_slot_values.append(None)
974
+ # slot_value can either be None, a string or a list of Literal objects
975
+ if slot_value is None:
976
+ slot_value = [None]
977
+ if isinstance(slot_value, str):
978
+ slot_value = [Literal(slot_value)]
979
+
980
+ slot_values_validity = [
981
+ sv is None
982
+ or re.sub(r'^[\'"](.+)[\'"]$', r"\1", sv.value) in valid_slot_values
983
+ for sv in slot_value
984
+ ]
985
+ if not all(slot_values_validity):
986
+ invalid_slot_values = [
987
+ sv
988
+ for (sv, slot_value_valid) in zip(slot_value, slot_values_validity)
989
+ if not slot_value_valid
990
+ ]
991
+ structlogger.error(
992
+ "validator.verify_predicates.link.invalid_condition",
993
+ step=step_id,
994
+ link=link_condition,
995
+ flow=flow_id,
996
+ event_info=(
997
+ f"Detected invalid condition '{link_condition}' "
998
+ f"at step '{step_id}' for flow id '{flow_id}'. "
999
+ f"Values {invalid_slot_values} are not valid values "
1000
+ f"for slot {slot_name}. "
1001
+ f"Please make sure that all conditions are valid."
1002
+ ),
1003
+ )
1004
+ return False
1005
+ return all_good
1006
+
1007
+ def _validate_categorical_and_boolean_values_check(
1008
+ self,
1009
+ predicate: Predicate,
1010
+ all_good: bool,
1011
+ step_id: str,
1012
+ link_condition: str,
1013
+ flow_id: str,
1014
+ ) -> bool:
1015
+ """Validates the categorical and boolean slot checks.
1016
+
1017
+ Validates that the categorical and boolean slots
1018
+ are checked against valid values.
1019
+
1020
+ Args:
1021
+ predicate: condition that is supposed to be validated
1022
+ all_good: flag whether all the validations have passed so far
1023
+ step_id: id of the step in which the values are being checked
1024
+ link_condition: condition where the values are being checked
1025
+ flow_id: id of the flow where the values are being checked
1026
+
1027
+ Returns:
1028
+ False, if validation failed, previous value of all_good, otherwise
1029
+ """
1030
+ predicate_syntax_tree = self._extract_predicate_syntax_tree(predicate)
1031
+ slot_name, slot_value = self._extract_slot_name_and_slot_value(
1032
+ predicate_syntax_tree
1033
+ )
1034
+
1035
+ if slot_name is None:
1036
+ return all_good
1037
+
1038
+ if slot_name[0] == "slots":
1039
+ slot_name = slot_name[1]
1040
+ # slots.{{context.variable}} gets evaluated to `slots.None`,
1041
+ # these predicates can only be validated during runtime
1042
+ if slot_name == "None":
1043
+ return all_good
1044
+ else:
1045
+ return all_good
1046
+
1047
+ try:
1048
+ slot = next(slot for slot in self.domain.slots if slot.name == slot_name)
1049
+ except StopIteration:
1050
+ structlogger.error(
1051
+ "validator.verify_predicates.link.invalid_condition",
1052
+ step=step_id,
1053
+ link=link_condition,
1054
+ flow=flow_id,
1055
+ event_info=(
1056
+ f"Detected invalid condition '{link_condition}' "
1057
+ f"at step '{step_id}' for flow id '{flow_id}'. "
1058
+ f"Slot {slot_name} is not defined in the domain file. "
1059
+ f"Please make sure that all conditions are valid."
1060
+ ),
1061
+ )
1062
+ return False
1063
+ if isinstance(slot, CategoricalSlot):
1064
+ return self._validate_categorical_value_check(
1065
+ slot_name,
1066
+ slot_value,
1067
+ slot.values,
1068
+ all_good,
1069
+ step_id,
1070
+ link_condition,
1071
+ flow_id,
1072
+ )
1073
+
1074
+ if (
1075
+ isinstance(slot, BooleanSlot)
1076
+ and isinstance(predicate_syntax_tree, CompareOperator)
1077
+ and not isinstance(predicate_syntax_tree.right.value, bool)
1078
+ ):
1079
+ structlogger.error(
1080
+ "validator.verify_predicates.link.invalid_condition",
1081
+ step=step_id,
1082
+ link=link_condition,
1083
+ flow=flow_id,
1084
+ event_info=(
1085
+ f"Detected invalid condition '{link_condition}' "
1086
+ f"at step '{step_id}' for flow id '{flow_id}'. "
1087
+ f"Boolean slots can only be compared to "
1088
+ f"boolean values (true, false). "
1089
+ f"Please make sure that all conditions are valid."
1090
+ ),
1091
+ )
1092
+ return False
1093
+ return all_good
1094
+
1095
+ def verify_predicates(self) -> bool:
1096
+ """Validate predicates used in flow step links and slot rejections."""
1097
+ all_good = True
1098
+ context = self._build_context()
1099
+
1100
+ for flow in self.flows.underlying_flows:
1101
+ if flow.guard_condition:
1102
+ predicate, all_good = self._construct_predicate(
1103
+ flow.guard_condition,
1104
+ flow.id,
1105
+ context,
1106
+ is_step=False,
1107
+ all_good=all_good,
1108
+ )
1109
+ if predicate and not predicate.is_valid():
1110
+ structlogger.error(
1111
+ "validator.verify_predicates.flow_guard.invalid_condition",
1112
+ flow=flow.id,
1113
+ flow_guard=flow.guard_condition,
1114
+ event_info=(
1115
+ f"Detected invalid flow guard condition "
1116
+ f"'{flow.guard_condition}' for flow id '{flow.id}'. "
1117
+ f"Please make sure that all conditions are valid."
1118
+ ),
1119
+ )
1120
+ all_good = False
1121
+ for step in flow.steps_with_calls_resolved:
1122
+ for link in step.next.links:
1123
+ if isinstance(link, IfFlowStepLink):
1124
+ all_good = self._verify_namespaces(
1125
+ link.condition, step.id, flow.id, all_good
1126
+ )
1127
+
1128
+ predicate, all_good = self._construct_predicate(
1129
+ link.condition,
1130
+ step.id,
1131
+ context,
1132
+ is_step=True,
1133
+ all_good=all_good,
1134
+ )
1135
+ if predicate and not predicate.is_valid():
1136
+ structlogger.error(
1137
+ "validator.verify_predicates.link.invalid_condition",
1138
+ step=step.id,
1139
+ link=link.condition,
1140
+ flow=flow.id,
1141
+ event_info=(
1142
+ f"Detected invalid condition '{link.condition}' "
1143
+ f"at step '{step.id}' for flow id '{flow.id}'. "
1144
+ f"Please make sure that all conditions are valid."
1145
+ ),
1146
+ )
1147
+ all_good = False
1148
+
1149
+ all_good = self._validate_categorical_and_boolean_values_check(
1150
+ predicate,
1151
+ all_good=all_good,
1152
+ step_id=step.id,
1153
+ link_condition=link.condition,
1154
+ flow_id=flow.id,
1155
+ )
1156
+
1157
+ if isinstance(step, CollectInformationFlowStep):
1158
+ predicates = [predicate.if_ for predicate in step.rejections]
1159
+ for predicate in predicates:
1160
+ all_good = self._verify_namespaces(
1161
+ predicate, step.id, flow.id, all_good
1162
+ )
1163
+
1164
+ pred, all_good = self._construct_predicate(
1165
+ predicate, step.id, context, is_step=True, all_good=all_good
1166
+ )
1167
+ if pred and not pred.is_valid():
1168
+ structlogger.error(
1169
+ "validator.verify_predicates.invalid_rejection",
1170
+ step=step.id,
1171
+ rejection=predicate,
1172
+ flow=flow.id,
1173
+ event_info=(
1174
+ f"Detected invalid rejection '{predicate}' "
1175
+ f"at `collect` step '{step.id}' "
1176
+ f"for flow id '{flow.id}'. "
1177
+ f"Please make sure that all conditions are valid."
1178
+ ),
1179
+ )
1180
+ all_good = False
1181
+ return all_good
1182
+
1183
+ def _verify_namespaces(
1184
+ self, predicate: str, step_id: str, flow_id: str, all_good: bool
1185
+ ) -> bool:
1186
+ slots = re.findall(r"\bslots\.\w+", predicate)
1187
+ results: List[bool] = [all_good]
1188
+
1189
+ if slots:
1190
+ domain_slots = {slot.name: slot for slot in self.domain.slots}
1191
+ for slot in slots:
1192
+ slot_name = slot.split(".")[1]
1193
+ if slot_name not in domain_slots:
1194
+ structlogger.error(
1195
+ "validator.verify_namespaces.invalid_slot",
1196
+ slot=slot_name,
1197
+ step=step_id,
1198
+ flow=flow_id,
1199
+ event_info=(
1200
+ f"Detected invalid slot '{slot_name}' "
1201
+ f"at step '{step_id}' "
1202
+ f"for flow id '{flow_id}'. "
1203
+ f"Please make sure that all slots are specified "
1204
+ f"in the domain file."
1205
+ ),
1206
+ )
1207
+ results.append(False)
1208
+
1209
+ if not slots:
1210
+ # no slots found, check if context namespace is used
1211
+ variables = re.findall(r"\bcontext\.\w+", predicate)
1212
+ if not variables:
1213
+ structlogger.error(
1214
+ "validator.verify_namespaces"
1215
+ ".referencing_variables_without_namespace",
1216
+ step=step_id,
1217
+ predicate=predicate,
1218
+ flow=flow_id,
1219
+ event_info=(
1220
+ f"Predicate '{predicate}' at step '{step_id}' for flow id "
1221
+ f"'{flow_id}' references one or more variables without "
1222
+ f"the `slots.` or `context.` namespace prefix. "
1223
+ f"Please make sure that all variables reference the required "
1224
+ f"namespace."
1225
+ ),
1226
+ )
1227
+ results.append(False)
1228
+
1229
+ return all(results)
1230
+
1231
+ def verify_flows(self) -> bool:
1232
+ """Checks for inconsistencies across flows."""
1233
+ structlogger.info("validation.flows.started")
1234
+
1235
+ if self.flows.is_empty():
1236
+ structlogger.warn(
1237
+ "validator.verify_flows",
1238
+ event_info=(
1239
+ "No flows were found in the data files. "
1240
+ "Will not proceed with flow validation."
1241
+ ),
1242
+ )
1243
+ return True
1244
+
1245
+ # add all flow validation conditions here
1246
+ flow_validation_conditions = [
1247
+ self.verify_flows_steps_against_domain(),
1248
+ self.verify_unique_flows(),
1249
+ self.verify_predicates(),
1250
+ self.verify_slot_persistence_configuration(),
1251
+ ]
1252
+
1253
+ all_good = all(flow_validation_conditions)
1254
+
1255
+ structlogger.info("validation.flows.ended")
1256
+
1257
+ return all_good
1258
+
1259
+ def validate_button_payloads(self) -> bool:
1260
+ """Check if the response button payloads are valid."""
1261
+ all_good = True
1262
+ for utter_name, response in self.domain.responses.items():
1263
+ for variation in response:
1264
+ for button in variation.get("buttons", []):
1265
+ payload = button.get("payload")
1266
+ if payload is None:
1267
+ structlogger.error(
1268
+ "validator.validate_button_payloads.missing_payload",
1269
+ event_info=(
1270
+ f"The button '{button.get('title')}' in response "
1271
+ f"'{utter_name}' does not have a payload. "
1272
+ f"Please add a payload to the button."
1273
+ ),
1274
+ )
1275
+ all_good = False
1276
+ continue
1277
+
1278
+ if not payload.strip():
1279
+ structlogger.error(
1280
+ "validator.validate_button_payloads.empty_payload",
1281
+ event_info=(
1282
+ f"The button '{button.get('title')}' in response "
1283
+ f"'{utter_name}' has an empty payload. "
1284
+ f"Please add a payload to the button."
1285
+ ),
1286
+ )
1287
+ all_good = False
1288
+ continue
1289
+
1290
+ regex_reader = create_regex_pattern_reader(
1291
+ UserMessage(text=payload), self.domain
1292
+ )
1293
+
1294
+ if regex_reader is None:
1295
+ structlogger.warning(
1296
+ "validator.validate_button_payloads.free_form_string",
1297
+ event_info=(
1298
+ "Using a free form string in payload of a button "
1299
+ "implies that the string will be sent to the NLU "
1300
+ "interpreter for parsing. To avoid the need for "
1301
+ "parsing at runtime, it is recommended to use one "
1302
+ "of the documented formats "
1303
+ "(https://rasa.com/docs/rasa-pro/concepts/responses#buttons)"
1304
+ ),
1305
+ )
1306
+ continue
1307
+
1308
+ if isinstance(
1309
+ regex_reader, CommandPayloadReader
1310
+ ) and regex_reader.is_above_slot_limit(payload):
1311
+ structlogger.error(
1312
+ "validator.validate_button_payloads.slot_limit_exceeded",
1313
+ event_info=(
1314
+ f"The button '{button.get('title')}' in response "
1315
+ f"'{utter_name}' has a payload that sets more than "
1316
+ f"{MAX_NUMBER_OF_SLOTS} slots. "
1317
+ f"Please make sure that the number of slots set by "
1318
+ f"the button payload does not exceed the limit."
1319
+ ),
1320
+ )
1321
+ all_good = False
1322
+ continue
1323
+
1324
+ if isinstance(regex_reader, YAMLStoryReader):
1325
+ # the payload could contain double curly braces
1326
+ # we need to remove 1 set of curly braces
1327
+ payload = payload.replace("{{", "{").replace("}}", "}")
1328
+
1329
+ resulting_message = regex_reader.unpack_regex_message(
1330
+ message=Message(data={"text": payload}), domain=self.domain
1331
+ )
1332
+
1333
+ if not (
1334
+ resulting_message.has_intent()
1335
+ or resulting_message.has_commands()
1336
+ ):
1337
+ structlogger.error(
1338
+ "validator.validate_button_payloads.invalid_payload_format",
1339
+ event_info=(
1340
+ f"The button '{button.get('title')}' in response "
1341
+ f"'{utter_name}' does not follow valid payload formats "
1342
+ f"for triggering a specific intent and entities or for "
1343
+ f"triggering a SetSlot command."
1344
+ ),
1345
+ calm_docs_link=DOCS_URL_RESPONSES + "#payload-syntax",
1346
+ nlu_docs_link=DOCS_URL_RESPONSES
1347
+ + "#triggering-intents-or-passing-entities",
1348
+ )
1349
+ all_good = False
1350
+
1351
+ if resulting_message.has_commands():
1352
+ # validate that slot names are unique
1353
+ slot_names = set()
1354
+ for command in resulting_message.get(COMMANDS, []):
1355
+ slot_name = command.get("name")
1356
+ if slot_name and slot_name in slot_names:
1357
+ structlogger.error(
1358
+ "validator.validate_button_payloads.duplicate_slot_name",
1359
+ event_info=(
1360
+ f"The button '{button.get('title')}' "
1361
+ f"in response '{utter_name}' has a "
1362
+ f"command to set the slot "
1363
+ f"'{slot_name}' multiple times. "
1364
+ f"Please make sure that each slot "
1365
+ f"is set only once."
1366
+ ),
1367
+ )
1368
+ all_good = False
1369
+ slot_names.add(slot_name)
1370
+
1371
+ return all_good
1372
+
1373
+ def validate_CALM_slot_mappings(self) -> bool:
1374
+ """Check if the usage of slot mappings in a CALM assistant is valid."""
1375
+ all_good = True
1376
+
1377
+ for slot in self.domain._user_slots:
1378
+ nlu_mappings = any(
1379
+ [
1380
+ SlotMappingType(
1381
+ mapping.get("type", SlotMappingType.FROM_LLM.value)
1382
+ ).is_predefined_type()
1383
+ for mapping in slot.mappings
1384
+ ]
1385
+ )
1386
+ llm_mappings = any(
1387
+ [
1388
+ SlotMappingType(mapping.get("type", SlotMappingType.FROM_LLM.value))
1389
+ == SlotMappingType.FROM_LLM
1390
+ for mapping in slot.mappings
1391
+ ]
1392
+ )
1393
+ custom_mappings = any(
1394
+ [
1395
+ SlotMappingType(mapping.get("type", SlotMappingType.FROM_LLM.value))
1396
+ == SlotMappingType.CUSTOM
1397
+ for mapping in slot.mappings
1398
+ ]
1399
+ )
1400
+
1401
+ all_good = self._slot_contains_all_mappings_types(
1402
+ llm_mappings, nlu_mappings, custom_mappings, slot.name, all_good
1403
+ )
1404
+
1405
+ all_good = self._custom_action_name_is_defined_in_the_domain(
1406
+ custom_mappings, slot, all_good
1407
+ )
1408
+
1409
+ all_good = self._config_contains_nlu_command_adapter(
1410
+ nlu_mappings, slot.name, all_good
1411
+ )
1412
+
1413
+ all_good = self._uses_from_llm_mappings_in_a_NLU_based_assistant(
1414
+ llm_mappings, slot.name, all_good
1415
+ )
1416
+
1417
+ return all_good
1418
+
1419
+ @staticmethod
1420
+ def _slot_contains_all_mappings_types(
1421
+ llm_mappings: bool,
1422
+ nlu_mappings: bool,
1423
+ custom_mappings: bool,
1424
+ slot_name: str,
1425
+ all_good: bool,
1426
+ ) -> bool:
1427
+ if llm_mappings and (nlu_mappings or custom_mappings):
1428
+ structlogger.error(
1429
+ "validator.validate_slot_mappings_in_CALM.llm_and_nlu_mappings",
1430
+ slot_name=slot_name,
1431
+ event_info=(
1432
+ f"The slot '{slot_name}' has both LLM and "
1433
+ f"NLU or custom slot mappings. "
1434
+ f"Please make sure that the slot has only one type of mapping."
1435
+ ),
1436
+ docs_link=DOCS_URL_DOMAIN + "#calm-slot-mappings",
1437
+ )
1438
+ all_good = False
1439
+
1440
+ return all_good
1441
+
1442
+ def _custom_action_name_is_defined_in_the_domain(
1443
+ self,
1444
+ custom_mappings: bool,
1445
+ slot: Slot,
1446
+ all_good: bool,
1447
+ ) -> bool:
1448
+ if not custom_mappings:
1449
+ return all_good
1450
+
1451
+ if not self.flows:
1452
+ return all_good
1453
+
1454
+ is_custom_action_defined = any(
1455
+ [
1456
+ mapping.get("action") is not None
1457
+ and mapping.get("action") in self.domain.action_names_or_texts
1458
+ for mapping in slot.mappings
1459
+ ]
1460
+ )
1461
+
1462
+ if is_custom_action_defined:
1463
+ return all_good
1464
+
1465
+ slot_collected_by_flows = any(
1466
+ [
1467
+ step.collect == slot.name
1468
+ for flow in self.flows.underlying_flows
1469
+ for step in flow.steps
1470
+ if isinstance(step, CollectInformationFlowStep)
1471
+ ]
1472
+ )
1473
+
1474
+ if not slot_collected_by_flows:
1475
+ # if the slot is not collected by any flow,
1476
+ # it could be a DM1 custom slot
1477
+ return all_good
1478
+
1479
+ custom_action_ask_name = f"action_ask_{slot.name}"
1480
+ if custom_action_ask_name not in self.domain.action_names_or_texts:
1481
+ structlogger.error(
1482
+ "validator.validate_slot_mappings_in_CALM.custom_action_not_in_domain",
1483
+ slot_name=slot.name,
1484
+ event_info=(
1485
+ f"The slot '{slot.name}' has a custom slot mapping, but "
1486
+ f"neither the action '{custom_action_ask_name}' nor "
1487
+ f"another custom action are defined in the domain file. "
1488
+ f"Please add one of the actions to your domain file."
1489
+ ),
1490
+ docs_link=DOCS_URL_DOMAIN + "#custom-slot-mappings",
1491
+ )
1492
+ all_good = False
1493
+
1494
+ return all_good
1495
+
1496
+ def _config_contains_nlu_command_adapter(
1497
+ self, nlu_mappings: bool, slot_name: str, all_good: bool
1498
+ ) -> bool:
1499
+ if not nlu_mappings:
1500
+ return all_good
1501
+
1502
+ if not self.flows:
1503
+ return all_good
1504
+
1505
+ contains_nlu_command_adapter = any(
1506
+ [
1507
+ component.get("name") == "NLUCommandAdapter"
1508
+ for component in self.config.get(CONFIG_PIPELINE_KEY, [])
1509
+ ]
1510
+ )
1511
+
1512
+ if not contains_nlu_command_adapter:
1513
+ structlogger.error(
1514
+ "validator.validate_slot_mappings_in_CALM.nlu_mappings_without_adapter",
1515
+ slot_name=slot_name,
1516
+ event_info=(
1517
+ f"The slot '{slot_name}' has NLU slot mappings, "
1518
+ f"but the NLUCommandAdapter is not present in the "
1519
+ f"pipeline. Please add the NLUCommandAdapter to the "
1520
+ f"pipeline in the config file."
1521
+ ),
1522
+ docs_link=DOCS_URL_DOMAIN + "#nlu-based-predefined-slot-mappings",
1523
+ )
1524
+ all_good = False
1525
+
1526
+ return all_good
1527
+
1528
+ def _uses_from_llm_mappings_in_a_NLU_based_assistant(
1529
+ self, llm_mappings: bool, slot_name: str, all_good: bool
1530
+ ) -> bool:
1531
+ if not llm_mappings:
1532
+ return all_good
1533
+
1534
+ if self.flows:
1535
+ return all_good
1536
+
1537
+ structlogger.error(
1538
+ "validator.validate_slot_mappings_in_CALM.llm_mappings_without_flows",
1539
+ slot_name=slot_name,
1540
+ event_info=(
1541
+ f"The slot '{slot_name}' has LLM slot mappings, "
1542
+ f"but no flows are present in the training data files. "
1543
+ f"Please add flows to the training data files."
1544
+ ),
1545
+ )
1546
+ return False
1547
+
1548
+ def verify_slot_persistence_configuration(self) -> bool:
1549
+ """Verifies the validity of slot persistence after flow ends configuration.
1550
+
1551
+ Only slots used in either a collect step or a set_slot step can be persisted and
1552
+ the configuration can either set at the flow level or the collect step level,
1553
+ but not both.
1554
+
1555
+ Returns:
1556
+ bool: True if all slot persistence configuration is valid, False otherwise.
1557
+
1558
+ Raises:
1559
+ DeprecationWarning: If reset_after_flow_ends is used in collect steps.
1560
+ """
1561
+ all_good = True
1562
+
1563
+ for flow in self.flows.underlying_flows:
1564
+ flow_id = flow.id
1565
+ persist_slots = flow.persisted_slots
1566
+ has_flow_level_persistence = True if persist_slots else False
1567
+ flow_slots = set()
1568
+
1569
+ for step in flow.steps_with_calls_resolved:
1570
+ if isinstance(step, SetSlotsFlowStep):
1571
+ flow_slots.update([slot["key"] for slot in step.slots])
1572
+
1573
+ elif isinstance(step, CollectInformationFlowStep):
1574
+ collect_step = step.collect
1575
+ flow_slots.add(collect_step)
1576
+ if not step.reset_after_flow_ends:
1577
+ warn_deprecated_collect_step_config(flow_id, collect_step)
1578
+
1579
+ if has_flow_level_persistence:
1580
+ structlogger.error(
1581
+ "validator.verify_slot_persistence_configuration.duplicate_config",
1582
+ flow=flow_id,
1583
+ collect_step=collect_step,
1584
+ event_info=get_duplicate_slot_persistence_config_error_message(
1585
+ flow_id, collect_step
1586
+ ),
1587
+ )
1588
+ all_good = False
1589
+
1590
+ if has_flow_level_persistence:
1591
+ if not self._is_persist_slots_valid(persist_slots, flow_slots, flow_id):
1592
+ all_good = False
1593
+ return all_good
1594
+
1595
+ def _is_persist_slots_valid(
1596
+ self, persist_slots: List[str], flow_slots: Set[str], flow_id: str
1597
+ ) -> bool:
1598
+ invalid_slots = set(persist_slots) - flow_slots
1599
+ is_valid = False if invalid_slots else True
1600
+
1601
+ if invalid_slots:
1602
+ structlogger.error(
1603
+ "validator.verify_slot_persistence_configuration.invalid_persist_slot",
1604
+ flow=flow_id,
1605
+ event_info=get_invalid_slot_persistence_config_error_message(
1606
+ flow_id, invalid_slots
1607
+ ),
1608
+ )
1609
+ return is_valid
1610
+
1611
+ def verify_studio_supported_validations(self) -> bool:
1612
+ """Validates the assistant project for Rasa Studio supported features.
1613
+
1614
+ Ensure to add new validations here if they are required for
1615
+ Rasa Studio Upload CLI.
1616
+ """
1617
+ if self.domain.is_empty():
1618
+ structlogger.error(
1619
+ "rasa.validator.verify_studio_supported_validations.empty_domain",
1620
+ event_info="Encountered empty domain during validation.",
1621
+ )
1622
+ sys.exit(1)
1623
+
1624
+ self.warn_if_config_mandatory_keys_are_not_set()
1625
+
1626
+ valid_responses = (
1627
+ self.check_for_no_empty_parenthesis_in_responses()
1628
+ and self.validate_button_payloads()
1629
+ )
1630
+ valid_nlu = self.verify_nlu()
1631
+ valid_flows = all(
1632
+ [
1633
+ self.verify_flows_steps_against_domain(),
1634
+ self.verify_unique_flows(),
1635
+ self.verify_predicates(),
1636
+ ]
1637
+ )
1638
+ valid_calm_slot_mappings = self.validate_CALM_slot_mappings()
1639
+
1640
+ all_good = (
1641
+ valid_responses and valid_nlu and valid_flows and valid_calm_slot_mappings
1642
+ )
1643
+
1644
+ return all_good