rasa-pro 3.12.0.dev2__py3-none-any.whl → 3.12.0.dev3__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 (502) hide show
  1. rasa/__main__.py +7 -7
  2. rasa/anonymization/anonymisation_rule_yaml_reader.py +1 -1
  3. rasa/anonymization/anonymization_pipeline.py +3 -3
  4. rasa/anonymization/anonymization_rule_executor.py +1 -1
  5. rasa/anonymization/anonymization_rule_orchestrator.py +2 -3
  6. rasa/cli/arguments/data.py +2 -2
  7. rasa/cli/arguments/evaluate.py +2 -1
  8. rasa/cli/arguments/interactive.py +1 -1
  9. rasa/cli/arguments/run.py +1 -1
  10. rasa/cli/arguments/test.py +7 -5
  11. rasa/cli/arguments/train.py +3 -3
  12. rasa/cli/arguments/visualize.py +2 -2
  13. rasa/cli/arguments/x.py +1 -0
  14. rasa/cli/data.py +4 -3
  15. rasa/cli/dialogue_understanding_test.py +116 -18
  16. rasa/cli/evaluate.py +1 -1
  17. rasa/cli/export.py +6 -6
  18. rasa/cli/interactive.py +4 -5
  19. rasa/cli/llm_fine_tuning.py +5 -5
  20. rasa/cli/markers.py +1 -2
  21. rasa/cli/project_templates/calm/actions/add_contact.py +1 -1
  22. rasa/cli/project_templates/tutorial/actions/actions.py +3 -2
  23. rasa/cli/shell.py +2 -3
  24. rasa/cli/studio/download.py +1 -2
  25. rasa/cli/studio/studio.py +2 -3
  26. rasa/cli/studio/train.py +0 -1
  27. rasa/cli/telemetry.py +2 -2
  28. rasa/cli/test.py +11 -11
  29. rasa/cli/utils.py +7 -5
  30. rasa/core/__init__.py +0 -1
  31. rasa/core/actions/action.py +42 -21
  32. rasa/core/actions/action_hangup.py +1 -1
  33. rasa/core/actions/action_repeat_bot_messages.py +2 -2
  34. rasa/core/actions/action_run_slot_rejections.py +2 -2
  35. rasa/core/actions/action_trigger_chitchat.py +1 -1
  36. rasa/core/actions/action_trigger_flow.py +5 -5
  37. rasa/core/actions/action_trigger_search.py +1 -1
  38. rasa/core/actions/forms.py +14 -12
  39. rasa/core/actions/http_custom_action_executor.py +8 -1
  40. rasa/core/actions/loops.py +3 -3
  41. rasa/core/actions/two_stage_fallback.py +13 -13
  42. rasa/core/auth_retry_tracker_store.py +1 -2
  43. rasa/core/brokers/broker.py +2 -1
  44. rasa/core/brokers/file.py +1 -1
  45. rasa/core/brokers/kafka.py +8 -8
  46. rasa/core/brokers/pika.py +8 -9
  47. rasa/core/brokers/sql.py +4 -3
  48. rasa/core/channels/__init__.py +3 -0
  49. rasa/core/channels/botframework.py +2 -2
  50. rasa/core/channels/callback.py +4 -4
  51. rasa/core/channels/channel.py +11 -11
  52. rasa/core/channels/console.py +0 -1
  53. rasa/core/channels/development_inspector.py +6 -6
  54. rasa/core/channels/facebook.py +5 -5
  55. rasa/core/channels/hangouts.py +7 -8
  56. rasa/core/channels/inspector/dist/assets/{arc-861ddd57.js → arc-632a63ec.js} +1 -1
  57. rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-921f02db.js → c4Diagram-d0fbc5ce-081e0df4.js} +1 -1
  58. rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-b436c4f8.js → classDiagram-936ed81e-3df0afc2.js} +1 -1
  59. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-511a23cb.js → classDiagram-v2-c3cb15f1-8c5ed31e.js} +1 -1
  60. rasa/core/channels/inspector/dist/assets/{createText-62fc7601-ef476ecd.js → createText-62fc7601-89c73b31.js} +1 -1
  61. rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-f1878e0a.js → edges-f2ad444c-4fc48c3e.js} +1 -1
  62. rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-fac75185.js → erDiagram-9d236eb7-907e0440.js} +1 -1
  63. rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-201c5bbc.js → flowDb-1972c806-9ec53a3c.js} +1 -1
  64. rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-f904ae41.js → flowDiagram-7ea5b25a-41da787a.js} +1 -1
  65. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-8bea338b.js +1 -0
  66. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-1813da66.js → flowchart-elk-definition-abe16c3d-ce370633.js} +1 -1
  67. rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-872af172.js → ganttDiagram-9b5ea136-90a36523.js} +1 -1
  68. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-34a0af5a.js → gitGraphDiagram-99d0ae7c-41e1aa3f.js} +1 -1
  69. rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-42ba3e3d.js → index-2c4b9a3b-e6f2af62.js} +1 -1
  70. rasa/core/channels/inspector/dist/assets/{index-37817b51.js → index-e793d777.js} +3 -3
  71. rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-6b731386.js → infoDiagram-736b4530-8ceba4db.js} +1 -1
  72. rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-e8579ac6.js → journeyDiagram-df861f2b-960d3809.js} +1 -1
  73. rasa/core/channels/inspector/dist/assets/{layout-89e6403a.js → layout-498807d8.js} +1 -1
  74. rasa/core/channels/inspector/dist/assets/{line-dc73d3fc.js → line-eeccc4e2.js} +1 -1
  75. rasa/core/channels/inspector/dist/assets/{linear-f5b1d2bc.js → linear-8a078617.js} +1 -1
  76. rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-82cb74fa.js → mindmap-definition-beec6740-396d17dd.js} +1 -1
  77. rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-bdf5f29b.js → pieDiagram-dbbf0591-dc9b5e1b.js} +1 -1
  78. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-c7a0cbe4.js → quadrantDiagram-4d7f4fd6-a08cba6d.js} +1 -1
  79. rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-7ec5410f.js → requirementDiagram-6fc4c22a-87242b9e.js} +1 -1
  80. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-caee5554.js → sankeyDiagram-8f13d901-53f6f391.js} +1 -1
  81. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-2935f8db.js → sequenceDiagram-b655622a-715c9c20.js} +1 -1
  82. rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-8f5d9693.js → stateDiagram-59f0c015-2e8fb31f.js} +1 -1
  83. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-d565d1de.js → stateDiagram-v2-2b26beab-7e2d2aa0.js} +1 -1
  84. rasa/core/channels/inspector/dist/assets/{styles-080da4f6-75ad421d.js → styles-080da4f6-4420cea6.js} +1 -1
  85. rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-7e764226.js → styles-3dcbcfbf-28676cf4.js} +1 -1
  86. rasa/core/channels/inspector/dist/assets/{styles-9c745c82-7a4e0e61.js → styles-9c745c82-cef936a6.js} +1 -1
  87. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-4019d1bf.js → svgDrawCommon-4835440b-151251e9.js} +1 -1
  88. rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-01ea12df.js → timeline-definition-5b62e21b-0d39bdb2.js} +1 -1
  89. rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-89407137.js → xychartDiagram-2b33534f-a03fa445.js} +1 -1
  90. rasa/core/channels/inspector/dist/index.html +3 -1
  91. rasa/core/channels/inspector/index.html +2 -0
  92. rasa/core/channels/inspector/src/App.tsx +1 -4
  93. rasa/core/channels/mattermost.py +4 -4
  94. rasa/core/channels/rasa_chat.py +4 -4
  95. rasa/core/channels/rest.py +11 -12
  96. rasa/core/channels/rocketchat.py +4 -3
  97. rasa/core/channels/slack.py +6 -5
  98. rasa/core/channels/socketio.py +7 -28
  99. rasa/core/channels/studio_chat.py +193 -0
  100. rasa/core/channels/telegram.py +73 -41
  101. rasa/core/channels/twilio.py +3 -3
  102. rasa/core/channels/vier_cvg.py +2 -2
  103. rasa/core/channels/voice_ready/audiocodes.py +8 -8
  104. rasa/core/channels/voice_ready/jambonz.py +5 -5
  105. rasa/core/channels/voice_ready/jambonz_protocol.py +3 -4
  106. rasa/core/channels/voice_ready/twilio_voice.py +9 -8
  107. rasa/core/channels/voice_ready/utils.py +1 -1
  108. rasa/core/channels/voice_stream/asr/asr_engine.py +2 -2
  109. rasa/core/channels/voice_stream/asr/azure.py +2 -2
  110. rasa/core/channels/voice_stream/asr/deepgram.py +57 -16
  111. rasa/core/channels/voice_stream/browser_audio.py +9 -6
  112. rasa/core/channels/voice_stream/call_state.py +2 -1
  113. rasa/core/channels/voice_stream/tts/azure.py +1 -2
  114. rasa/core/channels/voice_stream/tts/cartesia.py +5 -4
  115. rasa/core/channels/voice_stream/tts/tts_cache.py +3 -2
  116. rasa/core/channels/voice_stream/tts/tts_engine.py +1 -1
  117. rasa/core/channels/voice_stream/twilio_media_streams.py +10 -7
  118. rasa/core/channels/voice_stream/util.py +1 -1
  119. rasa/core/channels/voice_stream/voice_channel.py +15 -15
  120. rasa/core/channels/webexteams.py +3 -4
  121. rasa/core/evaluation/marker.py +7 -6
  122. rasa/core/evaluation/marker_base.py +15 -16
  123. rasa/core/evaluation/marker_stats.py +3 -4
  124. rasa/core/evaluation/marker_tracker_loader.py +5 -4
  125. rasa/core/exporter.py +4 -4
  126. rasa/core/featurizers/precomputation.py +8 -8
  127. rasa/core/featurizers/single_state_featurizer.py +7 -7
  128. rasa/core/featurizers/tracker_featurizers.py +13 -13
  129. rasa/core/http_interpreter.py +3 -4
  130. rasa/core/information_retrieval/__init__.py +1 -1
  131. rasa/core/information_retrieval/faiss.py +4 -4
  132. rasa/core/information_retrieval/information_retrieval.py +2 -2
  133. rasa/core/information_retrieval/milvus.py +3 -3
  134. rasa/core/information_retrieval/qdrant.py +3 -3
  135. rasa/core/jobs.py +1 -0
  136. rasa/core/lock.py +2 -3
  137. rasa/core/lock_store.py +3 -3
  138. rasa/core/migrate.py +11 -8
  139. rasa/core/nlg/__init__.py +1 -1
  140. rasa/core/nlg/callback.py +2 -3
  141. rasa/core/nlg/contextual_response_rephraser.py +63 -13
  142. rasa/core/nlg/generator.py +2 -2
  143. rasa/core/nlg/interpolator.py +4 -3
  144. rasa/core/nlg/response.py +3 -4
  145. rasa/core/nlg/summarize.py +1 -0
  146. rasa/core/persistor.py +3 -3
  147. rasa/core/policies/ensemble.py +10 -9
  148. rasa/core/policies/enterprise_search_policy.py +86 -21
  149. rasa/core/policies/flow_policy.py +13 -14
  150. rasa/core/policies/flows/flow_executor.py +35 -11
  151. rasa/core/policies/intentless_policy.py +6 -7
  152. rasa/core/policies/memoization.py +22 -20
  153. rasa/core/policies/policy.py +24 -22
  154. rasa/core/policies/rule_policy.py +37 -36
  155. rasa/core/policies/ted_policy.py +87 -85
  156. rasa/core/policies/unexpected_intent_policy.py +77 -75
  157. rasa/core/processor.py +96 -65
  158. rasa/core/run.py +1 -1
  159. rasa/core/secrets_manager/endpoints.py +2 -3
  160. rasa/core/secrets_manager/factory.py +2 -3
  161. rasa/core/secrets_manager/secret_manager.py +2 -3
  162. rasa/core/secrets_manager/vault.py +2 -2
  163. rasa/core/test.py +30 -30
  164. rasa/core/tracker_store.py +15 -15
  165. rasa/core/train.py +1 -1
  166. rasa/core/training/__init__.py +2 -2
  167. rasa/core/training/converters/responses_prefix_converter.py +1 -2
  168. rasa/core/training/interactive.py +13 -13
  169. rasa/core/training/story_conflict.py +4 -5
  170. rasa/core/training/training.py +3 -5
  171. rasa/core/utils.py +5 -5
  172. rasa/core/visualize.py +1 -1
  173. rasa/dialogue_understanding/coexistence/intent_based_router.py +2 -2
  174. rasa/dialogue_understanding/coexistence/llm_based_router.py +5 -5
  175. rasa/dialogue_understanding/commands/__init__.py +22 -22
  176. rasa/dialogue_understanding/commands/can_not_handle_command.py +20 -1
  177. rasa/dialogue_understanding/commands/cancel_flow_command.py +18 -7
  178. rasa/dialogue_understanding/commands/change_flow_command.py +18 -2
  179. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +18 -4
  180. rasa/dialogue_understanding/commands/clarify_command.py +19 -3
  181. rasa/dialogue_understanding/commands/command.py +19 -3
  182. rasa/dialogue_understanding/commands/correct_slots_command.py +3 -3
  183. rasa/dialogue_understanding/commands/error_command.py +1 -1
  184. rasa/dialogue_understanding/commands/free_form_answer_command.py +2 -1
  185. rasa/dialogue_understanding/commands/handle_code_change_command.py +2 -2
  186. rasa/dialogue_understanding/commands/human_handoff_command.py +16 -4
  187. rasa/dialogue_understanding/commands/knowledge_answer_command.py +18 -4
  188. rasa/dialogue_understanding/commands/noop_command.py +2 -1
  189. rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +16 -4
  190. rasa/dialogue_understanding/commands/restart_command.py +2 -5
  191. rasa/dialogue_understanding/commands/session_end_command.py +3 -5
  192. rasa/dialogue_understanding/commands/session_start_command.py +3 -5
  193. rasa/dialogue_understanding/commands/set_slot_command.py +27 -3
  194. rasa/dialogue_understanding/commands/skip_question_command.py +16 -4
  195. rasa/dialogue_understanding/commands/start_flow_command.py +17 -2
  196. rasa/dialogue_understanding/commands/user_silence_command.py +3 -5
  197. rasa/dialogue_understanding/commands/utils.py +64 -45
  198. rasa/dialogue_understanding/constants.py +1 -0
  199. rasa/dialogue_understanding/generator/command_generator.py +2 -119
  200. rasa/dialogue_understanding/generator/command_parser.py +201 -0
  201. rasa/dialogue_understanding/generator/constants.py +2 -2
  202. rasa/dialogue_understanding/generator/flow_retrieval.py +7 -7
  203. rasa/dialogue_understanding/generator/llm_based_command_generator.py +11 -57
  204. rasa/dialogue_understanding/generator/llm_command_generator.py +2 -1
  205. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +67 -120
  206. rasa/dialogue_understanding/generator/nlu_command_adapter.py +8 -10
  207. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +32 -93
  208. rasa/dialogue_understanding/generator/utils.py +45 -0
  209. rasa/dialogue_understanding/patterns/cancel.py +2 -1
  210. rasa/dialogue_understanding/patterns/cannot_handle.py +1 -0
  211. rasa/dialogue_understanding/patterns/chitchat.py +1 -1
  212. rasa/dialogue_understanding/patterns/clarify.py +2 -1
  213. rasa/dialogue_understanding/patterns/code_change.py +2 -0
  214. rasa/dialogue_understanding/patterns/collect_information.py +6 -3
  215. rasa/dialogue_understanding/patterns/completed.py +1 -1
  216. rasa/dialogue_understanding/patterns/continue_interrupted.py +10 -1
  217. rasa/dialogue_understanding/patterns/correction.py +4 -2
  218. rasa/dialogue_understanding/patterns/human_handoff.py +1 -1
  219. rasa/dialogue_understanding/patterns/internal_error.py +1 -0
  220. rasa/dialogue_understanding/patterns/search.py +1 -1
  221. rasa/dialogue_understanding/patterns/session_start.py +1 -1
  222. rasa/dialogue_understanding/patterns/skip_question.py +1 -0
  223. rasa/dialogue_understanding/patterns/user_silence.py +1 -1
  224. rasa/dialogue_understanding/processor/command_processor.py +13 -9
  225. rasa/dialogue_understanding/processor/command_processor_component.py +1 -1
  226. rasa/dialogue_understanding/stack/dialogue_stack.py +4 -3
  227. rasa/dialogue_understanding/stack/frames/__init__.py +2 -2
  228. rasa/dialogue_understanding/stack/frames/chit_chat_frame.py +4 -1
  229. rasa/dialogue_understanding/stack/frames/dialogue_stack_frame.py +2 -3
  230. rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +5 -2
  231. rasa/dialogue_understanding/stack/frames/search_frame.py +4 -1
  232. rasa/dialogue_understanding/stack/utils.py +8 -4
  233. rasa/dialogue_understanding/utils.py +121 -2
  234. rasa/dialogue_understanding_test/README.md +379 -0
  235. rasa/dialogue_understanding_test/command_comparison.py +60 -0
  236. rasa/dialogue_understanding_test/command_metric_calculation.py +110 -4
  237. rasa/dialogue_understanding_test/constants.py +6 -1
  238. rasa/dialogue_understanding_test/du_test_case.py +252 -38
  239. rasa/dialogue_understanding_test/du_test_result.py +281 -2
  240. rasa/dialogue_understanding_test/du_test_runner.py +239 -10
  241. rasa/dialogue_understanding_test/du_test_schema.yml +161 -0
  242. rasa/dialogue_understanding_test/io.py +338 -20
  243. rasa/dialogue_understanding_test/test_case_simulation/__init__.py +0 -0
  244. rasa/dialogue_understanding_test/test_case_simulation/exception.py +28 -0
  245. rasa/dialogue_understanding_test/test_case_simulation/test_case_tracker_simulator.py +336 -0
  246. rasa/dialogue_understanding_test/utils.py +70 -0
  247. rasa/dialogue_understanding_test/validation.py +59 -4
  248. rasa/e2e_test/aggregate_test_stats_calculator.py +1 -1
  249. rasa/e2e_test/assertions.py +1 -1
  250. rasa/e2e_test/e2e_config.py +1 -1
  251. rasa/e2e_test/e2e_test_case.py +3 -4
  252. rasa/e2e_test/e2e_test_converter.py +2 -3
  253. rasa/e2e_test/e2e_test_coverage_report.py +6 -6
  254. rasa/e2e_test/e2e_test_result.py +1 -1
  255. rasa/e2e_test/e2e_test_runner.py +134 -31
  256. rasa/e2e_test/stub_custom_action.py +1 -1
  257. rasa/e2e_test/utils/e2e_yaml_utils.py +1 -1
  258. rasa/e2e_test/utils/io.py +132 -65
  259. rasa/e2e_test/utils/validation.py +1 -1
  260. rasa/engine/caching.py +5 -7
  261. rasa/engine/constants.py +1 -1
  262. rasa/engine/graph.py +2 -2
  263. rasa/engine/recipes/default_components.py +13 -15
  264. rasa/engine/recipes/recipe.py +2 -2
  265. rasa/engine/runner/dask.py +2 -2
  266. rasa/engine/runner/interface.py +1 -0
  267. rasa/engine/storage/local_model_storage.py +5 -4
  268. rasa/engine/storage/resource.py +2 -1
  269. rasa/engine/storage/storage.py +5 -3
  270. rasa/engine/training/components.py +2 -1
  271. rasa/engine/training/fingerprinting.py +4 -2
  272. rasa/engine/training/graph_trainer.py +4 -4
  273. rasa/engine/training/hooks.py +2 -2
  274. rasa/engine/validation.py +34 -33
  275. rasa/exceptions.py +3 -2
  276. rasa/graph_components/converters/nlu_message_converter.py +3 -3
  277. rasa/graph_components/providers/domain_for_core_training_provider.py +3 -3
  278. rasa/graph_components/providers/domain_provider.py +3 -2
  279. rasa/graph_components/providers/flows_provider.py +2 -3
  280. rasa/graph_components/providers/forms_provider.py +4 -4
  281. rasa/graph_components/providers/nlu_training_data_provider.py +5 -3
  282. rasa/graph_components/providers/responses_provider.py +4 -4
  283. rasa/graph_components/providers/rule_only_provider.py +3 -2
  284. rasa/graph_components/providers/story_graph_provider.py +8 -8
  285. rasa/graph_components/providers/training_tracker_provider.py +3 -2
  286. rasa/graph_components/validators/default_recipe_validator.py +16 -16
  287. rasa/graph_components/validators/finetuning_validator.py +10 -8
  288. rasa/hooks.py +18 -12
  289. rasa/jupyter.py +2 -2
  290. rasa/llm_fine_tuning/annotation_module.py +4 -4
  291. rasa/llm_fine_tuning/conversations.py +6 -6
  292. rasa/llm_fine_tuning/llm_data_preparation_module.py +1 -1
  293. rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +4 -4
  294. rasa/llm_fine_tuning/paraphrasing/rephrase_validator.py +1 -1
  295. rasa/llm_fine_tuning/paraphrasing_module.py +1 -1
  296. rasa/llm_fine_tuning/storage.py +3 -3
  297. rasa/markers/marker.py +2 -3
  298. rasa/markers/marker_base.py +1 -2
  299. rasa/markers/upload.py +2 -2
  300. rasa/markers/validate.py +2 -3
  301. rasa/model.py +3 -5
  302. rasa/model_manager/config.py +1 -1
  303. rasa/model_manager/model_api.py +5 -4
  304. rasa/model_manager/runner_service.py +6 -6
  305. rasa/model_manager/socket_bridge.py +8 -3
  306. rasa/model_manager/studio_jwt_auth.py +1 -0
  307. rasa/model_manager/trainer_service.py +9 -7
  308. rasa/model_manager/utils.py +1 -1
  309. rasa/model_manager/warm_rasa_process.py +14 -8
  310. rasa/model_service.py +5 -6
  311. rasa/model_testing.py +13 -15
  312. rasa/nlu/classifiers/diet_classifier.py +72 -73
  313. rasa/nlu/classifiers/fallback_classifier.py +9 -8
  314. rasa/nlu/classifiers/keyword_intent_classifier.py +7 -6
  315. rasa/nlu/classifiers/logistic_regression_classifier.py +3 -3
  316. rasa/nlu/classifiers/mitie_intent_classifier.py +5 -4
  317. rasa/nlu/classifiers/regex_message_handler.py +3 -2
  318. rasa/nlu/classifiers/sklearn_intent_classifier.py +2 -2
  319. rasa/nlu/convert.py +2 -2
  320. rasa/nlu/emulators/dialogflow.py +3 -3
  321. rasa/nlu/emulators/luis.py +5 -5
  322. rasa/nlu/emulators/no_emulator.py +1 -0
  323. rasa/nlu/emulators/wit.py +4 -4
  324. rasa/nlu/extractors/crf_entity_extractor.py +11 -11
  325. rasa/nlu/extractors/duckling_entity_extractor.py +7 -6
  326. rasa/nlu/extractors/entity_synonyms.py +10 -9
  327. rasa/nlu/extractors/extractor.py +16 -16
  328. rasa/nlu/extractors/mitie_entity_extractor.py +10 -9
  329. rasa/nlu/extractors/regex_entity_extractor.py +11 -10
  330. rasa/nlu/extractors/spacy_entity_extractor.py +2 -2
  331. rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +15 -14
  332. rasa/nlu/featurizers/dense_featurizer/dense_featurizer.py +2 -1
  333. rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +10 -9
  334. rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +9 -7
  335. rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +13 -12
  336. rasa/nlu/featurizers/featurizer.py +5 -4
  337. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +6 -6
  338. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +4 -4
  339. rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +4 -4
  340. rasa/nlu/featurizers/sparse_featurizer/sparse_featurizer.py +2 -0
  341. rasa/nlu/model.py +0 -1
  342. rasa/nlu/selectors/response_selector.py +67 -68
  343. rasa/nlu/test.py +38 -38
  344. rasa/nlu/tokenizers/jieba_tokenizer.py +1 -2
  345. rasa/nlu/tokenizers/mitie_tokenizer.py +2 -2
  346. rasa/nlu/tokenizers/spacy_tokenizer.py +3 -3
  347. rasa/nlu/tokenizers/tokenizer.py +6 -7
  348. rasa/nlu/tokenizers/whitespace_tokenizer.py +1 -1
  349. rasa/nlu/utils/bilou_utils.py +7 -7
  350. rasa/nlu/utils/hugging_face/registry.py +22 -22
  351. rasa/nlu/utils/hugging_face/transformers_pre_post_processors.py +2 -1
  352. rasa/nlu/utils/mitie_utils.py +2 -1
  353. rasa/nlu/utils/pattern_utils.py +1 -1
  354. rasa/nlu/utils/spacy_utils.py +3 -3
  355. rasa/plugin.py +12 -1
  356. rasa/server.py +37 -1
  357. rasa/shared/constants.py +22 -2
  358. rasa/shared/core/command_payload_reader.py +15 -7
  359. rasa/shared/core/constants.py +4 -1
  360. rasa/shared/core/conversation.py +1 -2
  361. rasa/shared/core/events.py +47 -37
  362. rasa/shared/core/flows/__init__.py +0 -1
  363. rasa/shared/core/flows/flow.py +11 -11
  364. rasa/shared/core/flows/flow_step.py +19 -13
  365. rasa/shared/core/flows/flow_step_links.py +21 -14
  366. rasa/shared/core/flows/flow_step_sequence.py +6 -4
  367. rasa/shared/core/flows/flows_list.py +3 -3
  368. rasa/shared/core/flows/nlu_trigger.py +1 -1
  369. rasa/shared/core/flows/steps/__init__.py +2 -2
  370. rasa/shared/core/flows/steps/action.py +4 -3
  371. rasa/shared/core/flows/steps/call.py +4 -4
  372. rasa/shared/core/flows/steps/collect.py +7 -4
  373. rasa/shared/core/flows/steps/continuation.py +3 -1
  374. rasa/shared/core/flows/steps/end.py +3 -1
  375. rasa/shared/core/flows/steps/internal.py +3 -2
  376. rasa/shared/core/flows/steps/link.py +6 -4
  377. rasa/shared/core/flows/steps/no_operation.py +7 -5
  378. rasa/shared/core/flows/steps/set_slots.py +4 -3
  379. rasa/shared/core/flows/steps/start.py +3 -1
  380. rasa/shared/core/flows/utils.py +1 -0
  381. rasa/shared/core/flows/validation.py +3 -5
  382. rasa/shared/core/generator.py +20 -21
  383. rasa/shared/core/slot_mappings.py +15 -15
  384. rasa/shared/core/slots.py +3 -3
  385. rasa/shared/core/trackers.py +31 -31
  386. rasa/shared/core/training_data/loading.py +1 -1
  387. rasa/shared/core/training_data/story_reader/story_reader.py +3 -3
  388. rasa/shared/core/training_data/story_reader/story_step_builder.py +4 -4
  389. rasa/shared/core/training_data/story_reader/yaml_story_reader.py +29 -31
  390. rasa/shared/core/training_data/story_writer/yaml_story_writer.py +22 -24
  391. rasa/shared/core/training_data/structures.py +11 -12
  392. rasa/shared/core/training_data/visualization.py +10 -10
  393. rasa/shared/data.py +6 -6
  394. rasa/shared/engine/caching.py +0 -1
  395. rasa/shared/exceptions.py +2 -2
  396. rasa/shared/importers/rasa.py +5 -6
  397. rasa/shared/importers/utils.py +1 -1
  398. rasa/shared/nlu/constants.py +3 -0
  399. rasa/shared/nlu/training_data/entities_parser.py +6 -6
  400. rasa/shared/nlu/training_data/features.py +3 -3
  401. rasa/shared/nlu/training_data/formats/__init__.py +1 -1
  402. rasa/shared/nlu/training_data/formats/dialogflow.py +4 -5
  403. rasa/shared/nlu/training_data/formats/luis.py +7 -8
  404. rasa/shared/nlu/training_data/formats/rasa.py +4 -5
  405. rasa/shared/nlu/training_data/formats/rasa_yaml.py +17 -16
  406. rasa/shared/nlu/training_data/formats/readerwriter.py +8 -11
  407. rasa/shared/nlu/training_data/formats/wit.py +3 -4
  408. rasa/shared/nlu/training_data/loading.py +4 -4
  409. rasa/shared/nlu/training_data/lookup_tables_parser.py +1 -1
  410. rasa/shared/nlu/training_data/message.py +13 -14
  411. rasa/shared/nlu/training_data/schemas/data_schema.py +1 -1
  412. rasa/shared/nlu/training_data/schemas/responses.yml +1 -0
  413. rasa/shared/nlu/training_data/synonyms_parser.py +3 -3
  414. rasa/shared/nlu/training_data/training_data.py +12 -13
  415. rasa/shared/nlu/training_data/util.py +11 -10
  416. rasa/shared/providers/_configs/azure_openai_client_config.py +3 -119
  417. rasa/shared/providers/_configs/client_config.py +1 -3
  418. rasa/shared/providers/_configs/default_litellm_client_config.py +1 -3
  419. rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +1 -3
  420. rasa/shared/providers/_configs/litellm_router_client_config.py +1 -3
  421. rasa/shared/providers/_configs/model_group_config.py +2 -7
  422. rasa/shared/providers/_configs/openai_client_config.py +1 -3
  423. rasa/shared/providers/_configs/rasa_llm_client_config.py +1 -3
  424. rasa/shared/providers/_configs/self_hosted_llm_client_config.py +1 -3
  425. rasa/shared/providers/_configs/utils.py +1 -0
  426. rasa/shared/providers/_ssl_verification_utils.py +5 -6
  427. rasa/shared/providers/_utils.py +5 -5
  428. rasa/shared/providers/embedding/_base_litellm_embedding_client.py +1 -1
  429. rasa/shared/providers/embedding/azure_openai_embedding_client.py +3 -26
  430. rasa/shared/providers/embedding/embedding_client.py +1 -1
  431. rasa/shared/providers/embedding/litellm_router_embedding_client.py +1 -3
  432. rasa/shared/providers/llm/_base_litellm_client.py +1 -3
  433. rasa/shared/providers/llm/azure_openai_llm_client.py +25 -79
  434. rasa/shared/providers/llm/default_litellm_llm_client.py +1 -3
  435. rasa/shared/providers/llm/litellm_router_llm_client.py +2 -21
  436. rasa/shared/providers/llm/llm_client.py +1 -3
  437. rasa/shared/providers/llm/llm_response.py +41 -2
  438. rasa/shared/providers/llm/openai_llm_client.py +3 -9
  439. rasa/shared/providers/llm/rasa_llm_client.py +6 -20
  440. rasa/shared/providers/llm/self_hosted_llm_client.py +3 -9
  441. rasa/shared/providers/mappings.py +18 -19
  442. rasa/shared/providers/router/_base_litellm_router_client.py +1 -3
  443. rasa/shared/providers/router/router_client.py +1 -3
  444. rasa/shared/utils/cli.py +1 -1
  445. rasa/shared/utils/common.py +1 -1
  446. rasa/shared/utils/health_check/embeddings_health_check_mixin.py +1 -1
  447. rasa/shared/utils/health_check/health_check.py +3 -3
  448. rasa/shared/utils/health_check/llm_health_check_mixin.py +1 -1
  449. rasa/shared/utils/io.py +1 -1
  450. rasa/shared/utils/llm.py +5 -9
  451. rasa/shared/utils/pykwalify_extensions.py +1 -1
  452. rasa/shared/utils/schemas/events.py +1 -1
  453. rasa/shared/utils/yaml.py +29 -26
  454. rasa/studio/auth.py +3 -3
  455. rasa/studio/config.py +1 -2
  456. rasa/studio/data_handler.py +3 -3
  457. rasa/studio/download.py +1 -1
  458. rasa/studio/results_logger.py +3 -3
  459. rasa/studio/upload.py +2 -0
  460. rasa/telemetry.py +31 -0
  461. rasa/tracing/config.py +3 -3
  462. rasa/tracing/instrumentation/attribute_extractors.py +2 -0
  463. rasa/tracing/instrumentation/instrumentation.py +4 -4
  464. rasa/tracing/instrumentation/intentless_policy_instrumentation.py +1 -1
  465. rasa/tracing/instrumentation/metrics.py +11 -11
  466. rasa/tracing/metric_instrument_provider.py +14 -14
  467. rasa/utils/common.py +12 -9
  468. rasa/utils/endpoints.py +1 -1
  469. rasa/utils/io.py +7 -7
  470. rasa/utils/licensing.py +3 -4
  471. rasa/utils/log_utils.py +7 -6
  472. rasa/utils/ml_utils.py +1 -0
  473. rasa/utils/plotting.py +3 -3
  474. rasa/utils/sanic_error_handler.py +1 -1
  475. rasa/utils/tensorflow/callback.py +2 -2
  476. rasa/utils/tensorflow/crf.py +2 -2
  477. rasa/utils/tensorflow/data_generator.py +5 -5
  478. rasa/utils/tensorflow/environment.py +3 -3
  479. rasa/utils/tensorflow/feature_array.py +2 -3
  480. rasa/utils/tensorflow/layers.py +18 -12
  481. rasa/utils/tensorflow/layers_utils.py +2 -1
  482. rasa/utils/tensorflow/metrics.py +2 -2
  483. rasa/utils/tensorflow/model_data.py +7 -7
  484. rasa/utils/tensorflow/model_data_utils.py +10 -9
  485. rasa/utils/tensorflow/models.py +31 -32
  486. rasa/utils/tensorflow/rasa_layers.py +20 -19
  487. rasa/utils/tensorflow/types.py +2 -1
  488. rasa/utils/train_utils.py +23 -21
  489. rasa/utils/url_tools.py +1 -1
  490. rasa/validator.py +17 -1
  491. rasa/version.py +1 -1
  492. {rasa_pro-3.12.0.dev2.dist-info → rasa_pro-3.12.0.dev3.dist-info}/METADATA +8 -9
  493. rasa_pro-3.12.0.dev3.dist-info/RECORD +800 -0
  494. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-b080d6f2.js +0 -1
  495. rasa/shared/providers/_configs/azure_entra_id_client_creds.py +0 -40
  496. rasa/shared/providers/_configs/azure_entra_id_config.py +0 -533
  497. rasa/shared/providers/_configs/oauth_config.py +0 -33
  498. rasa/shared/providers/constants.py +0 -6
  499. rasa_pro-3.12.0.dev2.dist-info/RECORD +0 -793
  500. {rasa_pro-3.12.0.dev2.dist-info → rasa_pro-3.12.0.dev3.dist-info}/NOTICE +0 -0
  501. {rasa_pro-3.12.0.dev2.dist-info → rasa_pro-3.12.0.dev3.dist-info}/WHEEL +0 -0
  502. {rasa_pro-3.12.0.dev2.dist-info → rasa_pro-3.12.0.dev3.dist-info}/entry_points.txt +0 -0
@@ -1,11 +1,290 @@
1
- from typing import Optional
1
+ import typing
2
+ from typing import Any, Dict, List, Optional, Text
2
3
 
3
4
  from pydantic import BaseModel
4
5
 
5
- from rasa.dialogue_understanding_test.du_test_case import DialogueUnderstandingTestCase
6
+ from rasa.dialogue_understanding.commands import Command
7
+ from rasa.dialogue_understanding_test.du_test_case import (
8
+ DialogueUnderstandingTestCase,
9
+ DialogueUnderstandingTestStep,
10
+ )
11
+ from rasa.dialogue_understanding_test.utils import get_command_comparison
12
+
13
+ if typing.TYPE_CHECKING:
14
+ from rasa.dialogue_understanding_test.command_metric_calculation import (
15
+ CommandMetrics,
16
+ )
17
+
18
+ KEY_TEST_CASES_ACCURACY = "test_cases"
19
+ KEY_USER_UTTERANCES_ACCURACY = "user_utterances"
6
20
 
7
21
 
8
22
  class DialogueUnderstandingTestResult(BaseModel):
23
+ """Result of a single dialogue understanding test case."""
24
+
9
25
  test_case: DialogueUnderstandingTestCase
10
26
  passed: bool
11
27
  error_line: Optional[int] = None
28
+
29
+ def get_expected_commands(self) -> List[Command]:
30
+ return self.test_case.get_expected_commands()
31
+
32
+
33
+ class FailedTestStep(BaseModel):
34
+ """Failed test step information."""
35
+
36
+ file: str
37
+ test_case_name: str
38
+ failed_user_utterance: str
39
+ error_line: int
40
+ pass_status: bool
41
+ command_generators: List[str]
42
+ prompt: Optional[Dict[str, Any]] = None
43
+ expected_commands: List[Command]
44
+ predicted_commands: Dict[str, List[Command]]
45
+ conversation_with_diff: List[str]
46
+
47
+ @classmethod
48
+ def from_dialogue_understanding_test_step(
49
+ cls,
50
+ step: DialogueUnderstandingTestStep,
51
+ test_case: DialogueUnderstandingTestCase,
52
+ ) -> "FailedTestStep":
53
+ file_path = test_case.file or ""
54
+ user_utterance = step.text or ""
55
+ line_number = step.line or -1
56
+
57
+ predicted_commands: Dict[str, List[Command]] = {}
58
+ prompts: Optional[Dict[str, Any]] = None
59
+ command_generators: List[str] = []
60
+
61
+ if step.dialogue_understanding_output:
62
+ predicted_commands = step.dialogue_understanding_output.commands
63
+ command_generators = step.dialogue_understanding_output.get_component_names_that_predicted_commands() # noqa: E501
64
+ prompts = (
65
+ step.dialogue_understanding_output.get_component_name_to_user_prompts()
66
+ )
67
+
68
+ step_index = test_case.steps.index(step)
69
+
70
+ conversation_with_diff = test_case.to_readable_conversation(
71
+ until_step=step_index + 1
72
+ ) + get_command_comparison(step)
73
+
74
+ return cls(
75
+ file=file_path,
76
+ test_case_name=test_case.name,
77
+ failed_user_utterance=user_utterance,
78
+ error_line=line_number,
79
+ pass_status=False,
80
+ command_generators=command_generators,
81
+ prompt=prompts,
82
+ expected_commands=step.commands or [],
83
+ predicted_commands=predicted_commands,
84
+ conversation_with_diff=conversation_with_diff,
85
+ )
86
+
87
+ def to_dict(self, output_prompt: bool) -> Dict[Text, Any]:
88
+ step_info = {
89
+ "file": self.file,
90
+ "test_case": self.test_case_name,
91
+ "failed_user_utterance": self.failed_user_utterance,
92
+ "error_line": self.error_line,
93
+ "pass_status": self.pass_status,
94
+ "expected_commands": [
95
+ command.to_dsl() for command in self.expected_commands
96
+ ],
97
+ "predicted_commands": [
98
+ {
99
+ "component": component,
100
+ "commands": [command.to_dsl() for command in commands],
101
+ }
102
+ for component, commands in self.predicted_commands.items()
103
+ if commands
104
+ ],
105
+ }
106
+
107
+ if output_prompt and self.prompt:
108
+ step_info["prompts"] = [
109
+ {
110
+ component: [
111
+ {
112
+ "prompt_name": prompt_name,
113
+ "prompt_content": prompt_content,
114
+ }
115
+ for prompt_name, prompt_content in prompts
116
+ ],
117
+ }
118
+ for component, prompts in self.prompt.items()
119
+ ]
120
+
121
+ return step_info
122
+
123
+
124
+ class DialogueUnderstandingTestSuiteResult:
125
+ """Result of a dialogue understanding test suite.
126
+
127
+ Aggregates test results and provides metrics for the entire test suite
128
+ used to log the results to the console and write them to a file.
129
+ """
130
+
131
+ def __init__(self) -> None:
132
+ self.accuracy = {
133
+ KEY_TEST_CASES_ACCURACY: 0.0,
134
+ KEY_USER_UTTERANCES_ACCURACY: 0.0,
135
+ }
136
+ self.number_of_passed_tests = 0
137
+ self.number_of_failed_tests = 0
138
+ self.number_of_passed_user_utterances = 0
139
+ self.number_of_failed_user_utterances = 0
140
+ self.command_metrics: Optional[Dict[str, "CommandMetrics"]] = None
141
+ self.names_of_failed_tests: List[str] = []
142
+ self.names_of_passed_tests: List[str] = []
143
+ self.failed_test_steps: List[FailedTestStep] = []
144
+
145
+ @classmethod
146
+ def from_results(
147
+ cls,
148
+ failing_test_results: List[DialogueUnderstandingTestResult],
149
+ passing_test_results: List[DialogueUnderstandingTestResult],
150
+ command_metrics: Dict[str, "CommandMetrics"],
151
+ ) -> "DialogueUnderstandingTestSuiteResult":
152
+ """Create a DialogueUnderstandingTestSuiteResult object from the test results.
153
+
154
+ Create a new instance of DialogueUnderstandingTestSuiteResult by aggregating
155
+ metrics from passing and failing test results, along with command metrics.
156
+
157
+ Args:
158
+ failing_test_results: A list of DialogueUnderstandingTestResult objects
159
+ representing the test cases that did not pass.
160
+ passing_test_results: A list of DialogueUnderstandingTestResult objects
161
+ representing the test cases that passed.
162
+ command_metrics: A dictionary of command-specific performance metrics, keyed
163
+ by command name.
164
+
165
+ Returns:
166
+ A DialogueUnderstandingTestSuiteResult object containing aggregated test
167
+ suite metrics, including accuracy, counts of passed and failed test cases,
168
+ user utterance statistics, and command metrics.
169
+ """
170
+ instance = cls()
171
+
172
+ instance.number_of_passed_tests = len(passing_test_results)
173
+ instance.number_of_failed_tests = len(failing_test_results)
174
+ instance.accuracy[KEY_TEST_CASES_ACCURACY] = instance.number_of_passed_tests / (
175
+ instance.number_of_passed_tests + instance.number_of_failed_tests
176
+ )
177
+
178
+ instance._set_user_utterance_metrics(failing_test_results, passing_test_results)
179
+
180
+ instance.command_metrics = command_metrics
181
+
182
+ instance.names_of_passed_tests = [
183
+ passing_test_result.test_case.full_name()
184
+ for passing_test_result in passing_test_results
185
+ ]
186
+ instance.names_of_failed_tests = [
187
+ failing_test_result.test_case.full_name()
188
+ for failing_test_result in failing_test_results
189
+ ]
190
+
191
+ instance.failed_test_steps = cls._create_failed_steps_from_results(
192
+ failing_test_results
193
+ )
194
+
195
+ return instance
196
+
197
+ def _set_user_utterance_metrics(
198
+ self,
199
+ failing_test_results: List[DialogueUnderstandingTestResult],
200
+ passing_test_results: List[DialogueUnderstandingTestResult],
201
+ ) -> None:
202
+ # Create list of booleans indicating whether each user utterance
203
+ # passed or failed
204
+ user_utterances_status = [
205
+ step.has_passed()
206
+ for test in failing_test_results + passing_test_results
207
+ for step in test.test_case.iterate_over_user_steps()
208
+ ]
209
+ # Calculate number of passed and failed user utterances
210
+ self.number_of_passed_user_utterances = sum(user_utterances_status)
211
+ self.number_of_failed_user_utterances = (
212
+ len(user_utterances_status) - self.number_of_passed_user_utterances
213
+ )
214
+ # Calculate user utterance accuracy
215
+ self.accuracy[KEY_USER_UTTERANCES_ACCURACY] = (
216
+ self.number_of_passed_user_utterances
217
+ / (
218
+ self.number_of_failed_user_utterances
219
+ + self.number_of_passed_user_utterances
220
+ )
221
+ )
222
+
223
+ @staticmethod
224
+ def _create_failed_steps_from_results(
225
+ failing_test_results: List["DialogueUnderstandingTestResult"],
226
+ ) -> List[FailedTestStep]:
227
+ """Create list of FailedTestStep objects from failing test results.
228
+
229
+ Given a list of failing DialogueUnderstandingTestResult objects,
230
+ create and return a list of FailedTestStep objects for each failing user step.
231
+
232
+ Args:
233
+ failing_test_results: Results of failing Dialogue Understanding tests.
234
+
235
+ Returns:
236
+ List of aggregated FailedTestStep objects for logging to console and file.
237
+ """
238
+ failed_test_steps: List[FailedTestStep] = []
239
+
240
+ for result in failing_test_results:
241
+ test_case = result.test_case
242
+ for step in test_case.failed_user_steps():
243
+ failed_test_steps.append(
244
+ FailedTestStep.from_dialogue_understanding_test_step(
245
+ step, test_case
246
+ )
247
+ )
248
+
249
+ return failed_test_steps
250
+
251
+ def to_dict(self, output_prompt: bool = False) -> Dict[Text, Any]:
252
+ """Builds a dictionary for writing test results to a YML file.
253
+
254
+ Args:
255
+ output_prompt: Whether to log the prompt or not.
256
+ """
257
+ # 1. Accuracy block
258
+ result_dict: Dict[Text, Any] = {
259
+ "accuracy": {
260
+ "test_cases": self.accuracy[KEY_TEST_CASES_ACCURACY],
261
+ "user_utterances": self.accuracy[KEY_USER_UTTERANCES_ACCURACY],
262
+ },
263
+ "number_of_passed_tests": self.number_of_passed_tests,
264
+ "number_of_failed_tests": self.number_of_failed_tests,
265
+ "number_of_passed_user_utterances": self.number_of_passed_user_utterances,
266
+ "number_of_failed_user_utterances": self.number_of_failed_user_utterances,
267
+ }
268
+
269
+ cmd_metrics_output = {}
270
+ if self.command_metrics:
271
+ if isinstance(self.command_metrics, dict):
272
+ for cmd_name, metrics_obj in self.command_metrics.items():
273
+ cmd_metrics_output[cmd_name] = metrics_obj.as_dict()
274
+ else:
275
+ pass
276
+
277
+ result_dict["command_metrics"] = cmd_metrics_output
278
+
279
+ result_dict["names_of_passed_tests"] = self.names_of_passed_tests
280
+ result_dict["names_of_failed_tests"] = self.names_of_failed_tests
281
+
282
+ failed_steps_list = []
283
+ for failed_test_step in self.failed_test_steps:
284
+ failed_steps_list.append(
285
+ failed_test_step.to_dict(output_prompt=output_prompt)
286
+ )
287
+
288
+ result_dict["failed_test_steps"] = failed_steps_list
289
+
290
+ return result_dict
@@ -1,32 +1,52 @@
1
1
  import asyncio
2
- from typing import Dict, Optional, Text, Union, List
2
+ from typing import Any, Dict, List, Optional, Text
3
3
 
4
4
  import structlog
5
+ from tqdm import tqdm
5
6
 
7
+ from rasa.core.channels import CollectingOutputChannel, UserMessage
6
8
  from rasa.core.exceptions import AgentNotReady
7
9
  from rasa.core.persistor import StorageType
8
10
  from rasa.core.utils import AvailableEndpoints
9
- from rasa.dialogue_understanding_test.du_test_case import DialogueUnderstandingTestCase
11
+ from rasa.dialogue_understanding.commands import Command
12
+ from rasa.dialogue_understanding.utils import set_record_commands_and_prompts
13
+ from rasa.dialogue_understanding_test.du_test_case import (
14
+ DialogueUnderstandingOutput,
15
+ DialogueUnderstandingTestCase,
16
+ DialogueUnderstandingTestStep,
17
+ )
10
18
  from rasa.dialogue_understanding_test.du_test_result import (
11
19
  DialogueUnderstandingTestResult,
12
20
  )
21
+ from rasa.dialogue_understanding_test.test_case_simulation.test_case_tracker_simulator import ( # noqa: E501
22
+ TestCaseTrackerSimulator,
23
+ TestCaseTrackerSimulatorException,
24
+ TestCaseTrackerSimulatorResult,
25
+ )
26
+ from rasa.dialogue_understanding_test.utils import filter_metadata
13
27
  from rasa.e2e_test.e2e_test_case import (
14
28
  KEY_STUB_CUSTOM_ACTIONS,
15
- ActualStepOutput,
16
- TestStep,
17
29
  Fixture,
18
30
  Metadata,
19
31
  )
20
32
  from rasa.e2e_test.e2e_test_runner import E2ETestRunner
33
+ from rasa.shared.core.events import UserUttered
34
+ from rasa.shared.core.trackers import DialogueStateTracker
35
+ from rasa.shared.nlu.constants import PREDICTED_COMMANDS, PROMPTS
21
36
  from rasa.utils.endpoints import EndpointConfig
22
37
 
23
38
  structlogger = structlog.get_logger()
24
39
 
25
- TEST_TURNS_TYPE = Dict[int, Union[TestStep, ActualStepOutput]]
26
-
27
40
 
28
41
  class DialogueUnderstandingTestRunner:
29
- """Dialogue Understanding test suite runner."""
42
+ """Dialogue Understanding test suite runner.
43
+
44
+ Responsible for executing dialogue understanding test cases by simulating
45
+ conversations and validating expected outputs against actual responses.
46
+
47
+ Attributes:
48
+ agent: The Rasa agent instance used for processing messages
49
+ """
30
50
 
31
51
  def __init__(
32
52
  self,
@@ -62,7 +82,8 @@ class DialogueUnderstandingTestRunner:
62
82
  "load the trained model."
63
83
  )
64
84
 
65
- def _check_action_server(self, endpoints: AvailableEndpoints) -> None:
85
+ @staticmethod
86
+ def _check_action_server(endpoints: AvailableEndpoints) -> None:
66
87
  """Check if the action server is reachable."""
67
88
  are_custom_actions_stubbed = (
68
89
  endpoints
@@ -74,7 +95,7 @@ class DialogueUnderstandingTestRunner:
74
95
  endpoints, "dialogue_understanding_test_runner"
75
96
  )
76
97
 
77
- async def run_tests(
98
+ async def run_test_cases(
78
99
  self,
79
100
  test_cases: List[DialogueUnderstandingTestCase],
80
101
  fixtures: List[Fixture],
@@ -90,4 +111,212 @@ class DialogueUnderstandingTestRunner:
90
111
  Returns:
91
112
  List[DialogueUnderstandingTestResult]: List of test results.
92
113
  """
93
- return []
114
+ results = []
115
+ output_channel = CollectingOutputChannel()
116
+
117
+ structlogger.info("Starting dialogue understanding tests.")
118
+
119
+ for i in tqdm(range(len(test_cases))):
120
+ test_case = test_cases[i]
121
+
122
+ # set up the tracker by simulating the conversation
123
+ tracker_simulator = TestCaseTrackerSimulator(self.agent, test_case)
124
+ await tracker_simulator.initialize_tracker(fixtures)
125
+ try:
126
+ simulation_result = await tracker_simulator.simulate_test_case(metadata)
127
+ except TestCaseTrackerSimulatorException as e:
128
+ structlogger.error(
129
+ "Failed to simulate test case. Skipping test case.",
130
+ error=str(e),
131
+ )
132
+ continue
133
+
134
+ # run the actual test case
135
+ test_result = await self.run_test_case(
136
+ test_case, metadata, simulation_result, output_channel
137
+ )
138
+ results.append(test_result)
139
+
140
+ structlogger.info("Finished dialogue understanding tests.")
141
+
142
+ return results
143
+
144
+ async def run_test_case(
145
+ self,
146
+ test_case: DialogueUnderstandingTestCase,
147
+ metadata: List[Metadata],
148
+ simulation_result: TestCaseTrackerSimulatorResult,
149
+ output_channel: CollectingOutputChannel,
150
+ ) -> DialogueUnderstandingTestResult:
151
+ """Runs dialogue understanding test case.
152
+
153
+ Args:
154
+ test_case: The test case to run.
155
+ metadata: List of metadata.
156
+ simulation_result: The test case tracker.
157
+ output_channel: The output channel.
158
+
159
+ Returns:
160
+ A dialogue understanding test result.
161
+ """
162
+ test_passed = True
163
+
164
+ sender_id = simulation_result.sender_id
165
+ user_uttered_event_indices = simulation_result.user_uttered_event_indices
166
+ test_case_tracker = await self.agent.tracker_store.retrieve(sender_id)
167
+
168
+ for user_step_index, user_step in enumerate(
169
+ test_case.iterate_over_user_steps()
170
+ ):
171
+ if user_step_index >= len(user_uttered_event_indices):
172
+ # the conversation could not be simulated completely and was
173
+ # stopped early, no further user messages can be evaluated
174
+ return DialogueUnderstandingTestResult(
175
+ test_case=test_case, passed=test_passed
176
+ )
177
+
178
+ # create and save the tracker at the time just
179
+ # before the user message was sent
180
+ step_sender_id = f"{sender_id}_{user_step_index}"
181
+ await self._create_tracker_for_user_step(
182
+ step_sender_id,
183
+ test_case_tracker,
184
+ user_uttered_event_indices[user_step_index],
185
+ )
186
+
187
+ # send the user message
188
+ try:
189
+ await self._send_user_message(
190
+ step_sender_id,
191
+ test_case,
192
+ user_step,
193
+ metadata,
194
+ output_channel=output_channel,
195
+ )
196
+ except Exception as e:
197
+ structlogger.error(
198
+ "dialogue_understanding_test_runner.send_user_message.failed",
199
+ test_case=test_case.full_name(),
200
+ user_message=user_step.text,
201
+ error=str(e),
202
+ )
203
+ # as sending the user message failed, we cannot continue with the test
204
+ # as subsequent user message do not match the actual conversation
205
+ # return a test result up until this point
206
+ return DialogueUnderstandingTestResult(
207
+ test_case=test_case, passed=test_passed
208
+ )
209
+
210
+ # get the dialogue understanding output
211
+ tracker = await self.agent.tracker_store.retrieve(step_sender_id)
212
+ dialogue_understanding_output = self.get_dialogue_understanding_output(
213
+ tracker, user_uttered_event_indices[user_step_index]
214
+ )
215
+ user_step.dialogue_understanding_output = dialogue_understanding_output
216
+
217
+ # check if we have a command match
218
+ if not user_step.has_passed():
219
+ test_passed = False
220
+
221
+ return DialogueUnderstandingTestResult(test_case=test_case, passed=test_passed)
222
+
223
+ def get_dialogue_understanding_output(
224
+ self,
225
+ tracker: DialogueStateTracker,
226
+ index_user_uttered_event: int,
227
+ ) -> Optional[DialogueUnderstandingOutput]:
228
+ """Returns the dialogue understanding output.
229
+
230
+ Creates the dialogue understanding output from the commands and prompts
231
+ added to the user uttered event.
232
+
233
+ Args:
234
+ tracker: The tracker for the current test step.
235
+ index_user_uttered_event: The index of the user uttered event.
236
+
237
+ Returns:
238
+ The dialogue understanding output with commands and optionally prompts.
239
+ """
240
+ user_uttered_event = self._get_user_uttered_event_from_tracker(
241
+ tracker, index_user_uttered_event
242
+ )
243
+ if user_uttered_event is None:
244
+ return None
245
+
246
+ predicted_commands: Dict[str, Any] = user_uttered_event.parse_data.get( # type:ignore[assignment]
247
+ PREDICTED_COMMANDS, {}
248
+ )
249
+ # convert the predicted commands to Command objects
250
+ commands = {}
251
+ for component, list_of_commands in predicted_commands.items():
252
+ # remove any duplicate commands
253
+ commands[component] = list(
254
+ set(
255
+ [Command.command_from_json(command) for command in list_of_commands]
256
+ )
257
+ )
258
+
259
+ return DialogueUnderstandingOutput(
260
+ commands=commands,
261
+ prompts=user_uttered_event.parse_data.get(PROMPTS, []),
262
+ )
263
+
264
+ @staticmethod
265
+ def _get_user_uttered_event_from_tracker(
266
+ tracker: DialogueStateTracker,
267
+ index_user_uttered_event: int,
268
+ ) -> Optional[UserUttered]:
269
+ """Returns the user uttered event from the tracker at the given index."""
270
+ if (
271
+ tracker.events is None
272
+ or len(list(tracker.events)) <= index_user_uttered_event
273
+ ):
274
+ return None
275
+
276
+ user_uttered_event = list(tracker.events)[index_user_uttered_event]
277
+
278
+ if not user_uttered_event or not isinstance(user_uttered_event, UserUttered):
279
+ return None
280
+
281
+ return user_uttered_event
282
+
283
+ async def _create_tracker_for_user_step(
284
+ self,
285
+ step_sender_id: str,
286
+ test_case_tracker: DialogueStateTracker,
287
+ index_user_uttered_event: int,
288
+ ) -> None:
289
+ """Creates a tracker for the user step."""
290
+ tracker = test_case_tracker.copy()
291
+ # modify the sender id so that the test case tracker is not overwritten
292
+ tracker.sender_id = step_sender_id
293
+
294
+ if tracker.events:
295
+ # get timestamp of the event just before the user uttered event
296
+ timestamp = tracker.events[index_user_uttered_event - 1].timestamp
297
+ # revert the tracker to the event just before the user uttered event
298
+ tracker = tracker.travel_back_in_time(timestamp)
299
+
300
+ # store the tracker with the unique sender id
301
+ await self.agent.tracker_store.save(tracker)
302
+
303
+ async def _send_user_message(
304
+ self,
305
+ sender_id: str,
306
+ test_case: DialogueUnderstandingTestCase,
307
+ user_step: DialogueUnderstandingTestStep,
308
+ metadata: List[Metadata],
309
+ output_channel: CollectingOutputChannel = CollectingOutputChannel(),
310
+ ) -> None:
311
+ """Sends a user message to the agent."""
312
+ metadata_for_step = filter_metadata(test_case, user_step, metadata, sender_id)
313
+
314
+ user_message = UserMessage(
315
+ user_step.text,
316
+ output_channel,
317
+ sender_id,
318
+ metadata=metadata_for_step,
319
+ )
320
+
321
+ with set_record_commands_and_prompts():
322
+ await self.agent.handle_message(user_message)