rasa-pro 3.9.18__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 (662) hide show
  1. README.md +415 -0
  2. rasa/__init__.py +10 -0
  3. rasa/__main__.py +156 -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 +146 -0
  12. rasa/cli/__init__.py +5 -0
  13. rasa/cli/arguments/__init__.py +0 -0
  14. rasa/cli/arguments/data.py +81 -0
  15. rasa/cli/arguments/default_arguments.py +165 -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 +204 -0
  20. rasa/cli/arguments/shell.py +13 -0
  21. rasa/cli/arguments/test.py +211 -0
  22. rasa/cli/arguments/train.py +263 -0
  23. rasa/cli/arguments/visualize.py +34 -0
  24. rasa/cli/arguments/x.py +30 -0
  25. rasa/cli/data.py +292 -0
  26. rasa/cli/e2e_test.py +586 -0
  27. rasa/cli/evaluate.py +222 -0
  28. rasa/cli/export.py +250 -0
  29. rasa/cli/inspect.py +63 -0
  30. rasa/cli/interactive.py +164 -0
  31. rasa/cli/license.py +65 -0
  32. rasa/cli/markers.py +78 -0
  33. rasa/cli/project_templates/__init__.py +0 -0
  34. rasa/cli/project_templates/calm/actions/__init__.py +0 -0
  35. rasa/cli/project_templates/calm/actions/action_template.py +27 -0
  36. rasa/cli/project_templates/calm/actions/add_contact.py +30 -0
  37. rasa/cli/project_templates/calm/actions/db.py +57 -0
  38. rasa/cli/project_templates/calm/actions/list_contacts.py +22 -0
  39. rasa/cli/project_templates/calm/actions/remove_contact.py +35 -0
  40. rasa/cli/project_templates/calm/config.yml +12 -0
  41. rasa/cli/project_templates/calm/credentials.yml +33 -0
  42. rasa/cli/project_templates/calm/data/flows/add_contact.yml +31 -0
  43. rasa/cli/project_templates/calm/data/flows/list_contacts.yml +14 -0
  44. rasa/cli/project_templates/calm/data/flows/remove_contact.yml +29 -0
  45. rasa/cli/project_templates/calm/db/contacts.json +10 -0
  46. rasa/cli/project_templates/calm/domain/add_contact.yml +39 -0
  47. rasa/cli/project_templates/calm/domain/list_contacts.yml +17 -0
  48. rasa/cli/project_templates/calm/domain/remove_contact.yml +38 -0
  49. rasa/cli/project_templates/calm/domain/shared.yml +10 -0
  50. rasa/cli/project_templates/calm/e2e_tests/cancelations/user_cancels_during_a_correction.yml +16 -0
  51. rasa/cli/project_templates/calm/e2e_tests/cancelations/user_changes_mind_on_a_whim.yml +7 -0
  52. rasa/cli/project_templates/calm/e2e_tests/corrections/user_corrects_contact_handle.yml +20 -0
  53. rasa/cli/project_templates/calm/e2e_tests/corrections/user_corrects_contact_name.yml +19 -0
  54. rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_adds_contact_to_their_list.yml +15 -0
  55. rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_lists_contacts.yml +5 -0
  56. rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_removes_contact.yml +11 -0
  57. rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_removes_contact_from_list.yml +12 -0
  58. rasa/cli/project_templates/calm/endpoints.yml +45 -0
  59. rasa/cli/project_templates/default/actions/__init__.py +0 -0
  60. rasa/cli/project_templates/default/actions/actions.py +27 -0
  61. rasa/cli/project_templates/default/config.yml +44 -0
  62. rasa/cli/project_templates/default/credentials.yml +33 -0
  63. rasa/cli/project_templates/default/data/nlu.yml +91 -0
  64. rasa/cli/project_templates/default/data/rules.yml +13 -0
  65. rasa/cli/project_templates/default/data/stories.yml +30 -0
  66. rasa/cli/project_templates/default/domain.yml +34 -0
  67. rasa/cli/project_templates/default/endpoints.yml +42 -0
  68. rasa/cli/project_templates/default/tests/test_stories.yml +91 -0
  69. rasa/cli/project_templates/tutorial/actions.py +22 -0
  70. rasa/cli/project_templates/tutorial/config.yml +11 -0
  71. rasa/cli/project_templates/tutorial/credentials.yml +33 -0
  72. rasa/cli/project_templates/tutorial/data/flows.yml +8 -0
  73. rasa/cli/project_templates/tutorial/data/patterns.yml +6 -0
  74. rasa/cli/project_templates/tutorial/domain.yml +21 -0
  75. rasa/cli/project_templates/tutorial/endpoints.yml +45 -0
  76. rasa/cli/run.py +135 -0
  77. rasa/cli/scaffold.py +269 -0
  78. rasa/cli/shell.py +141 -0
  79. rasa/cli/studio/__init__.py +0 -0
  80. rasa/cli/studio/download.py +62 -0
  81. rasa/cli/studio/studio.py +266 -0
  82. rasa/cli/studio/train.py +59 -0
  83. rasa/cli/studio/upload.py +77 -0
  84. rasa/cli/telemetry.py +102 -0
  85. rasa/cli/test.py +280 -0
  86. rasa/cli/train.py +260 -0
  87. rasa/cli/utils.py +464 -0
  88. rasa/cli/visualize.py +40 -0
  89. rasa/cli/x.py +206 -0
  90. rasa/constants.py +37 -0
  91. rasa/core/__init__.py +17 -0
  92. rasa/core/actions/__init__.py +0 -0
  93. rasa/core/actions/action.py +1225 -0
  94. rasa/core/actions/action_clean_stack.py +59 -0
  95. rasa/core/actions/action_exceptions.py +24 -0
  96. rasa/core/actions/action_run_slot_rejections.py +207 -0
  97. rasa/core/actions/action_trigger_chitchat.py +31 -0
  98. rasa/core/actions/action_trigger_flow.py +109 -0
  99. rasa/core/actions/action_trigger_search.py +31 -0
  100. rasa/core/actions/constants.py +5 -0
  101. rasa/core/actions/custom_action_executor.py +188 -0
  102. rasa/core/actions/forms.py +741 -0
  103. rasa/core/actions/grpc_custom_action_executor.py +251 -0
  104. rasa/core/actions/http_custom_action_executor.py +140 -0
  105. rasa/core/actions/loops.py +114 -0
  106. rasa/core/actions/two_stage_fallback.py +186 -0
  107. rasa/core/agent.py +555 -0
  108. rasa/core/auth_retry_tracker_store.py +122 -0
  109. rasa/core/brokers/__init__.py +0 -0
  110. rasa/core/brokers/broker.py +126 -0
  111. rasa/core/brokers/file.py +58 -0
  112. rasa/core/brokers/kafka.py +322 -0
  113. rasa/core/brokers/pika.py +386 -0
  114. rasa/core/brokers/sql.py +86 -0
  115. rasa/core/channels/__init__.py +55 -0
  116. rasa/core/channels/audiocodes.py +463 -0
  117. rasa/core/channels/botframework.py +338 -0
  118. rasa/core/channels/callback.py +84 -0
  119. rasa/core/channels/channel.py +419 -0
  120. rasa/core/channels/console.py +241 -0
  121. rasa/core/channels/development_inspector.py +93 -0
  122. rasa/core/channels/facebook.py +419 -0
  123. rasa/core/channels/hangouts.py +329 -0
  124. rasa/core/channels/inspector/.eslintrc.cjs +25 -0
  125. rasa/core/channels/inspector/.gitignore +23 -0
  126. rasa/core/channels/inspector/README.md +54 -0
  127. rasa/core/channels/inspector/assets/favicon.ico +0 -0
  128. rasa/core/channels/inspector/assets/rasa-chat.js +2 -0
  129. rasa/core/channels/inspector/custom.d.ts +3 -0
  130. rasa/core/channels/inspector/dist/assets/arc-b6e548fe.js +1 -0
  131. rasa/core/channels/inspector/dist/assets/array-9f3ba611.js +1 -0
  132. rasa/core/channels/inspector/dist/assets/c4Diagram-d0fbc5ce-fa03ac9e.js +10 -0
  133. rasa/core/channels/inspector/dist/assets/classDiagram-936ed81e-ee67392a.js +2 -0
  134. rasa/core/channels/inspector/dist/assets/classDiagram-v2-c3cb15f1-9b283fae.js +2 -0
  135. rasa/core/channels/inspector/dist/assets/createText-62fc7601-8b6fcc2a.js +7 -0
  136. rasa/core/channels/inspector/dist/assets/edges-f2ad444c-22e77f4f.js +4 -0
  137. rasa/core/channels/inspector/dist/assets/erDiagram-9d236eb7-60ffc87f.js +51 -0
  138. rasa/core/channels/inspector/dist/assets/flowDb-1972c806-9dd802e4.js +6 -0
  139. rasa/core/channels/inspector/dist/assets/flowDiagram-7ea5b25a-5fa1912f.js +4 -0
  140. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-1844e5a5.js +1 -0
  141. rasa/core/channels/inspector/dist/assets/flowchart-elk-definition-abe16c3d-622a1fd2.js +139 -0
  142. rasa/core/channels/inspector/dist/assets/ganttDiagram-9b5ea136-e285a63a.js +266 -0
  143. rasa/core/channels/inspector/dist/assets/gitGraphDiagram-99d0ae7c-f237bdca.js +70 -0
  144. rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-128cfa44.ttf +0 -0
  145. rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-21dbcb97.woff +0 -0
  146. rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-222b5e26.svg +329 -0
  147. rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-9ad89b2a.woff2 +0 -0
  148. rasa/core/channels/inspector/dist/assets/index-2c4b9a3b-4b03d70e.js +1 -0
  149. rasa/core/channels/inspector/dist/assets/index-3ee28881.css +1 -0
  150. rasa/core/channels/inspector/dist/assets/index-a5d3e69d.js +1040 -0
  151. rasa/core/channels/inspector/dist/assets/infoDiagram-736b4530-72a0fa5f.js +7 -0
  152. rasa/core/channels/inspector/dist/assets/init-77b53fdd.js +1 -0
  153. rasa/core/channels/inspector/dist/assets/journeyDiagram-df861f2b-82218c41.js +139 -0
  154. rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-60c05ee4.woff +0 -0
  155. rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-8335d9b8.svg +438 -0
  156. rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-9cc39c75.ttf +0 -0
  157. rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-ead13ccf.woff2 +0 -0
  158. rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-16705655.woff2 +0 -0
  159. rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-5aeb07f9.woff +0 -0
  160. rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-9c459044.ttf +0 -0
  161. rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-9e2898a4.svg +435 -0
  162. rasa/core/channels/inspector/dist/assets/layout-78cff630.js +1 -0
  163. rasa/core/channels/inspector/dist/assets/line-5038b469.js +1 -0
  164. rasa/core/channels/inspector/dist/assets/linear-c4fc4098.js +1 -0
  165. rasa/core/channels/inspector/dist/assets/mindmap-definition-beec6740-c33c8ea6.js +109 -0
  166. rasa/core/channels/inspector/dist/assets/ordinal-ba9b4969.js +1 -0
  167. rasa/core/channels/inspector/dist/assets/path-53f90ab3.js +1 -0
  168. rasa/core/channels/inspector/dist/assets/pieDiagram-dbbf0591-a8d03059.js +35 -0
  169. rasa/core/channels/inspector/dist/assets/quadrantDiagram-4d7f4fd6-6a0e56b2.js +7 -0
  170. rasa/core/channels/inspector/dist/assets/requirementDiagram-6fc4c22a-2dc7c7bd.js +52 -0
  171. rasa/core/channels/inspector/dist/assets/sankeyDiagram-8f13d901-2360fe39.js +8 -0
  172. rasa/core/channels/inspector/dist/assets/sequenceDiagram-b655622a-41b9f9ad.js +122 -0
  173. rasa/core/channels/inspector/dist/assets/stateDiagram-59f0c015-0aad326f.js +1 -0
  174. rasa/core/channels/inspector/dist/assets/stateDiagram-v2-2b26beab-9847d984.js +1 -0
  175. rasa/core/channels/inspector/dist/assets/styles-080da4f6-564d890e.js +110 -0
  176. rasa/core/channels/inspector/dist/assets/styles-3dcbcfbf-38957613.js +159 -0
  177. rasa/core/channels/inspector/dist/assets/styles-9c745c82-f0fc6921.js +207 -0
  178. rasa/core/channels/inspector/dist/assets/svgDrawCommon-4835440b-ef3c5a77.js +1 -0
  179. rasa/core/channels/inspector/dist/assets/timeline-definition-5b62e21b-bf3e91c1.js +61 -0
  180. rasa/core/channels/inspector/dist/assets/xychartDiagram-2b33534f-4d4026c0.js +7 -0
  181. rasa/core/channels/inspector/dist/index.html +41 -0
  182. rasa/core/channels/inspector/index.html +39 -0
  183. rasa/core/channels/inspector/jest.config.ts +13 -0
  184. rasa/core/channels/inspector/package.json +48 -0
  185. rasa/core/channels/inspector/setupTests.ts +2 -0
  186. rasa/core/channels/inspector/src/App.tsx +170 -0
  187. rasa/core/channels/inspector/src/components/DiagramFlow.tsx +107 -0
  188. rasa/core/channels/inspector/src/components/DialogueInformation.tsx +187 -0
  189. rasa/core/channels/inspector/src/components/DialogueStack.tsx +151 -0
  190. rasa/core/channels/inspector/src/components/ExpandIcon.tsx +16 -0
  191. rasa/core/channels/inspector/src/components/FullscreenButton.tsx +45 -0
  192. rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +19 -0
  193. rasa/core/channels/inspector/src/components/NoActiveFlow.tsx +21 -0
  194. rasa/core/channels/inspector/src/components/RasaLogo.tsx +32 -0
  195. rasa/core/channels/inspector/src/components/SaraDiagrams.tsx +39 -0
  196. rasa/core/channels/inspector/src/components/Slots.tsx +91 -0
  197. rasa/core/channels/inspector/src/components/Welcome.tsx +54 -0
  198. rasa/core/channels/inspector/src/helpers/formatters.test.ts +382 -0
  199. rasa/core/channels/inspector/src/helpers/formatters.ts +240 -0
  200. rasa/core/channels/inspector/src/helpers/utils.ts +42 -0
  201. rasa/core/channels/inspector/src/main.tsx +13 -0
  202. rasa/core/channels/inspector/src/theme/Button/Button.ts +29 -0
  203. rasa/core/channels/inspector/src/theme/Heading/Heading.ts +31 -0
  204. rasa/core/channels/inspector/src/theme/Input/Input.ts +27 -0
  205. rasa/core/channels/inspector/src/theme/Link/Link.ts +10 -0
  206. rasa/core/channels/inspector/src/theme/Modal/Modal.ts +47 -0
  207. rasa/core/channels/inspector/src/theme/Table/Table.tsx +38 -0
  208. rasa/core/channels/inspector/src/theme/Tooltip/Tooltip.ts +12 -0
  209. rasa/core/channels/inspector/src/theme/base/breakpoints.ts +8 -0
  210. rasa/core/channels/inspector/src/theme/base/colors.ts +88 -0
  211. rasa/core/channels/inspector/src/theme/base/fonts/fontFaces.css +29 -0
  212. rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.eot +0 -0
  213. rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.svg +329 -0
  214. rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.ttf +0 -0
  215. rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.woff +0 -0
  216. rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.woff2 +0 -0
  217. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.eot +0 -0
  218. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.svg +438 -0
  219. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.ttf +0 -0
  220. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.woff +0 -0
  221. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.woff2 +0 -0
  222. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.eot +0 -0
  223. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.svg +435 -0
  224. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.ttf +0 -0
  225. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.woff +0 -0
  226. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.woff2 +0 -0
  227. rasa/core/channels/inspector/src/theme/base/radii.ts +9 -0
  228. rasa/core/channels/inspector/src/theme/base/shadows.ts +7 -0
  229. rasa/core/channels/inspector/src/theme/base/sizes.ts +7 -0
  230. rasa/core/channels/inspector/src/theme/base/space.ts +15 -0
  231. rasa/core/channels/inspector/src/theme/base/styles.ts +13 -0
  232. rasa/core/channels/inspector/src/theme/base/typography.ts +24 -0
  233. rasa/core/channels/inspector/src/theme/base/zIndices.ts +19 -0
  234. rasa/core/channels/inspector/src/theme/index.ts +101 -0
  235. rasa/core/channels/inspector/src/types.ts +64 -0
  236. rasa/core/channels/inspector/src/vite-env.d.ts +1 -0
  237. rasa/core/channels/inspector/tests/__mocks__/fileMock.ts +1 -0
  238. rasa/core/channels/inspector/tests/__mocks__/matchMedia.ts +16 -0
  239. rasa/core/channels/inspector/tests/__mocks__/styleMock.ts +1 -0
  240. rasa/core/channels/inspector/tests/renderWithProviders.tsx +14 -0
  241. rasa/core/channels/inspector/tsconfig.json +26 -0
  242. rasa/core/channels/inspector/tsconfig.node.json +10 -0
  243. rasa/core/channels/inspector/vite.config.ts +8 -0
  244. rasa/core/channels/inspector/yarn.lock +6156 -0
  245. rasa/core/channels/mattermost.py +229 -0
  246. rasa/core/channels/rasa_chat.py +126 -0
  247. rasa/core/channels/rest.py +225 -0
  248. rasa/core/channels/rocketchat.py +174 -0
  249. rasa/core/channels/slack.py +620 -0
  250. rasa/core/channels/socketio.py +274 -0
  251. rasa/core/channels/telegram.py +298 -0
  252. rasa/core/channels/twilio.py +169 -0
  253. rasa/core/channels/twilio_voice.py +367 -0
  254. rasa/core/channels/vier_cvg.py +374 -0
  255. rasa/core/channels/webexteams.py +134 -0
  256. rasa/core/concurrent_lock_store.py +210 -0
  257. rasa/core/constants.py +107 -0
  258. rasa/core/evaluation/__init__.py +0 -0
  259. rasa/core/evaluation/marker.py +267 -0
  260. rasa/core/evaluation/marker_base.py +923 -0
  261. rasa/core/evaluation/marker_stats.py +293 -0
  262. rasa/core/evaluation/marker_tracker_loader.py +103 -0
  263. rasa/core/exceptions.py +29 -0
  264. rasa/core/exporter.py +284 -0
  265. rasa/core/featurizers/__init__.py +0 -0
  266. rasa/core/featurizers/precomputation.py +410 -0
  267. rasa/core/featurizers/single_state_featurizer.py +421 -0
  268. rasa/core/featurizers/tracker_featurizers.py +1262 -0
  269. rasa/core/http_interpreter.py +89 -0
  270. rasa/core/information_retrieval/__init__.py +7 -0
  271. rasa/core/information_retrieval/faiss.py +121 -0
  272. rasa/core/information_retrieval/information_retrieval.py +129 -0
  273. rasa/core/information_retrieval/milvus.py +52 -0
  274. rasa/core/information_retrieval/qdrant.py +95 -0
  275. rasa/core/jobs.py +63 -0
  276. rasa/core/lock.py +139 -0
  277. rasa/core/lock_store.py +343 -0
  278. rasa/core/migrate.py +403 -0
  279. rasa/core/nlg/__init__.py +3 -0
  280. rasa/core/nlg/callback.py +146 -0
  281. rasa/core/nlg/contextual_response_rephraser.py +270 -0
  282. rasa/core/nlg/generator.py +230 -0
  283. rasa/core/nlg/interpolator.py +143 -0
  284. rasa/core/nlg/response.py +155 -0
  285. rasa/core/nlg/summarize.py +69 -0
  286. rasa/core/policies/__init__.py +0 -0
  287. rasa/core/policies/ensemble.py +329 -0
  288. rasa/core/policies/enterprise_search_policy.py +781 -0
  289. rasa/core/policies/enterprise_search_prompt_template.jinja2 +25 -0
  290. rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +60 -0
  291. rasa/core/policies/flow_policy.py +205 -0
  292. rasa/core/policies/flows/__init__.py +0 -0
  293. rasa/core/policies/flows/flow_exceptions.py +44 -0
  294. rasa/core/policies/flows/flow_executor.py +705 -0
  295. rasa/core/policies/flows/flow_step_result.py +43 -0
  296. rasa/core/policies/intentless_policy.py +922 -0
  297. rasa/core/policies/intentless_prompt_template.jinja2 +22 -0
  298. rasa/core/policies/memoization.py +538 -0
  299. rasa/core/policies/policy.py +725 -0
  300. rasa/core/policies/rule_policy.py +1273 -0
  301. rasa/core/policies/ted_policy.py +2169 -0
  302. rasa/core/policies/unexpected_intent_policy.py +1022 -0
  303. rasa/core/processor.py +1422 -0
  304. rasa/core/run.py +331 -0
  305. rasa/core/secrets_manager/__init__.py +0 -0
  306. rasa/core/secrets_manager/constants.py +32 -0
  307. rasa/core/secrets_manager/endpoints.py +391 -0
  308. rasa/core/secrets_manager/factory.py +233 -0
  309. rasa/core/secrets_manager/secret_manager.py +262 -0
  310. rasa/core/secrets_manager/vault.py +574 -0
  311. rasa/core/test.py +1335 -0
  312. rasa/core/tracker_store.py +1699 -0
  313. rasa/core/train.py +105 -0
  314. rasa/core/training/__init__.py +89 -0
  315. rasa/core/training/converters/__init__.py +0 -0
  316. rasa/core/training/converters/responses_prefix_converter.py +119 -0
  317. rasa/core/training/interactive.py +1745 -0
  318. rasa/core/training/story_conflict.py +381 -0
  319. rasa/core/training/training.py +93 -0
  320. rasa/core/utils.py +339 -0
  321. rasa/core/visualize.py +70 -0
  322. rasa/dialogue_understanding/__init__.py +0 -0
  323. rasa/dialogue_understanding/coexistence/__init__.py +0 -0
  324. rasa/dialogue_understanding/coexistence/constants.py +4 -0
  325. rasa/dialogue_understanding/coexistence/intent_based_router.py +196 -0
  326. rasa/dialogue_understanding/coexistence/llm_based_router.py +260 -0
  327. rasa/dialogue_understanding/coexistence/router_template.jinja2 +12 -0
  328. rasa/dialogue_understanding/commands/__init__.py +49 -0
  329. rasa/dialogue_understanding/commands/can_not_handle_command.py +70 -0
  330. rasa/dialogue_understanding/commands/cancel_flow_command.py +125 -0
  331. rasa/dialogue_understanding/commands/change_flow_command.py +44 -0
  332. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +57 -0
  333. rasa/dialogue_understanding/commands/clarify_command.py +86 -0
  334. rasa/dialogue_understanding/commands/command.py +85 -0
  335. rasa/dialogue_understanding/commands/correct_slots_command.py +297 -0
  336. rasa/dialogue_understanding/commands/error_command.py +79 -0
  337. rasa/dialogue_understanding/commands/free_form_answer_command.py +9 -0
  338. rasa/dialogue_understanding/commands/handle_code_change_command.py +73 -0
  339. rasa/dialogue_understanding/commands/human_handoff_command.py +66 -0
  340. rasa/dialogue_understanding/commands/knowledge_answer_command.py +57 -0
  341. rasa/dialogue_understanding/commands/noop_command.py +54 -0
  342. rasa/dialogue_understanding/commands/set_slot_command.py +160 -0
  343. rasa/dialogue_understanding/commands/skip_question_command.py +75 -0
  344. rasa/dialogue_understanding/commands/start_flow_command.py +107 -0
  345. rasa/dialogue_understanding/generator/__init__.py +21 -0
  346. rasa/dialogue_understanding/generator/command_generator.py +343 -0
  347. rasa/dialogue_understanding/generator/constants.py +18 -0
  348. rasa/dialogue_understanding/generator/flow_document_template.jinja2 +4 -0
  349. rasa/dialogue_understanding/generator/flow_retrieval.py +412 -0
  350. rasa/dialogue_understanding/generator/llm_based_command_generator.py +467 -0
  351. rasa/dialogue_understanding/generator/llm_command_generator.py +67 -0
  352. rasa/dialogue_understanding/generator/multi_step/__init__.py +0 -0
  353. rasa/dialogue_understanding/generator/multi_step/fill_slots_prompt.jinja2 +62 -0
  354. rasa/dialogue_understanding/generator/multi_step/handle_flows_prompt.jinja2 +38 -0
  355. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +827 -0
  356. rasa/dialogue_understanding/generator/nlu_command_adapter.py +218 -0
  357. rasa/dialogue_understanding/generator/single_step/__init__.py +0 -0
  358. rasa/dialogue_understanding/generator/single_step/command_prompt_template.jinja2 +57 -0
  359. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +345 -0
  360. rasa/dialogue_understanding/patterns/__init__.py +0 -0
  361. rasa/dialogue_understanding/patterns/cancel.py +111 -0
  362. rasa/dialogue_understanding/patterns/cannot_handle.py +43 -0
  363. rasa/dialogue_understanding/patterns/chitchat.py +37 -0
  364. rasa/dialogue_understanding/patterns/clarify.py +97 -0
  365. rasa/dialogue_understanding/patterns/code_change.py +41 -0
  366. rasa/dialogue_understanding/patterns/collect_information.py +90 -0
  367. rasa/dialogue_understanding/patterns/completed.py +40 -0
  368. rasa/dialogue_understanding/patterns/continue_interrupted.py +42 -0
  369. rasa/dialogue_understanding/patterns/correction.py +278 -0
  370. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +248 -0
  371. rasa/dialogue_understanding/patterns/human_handoff.py +37 -0
  372. rasa/dialogue_understanding/patterns/internal_error.py +47 -0
  373. rasa/dialogue_understanding/patterns/search.py +37 -0
  374. rasa/dialogue_understanding/patterns/skip_question.py +38 -0
  375. rasa/dialogue_understanding/processor/__init__.py +0 -0
  376. rasa/dialogue_understanding/processor/command_processor.py +687 -0
  377. rasa/dialogue_understanding/processor/command_processor_component.py +39 -0
  378. rasa/dialogue_understanding/stack/__init__.py +0 -0
  379. rasa/dialogue_understanding/stack/dialogue_stack.py +178 -0
  380. rasa/dialogue_understanding/stack/frames/__init__.py +19 -0
  381. rasa/dialogue_understanding/stack/frames/chit_chat_frame.py +27 -0
  382. rasa/dialogue_understanding/stack/frames/dialogue_stack_frame.py +137 -0
  383. rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +157 -0
  384. rasa/dialogue_understanding/stack/frames/pattern_frame.py +10 -0
  385. rasa/dialogue_understanding/stack/frames/search_frame.py +27 -0
  386. rasa/dialogue_understanding/stack/utils.py +211 -0
  387. rasa/e2e_test/__init__.py +0 -0
  388. rasa/e2e_test/constants.py +11 -0
  389. rasa/e2e_test/e2e_test_case.py +366 -0
  390. rasa/e2e_test/e2e_test_result.py +34 -0
  391. rasa/e2e_test/e2e_test_runner.py +768 -0
  392. rasa/e2e_test/e2e_test_schema.yml +85 -0
  393. rasa/engine/__init__.py +0 -0
  394. rasa/engine/caching.py +463 -0
  395. rasa/engine/constants.py +17 -0
  396. rasa/engine/exceptions.py +14 -0
  397. rasa/engine/graph.py +637 -0
  398. rasa/engine/loader.py +36 -0
  399. rasa/engine/recipes/__init__.py +0 -0
  400. rasa/engine/recipes/config_files/default_config.yml +44 -0
  401. rasa/engine/recipes/default_components.py +99 -0
  402. rasa/engine/recipes/default_recipe.py +1251 -0
  403. rasa/engine/recipes/graph_recipe.py +79 -0
  404. rasa/engine/recipes/recipe.py +93 -0
  405. rasa/engine/runner/__init__.py +0 -0
  406. rasa/engine/runner/dask.py +250 -0
  407. rasa/engine/runner/interface.py +49 -0
  408. rasa/engine/storage/__init__.py +0 -0
  409. rasa/engine/storage/local_model_storage.py +246 -0
  410. rasa/engine/storage/resource.py +110 -0
  411. rasa/engine/storage/storage.py +203 -0
  412. rasa/engine/training/__init__.py +0 -0
  413. rasa/engine/training/components.py +176 -0
  414. rasa/engine/training/fingerprinting.py +64 -0
  415. rasa/engine/training/graph_trainer.py +256 -0
  416. rasa/engine/training/hooks.py +164 -0
  417. rasa/engine/validation.py +873 -0
  418. rasa/env.py +5 -0
  419. rasa/exceptions.py +69 -0
  420. rasa/graph_components/__init__.py +0 -0
  421. rasa/graph_components/converters/__init__.py +0 -0
  422. rasa/graph_components/converters/nlu_message_converter.py +48 -0
  423. rasa/graph_components/providers/__init__.py +0 -0
  424. rasa/graph_components/providers/domain_for_core_training_provider.py +87 -0
  425. rasa/graph_components/providers/domain_provider.py +71 -0
  426. rasa/graph_components/providers/flows_provider.py +74 -0
  427. rasa/graph_components/providers/forms_provider.py +44 -0
  428. rasa/graph_components/providers/nlu_training_data_provider.py +56 -0
  429. rasa/graph_components/providers/responses_provider.py +44 -0
  430. rasa/graph_components/providers/rule_only_provider.py +49 -0
  431. rasa/graph_components/providers/story_graph_provider.py +43 -0
  432. rasa/graph_components/providers/training_tracker_provider.py +55 -0
  433. rasa/graph_components/validators/__init__.py +0 -0
  434. rasa/graph_components/validators/default_recipe_validator.py +550 -0
  435. rasa/graph_components/validators/finetuning_validator.py +302 -0
  436. rasa/hooks.py +112 -0
  437. rasa/jupyter.py +63 -0
  438. rasa/markers/__init__.py +0 -0
  439. rasa/markers/marker.py +269 -0
  440. rasa/markers/marker_base.py +828 -0
  441. rasa/markers/upload.py +74 -0
  442. rasa/markers/validate.py +21 -0
  443. rasa/model.py +118 -0
  444. rasa/model_testing.py +457 -0
  445. rasa/model_training.py +536 -0
  446. rasa/nlu/__init__.py +7 -0
  447. rasa/nlu/classifiers/__init__.py +3 -0
  448. rasa/nlu/classifiers/classifier.py +5 -0
  449. rasa/nlu/classifiers/diet_classifier.py +1881 -0
  450. rasa/nlu/classifiers/fallback_classifier.py +192 -0
  451. rasa/nlu/classifiers/keyword_intent_classifier.py +188 -0
  452. rasa/nlu/classifiers/llm_intent_classifier.py +519 -0
  453. rasa/nlu/classifiers/logistic_regression_classifier.py +253 -0
  454. rasa/nlu/classifiers/mitie_intent_classifier.py +156 -0
  455. rasa/nlu/classifiers/regex_message_handler.py +56 -0
  456. rasa/nlu/classifiers/sklearn_intent_classifier.py +330 -0
  457. rasa/nlu/constants.py +77 -0
  458. rasa/nlu/convert.py +40 -0
  459. rasa/nlu/emulators/__init__.py +0 -0
  460. rasa/nlu/emulators/dialogflow.py +55 -0
  461. rasa/nlu/emulators/emulator.py +49 -0
  462. rasa/nlu/emulators/luis.py +86 -0
  463. rasa/nlu/emulators/no_emulator.py +10 -0
  464. rasa/nlu/emulators/wit.py +56 -0
  465. rasa/nlu/extractors/__init__.py +0 -0
  466. rasa/nlu/extractors/crf_entity_extractor.py +715 -0
  467. rasa/nlu/extractors/duckling_entity_extractor.py +206 -0
  468. rasa/nlu/extractors/entity_synonyms.py +178 -0
  469. rasa/nlu/extractors/extractor.py +470 -0
  470. rasa/nlu/extractors/mitie_entity_extractor.py +293 -0
  471. rasa/nlu/extractors/regex_entity_extractor.py +220 -0
  472. rasa/nlu/extractors/spacy_entity_extractor.py +95 -0
  473. rasa/nlu/featurizers/__init__.py +0 -0
  474. rasa/nlu/featurizers/dense_featurizer/__init__.py +0 -0
  475. rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +445 -0
  476. rasa/nlu/featurizers/dense_featurizer/dense_featurizer.py +57 -0
  477. rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +768 -0
  478. rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +170 -0
  479. rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +132 -0
  480. rasa/nlu/featurizers/featurizer.py +89 -0
  481. rasa/nlu/featurizers/sparse_featurizer/__init__.py +0 -0
  482. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +867 -0
  483. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +571 -0
  484. rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +271 -0
  485. rasa/nlu/featurizers/sparse_featurizer/sparse_featurizer.py +9 -0
  486. rasa/nlu/model.py +24 -0
  487. rasa/nlu/persistor.py +282 -0
  488. rasa/nlu/run.py +27 -0
  489. rasa/nlu/selectors/__init__.py +0 -0
  490. rasa/nlu/selectors/response_selector.py +987 -0
  491. rasa/nlu/test.py +1940 -0
  492. rasa/nlu/tokenizers/__init__.py +0 -0
  493. rasa/nlu/tokenizers/jieba_tokenizer.py +148 -0
  494. rasa/nlu/tokenizers/mitie_tokenizer.py +75 -0
  495. rasa/nlu/tokenizers/spacy_tokenizer.py +72 -0
  496. rasa/nlu/tokenizers/tokenizer.py +239 -0
  497. rasa/nlu/tokenizers/whitespace_tokenizer.py +106 -0
  498. rasa/nlu/utils/__init__.py +35 -0
  499. rasa/nlu/utils/bilou_utils.py +462 -0
  500. rasa/nlu/utils/hugging_face/__init__.py +0 -0
  501. rasa/nlu/utils/hugging_face/registry.py +108 -0
  502. rasa/nlu/utils/hugging_face/transformers_pre_post_processors.py +311 -0
  503. rasa/nlu/utils/mitie_utils.py +113 -0
  504. rasa/nlu/utils/pattern_utils.py +168 -0
  505. rasa/nlu/utils/spacy_utils.py +310 -0
  506. rasa/plugin.py +90 -0
  507. rasa/server.py +1551 -0
  508. rasa/shared/__init__.py +0 -0
  509. rasa/shared/constants.py +192 -0
  510. rasa/shared/core/__init__.py +0 -0
  511. rasa/shared/core/command_payload_reader.py +109 -0
  512. rasa/shared/core/constants.py +167 -0
  513. rasa/shared/core/conversation.py +46 -0
  514. rasa/shared/core/domain.py +2107 -0
  515. rasa/shared/core/events.py +2504 -0
  516. rasa/shared/core/flows/__init__.py +7 -0
  517. rasa/shared/core/flows/flow.py +362 -0
  518. rasa/shared/core/flows/flow_step.py +146 -0
  519. rasa/shared/core/flows/flow_step_links.py +319 -0
  520. rasa/shared/core/flows/flow_step_sequence.py +70 -0
  521. rasa/shared/core/flows/flows_list.py +223 -0
  522. rasa/shared/core/flows/flows_yaml_schema.json +217 -0
  523. rasa/shared/core/flows/nlu_trigger.py +117 -0
  524. rasa/shared/core/flows/steps/__init__.py +24 -0
  525. rasa/shared/core/flows/steps/action.py +56 -0
  526. rasa/shared/core/flows/steps/call.py +64 -0
  527. rasa/shared/core/flows/steps/collect.py +112 -0
  528. rasa/shared/core/flows/steps/constants.py +5 -0
  529. rasa/shared/core/flows/steps/continuation.py +36 -0
  530. rasa/shared/core/flows/steps/end.py +22 -0
  531. rasa/shared/core/flows/steps/internal.py +44 -0
  532. rasa/shared/core/flows/steps/link.py +51 -0
  533. rasa/shared/core/flows/steps/no_operation.py +48 -0
  534. rasa/shared/core/flows/steps/set_slots.py +50 -0
  535. rasa/shared/core/flows/steps/start.py +30 -0
  536. rasa/shared/core/flows/validation.py +527 -0
  537. rasa/shared/core/flows/yaml_flows_io.py +278 -0
  538. rasa/shared/core/generator.py +908 -0
  539. rasa/shared/core/slot_mappings.py +526 -0
  540. rasa/shared/core/slots.py +649 -0
  541. rasa/shared/core/trackers.py +1177 -0
  542. rasa/shared/core/training_data/__init__.py +0 -0
  543. rasa/shared/core/training_data/loading.py +89 -0
  544. rasa/shared/core/training_data/story_reader/__init__.py +0 -0
  545. rasa/shared/core/training_data/story_reader/story_reader.py +129 -0
  546. rasa/shared/core/training_data/story_reader/story_step_builder.py +168 -0
  547. rasa/shared/core/training_data/story_reader/yaml_story_reader.py +888 -0
  548. rasa/shared/core/training_data/story_writer/__init__.py +0 -0
  549. rasa/shared/core/training_data/story_writer/story_writer.py +76 -0
  550. rasa/shared/core/training_data/story_writer/yaml_story_writer.py +444 -0
  551. rasa/shared/core/training_data/structures.py +838 -0
  552. rasa/shared/core/training_data/visualization.html +146 -0
  553. rasa/shared/core/training_data/visualization.py +603 -0
  554. rasa/shared/data.py +249 -0
  555. rasa/shared/engine/__init__.py +0 -0
  556. rasa/shared/engine/caching.py +26 -0
  557. rasa/shared/exceptions.py +163 -0
  558. rasa/shared/importers/__init__.py +0 -0
  559. rasa/shared/importers/importer.py +704 -0
  560. rasa/shared/importers/multi_project.py +203 -0
  561. rasa/shared/importers/rasa.py +99 -0
  562. rasa/shared/importers/utils.py +34 -0
  563. rasa/shared/nlu/__init__.py +0 -0
  564. rasa/shared/nlu/constants.py +47 -0
  565. rasa/shared/nlu/interpreter.py +10 -0
  566. rasa/shared/nlu/training_data/__init__.py +0 -0
  567. rasa/shared/nlu/training_data/entities_parser.py +208 -0
  568. rasa/shared/nlu/training_data/features.py +492 -0
  569. rasa/shared/nlu/training_data/formats/__init__.py +10 -0
  570. rasa/shared/nlu/training_data/formats/dialogflow.py +163 -0
  571. rasa/shared/nlu/training_data/formats/luis.py +87 -0
  572. rasa/shared/nlu/training_data/formats/rasa.py +135 -0
  573. rasa/shared/nlu/training_data/formats/rasa_yaml.py +603 -0
  574. rasa/shared/nlu/training_data/formats/readerwriter.py +244 -0
  575. rasa/shared/nlu/training_data/formats/wit.py +52 -0
  576. rasa/shared/nlu/training_data/loading.py +137 -0
  577. rasa/shared/nlu/training_data/lookup_tables_parser.py +30 -0
  578. rasa/shared/nlu/training_data/message.py +490 -0
  579. rasa/shared/nlu/training_data/schemas/__init__.py +0 -0
  580. rasa/shared/nlu/training_data/schemas/data_schema.py +85 -0
  581. rasa/shared/nlu/training_data/schemas/nlu.yml +53 -0
  582. rasa/shared/nlu/training_data/schemas/responses.yml +70 -0
  583. rasa/shared/nlu/training_data/synonyms_parser.py +42 -0
  584. rasa/shared/nlu/training_data/training_data.py +730 -0
  585. rasa/shared/nlu/training_data/util.py +223 -0
  586. rasa/shared/providers/__init__.py +0 -0
  587. rasa/shared/providers/openai/__init__.py +0 -0
  588. rasa/shared/providers/openai/clients.py +43 -0
  589. rasa/shared/providers/openai/session_handler.py +110 -0
  590. rasa/shared/utils/__init__.py +0 -0
  591. rasa/shared/utils/cli.py +72 -0
  592. rasa/shared/utils/common.py +308 -0
  593. rasa/shared/utils/constants.py +4 -0
  594. rasa/shared/utils/io.py +415 -0
  595. rasa/shared/utils/llm.py +404 -0
  596. rasa/shared/utils/pykwalify_extensions.py +27 -0
  597. rasa/shared/utils/schemas/__init__.py +0 -0
  598. rasa/shared/utils/schemas/config.yml +2 -0
  599. rasa/shared/utils/schemas/domain.yml +145 -0
  600. rasa/shared/utils/schemas/events.py +212 -0
  601. rasa/shared/utils/schemas/model_config.yml +46 -0
  602. rasa/shared/utils/schemas/stories.yml +173 -0
  603. rasa/shared/utils/yaml.py +786 -0
  604. rasa/studio/__init__.py +0 -0
  605. rasa/studio/auth.py +268 -0
  606. rasa/studio/config.py +127 -0
  607. rasa/studio/constants.py +18 -0
  608. rasa/studio/data_handler.py +359 -0
  609. rasa/studio/download.py +483 -0
  610. rasa/studio/results_logger.py +137 -0
  611. rasa/studio/train.py +135 -0
  612. rasa/studio/upload.py +433 -0
  613. rasa/telemetry.py +1737 -0
  614. rasa/tracing/__init__.py +0 -0
  615. rasa/tracing/config.py +353 -0
  616. rasa/tracing/constants.py +62 -0
  617. rasa/tracing/instrumentation/__init__.py +0 -0
  618. rasa/tracing/instrumentation/attribute_extractors.py +672 -0
  619. rasa/tracing/instrumentation/instrumentation.py +1185 -0
  620. rasa/tracing/instrumentation/intentless_policy_instrumentation.py +144 -0
  621. rasa/tracing/instrumentation/metrics.py +294 -0
  622. rasa/tracing/metric_instrument_provider.py +205 -0
  623. rasa/utils/__init__.py +0 -0
  624. rasa/utils/beta.py +83 -0
  625. rasa/utils/cli.py +28 -0
  626. rasa/utils/common.py +635 -0
  627. rasa/utils/converter.py +53 -0
  628. rasa/utils/endpoints.py +302 -0
  629. rasa/utils/io.py +260 -0
  630. rasa/utils/licensing.py +534 -0
  631. rasa/utils/log_utils.py +174 -0
  632. rasa/utils/mapper.py +210 -0
  633. rasa/utils/ml_utils.py +145 -0
  634. rasa/utils/plotting.py +362 -0
  635. rasa/utils/singleton.py +23 -0
  636. rasa/utils/tensorflow/__init__.py +0 -0
  637. rasa/utils/tensorflow/callback.py +112 -0
  638. rasa/utils/tensorflow/constants.py +116 -0
  639. rasa/utils/tensorflow/crf.py +492 -0
  640. rasa/utils/tensorflow/data_generator.py +440 -0
  641. rasa/utils/tensorflow/environment.py +161 -0
  642. rasa/utils/tensorflow/exceptions.py +5 -0
  643. rasa/utils/tensorflow/feature_array.py +366 -0
  644. rasa/utils/tensorflow/layers.py +1565 -0
  645. rasa/utils/tensorflow/layers_utils.py +113 -0
  646. rasa/utils/tensorflow/metrics.py +281 -0
  647. rasa/utils/tensorflow/model_data.py +798 -0
  648. rasa/utils/tensorflow/model_data_utils.py +499 -0
  649. rasa/utils/tensorflow/models.py +935 -0
  650. rasa/utils/tensorflow/rasa_layers.py +1094 -0
  651. rasa/utils/tensorflow/transformer.py +640 -0
  652. rasa/utils/tensorflow/types.py +6 -0
  653. rasa/utils/train_utils.py +572 -0
  654. rasa/utils/url_tools.py +53 -0
  655. rasa/utils/yaml.py +54 -0
  656. rasa/validator.py +1337 -0
  657. rasa/version.py +3 -0
  658. rasa_pro-3.9.18.dist-info/METADATA +563 -0
  659. rasa_pro-3.9.18.dist-info/NOTICE +5 -0
  660. rasa_pro-3.9.18.dist-info/RECORD +662 -0
  661. rasa_pro-3.9.18.dist-info/WHEEL +4 -0
  662. rasa_pro-3.9.18.dist-info/entry_points.txt +3 -0
rasa/core/processor.py ADDED
@@ -0,0 +1,1422 @@
1
+ import inspect
2
+ import copy
3
+ import logging
4
+ import structlog
5
+ import os
6
+ from pathlib import Path
7
+ import tarfile
8
+ import time
9
+ from types import LambdaType
10
+ from typing import Any, Dict, List, Optional, TYPE_CHECKING, Text, Tuple, Union
11
+
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
+ USER_INTENT_RESTART,
50
+ ACTION_LISTEN_NAME,
51
+ ACTION_SESSION_START_NAME,
52
+ FOLLOWUP_ACTION,
53
+ SESSION_START_METADATA_SLOT,
54
+ ACTION_EXTRACT_SLOTS,
55
+ )
56
+ from rasa.shared.core.events import (
57
+ ActionExecutionRejected,
58
+ BotUttered,
59
+ Event,
60
+ ReminderCancelled,
61
+ ReminderScheduled,
62
+ SlotSet,
63
+ UserUttered,
64
+ ActionExecuted,
65
+ )
66
+ from rasa.shared.constants import (
67
+ ASSISTANT_ID_KEY,
68
+ DOCS_URL_DOMAINS,
69
+ DEFAULT_SENDER_ID,
70
+ ROUTE_TO_CALM_SLOT,
71
+ DOCS_URL_NLU_BASED_POLICIES,
72
+ UTTER_PREFIX,
73
+ RASA_PATTERN_CANNOT_HANDLE_INVALID_INTENT,
74
+ )
75
+ from rasa.core.nlg import NaturalLanguageGenerator
76
+ from rasa.core.lock_store import LockStore
77
+ from rasa.utils.common import TempDirectoryPath, get_temp_dir_name
78
+ import rasa.core.tracker_store
79
+ import rasa.core.actions.action
80
+ import rasa.shared.core.trackers
81
+ from rasa.shared.core.trackers import DialogueStateTracker, EventVerbosity
82
+ from rasa.shared.nlu.constants import (
83
+ COMMANDS,
84
+ ENTITIES,
85
+ INTENT,
86
+ INTENT_NAME_KEY,
87
+ INTENT_RESPONSE_KEY,
88
+ PREDICTED_CONFIDENCE_KEY,
89
+ FULL_RETRIEVAL_INTENT_NAME_KEY,
90
+ RESPONSE_SELECTOR,
91
+ RESPONSE,
92
+ TEXT,
93
+ )
94
+ from rasa.shared.nlu.training_data.message import Message
95
+ from rasa.utils.endpoints import EndpointConfig
96
+
97
+ if TYPE_CHECKING:
98
+ from rasa.core.utils import AvailableEndpoints
99
+
100
+ logger = logging.getLogger(__name__)
101
+ structlogger = structlog.get_logger()
102
+
103
+ MAX_NUMBER_OF_PREDICTIONS = int(os.environ.get("MAX_NUMBER_OF_PREDICTIONS", "10"))
104
+
105
+
106
+ class MessageProcessor:
107
+ """The message processor is interface for communicating with a bot model."""
108
+
109
+ def __init__(
110
+ self,
111
+ model_path: Union[Text, Path],
112
+ tracker_store: rasa.core.tracker_store.TrackerStore,
113
+ lock_store: LockStore,
114
+ generator: NaturalLanguageGenerator,
115
+ action_endpoint: Optional[EndpointConfig] = None,
116
+ max_number_of_predictions: int = MAX_NUMBER_OF_PREDICTIONS,
117
+ on_circuit_break: Optional[LambdaType] = None,
118
+ http_interpreter: Optional[RasaNLUHttpInterpreter] = None,
119
+ endpoints: Optional["AvailableEndpoints"] = None,
120
+ ) -> None:
121
+ """Initializes a `MessageProcessor`."""
122
+ self.nlg = generator
123
+ self.tracker_store = tracker_store
124
+ self.lock_store = lock_store
125
+ self.max_number_of_predictions = max_number_of_predictions
126
+ self.on_circuit_break = on_circuit_break
127
+ self.action_endpoint = action_endpoint
128
+ self.model_filename, self.model_metadata, self.graph_runner = self._load_model(
129
+ model_path
130
+ )
131
+ self.endpoints = endpoints
132
+
133
+ if self.model_metadata.assistant_id is None:
134
+ rasa.shared.utils.io.raise_warning(
135
+ f"The model metadata does not contain a value for the "
136
+ f"'{ASSISTANT_ID_KEY}' attribute. Check that 'config.yml' "
137
+ f"file contains a value for the '{ASSISTANT_ID_KEY}' key "
138
+ f"and re-train the model. Failure to do so will result in "
139
+ f"streaming events without a unique assistant identifier.",
140
+ UserWarning,
141
+ )
142
+
143
+ self.model_path = Path(model_path)
144
+ self.domain = self.model_metadata.domain
145
+ self.http_interpreter = http_interpreter
146
+
147
+ @staticmethod
148
+ def _load_model(
149
+ model_path: Union[Text, Path],
150
+ ) -> Tuple[Text, ModelMetadata, GraphRunner]:
151
+ """Unpacks a model from a given path using the graph model loader."""
152
+ try:
153
+ if os.path.isfile(model_path):
154
+ model_tar = model_path
155
+ else:
156
+ model_file_path = get_latest_model(model_path)
157
+ if not model_file_path:
158
+ raise ModelNotFound(f"No model found at path '{model_path}'.")
159
+ model_tar = model_file_path
160
+ except TypeError:
161
+ raise ModelNotFound(f"Model {model_path} can not be loaded.")
162
+
163
+ logger.info(f"Loading model {model_tar}...")
164
+ with TempDirectoryPath(get_temp_dir_name()) as temporary_directory:
165
+ try:
166
+ metadata, runner = loader.load_predict_graph_runner(
167
+ Path(temporary_directory),
168
+ Path(model_tar),
169
+ LocalModelStorage,
170
+ DaskGraphRunner,
171
+ )
172
+ return os.path.basename(model_tar), metadata, runner
173
+ except tarfile.ReadError:
174
+ raise ModelNotFound(f"Model {model_path} can not be loaded.")
175
+
176
+ async def handle_message(
177
+ self, message: UserMessage
178
+ ) -> Optional[List[Dict[Text, Any]]]:
179
+ """Handle a single message with this processor."""
180
+ # preprocess message if necessary
181
+ tracker = await self.log_message(message, should_save_tracker=False)
182
+
183
+ if self.model_metadata.training_type == TrainingType.NLU:
184
+ await self.save_tracker(tracker)
185
+ rasa.shared.utils.io.raise_warning(
186
+ "No core model. Skipping action prediction and execution.",
187
+ docs=DOCS_URL_NLU_BASED_POLICIES,
188
+ )
189
+ return None
190
+
191
+ if not self.message_contains_commands(tracker.latest_message):
192
+ tracker = await self.run_action_extract_slots(
193
+ message.output_channel, tracker
194
+ )
195
+
196
+ await self._run_prediction_loop(message.output_channel, tracker)
197
+
198
+ await self.run_anonymization_pipeline(tracker)
199
+
200
+ await self.save_tracker(tracker)
201
+
202
+ if isinstance(message.output_channel, CollectingOutputChannel):
203
+ return message.output_channel.messages
204
+
205
+ return None
206
+
207
+ async def run_action_extract_slots(
208
+ self, output_channel: OutputChannel, tracker: DialogueStateTracker
209
+ ) -> DialogueStateTracker:
210
+ """Run action to extract slots and update the tracker accordingly.
211
+
212
+ Args:
213
+ output_channel: Output channel associated with the incoming user message.
214
+ tracker: A tracker representing a conversation state.
215
+
216
+ Returns:
217
+ the given (updated) tracker
218
+ """
219
+ action_extract_slots = rasa.core.actions.action.action_for_name_or_text(
220
+ ACTION_EXTRACT_SLOTS, self.domain, self.action_endpoint
221
+ )
222
+ metadata = await self._add_flows_to_metadata()
223
+
224
+ extraction_events = await action_extract_slots.run(
225
+ output_channel, self.nlg, tracker, self.domain, metadata
226
+ )
227
+
228
+ await self._send_bot_messages(extraction_events, tracker, output_channel)
229
+
230
+ tracker.update_with_events(extraction_events)
231
+
232
+ structlogger.debug(
233
+ "processor.extract.slots",
234
+ action_extract_slot=ACTION_EXTRACT_SLOTS,
235
+ len_extraction_events=len(extraction_events),
236
+ rasa_events=copy.deepcopy(extraction_events),
237
+ )
238
+
239
+ return tracker
240
+
241
+ async def run_anonymization_pipeline(self, tracker: DialogueStateTracker) -> None:
242
+ """Run the anonymization pipeline on the new tracker events.
243
+
244
+ Args:
245
+ tracker: A tracker representing a conversation state.
246
+ """
247
+ anonymization_pipeline = plugin_manager().hook.get_anonymization_pipeline()
248
+ if anonymization_pipeline is None:
249
+ return None
250
+
251
+ old_tracker = await self.tracker_store.retrieve(tracker.sender_id)
252
+ new_events = rasa.shared.core.trackers.TrackerEventDiffEngine.event_difference(
253
+ old_tracker, tracker
254
+ )
255
+
256
+ for event in new_events:
257
+ body = {"sender_id": tracker.sender_id}
258
+ body.update(event.as_dict())
259
+ anonymization_pipeline.run(body)
260
+
261
+ async def predict_next_for_sender_id(
262
+ self, sender_id: Text
263
+ ) -> Optional[Dict[Text, Any]]:
264
+ """Predict the next action for the given sender_id.
265
+
266
+ Args:
267
+ sender_id: Conversation ID.
268
+
269
+ Returns:
270
+ The prediction for the next action. `None` if no domain or policies loaded.
271
+ """
272
+ tracker = await self.fetch_tracker_and_update_session(sender_id)
273
+ result = await self.predict_next_with_tracker(tracker)
274
+
275
+ # save tracker state to continue conversation from this state
276
+ await self.save_tracker(tracker)
277
+
278
+ return result
279
+
280
+ async def predict_next_with_tracker(
281
+ self,
282
+ tracker: DialogueStateTracker,
283
+ verbosity: EventVerbosity = EventVerbosity.AFTER_RESTART,
284
+ ) -> Optional[Dict[Text, Any]]:
285
+ """Predict the next action for a given conversation state.
286
+
287
+ Args:
288
+ tracker: A tracker representing a conversation state.
289
+ verbosity: Verbosity for the returned conversation state.
290
+
291
+ Returns:
292
+ The prediction for the next action. `None` if no domain or policies loaded.
293
+ """
294
+ if self.model_metadata.training_type == TrainingType.NLU:
295
+ rasa.shared.utils.io.raise_warning(
296
+ "No core model. Skipping action prediction and execution.",
297
+ docs=DOCS_URL_NLU_BASED_POLICIES,
298
+ )
299
+ return None
300
+
301
+ prediction = await self._predict_next_with_tracker(tracker)
302
+
303
+ scores = [
304
+ {"action": a, "score": p}
305
+ for a, p in zip(self.domain.action_names_or_texts, prediction.probabilities)
306
+ ]
307
+ return {
308
+ "scores": scores,
309
+ "policy": prediction.policy_name,
310
+ "confidence": prediction.max_confidence,
311
+ "tracker": tracker.current_state(verbosity),
312
+ }
313
+
314
+ async def _update_tracker_session(
315
+ self,
316
+ tracker: DialogueStateTracker,
317
+ output_channel: OutputChannel,
318
+ metadata: Optional[Dict] = None,
319
+ ) -> None:
320
+ """Check the current session in `tracker` and update it if expired.
321
+
322
+ An 'action_session_start' is run if the latest tracker session has expired,
323
+ or if the tracker does not yet contain any events (only those after the last
324
+ restart are considered).
325
+
326
+ Args:
327
+ metadata: Data sent from client associated with the incoming user message.
328
+ tracker: Tracker to inspect.
329
+ output_channel: Output channel for potential utterances in a custom
330
+ `ActionSessionStart`.
331
+ """
332
+ if not tracker.applied_events() or self._has_session_expired(tracker):
333
+ logger.debug(
334
+ f"Starting a new session for conversation ID '{tracker.sender_id}'."
335
+ )
336
+
337
+ action_session_start = self._get_action(ACTION_SESSION_START_NAME)
338
+
339
+ if metadata:
340
+ tracker.update(
341
+ SlotSet(SESSION_START_METADATA_SLOT, metadata), self.domain
342
+ )
343
+
344
+ await self._run_action(
345
+ action=action_session_start,
346
+ tracker=tracker,
347
+ output_channel=output_channel,
348
+ nlg=self.nlg,
349
+ prediction=PolicyPrediction.for_action_name(
350
+ self.domain, ACTION_SESSION_START_NAME
351
+ ),
352
+ )
353
+
354
+ async def fetch_tracker_and_update_session(
355
+ self,
356
+ sender_id: Text,
357
+ output_channel: Optional[OutputChannel] = None,
358
+ metadata: Optional[Dict] = None,
359
+ ) -> DialogueStateTracker:
360
+ """Fetches tracker for `sender_id` and updates its conversation session.
361
+
362
+ If a new tracker is created, `action_session_start` is run.
363
+
364
+ Args:
365
+ metadata: Data sent from client associated with the incoming user message.
366
+ output_channel: Output channel associated with the incoming user message.
367
+ sender_id: Conversation ID for which to fetch the tracker.
368
+
369
+ Returns:
370
+ Tracker for `sender_id`.
371
+ """
372
+ tracker = await self.get_tracker(sender_id)
373
+
374
+ await self._update_tracker_session(tracker, output_channel, metadata)
375
+
376
+ return tracker
377
+
378
+ async def fetch_tracker_with_initial_session(
379
+ self,
380
+ sender_id: Text,
381
+ output_channel: Optional[OutputChannel] = None,
382
+ metadata: Optional[Dict] = None,
383
+ ) -> DialogueStateTracker:
384
+ """Fetches tracker for `sender_id` and runs a session start on a new one.
385
+
386
+ Args:
387
+ metadata: Data sent from client associated with the incoming user message.
388
+ output_channel: Output channel associated with the incoming user message.
389
+ sender_id: Conversation ID for which to fetch the tracker.
390
+
391
+ Returns:
392
+ Tracker for `sender_id`.
393
+ """
394
+ tracker = await self.get_tracker(sender_id)
395
+
396
+ # run session start only if the tracker is empty
397
+ if not tracker.events:
398
+ await self._update_tracker_session(tracker, output_channel, metadata)
399
+
400
+ return tracker
401
+
402
+ async def get_tracker(self, conversation_id: Text) -> DialogueStateTracker:
403
+ """Get the tracker for a conversation.
404
+
405
+ In contrast to `fetch_tracker_and_update_session` this does not add any
406
+ `action_session_start` or `session_start` events at the beginning of a
407
+ conversation.
408
+
409
+ Args:
410
+ conversation_id: The ID of the conversation for which the history should be
411
+ retrieved.
412
+
413
+ Returns:
414
+ Tracker for the conversation. Creates an empty tracker in case it's a new
415
+ conversation.
416
+ """
417
+ conversation_id = conversation_id or DEFAULT_SENDER_ID
418
+
419
+ tracker = await self.tracker_store.get_or_create_tracker(
420
+ conversation_id, append_action_listen=False
421
+ )
422
+ tracker.model_id = self.model_metadata.model_id
423
+ if tracker.assistant_id is None:
424
+ tracker.assistant_id = self.model_metadata.assistant_id
425
+ return tracker
426
+
427
+ async def fetch_full_tracker_with_initial_session(
428
+ self,
429
+ conversation_id: Text,
430
+ output_channel: Optional[OutputChannel] = None,
431
+ metadata: Optional[Dict] = None,
432
+ ) -> DialogueStateTracker:
433
+ """Get the full tracker for a conversation, including events after a restart.
434
+
435
+ Args:
436
+ conversation_id: The ID of the conversation for which the history should be
437
+ retrieved.
438
+ output_channel: Output channel associated with the incoming user message.
439
+ metadata: Data sent from client associated with the incoming user message.
440
+
441
+ Returns:
442
+ Tracker for the conversation. Creates an empty tracker with a new session
443
+ initialized in case it's a new conversation.
444
+ """
445
+ conversation_id = conversation_id or DEFAULT_SENDER_ID
446
+
447
+ tracker = await self.tracker_store.get_or_create_full_tracker(
448
+ conversation_id, False
449
+ )
450
+ tracker.model_id = self.model_metadata.model_id
451
+
452
+ if tracker.assistant_id is None:
453
+ tracker.assistant_id = self.model_metadata.assistant_id
454
+
455
+ if not tracker.events:
456
+ await self._update_tracker_session(tracker, output_channel, metadata)
457
+
458
+ return tracker
459
+
460
+ async def get_trackers_for_all_conversation_sessions(
461
+ self, conversation_id: Text
462
+ ) -> List[DialogueStateTracker]:
463
+ """Fetches all trackers for a conversation.
464
+
465
+ Individual trackers are returned for each conversation session found
466
+ for `conversation_id`.
467
+
468
+ Args:
469
+ conversation_id: The ID of the conversation for which the trackers should
470
+ be retrieved.
471
+
472
+ Returns:
473
+ Trackers for the conversation.
474
+ """
475
+ conversation_id = conversation_id or DEFAULT_SENDER_ID
476
+
477
+ tracker = await self.tracker_store.retrieve_full_tracker(conversation_id)
478
+
479
+ return rasa.shared.core.trackers.get_trackers_for_conversation_sessions(tracker)
480
+
481
+ async def log_message(
482
+ self, message: UserMessage, should_save_tracker: bool = True
483
+ ) -> DialogueStateTracker:
484
+ """Log `message` on tracker belonging to the message's conversation_id.
485
+
486
+ Optionally save the tracker if `should_save_tracker` is `True`. Tracker saving
487
+ can be skipped if the tracker returned by this method is used for further
488
+ processing and saved at a later stage.
489
+ """
490
+ tracker = await self.fetch_tracker_and_update_session(
491
+ message.sender_id, message.output_channel, message.metadata
492
+ )
493
+
494
+ await self._handle_message_with_tracker(message, tracker)
495
+
496
+ if should_save_tracker:
497
+ await self.save_tracker(tracker)
498
+
499
+ return tracker
500
+
501
+ async def execute_action(
502
+ self,
503
+ sender_id: Text,
504
+ action_name: Text,
505
+ output_channel: OutputChannel,
506
+ nlg: NaturalLanguageGenerator,
507
+ prediction: PolicyPrediction,
508
+ ) -> Optional[DialogueStateTracker]:
509
+ """Execute an action for a conversation.
510
+
511
+ Note that this might lead to unexpected bot behavior. Rather use an intent
512
+ to execute certain behavior within a conversation (e.g. by using
513
+ `trigger_external_user_uttered`).
514
+
515
+ Args:
516
+ sender_id: The ID of the conversation.
517
+ action_name: The name of the action which should be executed.
518
+ output_channel: The output channel which should be used for bot responses.
519
+ nlg: The response generator.
520
+ prediction: The prediction for the action.
521
+
522
+ Returns:
523
+ The new conversation state. Note that the new state is also persisted.
524
+ """
525
+ # we have a Tracker instance for each user
526
+ # which maintains conversation state
527
+ tracker = await self.fetch_tracker_and_update_session(sender_id, output_channel)
528
+
529
+ action = self._get_action(action_name)
530
+ await self._run_action(action, tracker, output_channel, nlg, prediction)
531
+
532
+ # save tracker state to continue conversation from this state
533
+ await self.save_tracker(tracker)
534
+
535
+ return tracker
536
+
537
+ async def predict_next_with_tracker_if_should(
538
+ self, tracker: DialogueStateTracker
539
+ ) -> Tuple[rasa.core.actions.action.Action, PolicyPrediction]:
540
+ """Predicts the next action the bot should take after seeing x.
541
+
542
+ This should be overwritten by more advanced policies to use
543
+ ML to predict the action.
544
+
545
+ Returns:
546
+ The index of the next action and prediction of the policy.
547
+
548
+ Raises:
549
+ ActionLimitReached if the limit of actions to predict has been reached.
550
+ """
551
+ should_predict_another_action = self.should_predict_another_action(
552
+ tracker.latest_action_name
553
+ )
554
+
555
+ if self.is_action_limit_reached(tracker, should_predict_another_action):
556
+ raise ActionLimitReached(
557
+ "The limit of actions to predict has been reached."
558
+ )
559
+
560
+ prediction = await self._predict_next_with_tracker(tracker)
561
+
562
+ action = rasa.core.actions.action.action_for_index(
563
+ prediction.max_confidence_index, self.domain, self.action_endpoint
564
+ )
565
+
566
+ logger.debug(
567
+ f"Predicted next action '{action.name()}' with confidence "
568
+ f"{prediction.max_confidence:.2f}."
569
+ )
570
+
571
+ return action, prediction
572
+
573
+ @staticmethod
574
+ def _is_reminder(e: Event, name: Text) -> bool:
575
+ return isinstance(e, ReminderScheduled) and e.name == name
576
+
577
+ @staticmethod
578
+ def _is_reminder_still_valid(
579
+ tracker: DialogueStateTracker, reminder_event: ReminderScheduled
580
+ ) -> bool:
581
+ """Check if the conversation has been restarted after reminder."""
582
+ for e in reversed(tracker.applied_events()):
583
+ if MessageProcessor._is_reminder(e, reminder_event.name):
584
+ return True
585
+ return False # not found in applied events --> has been restarted
586
+
587
+ @staticmethod
588
+ def _has_message_after_reminder(
589
+ tracker: DialogueStateTracker, reminder_event: ReminderScheduled
590
+ ) -> bool:
591
+ """Check if the user sent a message after the reminder."""
592
+ for e in reversed(tracker.events):
593
+ if MessageProcessor._is_reminder(e, reminder_event.name):
594
+ return False
595
+
596
+ if isinstance(e, UserUttered) and e.text:
597
+ return True
598
+
599
+ return True # tracker has probably been restarted
600
+
601
+ async def handle_reminder(
602
+ self,
603
+ reminder_event: ReminderScheduled,
604
+ sender_id: Text,
605
+ output_channel: OutputChannel,
606
+ ) -> None:
607
+ """Handle a reminder that is triggered asynchronously."""
608
+ async with self.lock_store.lock(sender_id):
609
+ tracker = await self.fetch_tracker_and_update_session(
610
+ sender_id, output_channel
611
+ )
612
+
613
+ if (
614
+ reminder_event.kill_on_user_message
615
+ and self._has_message_after_reminder(tracker, reminder_event)
616
+ or not self._is_reminder_still_valid(tracker, reminder_event)
617
+ ):
618
+ logger.debug(
619
+ f"Canceled reminder because it is outdated ({reminder_event})."
620
+ )
621
+ else:
622
+ intent = reminder_event.intent
623
+ entities: Union[List[Dict], Dict] = reminder_event.entities or {}
624
+ await self.trigger_external_user_uttered(
625
+ intent, entities, tracker, output_channel
626
+ )
627
+
628
+ async def trigger_external_user_uttered(
629
+ self,
630
+ intent_name: Text,
631
+ entities: Optional[Union[List[Dict[Text, Any]], Dict[Text, Text]]],
632
+ tracker: DialogueStateTracker,
633
+ output_channel: OutputChannel,
634
+ ) -> None:
635
+ """Triggers an external message.
636
+
637
+ Triggers an external message (like a user message, but invisible;
638
+ used, e.g., by a reminder or the trigger_intent endpoint).
639
+
640
+ Args:
641
+ intent_name: Name of the intent to be triggered.
642
+ entities: Entities to be passed on.
643
+ tracker: The tracker to which the event should be added.
644
+ output_channel: The output channel.
645
+ """
646
+ if isinstance(entities, list):
647
+ entity_list = entities
648
+ elif isinstance(entities, dict):
649
+ # Allow for a short-hand notation {"ent1": "val1", "ent2": "val2", ...}.
650
+ # Useful if properties like 'start', 'end', or 'extractor' are not given,
651
+ # e.g. for external events.
652
+ entity_list = [
653
+ {"entity": ent, "value": val} for ent, val in entities.items()
654
+ ]
655
+ elif not entities:
656
+ entity_list = []
657
+ else:
658
+ rasa.shared.utils.io.raise_warning(
659
+ f"Invalid entity specification: {entities}. Assuming no entities."
660
+ )
661
+ entity_list = []
662
+
663
+ # Set the new event's input channel to the latest input channel, so
664
+ # that we don't lose this property.
665
+ input_channel = tracker.get_latest_input_channel()
666
+
667
+ tracker.update(
668
+ UserUttered.create_external(intent_name, entity_list, input_channel),
669
+ self.domain,
670
+ )
671
+
672
+ tracker = await self.run_action_extract_slots(output_channel, tracker)
673
+
674
+ await self._run_prediction_loop(output_channel, tracker)
675
+ # save tracker state to continue conversation from this state
676
+ await self.save_tracker(tracker)
677
+
678
+ @staticmethod
679
+ def _log_slots(tracker: DialogueStateTracker) -> None:
680
+ # Log currently set slots
681
+ slots = {s.name: s.value for s in tracker.slots.values() if s.value is not None}
682
+
683
+ structlogger.debug("processor.slots.log", slots=slots)
684
+
685
+ def _check_for_unseen_features(self, parse_data: Dict[Text, Any]) -> None:
686
+ """Warns the user if the NLU parse data contains unrecognized features.
687
+
688
+ Checks intents and entities picked up by the NLU parsing
689
+ against the domain and warns the user of those that don't match.
690
+ Also considers a list of default intents that are valid but don't
691
+ need to be listed in the domain.
692
+
693
+ Args:
694
+ parse_data: Message parse data to check against the domain.
695
+ """
696
+ if not self.domain or self.domain.is_empty():
697
+ return
698
+
699
+ intent = parse_data["intent"][INTENT_NAME_KEY]
700
+ if intent and intent not in self.domain.intents:
701
+ rasa.shared.utils.io.raise_warning(
702
+ f"Parsed an intent '{intent}' "
703
+ f"which is not defined in the domain. "
704
+ f"Please make sure all intents are listed in the domain.",
705
+ docs=DOCS_URL_DOMAINS,
706
+ )
707
+
708
+ entities = parse_data["entities"] or []
709
+ for element in entities:
710
+ entity = element["entity"]
711
+ if entity and entity not in self.domain.entities:
712
+ rasa.shared.utils.io.raise_warning(
713
+ f"Parsed an entity '{entity}' "
714
+ f"which is not defined in the domain. "
715
+ f"Please make sure all entities are listed in the domain.",
716
+ docs=DOCS_URL_DOMAINS,
717
+ )
718
+
719
+ def _get_action(
720
+ self, action_name: Text
721
+ ) -> Optional[rasa.core.actions.action.Action]:
722
+ return rasa.core.actions.action.action_for_name_or_text(
723
+ action_name, self.domain, self.action_endpoint
724
+ )
725
+
726
+ async def parse_message(
727
+ self,
728
+ message: UserMessage,
729
+ tracker: Optional[DialogueStateTracker] = None,
730
+ only_output_properties: bool = True,
731
+ ) -> Dict[Text, Any]:
732
+ """Interprets the passed message.
733
+
734
+ Args:
735
+ message: Message to handle.
736
+ tracker: Tracker to use.
737
+ only_output_properties: If `True`, restrict the output to
738
+ Message.only_output_properties.
739
+
740
+ Returns:
741
+ Parsed data extracted from the message.
742
+ """
743
+ if self.http_interpreter:
744
+ parse_data = await self.http_interpreter.parse(message)
745
+ else:
746
+ regex_reader = create_regex_pattern_reader(message, self.domain)
747
+
748
+ processed_message = Message({TEXT: message.text})
749
+ if regex_reader:
750
+ processed_message = regex_reader.unpack_regex_message(
751
+ message=processed_message, domain=self.domain
752
+ )
753
+
754
+ # Invalid use of slash syntax
755
+ if (
756
+ processed_message.starts_with_slash_syntax()
757
+ and not processed_message.has_intent()
758
+ and not processed_message.has_commands()
759
+ ):
760
+ parse_data = self._parse_invalid_use_of_slash_syntax(
761
+ processed_message, tracker, only_output_properties
762
+ )
763
+
764
+ # Intent or commands are not explicitly present. Pass message to graph.
765
+ elif not (
766
+ processed_message.has_intent() or processed_message.has_commands()
767
+ ):
768
+ parse_data = await self._parse_message_with_graph(
769
+ message, tracker, only_output_properties
770
+ )
771
+
772
+ # Intents or commands are presents. Bypasses the standard parsing
773
+ # pipeline.
774
+ else:
775
+ parse_data = await self._parse_message_with_commands_and_intents(
776
+ processed_message, tracker, only_output_properties
777
+ )
778
+
779
+ self._update_full_retrieval_intent(parse_data)
780
+ structlogger.debug(
781
+ "processor.message.parse",
782
+ parse_data_text=copy.deepcopy(parse_data["text"]),
783
+ parse_data_intent=parse_data["intent"],
784
+ parse_data_entities=copy.deepcopy(parse_data["entities"]),
785
+ )
786
+
787
+ self._check_for_unseen_features(parse_data)
788
+
789
+ return parse_data
790
+
791
+ def _parse_invalid_use_of_slash_syntax(
792
+ self,
793
+ message: Message,
794
+ tracker: Optional[DialogueStateTracker] = None,
795
+ only_output_properties: bool = True,
796
+ ) -> Dict[Text, Any]:
797
+ structlogger.warning(
798
+ "processor.message.parse.invalid_use_of_slash_syntax",
799
+ event_info=(
800
+ "Message starts with '/', but no intents or commands are"
801
+ "passed. Returning CannotHandleCommand() as a fallback."
802
+ ),
803
+ message=message.get(TEXT),
804
+ )
805
+ parse_data: Dict[Text, Any] = {
806
+ TEXT: "",
807
+ INTENT: {INTENT_NAME_KEY: None, PREDICTED_CONFIDENCE_KEY: 0.0},
808
+ ENTITIES: [],
809
+ }
810
+ parse_data.update(
811
+ message.as_dict(only_output_properties=only_output_properties)
812
+ )
813
+ commands = parse_data.get(COMMANDS, [])
814
+ commands += [
815
+ CannotHandleCommand(RASA_PATTERN_CANNOT_HANDLE_INVALID_INTENT).as_dict()
816
+ ]
817
+
818
+ if (
819
+ tracker is not None
820
+ and tracker.has_coexistence_routing_slot
821
+ and tracker.get_slot(ROUTE_TO_CALM_SLOT) is None
822
+ ):
823
+ # if we are currently not routing to either CALM or dm1
824
+ # we make a sticky routing to CALM
825
+ commands += [SetSlotCommand(ROUTE_TO_CALM_SLOT, True).as_dict()]
826
+
827
+ parse_data[COMMANDS] = commands
828
+ return parse_data
829
+
830
+ async def _parse_message_with_commands_and_intents(
831
+ self,
832
+ message: Message,
833
+ tracker: Optional[DialogueStateTracker] = None,
834
+ only_output_properties: bool = True,
835
+ ) -> Dict[Text, Any]:
836
+ """Parses the message to handle commands or intent trigger."""
837
+ parse_data: Dict[Text, Any] = {
838
+ TEXT: "",
839
+ INTENT: {INTENT_NAME_KEY: None, PREDICTED_CONFIDENCE_KEY: 0.0},
840
+ ENTITIES: [],
841
+ }
842
+ parse_data.update(
843
+ message.as_dict(only_output_properties=only_output_properties)
844
+ )
845
+
846
+ commands = parse_data.get(COMMANDS, [])
847
+
848
+ # add commands from intent payloads
849
+ if tracker and not commands:
850
+ nlu_adapted_commands = await self._nlu_to_commands(parse_data, tracker)
851
+ commands += nlu_adapted_commands
852
+
853
+ if (
854
+ tracker.has_coexistence_routing_slot
855
+ and tracker.get_slot(ROUTE_TO_CALM_SLOT) is None
856
+ ):
857
+ # if we are currently not routing to either CALM or dm1
858
+ # we make a sticky routing to CALM if there are any commands
859
+ # from the trigger intent parsing
860
+ # or a sticky routing to dm1 if there are no commands
861
+ commands += [
862
+ SetSlotCommand(
863
+ ROUTE_TO_CALM_SLOT, len(nlu_adapted_commands) > 0
864
+ ).as_dict()
865
+ ]
866
+
867
+ parse_data[COMMANDS] = commands
868
+ return parse_data
869
+
870
+ def _update_full_retrieval_intent(self, parse_data: Dict[Text, Any]) -> None:
871
+ """Update the parse data with the full retrieval intent.
872
+
873
+ Args:
874
+ parse_data: Message parse data to update.
875
+ """
876
+ intent_name = parse_data.get(INTENT, {}).get(INTENT_NAME_KEY)
877
+ response_selector = parse_data.get(RESPONSE_SELECTOR, {})
878
+ all_retrieval_intents = response_selector.get("all_retrieval_intents", [])
879
+ if intent_name and intent_name in all_retrieval_intents:
880
+ retrieval_intent = (
881
+ response_selector.get(intent_name, {})
882
+ .get(RESPONSE, {})
883
+ .get(INTENT_RESPONSE_KEY)
884
+ )
885
+ parse_data[INTENT][FULL_RETRIEVAL_INTENT_NAME_KEY] = retrieval_intent
886
+
887
+ async def _nlu_to_commands(
888
+ self, parse_data: Dict[str, Any], tracker: DialogueStateTracker
889
+ ) -> List[Dict[str, Any]]:
890
+ """Converts the NLU parse data to commands using the adaptor.
891
+
892
+ This is used if we receive intents/entities directly using `/intent{...}`
893
+ syntax. In this case, the nlu graph is not run. Therefore, we need to
894
+ convert the parse data to commands outside the graph.
895
+ """
896
+ from rasa.dialogue_understanding.generator.nlu_command_adapter import (
897
+ NLUCommandAdapter,
898
+ )
899
+
900
+ commands = NLUCommandAdapter.convert_nlu_to_commands(
901
+ Message(parse_data), tracker, await self.get_flows(), self.domain
902
+ )
903
+
904
+ # if there are no converted commands and parsed data contains invalid intent
905
+ # add CannotHandleCommand as fallback
906
+ if len(commands) == 0 and self._contains_undefined_intent(Message(parse_data)):
907
+ structlogger.warning(
908
+ "processor.message.nlu_to_commands.invalid_intent",
909
+ event_info=(
910
+ f"No NLU commands converted and parsed data contains"
911
+ f"invalid intent: {parse_data[INTENT]['name']}. "
912
+ f"Returning CannotHandleCommand() as a fallback."
913
+ ),
914
+ invalid_intent=parse_data[INTENT]["name"],
915
+ )
916
+ commands.append(
917
+ CannotHandleCommand(RASA_PATTERN_CANNOT_HANDLE_INVALID_INTENT)
918
+ )
919
+
920
+ return [command.as_dict() for command in commands]
921
+
922
+ def _contains_undefined_intent(self, message: Message) -> bool:
923
+ """Checks if the message contains an intent that is undefined
924
+ in the domain.
925
+ """
926
+ intent_name = message.get(INTENT, {}).get("name")
927
+ return intent_name is not None and intent_name not in self.domain.intents
928
+
929
+ async def _parse_message_with_graph(
930
+ self,
931
+ message: UserMessage,
932
+ tracker: Optional[DialogueStateTracker] = None,
933
+ only_output_properties: bool = True,
934
+ ) -> Dict[Text, Any]:
935
+ """Interprets the passed message.
936
+
937
+ Arguments:
938
+ message: Message to handle
939
+ tracker: Tracker to use
940
+ only_output_properties: If `True`, restrict the output to
941
+ Message.only_output_properties.
942
+
943
+ Returns:
944
+ Parsed data extracted from the message.
945
+ """
946
+ results = await self.graph_runner.run(
947
+ inputs={PLACEHOLDER_MESSAGE: [message], PLACEHOLDER_TRACKER: tracker},
948
+ targets=[self.model_metadata.nlu_target],
949
+ )
950
+ parsed_messages = results[self.model_metadata.nlu_target]
951
+ parsed_message = parsed_messages[0]
952
+ parse_data = {
953
+ TEXT: "",
954
+ INTENT: {INTENT_NAME_KEY: None, PREDICTED_CONFIDENCE_KEY: 0.0},
955
+ ENTITIES: [],
956
+ COMMANDS: [],
957
+ }
958
+ parse_data.update(
959
+ parsed_message.as_dict(only_output_properties=only_output_properties)
960
+ )
961
+ return parse_data
962
+
963
+ async def _handle_message_with_tracker(
964
+ self, message: UserMessage, tracker: DialogueStateTracker
965
+ ) -> None:
966
+ if message.parse_data:
967
+ parse_data = message.parse_data
968
+ else:
969
+ parse_data = await self.parse_message(message, tracker)
970
+
971
+ # don't ever directly mutate the tracker
972
+ # - instead pass its events to log
973
+ tracker.update(
974
+ UserUttered(
975
+ message.text,
976
+ parse_data["intent"],
977
+ parse_data["entities"],
978
+ parse_data,
979
+ input_channel=message.input_channel,
980
+ message_id=message.message_id,
981
+ metadata=message.metadata,
982
+ ),
983
+ self.domain,
984
+ )
985
+
986
+ if parse_data["entities"]:
987
+ self._log_slots(tracker)
988
+
989
+ logger.debug(
990
+ f"Logged UserUtterance - tracker now has {len(tracker.events)} events."
991
+ )
992
+
993
+ @staticmethod
994
+ def _should_handle_message(tracker: DialogueStateTracker) -> bool:
995
+ return not tracker.is_paused() or (
996
+ tracker.latest_message is not None
997
+ and tracker.latest_message.intent.get(INTENT_NAME_KEY)
998
+ == USER_INTENT_RESTART
999
+ )
1000
+
1001
+ def _tracker_state_specific_action_limit(
1002
+ self, tracker: DialogueStateTracker
1003
+ ) -> int:
1004
+ """Select the action limit based on the tracker state.
1005
+
1006
+ Usually, we want to limit the number of predictions to the number of actions
1007
+ that have been executed in the conversation so far. However, if the
1008
+ conversation is currently in a state where the user is correcting the flow
1009
+ we want to allow for more predictions to be made as we might be traversing
1010
+ through a long flow.
1011
+
1012
+ Args:
1013
+ tracker: instance of DialogueStateTracker.
1014
+
1015
+ Returns:
1016
+ The maximum number of predictions to make.
1017
+ """
1018
+ reversed_events = list(tracker.events)[::-1]
1019
+ is_conversation_in_flow_correction = False
1020
+ for e in reversed_events:
1021
+ if isinstance(e, ActionExecuted):
1022
+ if e.action_name in (ACTION_LISTEN_NAME, ACTION_SESSION_START_NAME):
1023
+ break
1024
+ elif e.action_name == ACTION_CORRECT_FLOW_SLOT:
1025
+ is_conversation_in_flow_correction = True
1026
+ break
1027
+
1028
+ if is_conversation_in_flow_correction:
1029
+ # allow for more predictions to be made as we might be traversing through
1030
+ # a long flow. We multiply the number of predictions by 10 to allow for
1031
+ # more predictions to be made - the factor is a best guess.
1032
+ return self.max_number_of_predictions * 5
1033
+ return self.max_number_of_predictions
1034
+
1035
+ def is_action_limit_reached(
1036
+ self, tracker: DialogueStateTracker, should_predict_another_action: bool
1037
+ ) -> bool:
1038
+ """Check whether the maximum number of predictions has been met.
1039
+
1040
+ Args:
1041
+ tracker: instance of DialogueStateTracker.
1042
+ should_predict_another_action: Whether the last executed action allows
1043
+ for more actions to be predicted or not.
1044
+
1045
+ Returns:
1046
+ `True` if the limit of actions to predict has been reached.
1047
+ """
1048
+ reversed_events = list(tracker.events)[::-1]
1049
+ num_predicted_actions = 0
1050
+ state_specific_action_limit = self._tracker_state_specific_action_limit(tracker)
1051
+
1052
+ for e in reversed_events:
1053
+ if isinstance(e, ActionExecuted):
1054
+ if e.action_name in (ACTION_LISTEN_NAME, ACTION_SESSION_START_NAME):
1055
+ break
1056
+ num_predicted_actions += 1
1057
+
1058
+ return (
1059
+ num_predicted_actions >= state_specific_action_limit
1060
+ and should_predict_another_action
1061
+ )
1062
+
1063
+ async def _run_prediction_loop(
1064
+ self, output_channel: OutputChannel, tracker: DialogueStateTracker
1065
+ ) -> None:
1066
+ # keep taking actions decided by the policy until it chooses to 'listen'
1067
+ should_predict_another_action = True
1068
+
1069
+ tracker = await self.run_command_processor(tracker)
1070
+
1071
+ # action loop. predicts actions until we hit action listen
1072
+ while should_predict_another_action and self._should_handle_message(tracker):
1073
+ # this actually just calls the policy's method by the same name
1074
+ try:
1075
+ action, prediction = await self.predict_next_with_tracker_if_should(
1076
+ tracker
1077
+ )
1078
+ except ActionLimitReached:
1079
+ logger.warning(
1080
+ "Circuit breaker tripped. Stopped predicting "
1081
+ f"more actions for sender '{tracker.sender_id}'."
1082
+ )
1083
+ if self.on_circuit_break:
1084
+ # call a registered callback
1085
+ self.on_circuit_break(tracker, output_channel, self.nlg)
1086
+ break
1087
+
1088
+ if prediction.is_end_to_end_prediction:
1089
+ logger.debug(
1090
+ f"An end-to-end prediction was made which has triggered the 2nd "
1091
+ f"execution of the default action '{ACTION_EXTRACT_SLOTS}'."
1092
+ )
1093
+ tracker = await self.run_action_extract_slots(output_channel, tracker)
1094
+
1095
+ should_predict_another_action = await self._run_action(
1096
+ action, tracker, output_channel, self.nlg, prediction
1097
+ )
1098
+
1099
+ @staticmethod
1100
+ def should_predict_another_action(action_name: Text) -> bool:
1101
+ """Determine whether the processor should predict another action.
1102
+
1103
+ Args:
1104
+ action_name: Name of the latest executed action.
1105
+
1106
+ Returns:
1107
+ `False` if `action_name` is `ACTION_LISTEN_NAME` or
1108
+ `ACTION_SESSION_START_NAME`, otherwise `True`.
1109
+ """
1110
+ return action_name not in (ACTION_LISTEN_NAME, ACTION_SESSION_START_NAME)
1111
+
1112
+ async def execute_side_effects(
1113
+ self,
1114
+ events: List[Event],
1115
+ tracker: DialogueStateTracker,
1116
+ output_channel: Optional[OutputChannel],
1117
+ ) -> None:
1118
+ """Attach tracker, send bot messages, schedule and cancel reminders."""
1119
+ if output_channel:
1120
+ output_channel.attach_tracker_state(tracker)
1121
+ await self._send_bot_messages(events, tracker, output_channel)
1122
+ await self._schedule_reminders(events, tracker, output_channel)
1123
+ await self._cancel_reminders(events, tracker)
1124
+
1125
+ @staticmethod
1126
+ async def _send_bot_messages(
1127
+ events: List[Event],
1128
+ tracker: DialogueStateTracker,
1129
+ output_channel: OutputChannel,
1130
+ ) -> None:
1131
+ """Send all the bot messages that are logged in the events array."""
1132
+ for e in events:
1133
+ if not isinstance(e, BotUttered):
1134
+ continue
1135
+
1136
+ await output_channel.send_response(tracker.sender_id, e.message())
1137
+
1138
+ async def _schedule_reminders(
1139
+ self,
1140
+ events: List[Event],
1141
+ tracker: DialogueStateTracker,
1142
+ output_channel: OutputChannel,
1143
+ ) -> None:
1144
+ """Uses the scheduler to time a job to trigger the passed reminder.
1145
+
1146
+ Reminders with the same `id` property will overwrite one another
1147
+ (i.e. only one of them will eventually run).
1148
+ """
1149
+ for e in events:
1150
+ if not isinstance(e, ReminderScheduled):
1151
+ continue
1152
+
1153
+ (await jobs.scheduler()).add_job(
1154
+ self.handle_reminder,
1155
+ "date",
1156
+ run_date=e.trigger_date_time,
1157
+ args=[e, tracker.sender_id, output_channel],
1158
+ id=e.name,
1159
+ replace_existing=True,
1160
+ name=e.scheduled_job_name(tracker.sender_id),
1161
+ )
1162
+
1163
+ @staticmethod
1164
+ async def _cancel_reminders(
1165
+ events: List[Event], tracker: DialogueStateTracker
1166
+ ) -> None:
1167
+ """Cancel reminders that match the `ReminderCancelled` event."""
1168
+ # All Reminders specified by ReminderCancelled events will be cancelled
1169
+ for event in events:
1170
+ if isinstance(event, ReminderCancelled):
1171
+ scheduler = await jobs.scheduler()
1172
+ for scheduled_job in scheduler.get_jobs():
1173
+ if event.cancels_job_with_name(
1174
+ scheduled_job.name, tracker.sender_id
1175
+ ):
1176
+ scheduler.remove_job(scheduled_job.id)
1177
+
1178
+ async def run_command_processor(
1179
+ self, tracker: DialogueStateTracker
1180
+ ) -> DialogueStateTracker:
1181
+ """Run the command processor to apply commands to the stack.
1182
+
1183
+ The command processor applies all the commands from the NLU pipeline to the
1184
+ dialogue stack. The dialogue stack then acts as base for decision making for
1185
+ the policies that can use it.
1186
+
1187
+ Args:
1188
+ tracker: the dialogue state tracker
1189
+
1190
+ Returns:
1191
+ An updated tracker after commands have been applied
1192
+ """
1193
+ target = "command_processor"
1194
+ results = await self.graph_runner.run(
1195
+ inputs={PLACEHOLDER_TRACKER: tracker.copy()}, targets=[target]
1196
+ )
1197
+ events = results[target]
1198
+ tracker.update_with_events(events)
1199
+ return tracker
1200
+
1201
+ async def get_flows(self) -> FlowsList:
1202
+ """Get the list of flows from the graph."""
1203
+ target = "flows_provider"
1204
+ results = await self.graph_runner.run(inputs={}, targets=[target])
1205
+ return results[target]
1206
+
1207
+ async def _add_flows_to_metadata(self) -> Dict[Text, Any]:
1208
+ """Convert the flows to metadata."""
1209
+ flows = await self.get_flows()
1210
+ flows_metadata = {}
1211
+ for flow in flows.underlying_flows:
1212
+ flow_as_json = flow.as_json()
1213
+ flow_as_json.pop("id")
1214
+ flows_metadata[flow.id] = flow_as_json
1215
+
1216
+ return {"all_flows": flows_metadata}
1217
+
1218
+ async def _run_action(
1219
+ self,
1220
+ action: rasa.core.actions.action.Action,
1221
+ tracker: DialogueStateTracker,
1222
+ output_channel: OutputChannel,
1223
+ nlg: NaturalLanguageGenerator,
1224
+ prediction: PolicyPrediction,
1225
+ ) -> bool:
1226
+ # events and return values are used to update
1227
+ # the tracker state after an action has been taken
1228
+ try:
1229
+ # Use temporary tracker as we might need to discard the policy events in
1230
+ # case of a rejection.
1231
+ temporary_tracker = tracker.copy()
1232
+ temporary_tracker.update_with_events(prediction.events)
1233
+
1234
+ run_args = inspect.getfullargspec(action.run).args
1235
+ if "metadata" in run_args:
1236
+ metadata: Optional[Dict] = prediction.action_metadata
1237
+
1238
+ if isinstance(action, FormAction):
1239
+ flows_metadata = await self._add_flows_to_metadata()
1240
+ metadata = prediction.action_metadata or {}
1241
+ metadata.update(flows_metadata)
1242
+
1243
+ events = await action.run(
1244
+ output_channel,
1245
+ nlg,
1246
+ temporary_tracker,
1247
+ self.domain,
1248
+ metadata=metadata,
1249
+ )
1250
+ else:
1251
+ events = await action.run(
1252
+ output_channel, nlg, temporary_tracker, self.domain
1253
+ )
1254
+ except ActionExecutionRejection:
1255
+ events = [
1256
+ ActionExecutionRejected(
1257
+ action.name(), prediction.policy_name, prediction.max_confidence
1258
+ )
1259
+ ]
1260
+ tracker.update(events[0])
1261
+ return self.should_predict_another_action(action.name())
1262
+ except Exception:
1263
+ structlogger.exception(
1264
+ "rasa.core.processor.run_action.exception",
1265
+ event_info=f"Encountered an exception while "
1266
+ f"running action '{action.name()}'."
1267
+ f"Bot will continue, but the actions events are lost. "
1268
+ f"Please check the logs of your action server for "
1269
+ f"more information.",
1270
+ )
1271
+ events = []
1272
+
1273
+ self._log_action_on_tracker(tracker, action, events, prediction)
1274
+
1275
+ if any(isinstance(e, UserUttered) for e in events):
1276
+ logger.debug(
1277
+ f"A `UserUttered` event was returned by executing "
1278
+ f"action '{action.name()}'. This will run the default action "
1279
+ f"'{ACTION_EXTRACT_SLOTS}'."
1280
+ )
1281
+ tracker = await self.run_action_extract_slots(output_channel, tracker)
1282
+
1283
+ if action.name() != ACTION_LISTEN_NAME and not action.name().startswith(
1284
+ UTTER_PREFIX
1285
+ ):
1286
+ self._log_slots(tracker)
1287
+
1288
+ await self.execute_side_effects(events, tracker, output_channel)
1289
+
1290
+ return self.should_predict_another_action(action.name())
1291
+
1292
+ def _log_action_on_tracker(
1293
+ self,
1294
+ tracker: DialogueStateTracker,
1295
+ action: Action,
1296
+ events: Optional[List[Event]],
1297
+ prediction: PolicyPrediction,
1298
+ ) -> None:
1299
+ # Ensures that the code still works even if a lazy programmer missed
1300
+ # to type `return []` at the end of an action or the run method
1301
+ # returns `None` for some other reason.
1302
+ if events is None:
1303
+ events = []
1304
+
1305
+ action_was_rejected_manually = any(
1306
+ isinstance(event, ActionExecutionRejected) for event in events
1307
+ )
1308
+ if not action_was_rejected_manually:
1309
+ structlogger.debug(
1310
+ "processor.actions.policy_prediction",
1311
+ prediction_events=copy.deepcopy(prediction.events),
1312
+ policy_name=prediction.policy_name,
1313
+ action_name=action.name(),
1314
+ )
1315
+ tracker.update_with_events(prediction.events)
1316
+
1317
+ # log the action and its produced events
1318
+ tracker.update(action.event_for_successful_execution(prediction))
1319
+
1320
+ structlogger.debug(
1321
+ "processor.actions.log",
1322
+ action_name=action.name(),
1323
+ rasa_events=copy.deepcopy(events),
1324
+ )
1325
+ tracker.update_with_events(events)
1326
+
1327
+ def _has_session_expired(self, tracker: DialogueStateTracker) -> bool:
1328
+ """Determine whether the latest session in `tracker` has expired.
1329
+
1330
+ Args:
1331
+ tracker: Tracker to inspect.
1332
+
1333
+ Returns:
1334
+ `True` if the session in `tracker` has expired, `False` otherwise.
1335
+ """
1336
+ if not self.domain.session_config.are_sessions_enabled():
1337
+ # tracker has never expired if sessions are disabled
1338
+ return False
1339
+
1340
+ user_uttered_event: Optional[UserUttered] = tracker.get_last_event_for(
1341
+ UserUttered
1342
+ )
1343
+
1344
+ if not user_uttered_event:
1345
+ # there is no user event so far so the session should not be considered
1346
+ # expired
1347
+ return False
1348
+
1349
+ time_delta_in_seconds = time.time() - user_uttered_event.timestamp
1350
+ has_expired = (
1351
+ time_delta_in_seconds / 60
1352
+ > self.domain.session_config.session_expiration_time
1353
+ )
1354
+ if has_expired:
1355
+ logger.debug(
1356
+ f"The latest session for conversation ID '{tracker.sender_id}' has "
1357
+ f"expired."
1358
+ )
1359
+
1360
+ return has_expired
1361
+
1362
+ async def save_tracker(self, tracker: DialogueStateTracker) -> None:
1363
+ """Save the given tracker to the tracker store.
1364
+
1365
+ Args:
1366
+ tracker: Tracker to be saved.
1367
+ """
1368
+ await self.tracker_store.save(tracker)
1369
+
1370
+ async def _predict_next_with_tracker(
1371
+ self, tracker: DialogueStateTracker
1372
+ ) -> PolicyPrediction:
1373
+ """Collect predictions from ensemble and return action and predictions."""
1374
+ followup_action = tracker.followup_action
1375
+ if followup_action:
1376
+ tracker.clear_followup_action()
1377
+ if followup_action in self.domain.action_names_or_texts:
1378
+ prediction = PolicyPrediction.for_action_name(
1379
+ self.domain, followup_action, FOLLOWUP_ACTION
1380
+ )
1381
+ return prediction
1382
+
1383
+ logger.error(
1384
+ f"Trying to run unknown follow-up action '{followup_action}'. "
1385
+ "Instead of running that, Rasa Pro will ignore the action "
1386
+ "and predict the next action."
1387
+ )
1388
+
1389
+ target = self.model_metadata.core_target
1390
+ if not target:
1391
+ raise ValueError("Cannot predict next action if there is no core target.")
1392
+
1393
+ results = await self.graph_runner.run(
1394
+ inputs={
1395
+ PLACEHOLDER_TRACKER: tracker,
1396
+ PLACEHOLDER_ENDPOINTS: self.endpoints,
1397
+ },
1398
+ targets=[target],
1399
+ )
1400
+ policy_prediction = results[target]
1401
+ return policy_prediction
1402
+
1403
+ @staticmethod
1404
+ def message_contains_commands(latest_message: Optional[UserUttered]) -> bool:
1405
+ """Check if the latest message contains commands."""
1406
+ if latest_message is None:
1407
+ return False
1408
+
1409
+ commands = [
1410
+ Command.command_from_json(command) for command in latest_message.commands
1411
+ ]
1412
+ filtered_commands = [
1413
+ command
1414
+ for command in commands
1415
+ if not (
1416
+ isinstance(command, SetSlotCommand)
1417
+ and command.name == ROUTE_TO_CALM_SLOT
1418
+ )
1419
+ and not isinstance(command, NoopCommand)
1420
+ ]
1421
+
1422
+ return len(filtered_commands) > 0