rasa-pro 3.14.0a20__py3-none-any.whl → 3.14.0a23__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 (331) hide show
  1. rasa/__main__.py +15 -3
  2. rasa/agents/__init__.py +0 -0
  3. rasa/agents/agent_factory.py +122 -0
  4. rasa/agents/agent_manager.py +211 -0
  5. rasa/agents/constants.py +43 -0
  6. rasa/agents/core/__init__.py +0 -0
  7. rasa/agents/core/agent_protocol.py +107 -0
  8. rasa/agents/core/types.py +81 -0
  9. rasa/agents/exceptions.py +38 -0
  10. rasa/agents/protocol/__init__.py +5 -0
  11. rasa/agents/protocol/a2a/__init__.py +0 -0
  12. rasa/agents/protocol/a2a/a2a_agent.py +879 -0
  13. rasa/agents/protocol/mcp/__init__.py +0 -0
  14. rasa/agents/protocol/mcp/mcp_base_agent.py +726 -0
  15. rasa/agents/protocol/mcp/mcp_open_agent.py +327 -0
  16. rasa/agents/protocol/mcp/mcp_task_agent.py +522 -0
  17. rasa/agents/schemas/__init__.py +13 -0
  18. rasa/agents/schemas/agent_input.py +38 -0
  19. rasa/agents/schemas/agent_output.py +26 -0
  20. rasa/agents/schemas/agent_tool_result.py +65 -0
  21. rasa/agents/schemas/agent_tool_schema.py +186 -0
  22. rasa/agents/templates/__init__.py +0 -0
  23. rasa/agents/templates/mcp_open_agent_prompt_template.jinja2 +20 -0
  24. rasa/agents/templates/mcp_task_agent_prompt_template.jinja2 +22 -0
  25. rasa/agents/utils.py +206 -0
  26. rasa/agents/validation.py +485 -0
  27. rasa/api.py +24 -9
  28. rasa/builder/config.py +6 -2
  29. rasa/builder/guardrails/{lakera.py → clients.py} +55 -5
  30. rasa/builder/guardrails/constants.py +3 -0
  31. rasa/builder/guardrails/models.py +45 -10
  32. rasa/builder/guardrails/policy_checker.py +324 -0
  33. rasa/builder/guardrails/utils.py +42 -276
  34. rasa/builder/llm_service.py +32 -5
  35. rasa/builder/models.py +1 -0
  36. rasa/builder/project_generator.py +6 -1
  37. rasa/builder/service.py +16 -13
  38. rasa/builder/training_service.py +18 -24
  39. rasa/builder/validation_service.py +1 -1
  40. rasa/cli/arguments/default_arguments.py +12 -0
  41. rasa/cli/arguments/run.py +2 -0
  42. rasa/cli/arguments/train.py +2 -0
  43. rasa/cli/data.py +10 -8
  44. rasa/cli/dialogue_understanding_test.py +10 -7
  45. rasa/cli/e2e_test.py +9 -6
  46. rasa/cli/evaluate.py +4 -2
  47. rasa/cli/export.py +5 -2
  48. rasa/cli/inspect.py +8 -4
  49. rasa/cli/interactive.py +5 -4
  50. rasa/cli/llm_fine_tuning.py +11 -6
  51. rasa/cli/project_templates/finance/actions/general/__init__.py +0 -0
  52. rasa/cli/project_templates/finance/actions/general/action_human_handoff.py +49 -0
  53. rasa/cli/project_templates/finance/data/general/bot_challenge.yml +6 -0
  54. rasa/cli/project_templates/finance/data/general/goodbye.yml +1 -1
  55. rasa/cli/project_templates/finance/data/general/human_handoff.yml +1 -1
  56. rasa/cli/project_templates/finance/data/system/patterns/pattern_session_start.yml +1 -1
  57. rasa/cli/project_templates/finance/domain/general/_shared.yml +0 -14
  58. rasa/cli/project_templates/finance/domain/general/bot_challenge.yml +4 -0
  59. rasa/cli/project_templates/finance/domain/general/goodbye.yml +7 -0
  60. rasa/cli/project_templates/finance/domain/general/human_handoff.yml +3 -6
  61. rasa/cli/project_templates/finance/domain/general/welcome.yml +29 -1
  62. rasa/cli/project_templates/finance/tests/e2e_test_cases/accounts/check_balance.yml +9 -0
  63. rasa/cli/project_templates/finance/tests/e2e_test_cases/accounts/download_statements.yml +43 -0
  64. rasa/cli/project_templates/finance/tests/e2e_test_cases/cards/block_card.yml +55 -0
  65. rasa/cli/project_templates/finance/tests/e2e_test_cases/general/bot_challenge.yml +8 -0
  66. rasa/cli/project_templates/finance/tests/e2e_test_cases/general/feedback.yml +46 -0
  67. rasa/cli/project_templates/finance/tests/e2e_test_cases/general/goodbye.yml +9 -0
  68. rasa/cli/project_templates/finance/tests/e2e_test_cases/general/hello.yml +8 -0
  69. rasa/cli/project_templates/finance/tests/e2e_test_cases/general/human_handoff.yml +35 -0
  70. rasa/cli/project_templates/finance/tests/e2e_test_cases/general/patterns.yml +22 -0
  71. rasa/cli/project_templates/finance/tests/e2e_test_cases/transfers/transfer_money.yml +56 -0
  72. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/feedback.yml +1 -1
  73. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/hello.yml +1 -1
  74. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/human_handoff.yml +1 -1
  75. rasa/cli/project_templates/telco/tests/e2e_test_cases/general/patterns.yml +1 -1
  76. rasa/cli/project_templates/tutorial/credentials.yml +10 -0
  77. rasa/cli/run.py +12 -10
  78. rasa/cli/scaffold.py +4 -4
  79. rasa/cli/shell.py +9 -5
  80. rasa/cli/studio/studio.py +1 -1
  81. rasa/cli/test.py +34 -14
  82. rasa/cli/train.py +41 -28
  83. rasa/cli/utils.py +1 -393
  84. rasa/cli/validation/__init__.py +0 -0
  85. rasa/cli/validation/bot_config.py +223 -0
  86. rasa/cli/validation/config_path_validation.py +257 -0
  87. rasa/cli/x.py +8 -4
  88. rasa/constants.py +7 -1
  89. rasa/core/actions/action.py +51 -10
  90. rasa/core/actions/action_run_slot_rejections.py +1 -1
  91. rasa/core/actions/direct_custom_actions_executor.py +9 -2
  92. rasa/core/actions/grpc_custom_action_executor.py +1 -1
  93. rasa/core/agent.py +19 -2
  94. rasa/core/available_agents.py +229 -0
  95. rasa/core/brokers/kafka.py +1 -1
  96. rasa/core/channels/__init__.py +82 -35
  97. rasa/core/channels/development_inspector.py +3 -3
  98. rasa/core/channels/inspector/README.md +25 -13
  99. rasa/core/channels/inspector/dist/assets/{arc-35222594.js → arc-6177260a.js} +1 -1
  100. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-a0efbfd3.js → blockDiagram-38ab4fdb-b054f038.js} +1 -1
  101. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-0584c0f2.js → c4Diagram-3d4e48cf-f25427d5.js} +1 -1
  102. rasa/core/channels/inspector/dist/assets/channel-bf9cbb34.js +1 -0
  103. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-39f40dbe.js → classDiagram-70f12bd4-c7a2af53.js} +1 -1
  104. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-1ad755f3.js → classDiagram-v2-f2320105-58db65c0.js} +1 -1
  105. rasa/core/channels/inspector/dist/assets/clone-8f9083bb.js +1 -0
  106. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-b0f4f0fe.js → createText-2e5e7dd3-088372e2.js} +1 -1
  107. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-9039bff9.js → edges-e0da2a9e-58676240.js} +1 -1
  108. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-65c9b127.js → erDiagram-9861fffd-0c14d7c6.js} +1 -1
  109. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-4f08b38e.js → flowDb-956e92f1-ea63f85c.js} +1 -1
  110. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-e95c362a.js → flowDiagram-66a62f08-a2af48cd.js} +1 -1
  111. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-9ecd5b59.js +1 -0
  112. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-703c3015.js → flowchart-elk-definition-4a651766-6937abe7.js} +1 -1
  113. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-699328ea.js → ganttDiagram-c361ad54-7473f357.js} +1 -1
  114. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-04cf4b05.js → gitGraphDiagram-72cf32ee-d0c9405e.js} +1 -1
  115. rasa/core/channels/inspector/dist/assets/{graph-ee94449e.js → graph-0a6f8466.js} +1 -1
  116. rasa/core/channels/inspector/dist/assets/{index-3862675e-940162b4.js → index-3862675e-7610671a.js} +1 -1
  117. rasa/core/channels/inspector/dist/assets/index-74e01d94.js +1354 -0
  118. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-c79c2866.js → infoDiagram-f8f76790-be397dc7.js} +1 -1
  119. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-84489d30.js → journeyDiagram-49397b02-4cefbf62.js} +1 -1
  120. rasa/core/channels/inspector/dist/assets/{layout-a9aa9858.js → layout-e7fbc2bf.js} +1 -1
  121. rasa/core/channels/inspector/dist/assets/{line-eb73cf26.js → line-a8aa457c.js} +1 -1
  122. rasa/core/channels/inspector/dist/assets/{linear-b3399f9a.js → linear-3351e0d2.js} +1 -1
  123. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-b095bf1a.js → mindmap-definition-fc14e90a-b8cbf605.js} +1 -1
  124. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-07644b66.js → pieDiagram-8a3498a8-f327f774.js} +1 -1
  125. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-573a3f9c.js → quadrantDiagram-120e2f19-2854c591.js} +1 -1
  126. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-d457e1e1.js → requirementDiagram-deff3bca-964985d5.js} +1 -1
  127. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-9d26e1a2.js → sankeyDiagram-04a897e0-edeb4f33.js} +1 -1
  128. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-3a9cde10.js → sequenceDiagram-704730f1-fcf70125.js} +1 -1
  129. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-4f3e8cec.js → stateDiagram-587899a1-0e770395.js} +1 -1
  130. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-e617e5bf.js → stateDiagram-v2-d93cdb3a-af8dcd22.js} +1 -1
  131. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-eab30d2f.js → styles-6aaf32cf-36a9e70d.js} +1 -1
  132. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-09994be2.js → styles-9a916d00-884a8b5b.js} +1 -1
  133. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-b7110364.js → styles-c10674c1-dc097813.js} +1 -1
  134. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-3ebc92ad.js → svgDrawCommon-08f97a94-5a2c7eed.js} +1 -1
  135. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-7d13d2f2.js → timeline-definition-85554ec2-e89c4f6e.js} +1 -1
  136. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-488385e1.js → xychartDiagram-e933f94c-afb6fe56.js} +1 -1
  137. rasa/core/channels/inspector/dist/index.html +1 -1
  138. rasa/core/channels/inspector/package.json +18 -18
  139. rasa/core/channels/inspector/src/App.tsx +29 -4
  140. rasa/core/channels/inspector/src/components/DialogueAgentStack.tsx +108 -0
  141. rasa/core/channels/inspector/src/components/{DialogueStack.tsx → DialogueHistoryStack.tsx} +4 -2
  142. rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +7 -4
  143. rasa/core/channels/inspector/src/helpers/formatters.test.ts +4 -0
  144. rasa/core/channels/inspector/src/helpers/formatters.ts +24 -3
  145. rasa/core/channels/inspector/src/helpers/utils.test.ts +127 -0
  146. rasa/core/channels/inspector/src/helpers/utils.ts +66 -1
  147. rasa/core/channels/inspector/src/theme/base/styles.ts +19 -1
  148. rasa/core/channels/inspector/src/types.ts +21 -0
  149. rasa/core/channels/inspector/yarn.lock +336 -189
  150. rasa/core/channels/studio_chat.py +6 -6
  151. rasa/core/channels/telegram.py +4 -9
  152. rasa/core/channels/voice_stream/browser_audio.py +2 -0
  153. rasa/core/channels/voice_stream/genesys.py +1 -1
  154. rasa/core/channels/voice_stream/tts/deepgram.py +140 -0
  155. rasa/core/channels/voice_stream/twilio_media_streams.py +5 -1
  156. rasa/core/channels/voice_stream/voice_channel.py +3 -0
  157. rasa/core/config/__init__.py +0 -0
  158. rasa/core/{available_endpoints.py → config/available_endpoints.py} +51 -16
  159. rasa/core/config/configuration.py +260 -0
  160. rasa/core/config/credentials.py +19 -0
  161. rasa/core/config/message_procesing_config.py +34 -0
  162. rasa/core/constants.py +5 -0
  163. rasa/core/iam_credentials_providers/aws_iam_credentials_providers.py +88 -3
  164. rasa/core/iam_credentials_providers/credentials_provider_protocol.py +2 -1
  165. rasa/core/lock_store.py +6 -4
  166. rasa/core/nlg/generator.py +1 -1
  167. rasa/core/policies/enterprise_search_policy.py +5 -3
  168. rasa/core/policies/flow_policy.py +4 -4
  169. rasa/core/policies/flows/agent_executor.py +632 -0
  170. rasa/core/policies/flows/flow_executor.py +137 -76
  171. rasa/core/policies/flows/mcp_tool_executor.py +298 -0
  172. rasa/core/policies/intentless_policy.py +1 -1
  173. rasa/core/policies/ted_policy.py +20 -12
  174. rasa/core/policies/unexpected_intent_policy.py +6 -0
  175. rasa/core/processor.py +68 -44
  176. rasa/core/redis_connection_factory.py +78 -20
  177. rasa/core/run.py +37 -8
  178. rasa/core/test.py +4 -0
  179. rasa/core/tracker_stores/sql_tracker_store.py +1 -1
  180. rasa/core/tracker_stores/tracker_store.py +3 -7
  181. rasa/core/train.py +1 -1
  182. rasa/core/training/interactive.py +20 -18
  183. rasa/core/training/story_conflict.py +5 -5
  184. rasa/core/utils.py +22 -23
  185. rasa/dialogue_understanding/commands/__init__.py +8 -0
  186. rasa/dialogue_understanding/commands/cancel_flow_command.py +19 -5
  187. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +21 -2
  188. rasa/dialogue_understanding/commands/clarify_command.py +20 -2
  189. rasa/dialogue_understanding/commands/continue_agent_command.py +91 -0
  190. rasa/dialogue_understanding/commands/knowledge_answer_command.py +21 -2
  191. rasa/dialogue_understanding/commands/restart_agent_command.py +162 -0
  192. rasa/dialogue_understanding/commands/start_flow_command.py +68 -7
  193. rasa/dialogue_understanding/commands/utils.py +124 -2
  194. rasa/dialogue_understanding/generator/command_parser.py +4 -0
  195. rasa/dialogue_understanding/generator/llm_based_command_generator.py +50 -12
  196. rasa/dialogue_understanding/generator/llm_command_generator.py +1 -1
  197. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +1 -1
  198. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +66 -0
  199. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +66 -0
  200. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +89 -0
  201. rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +88 -0
  202. rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +42 -7
  203. rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +40 -3
  204. rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +20 -3
  205. rasa/dialogue_understanding/patterns/cancel.py +27 -6
  206. rasa/dialogue_understanding/patterns/clarify.py +3 -14
  207. rasa/dialogue_understanding/patterns/continue_interrupted.py +239 -6
  208. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +46 -8
  209. rasa/dialogue_understanding/processor/command_processor.py +136 -15
  210. rasa/dialogue_understanding/stack/dialogue_stack.py +98 -2
  211. rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +57 -0
  212. rasa/dialogue_understanding/stack/utils.py +57 -3
  213. rasa/dialogue_understanding/utils.py +24 -4
  214. rasa/dialogue_understanding_test/du_test_runner.py +8 -3
  215. rasa/e2e_test/e2e_test_runner.py +13 -3
  216. rasa/engine/caching.py +2 -2
  217. rasa/engine/constants.py +1 -1
  218. rasa/engine/loader.py +12 -0
  219. rasa/engine/recipes/default_components.py +138 -49
  220. rasa/engine/recipes/default_recipe.py +108 -11
  221. rasa/engine/runner/dask.py +8 -5
  222. rasa/engine/validation.py +19 -6
  223. rasa/graph_components/validators/default_recipe_validator.py +86 -28
  224. rasa/hooks.py +5 -5
  225. rasa/llm_fine_tuning/utils.py +2 -2
  226. rasa/model_training.py +60 -47
  227. rasa/nlu/classifiers/diet_classifier.py +198 -98
  228. rasa/nlu/classifiers/logistic_regression_classifier.py +1 -4
  229. rasa/nlu/classifiers/mitie_intent_classifier.py +3 -0
  230. rasa/nlu/classifiers/sklearn_intent_classifier.py +1 -3
  231. rasa/nlu/extractors/crf_entity_extractor.py +9 -10
  232. rasa/nlu/extractors/mitie_entity_extractor.py +3 -0
  233. rasa/nlu/extractors/spacy_entity_extractor.py +3 -0
  234. rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +4 -0
  235. rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +5 -0
  236. rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +2 -0
  237. rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +3 -0
  238. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +4 -2
  239. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +4 -0
  240. rasa/nlu/selectors/response_selector.py +10 -2
  241. rasa/nlu/tokenizers/jieba_tokenizer.py +3 -4
  242. rasa/nlu/tokenizers/mitie_tokenizer.py +3 -2
  243. rasa/nlu/tokenizers/spacy_tokenizer.py +3 -2
  244. rasa/nlu/utils/mitie_utils.py +3 -0
  245. rasa/nlu/utils/spacy_utils.py +3 -2
  246. rasa/plugin.py +8 -8
  247. rasa/privacy/privacy_manager.py +12 -3
  248. rasa/server.py +15 -3
  249. rasa/shared/agents/__init__.py +0 -0
  250. rasa/shared/agents/auth/__init__.py +0 -0
  251. rasa/shared/agents/auth/agent_auth_factory.py +105 -0
  252. rasa/shared/agents/auth/agent_auth_manager.py +92 -0
  253. rasa/shared/agents/auth/auth_strategy/__init__.py +19 -0
  254. rasa/shared/agents/auth/auth_strategy/agent_auth_strategy.py +52 -0
  255. rasa/shared/agents/auth/auth_strategy/api_key_auth_strategy.py +42 -0
  256. rasa/shared/agents/auth/auth_strategy/bearer_token_auth_strategy.py +28 -0
  257. rasa/shared/agents/auth/auth_strategy/oauth2_auth_strategy.py +167 -0
  258. rasa/shared/agents/auth/constants.py +12 -0
  259. rasa/shared/agents/auth/types.py +12 -0
  260. rasa/shared/agents/utils.py +35 -0
  261. rasa/shared/constants.py +8 -0
  262. rasa/shared/core/constants.py +16 -1
  263. rasa/shared/core/domain.py +0 -7
  264. rasa/shared/core/events.py +327 -0
  265. rasa/shared/core/flows/constants.py +5 -0
  266. rasa/shared/core/flows/flow.py +1 -1
  267. rasa/shared/core/flows/flows_list.py +21 -5
  268. rasa/shared/core/flows/flows_yaml_schema.json +119 -184
  269. rasa/shared/core/flows/steps/call.py +49 -5
  270. rasa/shared/core/flows/steps/collect.py +98 -13
  271. rasa/shared/core/flows/validation.py +372 -8
  272. rasa/shared/core/flows/yaml_flows_io.py +3 -2
  273. rasa/shared/core/slots.py +2 -2
  274. rasa/shared/core/trackers.py +5 -2
  275. rasa/shared/exceptions.py +16 -0
  276. rasa/shared/importers/rasa.py +1 -1
  277. rasa/shared/importers/utils.py +9 -3
  278. rasa/shared/providers/llm/_base_litellm_client.py +41 -9
  279. rasa/shared/providers/llm/litellm_router_llm_client.py +8 -4
  280. rasa/shared/providers/llm/llm_client.py +7 -3
  281. rasa/shared/providers/llm/llm_response.py +66 -0
  282. rasa/shared/providers/llm/self_hosted_llm_client.py +8 -4
  283. rasa/shared/utils/common.py +24 -0
  284. rasa/shared/utils/health_check/health_check.py +7 -3
  285. rasa/shared/utils/llm.py +39 -16
  286. rasa/shared/utils/mcp/__init__.py +0 -0
  287. rasa/shared/utils/mcp/server_connection.py +247 -0
  288. rasa/shared/utils/mcp/utils.py +20 -0
  289. rasa/shared/utils/schemas/events.py +42 -0
  290. rasa/shared/utils/yaml.py +3 -1
  291. rasa/studio/pull/pull.py +3 -2
  292. rasa/studio/train.py +8 -7
  293. rasa/studio/upload.py +3 -6
  294. rasa/telemetry.py +69 -5
  295. rasa/tracing/config.py +45 -12
  296. rasa/tracing/constants.py +14 -0
  297. rasa/tracing/instrumentation/attribute_extractors.py +142 -9
  298. rasa/tracing/instrumentation/instrumentation.py +626 -21
  299. rasa/tracing/instrumentation/intentless_policy_instrumentation.py +4 -4
  300. rasa/tracing/instrumentation/metrics.py +32 -0
  301. rasa/tracing/metric_instrument_provider.py +68 -0
  302. rasa/utils/common.py +92 -1
  303. rasa/utils/endpoints.py +11 -2
  304. rasa/utils/log_utils.py +96 -5
  305. rasa/utils/ml_utils.py +1 -1
  306. rasa/utils/pypred.py +38 -0
  307. rasa/utils/tensorflow/__init__.py +7 -0
  308. rasa/utils/tensorflow/callback.py +136 -101
  309. rasa/utils/tensorflow/crf.py +1 -1
  310. rasa/utils/tensorflow/data_generator.py +21 -8
  311. rasa/utils/tensorflow/layers.py +21 -11
  312. rasa/utils/tensorflow/metrics.py +7 -3
  313. rasa/utils/tensorflow/models.py +56 -8
  314. rasa/utils/tensorflow/rasa_layers.py +8 -6
  315. rasa/utils/tensorflow/transformer.py +2 -3
  316. rasa/utils/train_utils.py +54 -24
  317. rasa/validator.py +17 -13
  318. rasa/version.py +1 -1
  319. {rasa_pro-3.14.0a20.dist-info → rasa_pro-3.14.0a23.dist-info}/METADATA +48 -42
  320. {rasa_pro-3.14.0a20.dist-info → rasa_pro-3.14.0a23.dist-info}/RECORD +323 -251
  321. rasa/builder/scrape_rasa_docs.py +0 -97
  322. rasa/cli/project_templates/finance/data/general/agent_details.yml +0 -6
  323. rasa/cli/project_templates/finance/domain/_system/patterns/pattern_session_start.yml +0 -11
  324. rasa/cli/project_templates/finance/domain/general/agent_details.yml +0 -31
  325. rasa/core/channels/inspector/dist/assets/channel-8e08bed9.js +0 -1
  326. rasa/core/channels/inspector/dist/assets/clone-78c82dea.js +0 -1
  327. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-2b08f601.js +0 -1
  328. rasa/core/channels/inspector/dist/assets/index-c941dcb3.js +0 -1336
  329. {rasa_pro-3.14.0a20.dist-info → rasa_pro-3.14.0a23.dist-info}/NOTICE +0 -0
  330. {rasa_pro-3.14.0a20.dist-info → rasa_pro-3.14.0a23.dist-info}/WHEEL +0 -0
  331. {rasa_pro-3.14.0a20.dist-info → rasa_pro-3.14.0a23.dist-info}/entry_points.txt +0 -0
rasa/core/run.py CHANGED
@@ -30,34 +30,35 @@ from rasa import server, telemetry
30
30
  from rasa.constants import ENV_SANIC_BACKLOG
31
31
  from rasa.core import agent, channels, constants
32
32
  from rasa.core.agent import Agent
33
- from rasa.core.available_endpoints import AvailableEndpoints
33
+ from rasa.core.available_agents import AvailableAgents
34
34
  from rasa.core.channels import console
35
35
  from rasa.core.channels.channel import InputChannel
36
36
  from rasa.core.channels.development_inspector import DevelopmentInspectProxy
37
+ from rasa.core.config.available_endpoints import AvailableEndpoints
38
+ from rasa.core.config.credentials import CredentialsConfig
37
39
  from rasa.core.persistor import StorageType
38
40
  from rasa.shared.exceptions import RasaException
39
- from rasa.shared.utils.yaml import read_config_file
40
41
  from rasa.utils import licensing
41
42
 
42
43
  logger = logging.getLogger() # get the root logger
43
44
 
44
45
 
45
46
  def create_input_channels(
46
- channel: Optional[Text], credentials_file: Optional[Text]
47
+ channel: Optional[Text], credentials_config: Optional[CredentialsConfig]
47
48
  ) -> List[InputChannel]:
48
49
  """Instantiate the chosen input channel.
49
50
 
50
51
  Args:
51
52
  channel (optional): The name of the specific input channel to create.
52
- credentials_file: Path to the credentials file containing channel credentials.
53
+ credentials_config: CredentialsConfig object containing channel credentials.
53
54
 
54
55
  Returns:
55
56
  A list of instantiated input channels. If a specific channel is provided,
56
57
  it returns a list with that single channel. If no channel is specified,
57
58
  it returns a list of all channels defined in the credentials file.
58
59
  """
59
- if credentials_file:
60
- all_credentials = read_config_file(credentials_file)
60
+ if credentials_config:
61
+ all_credentials = credentials_config.channels
61
62
  else:
62
63
  all_credentials = {}
63
64
  if channel:
@@ -96,10 +97,32 @@ def _create_single_channel(
96
97
  """
97
98
  from rasa.core.channels import BUILTIN_CHANNELS
98
99
 
100
+ # Channels that have optional dependencies
101
+ channels_with_optional_deps = {
102
+ "facebook": "fbmessenger",
103
+ "slack": "slack-sdk",
104
+ "telegram": "aiogram",
105
+ "twilio": "twilio",
106
+ "twilio_voice": "twilio",
107
+ "twilio_media_streams": "twilio",
108
+ "webexteams": "webexteamssdk",
109
+ "vier_cvg": "cvg_sdk",
110
+ }
111
+
99
112
  if channel in BUILTIN_CHANNELS:
100
113
  channel_class = BUILTIN_CHANNELS[channel]
101
114
 
102
115
  return channel_class.from_credentials(credentials)
116
+ elif channel in channels_with_optional_deps:
117
+ # Channel is known but not available due to missing dependency
118
+ dependency = channels_with_optional_deps[channel]
119
+ raise RasaException(
120
+ f"Channel '{channel}' is not available "
121
+ f"due to missing '{dependency}' dependency. "
122
+ f"Please install the required extra by running: "
123
+ f"pip install 'rasa-pro[channels]' OR "
124
+ f"poetry add 'rasa-pro[channels]'"
125
+ )
103
126
  else:
104
127
  # try to load channel based on class name
105
128
  try:
@@ -151,6 +174,7 @@ def configure_app(
151
174
  route: Optional[Text] = "/webhooks/",
152
175
  port: int = constants.DEFAULT_SERVER_PORT,
153
176
  endpoints: Optional[AvailableEndpoints] = None,
177
+ sub_agents: Optional[AvailableAgents] = None,
154
178
  log_file: Optional[Text] = None,
155
179
  conversation_id: Optional[Text] = uuid.uuid4().hex,
156
180
  use_syslog: bool = False,
@@ -179,6 +203,7 @@ def configure_app(
179
203
  jwt_private_key=jwt_private_key,
180
204
  jwt_method=jwt_method,
181
205
  endpoints=endpoints,
206
+ sub_agents=sub_agents,
182
207
  is_inspector_enabled=is_inspector_enabled,
183
208
  )
184
209
  )
@@ -234,7 +259,7 @@ def serve_application(
234
259
  channel: Optional[Text] = None,
235
260
  interface: Optional[Text] = constants.DEFAULT_SERVER_INTERFACE,
236
261
  port: int = constants.DEFAULT_SERVER_PORT,
237
- credentials: Optional[Text] = None,
262
+ credentials: Optional[CredentialsConfig] = None,
238
263
  cors: Optional[Union[Text, List[Text]]] = None,
239
264
  auth_token: Optional[Text] = None,
240
265
  enable_api: bool = True,
@@ -243,6 +268,7 @@ def serve_application(
243
268
  jwt_private_key: Optional[Text] = None,
244
269
  jwt_method: Optional[Text] = None,
245
270
  endpoints: Optional[AvailableEndpoints] = None,
271
+ sub_agents: Optional[AvailableAgents] = None,
246
272
  remote_storage: Optional[StorageType] = None,
247
273
  log_file: Optional[Text] = None,
248
274
  ssl_certificate: Optional[Text] = None,
@@ -283,6 +309,7 @@ def serve_application(
283
309
  jwt_method,
284
310
  port=port,
285
311
  endpoints=endpoints,
312
+ sub_agents=sub_agents,
286
313
  log_file=log_file,
287
314
  conversation_id=conversation_id,
288
315
  use_syslog=use_syslog,
@@ -302,7 +329,7 @@ def serve_application(
302
329
  logger.info(f"Starting Rasa server on {protocol}://{interface}:{port}")
303
330
 
304
331
  app.register_listener(
305
- partial(load_agent_on_start, model_path, endpoints, remote_storage),
332
+ partial(load_agent_on_start, model_path, endpoints, remote_storage, sub_agents),
306
333
  "before_server_start",
307
334
  )
308
335
 
@@ -340,6 +367,7 @@ async def load_agent_on_start(
340
367
  model_path: Text,
341
368
  endpoints: AvailableEndpoints,
342
369
  remote_storage: Optional[StorageType],
370
+ sub_agents: Optional[AvailableAgents],
343
371
  app: Sanic,
344
372
  loop: AbstractEventLoop,
345
373
  ) -> Agent:
@@ -352,6 +380,7 @@ async def load_agent_on_start(
352
380
  model_path=model_path,
353
381
  remote_storage=remote_storage,
354
382
  endpoints=endpoints,
383
+ sub_agents=sub_agents,
355
384
  loop=loop,
356
385
  )
357
386
 
rasa/core/test.py CHANGED
@@ -1281,6 +1281,10 @@ async def compare_models_in_dir(
1281
1281
  for k, v in number_correct_in_run.items():
1282
1282
  number_correct[k].append(v)
1283
1283
 
1284
+ logger.info("current working directory: " + os.getcwd())
1285
+ logger.info(
1286
+ f"Writing model comparison results to '{os.path.join(output, RESULTS_FILE)}'"
1287
+ )
1284
1288
  rasa.shared.utils.io.dump_obj_as_json_to_file(
1285
1289
  os.path.join(output, RESULTS_FILE), number_correct
1286
1290
  )
@@ -236,7 +236,7 @@ class SQLTrackerStore(TrackerStore, SerializedTrackerAsText):
236
236
  )
237
237
  )
238
238
  if iam_credentials_provider is not None:
239
- credentials = iam_credentials_provider.get_credentials()
239
+ credentials = iam_credentials_provider.get_temporary_credentials()
240
240
  if credentials.auth_token:
241
241
  password = credentials.auth_token
242
242
  structlogger.debug(
@@ -542,7 +542,7 @@ class FailSafeTrackerStore(TrackerStore):
542
542
  return self._tracker_store.domain
543
543
 
544
544
  @domain.setter
545
- def domain(self, domain: Domain) -> None:
545
+ def domain(self, domain: Optional[Domain]) -> None:
546
546
  self._tracker_store.domain = domain
547
547
 
548
548
  if self._fallback_tracker_store:
@@ -805,9 +805,7 @@ class AwaitableTrackerStore(TrackerStore):
805
805
  async def retrieve(self, sender_id: Text) -> Optional[DialogueStateTracker]:
806
806
  """Wrapper to call `retrieve` method of primary tracker store."""
807
807
  result = self._tracker_store.retrieve(sender_id)
808
- return (
809
- await result if isawaitable(result) else result # type: ignore[return-value, misc]
810
- )
808
+ return await result if isawaitable(result) else result
811
809
 
812
810
  async def keys(self) -> Iterable[Text]:
813
811
  """Wrapper to call `keys` method of primary tracker store."""
@@ -834,6 +832,4 @@ class AwaitableTrackerStore(TrackerStore):
834
832
  ) -> Optional[DialogueStateTracker]:
835
833
  """Wrapper to call `retrieve_full_tracker` method of primary tracker store."""
836
834
  result = self._tracker_store.retrieve_full_tracker(conversation_id)
837
- return (
838
- await result if isawaitable(result) else result # type: ignore[return-value, misc]
839
- )
835
+ return await result if isawaitable(result) else result
rasa/core/train.py CHANGED
@@ -46,7 +46,7 @@ async def train_comparison_models(
46
46
  output=str(Path(output_path, f"run_{r +1}")),
47
47
  fixed_model_name=config_name + PERCENTAGE_KEY + str(percentage),
48
48
  additional_arguments={
49
- **additional_arguments,
49
+ **(additional_arguments or {}),
50
50
  "exclusion_percentage": percentage,
51
51
  },
52
52
  )
@@ -47,7 +47,7 @@ import rasa.shared.utils.io
47
47
  import rasa.utils.io as io_utils
48
48
  from rasa import telemetry
49
49
  from rasa.core import run, utils
50
- from rasa.core.available_endpoints import AvailableEndpoints
50
+ from rasa.core.config.configuration import Configuration
51
51
  from rasa.core.constants import DEFAULT_SERVER_FORMAT, DEFAULT_SERVER_PORT
52
52
  from rasa.shared.constants import (
53
53
  DEFAULT_SENDER_ID,
@@ -91,7 +91,7 @@ from rasa.shared.core.training_data.visualization import (
91
91
  )
92
92
  from rasa.shared.exceptions import InvalidConfigException
93
93
  from rasa.shared.importers.rasa import TrainingDataImporter
94
- from rasa.shared.nlu.constants import INTENT_NAME_KEY, TEXT
94
+ from rasa.shared.nlu.constants import ENTITIES, INTENT, INTENT_NAME_KEY, TEXT
95
95
 
96
96
  # noinspection PyProtectedMember
97
97
  from rasa.shared.nlu.training_data import loading
@@ -789,7 +789,7 @@ def _collect_messages(events: List[Dict[Text, Any]]) -> List[Message]:
789
789
  data = event.get("parse_data", {})
790
790
  rasa_nlu_training_data_utils.remove_untrainable_entities_from(data)
791
791
  msg = Message.build(
792
- data["text"], data["intent"][INTENT_NAME_KEY], data["entities"]
792
+ data[TEXT], data[INTENT][INTENT_NAME_KEY], data[ENTITIES]
793
793
  )
794
794
  messages.append(msg)
795
795
  elif event.get("event") == UserUtteranceReverted.type_name and messages:
@@ -901,13 +901,13 @@ def _get_nlu_target_format(export_path: Text) -> Text:
901
901
 
902
902
  def _entities_from_messages(messages: List[Message]) -> List[Text]:
903
903
  """Return all entities that occur in at least one of the messages."""
904
- return list({e["entity"] for m in messages for e in m.data.get("entities", [])})
904
+ return list({e["entity"] for m in messages for e in m.data.get(ENTITIES, [])})
905
905
 
906
906
 
907
907
  def _intents_from_messages(messages: List[Message]) -> Set[Text]:
908
908
  """Return all intents that occur in at least one of the messages."""
909
909
  # set of distinct intents
910
- distinct_intents = {m.data["intent"] for m in messages if "intent" in m.data}
910
+ distinct_intents = {m.data[INTENT] for m in messages if INTENT in m.data}
911
911
 
912
912
  return distinct_intents
913
913
 
@@ -1191,11 +1191,11 @@ def _as_md_message(parse_data: Dict[Text, Any]) -> Text:
1191
1191
  """Display the parse data of a message in markdown format."""
1192
1192
  from rasa.shared.nlu.training_data.formats.readerwriter import TrainingDataWriter
1193
1193
 
1194
- if parse_data.get("text", "").startswith(INTENT_MESSAGE_PREFIX):
1195
- return parse_data["text"]
1194
+ if parse_data.get(TEXT, "").startswith(INTENT_MESSAGE_PREFIX):
1195
+ return parse_data[TEXT]
1196
1196
 
1197
- if not parse_data.get("entities"):
1198
- parse_data["entities"] = []
1197
+ if not parse_data.get(ENTITIES):
1198
+ parse_data[ENTITIES] = []
1199
1199
 
1200
1200
  return TrainingDataWriter.generate_message(parse_data)
1201
1201
 
@@ -1207,7 +1207,7 @@ def _validate_user_regex(latest_message: Dict[Text, Any], intents: List[Text]) -
1207
1207
  `/greet`. Return `True` if the intent is a known one.
1208
1208
  """
1209
1209
  parse_data = latest_message.get("parse_data", {})
1210
- intent = parse_data.get("intent", {}).get(INTENT_NAME_KEY)
1210
+ intent = parse_data.get(INTENT, {}).get(INTENT_NAME_KEY)
1211
1211
 
1212
1212
  if intent in intents:
1213
1213
  return True
@@ -1224,8 +1224,8 @@ async def _validate_user_text(
1224
1224
  """
1225
1225
  parse_data = latest_message.get("parse_data", {})
1226
1226
  text = _as_md_message(parse_data)
1227
- intent = parse_data.get("intent", {}).get(INTENT_NAME_KEY)
1228
- entities = parse_data.get("entities", [])
1227
+ intent = parse_data.get(INTENT, {}).get(INTENT_NAME_KEY)
1228
+ entities = parse_data.get(ENTITIES, [])
1229
1229
  if entities:
1230
1230
  message = (
1231
1231
  f"Is the intent '{intent}' correct for '{text}' and are "
@@ -1276,9 +1276,9 @@ async def _validate_nlu(
1276
1276
 
1277
1277
  entities = await _correct_entities(latest_message, endpoint, conversation_id)
1278
1278
  corrected_nlu = {
1279
- "intent": corrected_intent,
1280
- "entities": entities,
1281
- "text": latest_message.get("text"),
1279
+ INTENT: corrected_intent,
1280
+ ENTITIES: entities,
1281
+ TEXT: latest_message.get("text"),
1282
1282
  }
1283
1283
 
1284
1284
  await _correct_wrong_nlu(corrected_nlu, events, endpoint, conversation_id)
@@ -1315,9 +1315,9 @@ def _merge_annotated_and_original_entities(
1315
1315
  # overwrite entities which have already been
1316
1316
  # annotated in the original annotation to preserve
1317
1317
  # additional entity parser information
1318
- entities = parse_annotated.get("entities", [])[:]
1318
+ entities = parse_annotated.get(ENTITIES, [])[:]
1319
1319
  for i, entity in enumerate(entities):
1320
- for original_entity in parse_original.get("entities", []):
1320
+ for original_entity in parse_original.get(ENTITIES, []):
1321
1321
  if _is_same_entity_annotation(entity, original_entity):
1322
1322
  entities[i] = original_entity
1323
1323
  break
@@ -1687,7 +1687,9 @@ def run_interactive_learning(
1687
1687
  p = None
1688
1688
 
1689
1689
  app = run.configure_app(port=port, conversation_id="default", enable_api=True)
1690
- endpoints = AvailableEndpoints.get_instance(server_args.get("endpoints"))
1690
+ endpoints = Configuration.initialise_endpoints(
1691
+ endpoints_path=server_args.get("endpoints")
1692
+ ).endpoints
1691
1693
 
1692
1694
  # before_server_start handlers make sure the agent is loaded before the
1693
1695
  # interactive learning IO starts
@@ -14,7 +14,7 @@ from rasa.shared.core.constants import (
14
14
  from rasa.shared.core.domain import Domain, State
15
15
  from rasa.shared.core.events import ActionExecuted, Event
16
16
  from rasa.shared.core.generator import TrackerWithCachedStates
17
- from rasa.shared.nlu.constants import TEXT
17
+ from rasa.shared.nlu.constants import INTENT, TEXT
18
18
  from rasa.shared.nlu.training_data.message import Message
19
19
 
20
20
  logger = logging.getLogger(__name__)
@@ -362,12 +362,12 @@ def _get_previous_event(
362
362
  previous_event_type = "bot utterance"
363
363
  previous_event_name = state[PREVIOUS_ACTION]["action_text"]
364
364
  elif USER in state.keys():
365
- if "intent" in state[USER]:
365
+ if INTENT in state[USER]:
366
366
  previous_event_type = "intent"
367
- previous_event_name = state[USER]["intent"]
368
- elif "text" in state[USER]:
367
+ previous_event_name = state[USER][INTENT]
368
+ elif TEXT in state[USER]:
369
369
  previous_event_type = "user utterance"
370
- previous_event_name = state[USER]["text"]
370
+ previous_event_name = state[USER][TEXT]
371
371
 
372
372
  if not isinstance(previous_event_name, (str, type(None))):
373
373
  # While the Substate type doesn't restrict the value of `action_text` /
rasa/core/utils.py CHANGED
@@ -1,17 +1,16 @@
1
1
  import logging
2
2
  import os
3
+ import re
3
4
  from pathlib import Path
4
5
  from socket import SOCK_DGRAM, SOCK_STREAM
5
- from typing import TYPE_CHECKING, Any, Dict, Optional, Set, Text, Tuple, Union
6
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Text, Tuple, Union
6
7
 
7
8
  import numpy as np
8
9
  import structlog
9
10
  from sanic import Sanic
10
11
 
11
- import rasa.cli.utils as cli_utils
12
12
  import rasa.shared.utils.io
13
13
  from rasa.constants import DEFAULT_SANIC_WORKERS, ENV_SANIC_WORKERS
14
- from rasa.core.available_endpoints import AvailableEndpoints
15
14
  from rasa.core.constants import (
16
15
  ACTIVE_FLOW_METADATA_KEY,
17
16
  DOMAIN_GROUND_TRUTH_METADATA_KEY,
@@ -19,7 +18,7 @@ from rasa.core.constants import (
19
18
  UTTER_SOURCE_METADATA_KEY,
20
19
  )
21
20
  from rasa.core.lock_store import InMemoryLockStore, LockStore, RedisLockStore
22
- from rasa.shared.constants import DEFAULT_ENDPOINTS_PATH, TCP_PROTOCOL
21
+ from rasa.shared.constants import TCP_PROTOCOL
23
22
  from rasa.shared.core.constants import (
24
23
  SlotMappingType,
25
24
  )
@@ -37,25 +36,6 @@ if TYPE_CHECKING:
37
36
  structlogger = structlog.get_logger()
38
37
 
39
38
 
40
- def read_endpoints_from_path(
41
- endpoints_path: Optional[Union[Path, str]] = None,
42
- ) -> AvailableEndpoints:
43
- """Get `AvailableEndpoints` object from specified path.
44
-
45
- Args:
46
- endpoints_path: Path of the endpoints file to be read. If `None` the
47
- default path for that file is used (`endpoints.yml`).
48
-
49
- Returns:
50
- `AvailableEndpoints` object read from endpoints file.
51
-
52
- """
53
- endpoints_config_path = cli_utils.get_validated_path(
54
- endpoints_path, "endpoints", DEFAULT_ENDPOINTS_PATH, True
55
- )
56
- return AvailableEndpoints.get_instance(endpoints_config_path)
57
-
58
-
59
39
  def configure_file_logging(
60
40
  logger_obj: logging.Logger,
61
41
  log_file: Optional[Text],
@@ -359,3 +339,22 @@ def should_force_slot_filling(
359
339
  return True, slot_name
360
340
 
361
341
  return False, None
342
+
343
+
344
+ def get_slot_names_from_exit_conditions(exit_conditions: List[str]) -> List[str]:
345
+ """Extract slot names from exit conditions.
346
+
347
+ Args:
348
+ exit_conditions: The exit conditions to extract slot names from.
349
+
350
+ Returns:
351
+ A list of slot names.
352
+ """
353
+ # Find all unique names matching "slots.<name>"
354
+ return list(
355
+ {
356
+ name
357
+ for condition in exit_conditions
358
+ for name in re.findall(r"\bslots\.(\w+)", condition)
359
+ }
360
+ )
@@ -8,6 +8,9 @@ from rasa.dialogue_understanding.commands.chit_chat_answer_command import (
8
8
  )
9
9
  from rasa.dialogue_understanding.commands.clarify_command import ClarifyCommand
10
10
  from rasa.dialogue_understanding.commands.command import Command
11
+ from rasa.dialogue_understanding.commands.continue_agent_command import (
12
+ ContinueAgentCommand,
13
+ )
11
14
  from rasa.dialogue_understanding.commands.correct_slots_command import (
12
15
  CorrectedSlot,
13
16
  CorrectSlotsCommand,
@@ -29,6 +32,9 @@ from rasa.dialogue_understanding.commands.noop_command import NoopCommand
29
32
  from rasa.dialogue_understanding.commands.repeat_bot_messages_command import (
30
33
  RepeatBotMessagesCommand,
31
34
  )
35
+ from rasa.dialogue_understanding.commands.restart_agent_command import (
36
+ RestartAgentCommand,
37
+ )
32
38
  from rasa.dialogue_understanding.commands.restart_command import RestartCommand
33
39
  from rasa.dialogue_understanding.commands.session_end_command import SessionEndCommand
34
40
  from rasa.dialogue_understanding.commands.session_start_command import (
@@ -62,4 +68,6 @@ __all__ = [
62
68
  "SessionEndCommand",
63
69
  "RepeatBotMessagesCommand",
64
70
  "RestartCommand",
71
+ "ContinueAgentCommand",
72
+ "RestartAgentCommand",
65
73
  ]
@@ -6,6 +6,9 @@ from typing import Any, Dict, List
6
6
 
7
7
  import structlog
8
8
 
9
+ from rasa.core.policies.flows.agent_executor import (
10
+ remove_agent_stack_frame,
11
+ )
9
12
  from rasa.dialogue_understanding.commands.command import Command
10
13
  from rasa.dialogue_understanding.commands.command_syntax_manager import (
11
14
  CommandSyntaxManager,
@@ -18,7 +21,7 @@ from rasa.dialogue_understanding.stack.frames.flow_stack_frame import (
18
21
  UserFlowStackFrame,
19
22
  )
20
23
  from rasa.dialogue_understanding.stack.utils import top_user_flow_frame
21
- from rasa.shared.core.events import Event, FlowCancelled
24
+ from rasa.shared.core.events import AgentCancelled, Event, FlowCancelled
22
25
  from rasa.shared.core.flows import FlowsList
23
26
  from rasa.shared.core.trackers import DialogueStateTracker
24
27
 
@@ -48,8 +51,7 @@ class CancelFlowCommand(Command):
48
51
  """Selects the frames that were canceled.
49
52
 
50
53
  Args:
51
- dialogue_stack: The dialogue stack.
52
- current_flow: The current flow.
54
+ stack: The dialogue stack.
53
55
 
54
56
  Returns:
55
57
  The frames that were canceled.
@@ -71,8 +73,7 @@ class CancelFlowCommand(Command):
71
73
  # we should never get here as we should always find the user flow
72
74
  # that was canceled.
73
75
  raise ValueError(
74
- f"Could not find a user flow frame to cancel. "
75
- f"Current stack: {stack}."
76
+ f"Could not find a user flow frame to cancel. Current stack: {stack}."
76
77
  )
77
78
 
78
79
  def run_command_on_tracker(
@@ -106,6 +107,19 @@ class CancelFlowCommand(Command):
106
107
  )
107
108
  return []
108
109
 
110
+ if agent_frame := original_tracker.stack.find_active_agent_stack_frame_for_flow(
111
+ current_flow.id
112
+ ):
113
+ structlogger.debug(
114
+ "cancel_command.remove_agent_stack_frame",
115
+ command=self,
116
+ frame=agent_frame,
117
+ )
118
+ remove_agent_stack_frame(stack, agent_frame.agent_id)
119
+ applied_events.append(
120
+ AgentCancelled(agent_id=agent_frame.agent_id, flow_id=current_flow.id)
121
+ )
122
+
109
123
  # we pass in the original dialogue stack (before any of the currently
110
124
  # predicted commands were applied) to make sure we don't cancel any
111
125
  # frames that were added by the currently predicted commands.
@@ -12,7 +12,11 @@ from rasa.dialogue_understanding.commands.free_form_answer_command import (
12
12
  FreeFormAnswerCommand,
13
13
  )
14
14
  from rasa.dialogue_understanding.patterns.chitchat import ChitchatPatternFlowStackFrame
15
- from rasa.shared.core.events import Event
15
+ from rasa.dialogue_understanding.stack.frames.flow_stack_frame import (
16
+ AgentStackFrame,
17
+ AgentState,
18
+ )
19
+ from rasa.shared.core.events import AgentInterrupted, Event
16
20
  from rasa.shared.core.flows import FlowsList
17
21
  from rasa.shared.core.trackers import DialogueStateTracker
18
22
 
@@ -52,8 +56,23 @@ class ChitChatAnswerCommand(FreeFormAnswerCommand):
52
56
  The events to apply to the tracker.
53
57
  """
54
58
  stack = tracker.stack
59
+
60
+ applied_events: List[Event] = []
61
+
62
+ # if the top stack frame is an agent stack frame, we need to
63
+ # update the state to INTERRUPTED and add an AgentInterrupted event
64
+ if top_stack_frame := stack.top():
65
+ if isinstance(top_stack_frame, AgentStackFrame):
66
+ applied_events.append(
67
+ AgentInterrupted(
68
+ top_stack_frame.agent_id,
69
+ top_stack_frame.flow_id,
70
+ )
71
+ )
72
+ top_stack_frame.state = AgentState.INTERRUPTED
73
+
55
74
  stack.push(ChitchatPatternFlowStackFrame())
56
- return tracker.create_stack_updated_events(stack)
75
+ return applied_events + tracker.create_stack_updated_events(stack)
57
76
 
58
77
  def __hash__(self) -> int:
59
78
  return hash(self.command())
@@ -13,7 +13,11 @@ from rasa.dialogue_understanding.commands.command_syntax_manager import (
13
13
  )
14
14
  from rasa.dialogue_understanding.commands.utils import extract_cleaned_options
15
15
  from rasa.dialogue_understanding.patterns.clarify import ClarifyPatternFlowStackFrame
16
- from rasa.shared.core.events import Event
16
+ from rasa.dialogue_understanding.stack.frames.flow_stack_frame import (
17
+ AgentStackFrame,
18
+ AgentState,
19
+ )
20
+ from rasa.shared.core.events import AgentInterrupted, Event
17
21
  from rasa.shared.core.flows import FlowsList
18
22
  from rasa.shared.core.trackers import DialogueStateTracker
19
23
 
@@ -85,8 +89,22 @@ class ClarifyCommand(Command):
85
89
  if flow is not None
86
90
  ]
87
91
 
92
+ applied_events: List[Event] = []
93
+
94
+ # if the top stack frame is an agent stack frame, we need to
95
+ # update the state to INTERRUPTED and add an AgentInterrupted event
96
+ if top_stack_frame := stack.top():
97
+ if isinstance(top_stack_frame, AgentStackFrame):
98
+ applied_events.append(
99
+ AgentInterrupted(
100
+ top_stack_frame.agent_id,
101
+ top_stack_frame.flow_id,
102
+ )
103
+ )
104
+ top_stack_frame.state = AgentState.INTERRUPTED
105
+
88
106
  stack.push(ClarifyPatternFlowStackFrame(names=names))
89
- return tracker.create_stack_updated_events(stack)
107
+ return applied_events + tracker.create_stack_updated_events(stack)
90
108
 
91
109
  def __hash__(self) -> int:
92
110
  return hash(tuple(self.options))
@@ -0,0 +1,91 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from dataclasses import dataclass
5
+ from typing import Any, Dict, List
6
+
7
+ import structlog
8
+
9
+ from rasa.dialogue_understanding.commands.command import Command
10
+ from rasa.dialogue_understanding.commands.command_syntax_manager import (
11
+ CommandSyntaxManager,
12
+ CommandSyntaxVersion,
13
+ )
14
+ from rasa.shared.core.events import Event
15
+ from rasa.shared.core.flows import FlowsList
16
+ from rasa.shared.core.trackers import DialogueStateTracker
17
+
18
+ structlogger = structlog.get_logger()
19
+
20
+
21
+ @dataclass
22
+ class ContinueAgentCommand(Command):
23
+ """A command to continue the currently active agent's execution."""
24
+
25
+ @classmethod
26
+ def command(cls) -> str:
27
+ """Returns the command type."""
28
+ return "continue agent"
29
+
30
+ @classmethod
31
+ def from_dict(cls, data: Dict[str, Any]) -> ContinueAgentCommand:
32
+ """Converts the dictionary to a command.
33
+
34
+ Returns:
35
+ The converted dictionary.
36
+ """
37
+ return ContinueAgentCommand()
38
+
39
+ def run_command_on_tracker(
40
+ self,
41
+ tracker: DialogueStateTracker,
42
+ all_flows: FlowsList,
43
+ original_tracker: DialogueStateTracker,
44
+ ) -> List[Event]:
45
+ """Runs the command on the tracker.
46
+
47
+ Args:
48
+ tracker: The tracker to run the command on.
49
+ all_flows: All flows in the assistant.
50
+ original_tracker: The tracker before any command was executed.
51
+
52
+ Returns:
53
+ The events to apply to the tracker.
54
+ """
55
+ # do nothing
56
+ return []
57
+
58
+ def __hash__(self) -> int:
59
+ return hash(self.command())
60
+
61
+ def __eq__(self, other: object) -> bool:
62
+ return isinstance(other, ContinueAgentCommand)
63
+
64
+ def to_dsl(self) -> str:
65
+ """Converts the command to a DSL string."""
66
+ mapper = {
67
+ CommandSyntaxVersion.v1: "ContinueAgent()",
68
+ CommandSyntaxVersion.v2: "continue agent",
69
+ CommandSyntaxVersion.v3: "continue agent",
70
+ }
71
+ return mapper.get(
72
+ CommandSyntaxManager.get_syntax_version(),
73
+ mapper[CommandSyntaxManager.get_default_syntax_version()],
74
+ )
75
+
76
+ @classmethod
77
+ def from_dsl(cls, match: re.Match, **kwargs: Any) -> ContinueAgentCommand:
78
+ """Converts a DSL string to a command."""
79
+ return ContinueAgentCommand()
80
+
81
+ @staticmethod
82
+ def regex_pattern() -> str:
83
+ mapper = {
84
+ CommandSyntaxVersion.v1: r"ContinueAgent\(\)",
85
+ CommandSyntaxVersion.v2: r"""^[\s\W\d]*continue agent['"`]*$""",
86
+ CommandSyntaxVersion.v3: r"""^[\s\W\d]*continue agent['"`]*$""",
87
+ }
88
+ return mapper.get(
89
+ CommandSyntaxManager.get_syntax_version(),
90
+ mapper[CommandSyntaxManager.get_default_syntax_version()],
91
+ )