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/core/processor.py ADDED
@@ -0,0 +1,1465 @@
1
+ import inspect
2
+ import copy
3
+ import logging
4
+ import structlog
5
+ import os
6
+ import re
7
+ from pathlib import Path
8
+ import tarfile
9
+ import time
10
+ from types import LambdaType
11
+ from typing import Any, Dict, List, Optional, TYPE_CHECKING, Text, Tuple, Union
12
+ from rasa.core.actions.action_exceptions import ActionExecutionRejection
13
+ from rasa.core.actions.forms import FormAction
14
+ from rasa.core.http_interpreter import RasaNLUHttpInterpreter
15
+ from rasa.dialogue_understanding.commands import (
16
+ Command,
17
+ NoopCommand,
18
+ SetSlotCommand,
19
+ CannotHandleCommand,
20
+ )
21
+ from rasa.engine import loader
22
+ from rasa.engine.constants import (
23
+ PLACEHOLDER_MESSAGE,
24
+ PLACEHOLDER_TRACKER,
25
+ PLACEHOLDER_ENDPOINTS,
26
+ )
27
+ from rasa.engine.runner.dask import DaskGraphRunner
28
+ from rasa.engine.storage.local_model_storage import LocalModelStorage
29
+ from rasa.engine.storage.storage import ModelMetadata
30
+ from rasa.model import get_latest_model
31
+ from rasa.plugin import plugin_manager
32
+ from rasa.shared.core.flows import FlowsList
33
+ from rasa.shared.data import TrainingType, create_regex_pattern_reader
34
+ import rasa.shared.utils.io
35
+ import rasa.core.actions.action
36
+ from rasa.core import jobs
37
+ from rasa.core.actions.action import Action
38
+ from rasa.core.channels.channel import (
39
+ CollectingOutputChannel,
40
+ OutputChannel,
41
+ UserMessage,
42
+ )
43
+ import rasa.core.utils
44
+ from rasa.core.policies.policy import PolicyPrediction
45
+ from rasa.engine.runner.interface import GraphRunner
46
+ from rasa.exceptions import ActionLimitReached, ModelNotFound
47
+ from rasa.shared.core.constants import (
48
+ ACTION_CORRECT_FLOW_SLOT,
49
+ SLOT_CONSECUTIVE_SILENCE_TIMEOUTS,
50
+ SLOT_SILENCE_TIMEOUT,
51
+ USER_INTENT_RESTART,
52
+ ACTION_LISTEN_NAME,
53
+ ACTION_SESSION_START_NAME,
54
+ FOLLOWUP_ACTION,
55
+ SESSION_START_METADATA_SLOT,
56
+ ACTION_EXTRACT_SLOTS,
57
+ USER_INTENT_SILENCE_TIMEOUT,
58
+ )
59
+ from rasa.shared.core.events import (
60
+ ActionExecutionRejected,
61
+ BotUttered,
62
+ Event,
63
+ ReminderCancelled,
64
+ ReminderScheduled,
65
+ SlotSet,
66
+ UserUttered,
67
+ ActionExecuted,
68
+ )
69
+ from rasa.shared.constants import (
70
+ ASSISTANT_ID_KEY,
71
+ DOCS_URL_DOMAINS,
72
+ DEFAULT_SENDER_ID,
73
+ ROUTE_TO_CALM_SLOT,
74
+ DOCS_URL_NLU_BASED_POLICIES,
75
+ UTTER_PREFIX,
76
+ RASA_PATTERN_CANNOT_HANDLE_INVALID_INTENT,
77
+ )
78
+ from rasa.core.nlg import NaturalLanguageGenerator
79
+ from rasa.core.lock_store import LockStore
80
+ from rasa.utils.common import TempDirectoryPath, get_temp_dir_name
81
+ import rasa.core.tracker_store
82
+ import rasa.core.actions.action
83
+ import rasa.shared.core.trackers
84
+ from rasa.shared.core.trackers import DialogueStateTracker, EventVerbosity
85
+ from rasa.shared.nlu.constants import (
86
+ COMMANDS,
87
+ ENTITIES,
88
+ INTENT,
89
+ INTENT_NAME_KEY,
90
+ INTENT_RESPONSE_KEY,
91
+ PREDICTED_CONFIDENCE_KEY,
92
+ FULL_RETRIEVAL_INTENT_NAME_KEY,
93
+ RESPONSE_SELECTOR,
94
+ RESPONSE,
95
+ TEXT,
96
+ )
97
+ from rasa.shared.nlu.training_data.message import Message
98
+ from rasa.utils.endpoints import EndpointConfig
99
+
100
+ if TYPE_CHECKING:
101
+ from rasa.core.utils import AvailableEndpoints
102
+
103
+ logger = logging.getLogger(__name__)
104
+ structlogger = structlog.get_logger()
105
+
106
+ MAX_NUMBER_OF_PREDICTIONS = int(os.environ.get("MAX_NUMBER_OF_PREDICTIONS", "10"))
107
+ MAX_NUMBER_OF_PREDICTIONS_CALM = int(
108
+ os.environ.get("MAX_NUMBER_OF_PREDICTIONS_CALM", "1000")
109
+ )
110
+
111
+
112
+ class MessageProcessor:
113
+ """The message processor is interface for communicating with a bot model."""
114
+
115
+ def __init__(
116
+ self,
117
+ model_path: Union[Text, Path],
118
+ tracker_store: rasa.core.tracker_store.TrackerStore,
119
+ lock_store: LockStore,
120
+ generator: NaturalLanguageGenerator,
121
+ action_endpoint: Optional[EndpointConfig] = None,
122
+ max_number_of_predictions: int = MAX_NUMBER_OF_PREDICTIONS,
123
+ max_number_of_predictions_calm: int = MAX_NUMBER_OF_PREDICTIONS_CALM,
124
+ on_circuit_break: Optional[LambdaType] = None,
125
+ http_interpreter: Optional[RasaNLUHttpInterpreter] = None,
126
+ endpoints: Optional["AvailableEndpoints"] = None,
127
+ ) -> None:
128
+ """Initializes a `MessageProcessor`."""
129
+ self.nlg = generator
130
+ self.tracker_store = tracker_store
131
+ self.lock_store = lock_store
132
+ self.on_circuit_break = on_circuit_break
133
+ self.action_endpoint = action_endpoint
134
+ self.model_filename, self.model_metadata, self.graph_runner = self._load_model(
135
+ model_path
136
+ )
137
+ self.endpoints = endpoints
138
+
139
+ self.max_number_of_predictions = max_number_of_predictions
140
+ self.max_number_of_predictions_calm = max_number_of_predictions_calm
141
+ self.is_calm_assistant = self._is_calm_assistant()
142
+
143
+ if self.model_metadata.assistant_id is None:
144
+ rasa.shared.utils.io.raise_warning(
145
+ f"The model metadata does not contain a value for the "
146
+ f"'{ASSISTANT_ID_KEY}' attribute. Check that 'config.yml' "
147
+ f"file contains a value for the '{ASSISTANT_ID_KEY}' key "
148
+ f"and re-train the model. Failure to do so will result in "
149
+ f"streaming events without a unique assistant identifier.",
150
+ UserWarning,
151
+ )
152
+
153
+ self.model_path = Path(model_path)
154
+ self.domain = self.model_metadata.domain
155
+ self.http_interpreter = http_interpreter
156
+
157
+ @staticmethod
158
+ def _load_model(
159
+ model_path: Union[Text, Path],
160
+ ) -> Tuple[Text, ModelMetadata, GraphRunner]:
161
+ """Unpacks a model from a given path using the graph model loader."""
162
+ try:
163
+ if os.path.isfile(model_path):
164
+ model_tar = model_path
165
+ else:
166
+ model_file_path = get_latest_model(model_path)
167
+ if not model_file_path:
168
+ raise ModelNotFound(f"No model found at path '{model_path}'.")
169
+ model_tar = model_file_path
170
+ except TypeError:
171
+ raise ModelNotFound(f"Model {model_path} can not be loaded.")
172
+
173
+ logger.info(f"Loading model {model_tar}...")
174
+ with TempDirectoryPath(get_temp_dir_name()) as temporary_directory:
175
+ try:
176
+ metadata, runner = loader.load_predict_graph_runner(
177
+ Path(temporary_directory),
178
+ Path(model_tar),
179
+ LocalModelStorage,
180
+ DaskGraphRunner,
181
+ )
182
+ return os.path.basename(model_tar), metadata, runner
183
+ except tarfile.ReadError:
184
+ raise ModelNotFound(f"Model {model_path} can not be loaded.")
185
+
186
+ async def handle_message(
187
+ self, message: UserMessage
188
+ ) -> Optional[List[Dict[Text, Any]]]:
189
+ """Handle a single message with this processor."""
190
+ # preprocess message if necessary
191
+ tracker = await self.log_message(message, should_save_tracker=False)
192
+
193
+ if self.model_metadata.training_type == TrainingType.NLU:
194
+ await self.save_tracker(tracker)
195
+ rasa.shared.utils.io.raise_warning(
196
+ "No core model. Skipping action prediction and execution.",
197
+ docs=DOCS_URL_NLU_BASED_POLICIES,
198
+ )
199
+ return None
200
+
201
+ if not self.message_contains_commands(tracker.latest_message):
202
+ tracker = await self.run_action_extract_slots(
203
+ message.output_channel, tracker
204
+ )
205
+
206
+ await self._run_prediction_loop(message.output_channel, tracker)
207
+
208
+ await self.run_anonymization_pipeline(tracker)
209
+
210
+ await self.save_tracker(tracker)
211
+
212
+ if isinstance(message.output_channel, CollectingOutputChannel):
213
+ return message.output_channel.messages
214
+
215
+ return None
216
+
217
+ async def run_action_extract_slots(
218
+ self, output_channel: OutputChannel, tracker: DialogueStateTracker
219
+ ) -> DialogueStateTracker:
220
+ """Run action to extract slots and update the tracker accordingly.
221
+
222
+ Args:
223
+ output_channel: Output channel associated with the incoming user message.
224
+ tracker: A tracker representing a conversation state.
225
+
226
+ Returns:
227
+ the given (updated) tracker
228
+ """
229
+ action_extract_slots = rasa.core.actions.action.action_for_name_or_text(
230
+ ACTION_EXTRACT_SLOTS, self.domain, self.action_endpoint
231
+ )
232
+ metadata = await self._add_flows_to_metadata()
233
+
234
+ extraction_events = await action_extract_slots.run(
235
+ output_channel, self.nlg, tracker, self.domain, metadata
236
+ )
237
+
238
+ await self._send_bot_messages(extraction_events, tracker, output_channel)
239
+
240
+ tracker.update_with_events(extraction_events)
241
+
242
+ structlogger.debug(
243
+ "processor.extract.slots",
244
+ action_extract_slot=ACTION_EXTRACT_SLOTS,
245
+ len_extraction_events=len(extraction_events),
246
+ rasa_events=copy.deepcopy(extraction_events),
247
+ )
248
+
249
+ return tracker
250
+
251
+ async def run_anonymization_pipeline(self, tracker: DialogueStateTracker) -> None:
252
+ """Run the anonymization pipeline on the new tracker events.
253
+
254
+ Args:
255
+ tracker: A tracker representing a conversation state.
256
+ """
257
+ anonymization_pipeline = plugin_manager().hook.get_anonymization_pipeline()
258
+ if anonymization_pipeline is None:
259
+ return None
260
+
261
+ old_tracker = await self.tracker_store.retrieve(tracker.sender_id)
262
+ new_events = rasa.shared.core.trackers.TrackerEventDiffEngine.event_difference(
263
+ old_tracker, tracker
264
+ )
265
+
266
+ for event in new_events:
267
+ body = {"sender_id": tracker.sender_id}
268
+ body.update(event.as_dict())
269
+ anonymization_pipeline.run(body)
270
+
271
+ async def predict_next_for_sender_id(
272
+ self, sender_id: Text
273
+ ) -> Optional[Dict[Text, Any]]:
274
+ """Predict the next action for the given sender_id.
275
+
276
+ Args:
277
+ sender_id: Conversation ID.
278
+
279
+ Returns:
280
+ The prediction for the next action. `None` if no domain or policies loaded.
281
+ """
282
+ tracker = await self.fetch_tracker_and_update_session(sender_id)
283
+ result = await self.predict_next_with_tracker(tracker)
284
+
285
+ # save tracker state to continue conversation from this state
286
+ await self.save_tracker(tracker)
287
+
288
+ return result
289
+
290
+ async def predict_next_with_tracker(
291
+ self,
292
+ tracker: DialogueStateTracker,
293
+ verbosity: EventVerbosity = EventVerbosity.AFTER_RESTART,
294
+ ) -> Optional[Dict[Text, Any]]:
295
+ """Predict the next action for a given conversation state.
296
+
297
+ Args:
298
+ tracker: A tracker representing a conversation state.
299
+ verbosity: Verbosity for the returned conversation state.
300
+
301
+ Returns:
302
+ The prediction for the next action. `None` if no domain or policies loaded.
303
+ """
304
+ if self.model_metadata.training_type == TrainingType.NLU:
305
+ rasa.shared.utils.io.raise_warning(
306
+ "No core model. Skipping action prediction and execution.",
307
+ docs=DOCS_URL_NLU_BASED_POLICIES,
308
+ )
309
+ return None
310
+
311
+ prediction = await self._predict_next_with_tracker(tracker)
312
+
313
+ scores = [
314
+ {"action": a, "score": p}
315
+ for a, p in zip(self.domain.action_names_or_texts, prediction.probabilities)
316
+ ]
317
+ return {
318
+ "scores": scores,
319
+ "policy": prediction.policy_name,
320
+ "confidence": prediction.max_confidence,
321
+ "tracker": tracker.current_state(verbosity),
322
+ }
323
+
324
+ async def _update_tracker_session(
325
+ self,
326
+ tracker: DialogueStateTracker,
327
+ output_channel: OutputChannel,
328
+ metadata: Optional[Dict] = None,
329
+ ) -> None:
330
+ """Check the current session in `tracker` and update it if expired.
331
+
332
+ An 'action_session_start' is run if the latest tracker session has expired,
333
+ or if the tracker does not yet contain any events (only those after the last
334
+ restart are considered).
335
+
336
+ Args:
337
+ metadata: Data sent from client associated with the incoming user message.
338
+ tracker: Tracker to inspect.
339
+ output_channel: Output channel for potential utterances in a custom
340
+ `ActionSessionStart`.
341
+ """
342
+ if not tracker.applied_events() or self._has_session_expired(tracker):
343
+ logger.debug(
344
+ f"Starting a new session for conversation ID '{tracker.sender_id}'."
345
+ )
346
+
347
+ action_session_start = self._get_action(ACTION_SESSION_START_NAME)
348
+
349
+ if metadata:
350
+ tracker.update(
351
+ SlotSet(SESSION_START_METADATA_SLOT, metadata), self.domain
352
+ )
353
+
354
+ await self._run_action(
355
+ action=action_session_start,
356
+ tracker=tracker,
357
+ output_channel=output_channel,
358
+ nlg=self.nlg,
359
+ prediction=PolicyPrediction.for_action_name(
360
+ self.domain, ACTION_SESSION_START_NAME
361
+ ),
362
+ )
363
+
364
+ async def fetch_tracker_and_update_session(
365
+ self,
366
+ sender_id: Text,
367
+ output_channel: Optional[OutputChannel] = None,
368
+ metadata: Optional[Dict] = None,
369
+ ) -> DialogueStateTracker:
370
+ """Fetches tracker for `sender_id` and updates its conversation session.
371
+
372
+ If a new tracker is created, `action_session_start` is run.
373
+
374
+ Args:
375
+ metadata: Data sent from client associated with the incoming user message.
376
+ output_channel: Output channel associated with the incoming user message.
377
+ sender_id: Conversation ID for which to fetch the tracker.
378
+
379
+ Returns:
380
+ Tracker for `sender_id`.
381
+ """
382
+ tracker = await self.get_tracker(sender_id)
383
+
384
+ await self._update_tracker_session(tracker, output_channel, metadata)
385
+
386
+ return tracker
387
+
388
+ async def fetch_tracker_with_initial_session(
389
+ self,
390
+ sender_id: Text,
391
+ output_channel: Optional[OutputChannel] = None,
392
+ metadata: Optional[Dict] = None,
393
+ ) -> DialogueStateTracker:
394
+ """Fetches tracker for `sender_id` and runs a session start on a new one.
395
+
396
+ Args:
397
+ metadata: Data sent from client associated with the incoming user message.
398
+ output_channel: Output channel associated with the incoming user message.
399
+ sender_id: Conversation ID for which to fetch the tracker.
400
+
401
+ Returns:
402
+ Tracker for `sender_id`.
403
+ """
404
+ tracker = await self.get_tracker(sender_id)
405
+
406
+ # run session start only if the tracker is empty
407
+ if not tracker.events:
408
+ await self._update_tracker_session(tracker, output_channel, metadata)
409
+
410
+ return tracker
411
+
412
+ async def get_tracker(self, conversation_id: Text) -> DialogueStateTracker:
413
+ """Get the tracker for a conversation.
414
+
415
+ In contrast to `fetch_tracker_and_update_session` this does not add any
416
+ `action_session_start` or `session_start` events at the beginning of a
417
+ conversation.
418
+
419
+ Args:
420
+ conversation_id: The ID of the conversation for which the history should be
421
+ retrieved.
422
+
423
+ Returns:
424
+ Tracker for the conversation. Creates an empty tracker in case it's a new
425
+ conversation.
426
+ """
427
+ conversation_id = conversation_id or DEFAULT_SENDER_ID
428
+
429
+ tracker = await self.tracker_store.get_or_create_tracker(
430
+ conversation_id, append_action_listen=False
431
+ )
432
+ tracker.model_id = self.model_metadata.model_id
433
+ if tracker.assistant_id is None:
434
+ tracker.assistant_id = self.model_metadata.assistant_id
435
+ return tracker
436
+
437
+ async def fetch_full_tracker_with_initial_session(
438
+ self,
439
+ conversation_id: Text,
440
+ output_channel: Optional[OutputChannel] = None,
441
+ metadata: Optional[Dict] = None,
442
+ ) -> DialogueStateTracker:
443
+ """Get the full tracker for a conversation, including events after a restart.
444
+
445
+ Args:
446
+ conversation_id: The ID of the conversation for which the history should be
447
+ retrieved.
448
+ output_channel: Output channel associated with the incoming user message.
449
+ metadata: Data sent from client associated with the incoming user message.
450
+
451
+ Returns:
452
+ Tracker for the conversation. Creates an empty tracker with a new session
453
+ initialized in case it's a new conversation.
454
+ """
455
+ conversation_id = conversation_id or DEFAULT_SENDER_ID
456
+
457
+ tracker = await self.tracker_store.get_or_create_full_tracker(
458
+ conversation_id, False
459
+ )
460
+ tracker.model_id = self.model_metadata.model_id
461
+
462
+ if tracker.assistant_id is None:
463
+ tracker.assistant_id = self.model_metadata.assistant_id
464
+
465
+ if not tracker.events:
466
+ await self._update_tracker_session(tracker, output_channel, metadata)
467
+
468
+ return tracker
469
+
470
+ async def get_trackers_for_all_conversation_sessions(
471
+ self, conversation_id: Text
472
+ ) -> List[DialogueStateTracker]:
473
+ """Fetches all trackers for a conversation.
474
+
475
+ Individual trackers are returned for each conversation session found
476
+ for `conversation_id`.
477
+
478
+ Args:
479
+ conversation_id: The ID of the conversation for which the trackers should
480
+ be retrieved.
481
+
482
+ Returns:
483
+ Trackers for the conversation.
484
+ """
485
+ conversation_id = conversation_id or DEFAULT_SENDER_ID
486
+
487
+ tracker = await self.tracker_store.retrieve_full_tracker(conversation_id)
488
+
489
+ return rasa.shared.core.trackers.get_trackers_for_conversation_sessions(tracker)
490
+
491
+ async def log_message(
492
+ self, message: UserMessage, should_save_tracker: bool = True
493
+ ) -> DialogueStateTracker:
494
+ """Log `message` on tracker belonging to the message's conversation_id.
495
+
496
+ Optionally save the tracker if `should_save_tracker` is `True`. Tracker saving
497
+ can be skipped if the tracker returned by this method is used for further
498
+ processing and saved at a later stage.
499
+ """
500
+ tracker = await self.fetch_tracker_and_update_session(
501
+ message.sender_id, message.output_channel, message.metadata
502
+ )
503
+
504
+ await self._handle_message_with_tracker(message, tracker)
505
+
506
+ if should_save_tracker:
507
+ await self.save_tracker(tracker)
508
+
509
+ return tracker
510
+
511
+ async def execute_action(
512
+ self,
513
+ sender_id: Text,
514
+ action_name: Text,
515
+ output_channel: OutputChannel,
516
+ nlg: NaturalLanguageGenerator,
517
+ prediction: PolicyPrediction,
518
+ ) -> Optional[DialogueStateTracker]:
519
+ """Execute an action for a conversation.
520
+
521
+ Note that this might lead to unexpected bot behavior. Rather use an intent
522
+ to execute certain behavior within a conversation (e.g. by using
523
+ `trigger_external_user_uttered`).
524
+
525
+ Args:
526
+ sender_id: The ID of the conversation.
527
+ action_name: The name of the action which should be executed.
528
+ output_channel: The output channel which should be used for bot responses.
529
+ nlg: The response generator.
530
+ prediction: The prediction for the action.
531
+
532
+ Returns:
533
+ The new conversation state. Note that the new state is also persisted.
534
+ """
535
+ # we have a Tracker instance for each user
536
+ # which maintains conversation state
537
+ tracker = await self.fetch_tracker_and_update_session(sender_id, output_channel)
538
+
539
+ action = self._get_action(action_name)
540
+ await self._run_action(action, tracker, output_channel, nlg, prediction)
541
+
542
+ # save tracker state to continue conversation from this state
543
+ await self.save_tracker(tracker)
544
+
545
+ return tracker
546
+
547
+ async def predict_next_with_tracker_if_should(
548
+ self, tracker: DialogueStateTracker
549
+ ) -> Tuple[rasa.core.actions.action.Action, PolicyPrediction]:
550
+ """Predicts the next action the bot should take after seeing x.
551
+
552
+ This should be overwritten by more advanced policies to use
553
+ ML to predict the action.
554
+
555
+ Returns:
556
+ The index of the next action and prediction of the policy.
557
+
558
+ Raises:
559
+ ActionLimitReached if the limit of actions to predict has been reached.
560
+ """
561
+ should_predict_another_action = self.should_predict_another_action(
562
+ tracker.latest_action_name
563
+ )
564
+
565
+ if self.is_action_limit_reached(tracker, should_predict_another_action):
566
+ raise ActionLimitReached(
567
+ "The limit of actions to predict has been reached."
568
+ )
569
+
570
+ prediction = await self._predict_next_with_tracker(tracker)
571
+
572
+ action = rasa.core.actions.action.action_for_index(
573
+ prediction.max_confidence_index, self.domain, self.action_endpoint
574
+ )
575
+
576
+ logger.debug(
577
+ f"Predicted next action '{action.name()}' with confidence "
578
+ f"{prediction.max_confidence:.2f}."
579
+ )
580
+
581
+ return action, prediction
582
+
583
+ @staticmethod
584
+ def _is_reminder(e: Event, name: Text) -> bool:
585
+ return isinstance(e, ReminderScheduled) and e.name == name
586
+
587
+ @staticmethod
588
+ def _is_reminder_still_valid(
589
+ tracker: DialogueStateTracker, reminder_event: ReminderScheduled
590
+ ) -> bool:
591
+ """Check if the conversation has been restarted after reminder."""
592
+ for e in reversed(tracker.applied_events()):
593
+ if MessageProcessor._is_reminder(e, reminder_event.name):
594
+ return True
595
+ return False # not found in applied events --> has been restarted
596
+
597
+ @staticmethod
598
+ def _has_message_after_reminder(
599
+ tracker: DialogueStateTracker, reminder_event: ReminderScheduled
600
+ ) -> bool:
601
+ """Check if the user sent a message after the reminder."""
602
+ for e in reversed(tracker.events):
603
+ if MessageProcessor._is_reminder(e, reminder_event.name):
604
+ return False
605
+
606
+ if isinstance(e, UserUttered) and e.text:
607
+ return True
608
+
609
+ return True # tracker has probably been restarted
610
+
611
+ async def handle_reminder(
612
+ self,
613
+ reminder_event: ReminderScheduled,
614
+ sender_id: Text,
615
+ output_channel: OutputChannel,
616
+ ) -> None:
617
+ """Handle a reminder that is triggered asynchronously."""
618
+ async with self.lock_store.lock(sender_id):
619
+ tracker = await self.fetch_tracker_and_update_session(
620
+ sender_id, output_channel
621
+ )
622
+
623
+ if (
624
+ reminder_event.kill_on_user_message
625
+ and self._has_message_after_reminder(tracker, reminder_event)
626
+ or not self._is_reminder_still_valid(tracker, reminder_event)
627
+ ):
628
+ logger.debug(
629
+ f"Canceled reminder because it is outdated ({reminder_event})."
630
+ )
631
+ else:
632
+ intent = reminder_event.intent
633
+ entities: Union[List[Dict], Dict] = reminder_event.entities or {}
634
+ await self.trigger_external_user_uttered(
635
+ intent, entities, tracker, output_channel
636
+ )
637
+
638
+ async def trigger_external_user_uttered(
639
+ self,
640
+ intent_name: Text,
641
+ entities: Optional[Union[List[Dict[Text, Any]], Dict[Text, Text]]],
642
+ tracker: DialogueStateTracker,
643
+ output_channel: OutputChannel,
644
+ ) -> None:
645
+ """Triggers an external message.
646
+
647
+ Triggers an external message (like a user message, but invisible;
648
+ used, e.g., by a reminder or the trigger_intent endpoint).
649
+
650
+ Args:
651
+ intent_name: Name of the intent to be triggered.
652
+ entities: Entities to be passed on.
653
+ tracker: The tracker to which the event should be added.
654
+ output_channel: The output channel.
655
+ """
656
+ if isinstance(entities, list):
657
+ entity_list = entities
658
+ elif isinstance(entities, dict):
659
+ # Allow for a short-hand notation {"ent1": "val1", "ent2": "val2", ...}.
660
+ # Useful if properties like 'start', 'end', or 'extractor' are not given,
661
+ # e.g. for external events.
662
+ entity_list = [
663
+ {"entity": ent, "value": val} for ent, val in entities.items()
664
+ ]
665
+ elif not entities:
666
+ entity_list = []
667
+ else:
668
+ rasa.shared.utils.io.raise_warning(
669
+ f"Invalid entity specification: {entities}. Assuming no entities."
670
+ )
671
+ entity_list = []
672
+
673
+ # Set the new event's input channel to the latest input channel, so
674
+ # that we don't lose this property.
675
+ input_channel = tracker.get_latest_input_channel()
676
+
677
+ tracker.update(
678
+ UserUttered.create_external(intent_name, entity_list, input_channel),
679
+ self.domain,
680
+ )
681
+
682
+ tracker = await self.run_action_extract_slots(output_channel, tracker)
683
+
684
+ await self._run_prediction_loop(output_channel, tracker)
685
+ # save tracker state to continue conversation from this state
686
+ await self.save_tracker(tracker)
687
+
688
+ @staticmethod
689
+ def _log_slots(tracker: DialogueStateTracker) -> None:
690
+ # Log currently set slots
691
+ slots = {s.name: s.value for s in tracker.slots.values() if s.value is not None}
692
+
693
+ structlogger.debug("processor.slots.log", slots=slots)
694
+
695
+ def _check_for_unseen_features(self, parse_data: Dict[Text, Any]) -> None:
696
+ """Warns the user if the NLU parse data contains unrecognized features.
697
+
698
+ Checks intents and entities picked up by the NLU parsing
699
+ against the domain and warns the user of those that don't match.
700
+ Also considers a list of default intents that are valid but don't
701
+ need to be listed in the domain.
702
+
703
+ Args:
704
+ parse_data: Message parse data to check against the domain.
705
+ """
706
+ if not self.domain or self.domain.is_empty():
707
+ return
708
+
709
+ intent = parse_data["intent"][INTENT_NAME_KEY]
710
+ if intent and intent not in self.domain.intents:
711
+ rasa.shared.utils.io.raise_warning(
712
+ f"Parsed an intent '{intent}' "
713
+ f"which is not defined in the domain. "
714
+ f"Please make sure all intents are listed in the domain.",
715
+ docs=DOCS_URL_DOMAINS,
716
+ )
717
+
718
+ entities = parse_data["entities"] or []
719
+ for element in entities:
720
+ entity = element["entity"]
721
+ if entity and entity not in self.domain.entities:
722
+ rasa.shared.utils.io.raise_warning(
723
+ f"Parsed an entity '{entity}' "
724
+ f"which is not defined in the domain. "
725
+ f"Please make sure all entities are listed in the domain.",
726
+ docs=DOCS_URL_DOMAINS,
727
+ )
728
+
729
+ def _get_action(
730
+ self, action_name: Text
731
+ ) -> Optional[rasa.core.actions.action.Action]:
732
+ return rasa.core.actions.action.action_for_name_or_text(
733
+ action_name, self.domain, self.action_endpoint
734
+ )
735
+
736
+ async def parse_message(
737
+ self,
738
+ message: UserMessage,
739
+ tracker: Optional[DialogueStateTracker] = None,
740
+ only_output_properties: bool = True,
741
+ ) -> Dict[Text, Any]:
742
+ """Interprets the passed message.
743
+
744
+ Args:
745
+ message: Message to handle.
746
+ tracker: Tracker to use.
747
+ only_output_properties: If `True`, restrict the output to
748
+ Message.only_output_properties.
749
+
750
+ Returns:
751
+ Parsed data extracted from the message.
752
+ """
753
+ if self.http_interpreter:
754
+ parse_data = await self.http_interpreter.parse(message)
755
+ else:
756
+ regex_reader = create_regex_pattern_reader(message, self.domain)
757
+
758
+ processed_message = Message({TEXT: message.text})
759
+ if regex_reader:
760
+ processed_message = regex_reader.unpack_regex_message(
761
+ message=processed_message, domain=self.domain
762
+ )
763
+
764
+ # Invalid use of slash syntax, sanitize the message before passing
765
+ # it to the graph
766
+ if (
767
+ processed_message.starts_with_slash_syntax()
768
+ and not processed_message.has_intent()
769
+ and not processed_message.has_commands()
770
+ ):
771
+ message = self._sanitize_message(message)
772
+
773
+ # Intent or commands are not explicitly present. Pass message to graph.
774
+ if not (processed_message.has_intent() or processed_message.has_commands()):
775
+ parse_data = await self._parse_message_with_graph(
776
+ message, tracker, only_output_properties
777
+ )
778
+
779
+ # Intents or commands are presents. Bypasses the standard parsing
780
+ # pipeline.
781
+ else:
782
+ parse_data = await self._parse_message_with_commands_and_intents(
783
+ processed_message, tracker, only_output_properties
784
+ )
785
+
786
+ self._update_full_retrieval_intent(parse_data)
787
+ structlogger.debug(
788
+ "processor.message.parse",
789
+ parse_data_text=copy.deepcopy(parse_data["text"]),
790
+ parse_data_intent=parse_data["intent"],
791
+ parse_data_entities=copy.deepcopy(parse_data["entities"]),
792
+ )
793
+
794
+ self._check_for_unseen_features(parse_data)
795
+ # resetting timeouts variables whenever something that is not a timeout occurs
796
+ if (
797
+ parse_data.get(INTENT, {}).get(INTENT_NAME_KEY)
798
+ != USER_INTENT_SILENCE_TIMEOUT
799
+ and tracker
800
+ ):
801
+ if (
802
+ SLOT_CONSECUTIVE_SILENCE_TIMEOUTS in tracker.slots
803
+ and tracker.slots[SLOT_CONSECUTIVE_SILENCE_TIMEOUTS].value != 0.0
804
+ ):
805
+ tracker.update(SlotSet(SLOT_CONSECUTIVE_SILENCE_TIMEOUTS, 0.0))
806
+ if (
807
+ SLOT_SILENCE_TIMEOUT in tracker.slots
808
+ and tracker.slots[SLOT_SILENCE_TIMEOUT].value
809
+ != tracker.slots[SLOT_SILENCE_TIMEOUT].initial_value
810
+ ):
811
+ tracker.update(
812
+ SlotSet(
813
+ SLOT_SILENCE_TIMEOUT,
814
+ tracker.slots[SLOT_SILENCE_TIMEOUT].initial_value,
815
+ )
816
+ )
817
+
818
+ return parse_data
819
+
820
+ def _sanitize_message(self, message: UserMessage) -> UserMessage:
821
+ """Sanitize user message by removing prepended slashes before the
822
+ actual content.
823
+ """
824
+ # Regex pattern to match leading slashes and any whitespace before
825
+ # actual content
826
+ pattern = r"^[/\s]+"
827
+ # Remove the matched pattern from the beginning of the message
828
+ message.text = re.sub(pattern, "", message.text).strip()
829
+ return message
830
+
831
+ async def _parse_message_with_commands_and_intents(
832
+ self,
833
+ message: Message,
834
+ tracker: Optional[DialogueStateTracker] = None,
835
+ only_output_properties: bool = True,
836
+ ) -> Dict[Text, Any]:
837
+ """Parses the message to handle commands or intent trigger."""
838
+ parse_data: Dict[Text, Any] = {
839
+ TEXT: "",
840
+ INTENT: {INTENT_NAME_KEY: None, PREDICTED_CONFIDENCE_KEY: 0.0},
841
+ ENTITIES: [],
842
+ }
843
+ parse_data.update(
844
+ message.as_dict(only_output_properties=only_output_properties)
845
+ )
846
+
847
+ commands = parse_data.get(COMMANDS, [])
848
+
849
+ # add commands from intent payloads
850
+ if tracker and not commands:
851
+ nlu_adapted_commands = await self._nlu_to_commands(parse_data, tracker)
852
+ commands += nlu_adapted_commands
853
+
854
+ if (
855
+ tracker.has_coexistence_routing_slot
856
+ and tracker.get_slot(ROUTE_TO_CALM_SLOT) is None
857
+ ):
858
+ # if we are currently not routing to either CALM or dm1
859
+ # we make a sticky routing to CALM if there are any commands
860
+ # from the trigger intent parsing
861
+ # or a sticky routing to dm1 if there are no commands
862
+ commands += [
863
+ SetSlotCommand(
864
+ ROUTE_TO_CALM_SLOT, len(nlu_adapted_commands) > 0
865
+ ).as_dict()
866
+ ]
867
+
868
+ parse_data[COMMANDS] = commands
869
+ return parse_data
870
+
871
+ def _update_full_retrieval_intent(self, parse_data: Dict[Text, Any]) -> None:
872
+ """Update the parse data with the full retrieval intent.
873
+
874
+ Args:
875
+ parse_data: Message parse data to update.
876
+ """
877
+ intent_name = parse_data.get(INTENT, {}).get(INTENT_NAME_KEY)
878
+ response_selector = parse_data.get(RESPONSE_SELECTOR, {})
879
+ all_retrieval_intents = response_selector.get("all_retrieval_intents", [])
880
+ if intent_name and intent_name in all_retrieval_intents:
881
+ retrieval_intent = (
882
+ response_selector.get(intent_name, {})
883
+ .get(RESPONSE, {})
884
+ .get(INTENT_RESPONSE_KEY)
885
+ )
886
+ parse_data[INTENT][FULL_RETRIEVAL_INTENT_NAME_KEY] = retrieval_intent
887
+
888
+ async def _nlu_to_commands(
889
+ self, parse_data: Dict[str, Any], tracker: DialogueStateTracker
890
+ ) -> List[Dict[str, Any]]:
891
+ """Converts the NLU parse data to commands using the adaptor.
892
+
893
+ This is used if we receive intents/entities directly using `/intent{...}`
894
+ syntax. In this case, the nlu graph is not run. Therefore, we need to
895
+ convert the parse data to commands outside the graph.
896
+ """
897
+ from rasa.dialogue_understanding.generator.nlu_command_adapter import (
898
+ NLUCommandAdapter,
899
+ )
900
+
901
+ commands = NLUCommandAdapter.convert_nlu_to_commands(
902
+ Message(parse_data), tracker, await self.get_flows(), self.domain
903
+ )
904
+
905
+ # if there are no converted commands and parsed data contains invalid intent
906
+ # add CannotHandleCommand as fallback
907
+ if len(commands) == 0 and self._contains_undefined_intent(Message(parse_data)):
908
+ structlogger.warning(
909
+ "processor.message.nlu_to_commands.invalid_intent",
910
+ event_info=(
911
+ f"No NLU commands converted and parsed data contains"
912
+ f"invalid intent: {parse_data[INTENT]['name']}. "
913
+ f"Returning CannotHandleCommand() as a fallback."
914
+ ),
915
+ invalid_intent=parse_data[INTENT]["name"],
916
+ )
917
+ commands.append(
918
+ CannotHandleCommand(RASA_PATTERN_CANNOT_HANDLE_INVALID_INTENT)
919
+ )
920
+
921
+ return [command.as_dict() for command in commands]
922
+
923
+ def _contains_undefined_intent(self, message: Message) -> bool:
924
+ """Checks if the message contains an intent that is undefined
925
+ in the domain.
926
+ """
927
+ intent_name = message.get(INTENT, {}).get("name")
928
+ return intent_name is not None and intent_name not in self.domain.intents
929
+
930
+ async def _parse_message_with_graph(
931
+ self,
932
+ message: UserMessage,
933
+ tracker: Optional[DialogueStateTracker] = None,
934
+ only_output_properties: bool = True,
935
+ ) -> Dict[Text, Any]:
936
+ """Interprets the passed message.
937
+
938
+ Arguments:
939
+ message: Message to handle
940
+ tracker: Tracker to use
941
+ only_output_properties: If `True`, restrict the output to
942
+ Message.only_output_properties.
943
+
944
+ Returns:
945
+ Parsed data extracted from the message.
946
+ """
947
+ results = await self.graph_runner.run(
948
+ inputs={PLACEHOLDER_MESSAGE: [message], PLACEHOLDER_TRACKER: tracker},
949
+ targets=[self.model_metadata.nlu_target],
950
+ )
951
+ parsed_messages = results[self.model_metadata.nlu_target]
952
+ parsed_message = parsed_messages[0]
953
+ parse_data = {
954
+ TEXT: "",
955
+ INTENT: {INTENT_NAME_KEY: None, PREDICTED_CONFIDENCE_KEY: 0.0},
956
+ ENTITIES: [],
957
+ COMMANDS: [],
958
+ }
959
+ parse_data.update(
960
+ parsed_message.as_dict(only_output_properties=only_output_properties)
961
+ )
962
+ return parse_data
963
+
964
+ async def _handle_message_with_tracker(
965
+ self, message: UserMessage, tracker: DialogueStateTracker
966
+ ) -> None:
967
+ if message.parse_data:
968
+ parse_data = message.parse_data
969
+ else:
970
+ parse_data = await self.parse_message(message, tracker)
971
+
972
+ # don't ever directly mutate the tracker
973
+ # - instead pass its events to log
974
+ tracker.update(
975
+ UserUttered(
976
+ message.text,
977
+ parse_data["intent"],
978
+ parse_data["entities"],
979
+ parse_data,
980
+ input_channel=message.input_channel,
981
+ message_id=message.message_id,
982
+ metadata=message.metadata,
983
+ ),
984
+ self.domain,
985
+ )
986
+
987
+ if parse_data["entities"]:
988
+ self._log_slots(tracker)
989
+
990
+ logger.debug(
991
+ f"Logged UserUtterance - tracker now has {len(tracker.events)} events."
992
+ )
993
+
994
+ @staticmethod
995
+ def _should_handle_message(tracker: DialogueStateTracker) -> bool:
996
+ return not tracker.is_paused() or (
997
+ tracker.latest_message is not None
998
+ and tracker.latest_message.intent.get(INTENT_NAME_KEY)
999
+ == USER_INTENT_RESTART
1000
+ )
1001
+
1002
+ def _tracker_state_specific_action_limit(
1003
+ self, tracker: DialogueStateTracker
1004
+ ) -> int:
1005
+ """Select the action limit based on the tracker state.
1006
+
1007
+ This function determines the maximum number of predictions that should be
1008
+ made during a dialogue conversation. Typically, the number of predictions
1009
+ is limited to the number of actions executed so far in the conversation.
1010
+ However, in certain states (e.g., when the user is correcting the
1011
+ conversation flow), more predictions may be allowed as the system traverses
1012
+ through a long dialogue flow.
1013
+
1014
+ Additionally, if the `ROUTE_TO_CALM_SLOT` is present in the tracker slots,
1015
+ the action limit is adjusted to a separate limit for CALM-based flows.
1016
+
1017
+ Args:
1018
+ tracker: instance of DialogueStateTracker.
1019
+
1020
+ Returns:
1021
+ The maximum number of predictions to make.
1022
+ """
1023
+ # Check if it is a CALM assistant and if so, that the `ROUTE_TO_CALM_SLOT`
1024
+ # is either not present or set to `True`.
1025
+ # If it does, use the specific prediction limit for CALM assistants.
1026
+ # Otherwise, use the default prediction limit.
1027
+ if self.is_calm_assistant and (
1028
+ not tracker.has_coexistence_routing_slot
1029
+ or tracker.get_slot(ROUTE_TO_CALM_SLOT)
1030
+ ):
1031
+ max_number_of_predictions = self.max_number_of_predictions_calm
1032
+ else:
1033
+ max_number_of_predictions = self.max_number_of_predictions
1034
+
1035
+ reversed_events = list(tracker.events)[::-1]
1036
+ is_conversation_in_flow_correction = False
1037
+ for e in reversed_events:
1038
+ if isinstance(e, ActionExecuted):
1039
+ if e.action_name in (ACTION_LISTEN_NAME, ACTION_SESSION_START_NAME):
1040
+ break
1041
+ elif e.action_name == ACTION_CORRECT_FLOW_SLOT:
1042
+ is_conversation_in_flow_correction = True
1043
+ break
1044
+
1045
+ if is_conversation_in_flow_correction:
1046
+ # allow for more predictions to be made as we might be traversing through
1047
+ # a long flow. We multiply the number of predictions by 10 to allow for
1048
+ # more predictions to be made - the factor is a best guess.
1049
+ return max_number_of_predictions * 5
1050
+
1051
+ # Return the default
1052
+ return max_number_of_predictions
1053
+
1054
+ def is_action_limit_reached(
1055
+ self, tracker: DialogueStateTracker, should_predict_another_action: bool
1056
+ ) -> bool:
1057
+ """Check whether the maximum number of predictions has been met.
1058
+
1059
+ Args:
1060
+ tracker: instance of DialogueStateTracker.
1061
+ should_predict_another_action: Whether the last executed action allows
1062
+ for more actions to be predicted or not.
1063
+
1064
+ Returns:
1065
+ `True` if the limit of actions to predict has been reached.
1066
+ """
1067
+ reversed_events = list(tracker.events)[::-1]
1068
+ num_predicted_actions = 0
1069
+ state_specific_action_limit = self._tracker_state_specific_action_limit(tracker)
1070
+
1071
+ for e in reversed_events:
1072
+ if isinstance(e, ActionExecuted):
1073
+ if e.action_name in (ACTION_LISTEN_NAME, ACTION_SESSION_START_NAME):
1074
+ break
1075
+ num_predicted_actions += 1
1076
+
1077
+ return (
1078
+ num_predicted_actions >= state_specific_action_limit
1079
+ and should_predict_another_action
1080
+ )
1081
+
1082
+ async def _run_prediction_loop(
1083
+ self, output_channel: OutputChannel, tracker: DialogueStateTracker
1084
+ ) -> None:
1085
+ # keep taking actions decided by the policy until it chooses to 'listen'
1086
+ should_predict_another_action = True
1087
+
1088
+ tracker = await self.run_command_processor(tracker)
1089
+
1090
+ # action loop. predicts actions until we hit action listen
1091
+ while should_predict_another_action and self._should_handle_message(tracker):
1092
+ # this actually just calls the policy's method by the same name
1093
+ try:
1094
+ action, prediction = await self.predict_next_with_tracker_if_should(
1095
+ tracker
1096
+ )
1097
+ except ActionLimitReached:
1098
+ logger.warning(
1099
+ "Circuit breaker tripped. Stopped predicting "
1100
+ f"more actions for sender '{tracker.sender_id}'."
1101
+ )
1102
+ if self.on_circuit_break:
1103
+ # call a registered callback
1104
+ self.on_circuit_break(tracker, output_channel, self.nlg)
1105
+ break
1106
+
1107
+ if prediction.is_end_to_end_prediction:
1108
+ logger.debug(
1109
+ f"An end-to-end prediction was made which has triggered the 2nd "
1110
+ f"execution of the default action '{ACTION_EXTRACT_SLOTS}'."
1111
+ )
1112
+ tracker = await self.run_action_extract_slots(output_channel, tracker)
1113
+
1114
+ should_predict_another_action = await self._run_action(
1115
+ action, tracker, output_channel, self.nlg, prediction
1116
+ )
1117
+
1118
+ @staticmethod
1119
+ def should_predict_another_action(action_name: Text) -> bool:
1120
+ """Determine whether the processor should predict another action.
1121
+
1122
+ Args:
1123
+ action_name: Name of the latest executed action.
1124
+
1125
+ Returns:
1126
+ `False` if `action_name` is `ACTION_LISTEN_NAME` or
1127
+ `ACTION_SESSION_START_NAME`, otherwise `True`.
1128
+ """
1129
+ return action_name not in (ACTION_LISTEN_NAME, ACTION_SESSION_START_NAME)
1130
+
1131
+ async def execute_side_effects(
1132
+ self,
1133
+ events: List[Event],
1134
+ tracker: DialogueStateTracker,
1135
+ output_channel: Optional[OutputChannel],
1136
+ ) -> None:
1137
+ """Attach tracker, send bot messages, schedule and cancel reminders."""
1138
+ if output_channel:
1139
+ output_channel.attach_tracker_state(tracker)
1140
+ await self._send_bot_messages(events, tracker, output_channel)
1141
+ await self._schedule_reminders(events, tracker, output_channel)
1142
+ await self._cancel_reminders(events, tracker)
1143
+
1144
+ @staticmethod
1145
+ async def _send_bot_messages(
1146
+ events: List[Event],
1147
+ tracker: DialogueStateTracker,
1148
+ output_channel: OutputChannel,
1149
+ ) -> None:
1150
+ """Send all the bot messages that are logged in the events array."""
1151
+ for e in events:
1152
+ if not isinstance(e, BotUttered):
1153
+ continue
1154
+
1155
+ await output_channel.send_response(tracker.sender_id, e.message())
1156
+
1157
+ async def _schedule_reminders(
1158
+ self,
1159
+ events: List[Event],
1160
+ tracker: DialogueStateTracker,
1161
+ output_channel: OutputChannel,
1162
+ ) -> None:
1163
+ """Uses the scheduler to time a job to trigger the passed reminder.
1164
+
1165
+ Reminders with the same `id` property will overwrite one another
1166
+ (i.e. only one of them will eventually run).
1167
+ """
1168
+ for e in events:
1169
+ if not isinstance(e, ReminderScheduled):
1170
+ continue
1171
+
1172
+ (await jobs.scheduler()).add_job(
1173
+ self.handle_reminder,
1174
+ "date",
1175
+ run_date=e.trigger_date_time,
1176
+ args=[e, tracker.sender_id, output_channel],
1177
+ id=e.name,
1178
+ replace_existing=True,
1179
+ name=e.scheduled_job_name(tracker.sender_id),
1180
+ )
1181
+
1182
+ @staticmethod
1183
+ async def _cancel_reminders(
1184
+ events: List[Event], tracker: DialogueStateTracker
1185
+ ) -> None:
1186
+ """Cancel reminders that match the `ReminderCancelled` event."""
1187
+ # All Reminders specified by ReminderCancelled events will be cancelled
1188
+ for event in events:
1189
+ if isinstance(event, ReminderCancelled):
1190
+ scheduler = await jobs.scheduler()
1191
+ for scheduled_job in scheduler.get_jobs():
1192
+ if event.cancels_job_with_name(
1193
+ scheduled_job.name, tracker.sender_id
1194
+ ):
1195
+ scheduler.remove_job(scheduled_job.id)
1196
+
1197
+ async def run_command_processor(
1198
+ self, tracker: DialogueStateTracker
1199
+ ) -> DialogueStateTracker:
1200
+ """Run the command processor to apply commands to the stack.
1201
+
1202
+ The command processor applies all the commands from the NLU pipeline to the
1203
+ dialogue stack. The dialogue stack then acts as base for decision making for
1204
+ the policies that can use it.
1205
+
1206
+ Args:
1207
+ tracker: the dialogue state tracker
1208
+
1209
+ Returns:
1210
+ An updated tracker after commands have been applied
1211
+ """
1212
+ target = "command_processor"
1213
+ results = await self.graph_runner.run(
1214
+ inputs={PLACEHOLDER_TRACKER: tracker.copy()}, targets=[target]
1215
+ )
1216
+ events = results[target]
1217
+ tracker.update_with_events(events)
1218
+ return tracker
1219
+
1220
+ async def get_flows(self) -> FlowsList:
1221
+ """Get the list of flows from the graph."""
1222
+ target = "flows_provider"
1223
+ results = await self.graph_runner.run(inputs={}, targets=[target])
1224
+ return results[target]
1225
+
1226
+ async def _add_flows_to_metadata(self) -> Dict[Text, Any]:
1227
+ """Convert the flows to metadata."""
1228
+ flows = await self.get_flows()
1229
+ flows_metadata = {}
1230
+ for flow in flows.underlying_flows:
1231
+ flow_as_json = flow.as_json()
1232
+ flow_as_json.pop("id")
1233
+ flows_metadata[flow.id] = flow_as_json
1234
+
1235
+ return {"all_flows": flows_metadata}
1236
+
1237
+ async def _run_action(
1238
+ self,
1239
+ action: rasa.core.actions.action.Action,
1240
+ tracker: DialogueStateTracker,
1241
+ output_channel: OutputChannel,
1242
+ nlg: NaturalLanguageGenerator,
1243
+ prediction: PolicyPrediction,
1244
+ ) -> bool:
1245
+ # events and return values are used to update
1246
+ # the tracker state after an action has been taken
1247
+ try:
1248
+ # Use temporary tracker as we might need to discard the policy events in
1249
+ # case of a rejection.
1250
+ temporary_tracker = tracker.copy()
1251
+ temporary_tracker.update_with_events(prediction.events)
1252
+
1253
+ run_args = inspect.getfullargspec(action.run).args
1254
+ if "metadata" in run_args:
1255
+ metadata: Optional[Dict] = prediction.action_metadata
1256
+
1257
+ if isinstance(action, FormAction):
1258
+ flows_metadata = await self._add_flows_to_metadata()
1259
+ metadata = prediction.action_metadata or {}
1260
+ metadata.update(flows_metadata)
1261
+
1262
+ events = await action.run(
1263
+ output_channel,
1264
+ nlg,
1265
+ temporary_tracker,
1266
+ self.domain,
1267
+ metadata=metadata,
1268
+ )
1269
+ else:
1270
+ events = await action.run(
1271
+ output_channel, nlg, temporary_tracker, self.domain
1272
+ )
1273
+ except ActionExecutionRejection:
1274
+ events = [
1275
+ ActionExecutionRejected(
1276
+ action.name(), prediction.policy_name, prediction.max_confidence
1277
+ )
1278
+ ]
1279
+ tracker.update(events[0])
1280
+ return self.should_predict_another_action(action.name())
1281
+ except Exception:
1282
+ structlogger.exception(
1283
+ "rasa.core.processor.run_action.exception",
1284
+ event_info=f"Encountered an exception while "
1285
+ f"running action '{action.name()}'."
1286
+ f"Bot will continue, but the actions events are lost. "
1287
+ f"Please check the logs of your action server for "
1288
+ f"more information.",
1289
+ )
1290
+ events = []
1291
+
1292
+ self._log_action_on_tracker(tracker, action, events, prediction)
1293
+
1294
+ if any(isinstance(e, UserUttered) for e in events):
1295
+ logger.debug(
1296
+ f"A `UserUttered` event was returned by executing "
1297
+ f"action '{action.name()}'. This will run the default action "
1298
+ f"'{ACTION_EXTRACT_SLOTS}'."
1299
+ )
1300
+ tracker = await self.run_action_extract_slots(output_channel, tracker)
1301
+
1302
+ if action.name() != ACTION_LISTEN_NAME and not action.name().startswith(
1303
+ UTTER_PREFIX
1304
+ ):
1305
+ self._log_slots(tracker)
1306
+
1307
+ await self.execute_side_effects(events, tracker, output_channel)
1308
+
1309
+ return self.should_predict_another_action(action.name())
1310
+
1311
+ def _log_action_on_tracker(
1312
+ self,
1313
+ tracker: DialogueStateTracker,
1314
+ action: Action,
1315
+ events: Optional[List[Event]],
1316
+ prediction: PolicyPrediction,
1317
+ ) -> None:
1318
+ # Ensures that the code still works even if a lazy programmer missed
1319
+ # to type `return []` at the end of an action or the run method
1320
+ # returns `None` for some other reason.
1321
+ if events is None:
1322
+ events = []
1323
+
1324
+ action_was_rejected_manually = any(
1325
+ isinstance(event, ActionExecutionRejected) for event in events
1326
+ )
1327
+ if not action_was_rejected_manually:
1328
+ structlogger.debug(
1329
+ "processor.actions.policy_prediction",
1330
+ prediction_events=copy.deepcopy(prediction.events),
1331
+ policy_name=prediction.policy_name,
1332
+ action_name=action.name(),
1333
+ )
1334
+ tracker.update_with_events(prediction.events)
1335
+
1336
+ # log the action and its produced events
1337
+ tracker.update(action.event_for_successful_execution(prediction))
1338
+
1339
+ structlogger.debug(
1340
+ "processor.actions.log",
1341
+ action_name=action.name(),
1342
+ rasa_events=copy.deepcopy(events),
1343
+ )
1344
+ tracker.update_with_events(events)
1345
+
1346
+ def _has_session_expired(self, tracker: DialogueStateTracker) -> bool:
1347
+ """Determine whether the latest session in `tracker` has expired.
1348
+
1349
+ Args:
1350
+ tracker: Tracker to inspect.
1351
+
1352
+ Returns:
1353
+ `True` if the session in `tracker` has expired, `False` otherwise.
1354
+ """
1355
+ if not self.domain.session_config.are_sessions_enabled():
1356
+ # tracker has never expired if sessions are disabled
1357
+ return False
1358
+
1359
+ user_uttered_event: Optional[UserUttered] = tracker.get_last_event_for(
1360
+ UserUttered
1361
+ )
1362
+
1363
+ if not user_uttered_event:
1364
+ # there is no user event so far so the session should not be considered
1365
+ # expired
1366
+ return False
1367
+
1368
+ time_delta_in_seconds = time.time() - user_uttered_event.timestamp
1369
+ has_expired = (
1370
+ time_delta_in_seconds / 60
1371
+ > self.domain.session_config.session_expiration_time
1372
+ )
1373
+ if has_expired:
1374
+ logger.debug(
1375
+ f"The latest session for conversation ID '{tracker.sender_id}' has "
1376
+ f"expired."
1377
+ )
1378
+
1379
+ return has_expired
1380
+
1381
+ async def save_tracker(self, tracker: DialogueStateTracker) -> None:
1382
+ """Save the given tracker to the tracker store.
1383
+
1384
+ Args:
1385
+ tracker: Tracker to be saved.
1386
+ """
1387
+ await self.tracker_store.save(tracker)
1388
+
1389
+ async def _predict_next_with_tracker(
1390
+ self, tracker: DialogueStateTracker
1391
+ ) -> PolicyPrediction:
1392
+ """Collect predictions from ensemble and return action and predictions."""
1393
+ followup_action = tracker.followup_action
1394
+ if followup_action:
1395
+ tracker.clear_followup_action()
1396
+ if followup_action in self.domain.action_names_or_texts:
1397
+ prediction = PolicyPrediction.for_action_name(
1398
+ self.domain, followup_action, FOLLOWUP_ACTION
1399
+ )
1400
+ return prediction
1401
+
1402
+ logger.error(
1403
+ f"Trying to run unknown follow-up action '{followup_action}'. "
1404
+ "Instead of running that, Rasa Pro will ignore the action "
1405
+ "and predict the next action."
1406
+ )
1407
+
1408
+ target = self.model_metadata.core_target
1409
+ if not target:
1410
+ raise ValueError("Cannot predict next action if there is no core target.")
1411
+
1412
+ results = await self.graph_runner.run(
1413
+ inputs={
1414
+ PLACEHOLDER_TRACKER: tracker,
1415
+ PLACEHOLDER_ENDPOINTS: self.endpoints,
1416
+ },
1417
+ targets=[target],
1418
+ )
1419
+ policy_prediction = results[target]
1420
+ return policy_prediction
1421
+
1422
+ @staticmethod
1423
+ def message_contains_commands(latest_message: Optional[UserUttered]) -> bool:
1424
+ """Check if the latest message contains commands."""
1425
+ if latest_message is None:
1426
+ return False
1427
+
1428
+ commands = [
1429
+ Command.command_from_json(command) for command in latest_message.commands
1430
+ ]
1431
+ filtered_commands = [
1432
+ command
1433
+ for command in commands
1434
+ if not (
1435
+ isinstance(command, SetSlotCommand)
1436
+ and command.name == ROUTE_TO_CALM_SLOT
1437
+ )
1438
+ and not isinstance(command, NoopCommand)
1439
+ ]
1440
+
1441
+ return len(filtered_commands) > 0
1442
+
1443
+ def _is_calm_assistant(self) -> bool:
1444
+ """Inspects the nodes of the graph schema to determine whether
1445
+ any node is associated with the `FlowPolicy`, which is indicative of a
1446
+ CALM assistant setup.
1447
+
1448
+ Returns:
1449
+ bool: True if any node in the graph schema uses `FlowPolicy`.
1450
+ """
1451
+ # Get the graph schema's nodes from the graph runner.
1452
+ nodes: dict[str, Any] = self.graph_runner._graph_schema.nodes # type: ignore[attr-defined]
1453
+
1454
+ flow_policy_class_path = "rasa.core.policies.flow_policy.FlowPolicy"
1455
+ # Iterate over the nodes and check if any node uses `FlowPolicy`.
1456
+ for node_name, schema_node in nodes.items():
1457
+ if (
1458
+ schema_node.uses is not None
1459
+ and f"{schema_node.uses.__module__}.{schema_node.uses.__name__}"
1460
+ == flow_policy_class_path
1461
+ ):
1462
+ return True
1463
+
1464
+ # Return False if no node is found using `FlowPolicy`.
1465
+ return False