rasa-pro 3.13.1a18__py3-none-any.whl → 3.13.1a20__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 (273) hide show
  1. rasa/__main__.py +8 -0
  2. rasa/builder/auth.py +71 -0
  3. rasa/builder/config.py +16 -0
  4. rasa/builder/copilot/constants.py +15 -0
  5. rasa/builder/copilot/copilot.py +342 -0
  6. rasa/builder/copilot/copilot_response_handler.py +471 -0
  7. rasa/builder/copilot/exceptions.py +20 -0
  8. rasa/builder/copilot/models.py +344 -0
  9. rasa/builder/copilot/prompts/copilot_system_prompt.jinja2 +495 -0
  10. rasa/builder/copilot/telemetry.py +195 -0
  11. rasa/builder/document_retrieval/__init__.py +0 -0
  12. rasa/builder/document_retrieval/constants.py +16 -0
  13. rasa/builder/{inkeep_document_retrieval.py → document_retrieval/inkeep_document_retrieval.py} +53 -44
  14. rasa/builder/document_retrieval/models.py +62 -0
  15. rasa/builder/download.py +140 -0
  16. rasa/builder/guardrails/__init__.py +1 -0
  17. rasa/builder/guardrails/constants.py +4 -0
  18. rasa/builder/guardrails/exceptions.py +4 -0
  19. rasa/builder/guardrails/lakera.py +188 -0
  20. rasa/builder/guardrails/models.py +199 -0
  21. rasa/builder/guardrails/utils.py +305 -0
  22. rasa/builder/job_manager.py +87 -0
  23. rasa/builder/jobs.py +232 -0
  24. rasa/builder/llm_service.py +89 -173
  25. rasa/builder/logging_utils.py +162 -4
  26. rasa/builder/main.py +29 -16
  27. rasa/builder/models.py +93 -121
  28. rasa/builder/project_generator.py +91 -7
  29. rasa/builder/scrape_rasa_docs.py +1 -1
  30. rasa/builder/service.py +650 -452
  31. rasa/builder/shared/tracker_context.py +212 -0
  32. rasa/builder/validation_service.py +4 -4
  33. rasa/cli/data.py +8 -3
  34. rasa/cli/project_templates/basic/actions/action_api.py +15 -0
  35. rasa/cli/project_templates/basic/actions/action_human_handoff.py +44 -0
  36. rasa/cli/project_templates/basic/config.yml +23 -0
  37. rasa/cli/project_templates/{plain → basic}/credentials.yml +8 -7
  38. rasa/cli/project_templates/basic/data/general/feedback.yml +20 -0
  39. rasa/cli/project_templates/basic/data/general/goodbye.yml +6 -0
  40. rasa/cli/project_templates/basic/data/general/hello.yml +7 -0
  41. rasa/cli/project_templates/basic/data/general/help.yml +6 -0
  42. rasa/cli/project_templates/basic/data/general/human_handoff.yml +16 -0
  43. rasa/cli/project_templates/basic/data/general/welcome.yml +9 -0
  44. rasa/cli/project_templates/{finance/data/patterns → basic/data/system}/pattern_completed.yml +2 -1
  45. rasa/cli/project_templates/basic/data/system/pattern_correction.yml +7 -0
  46. rasa/cli/project_templates/basic/data/system/pattern_search.yml +8 -0
  47. rasa/cli/project_templates/basic/data/system/pattern_session_start.yml +8 -0
  48. rasa/cli/project_templates/basic/docs/rasa_assistant_qa.txt +65 -0
  49. rasa/cli/project_templates/basic/docs/template.txt +7 -0
  50. rasa/cli/project_templates/basic/domain/general/assistant_details.yml +12 -0
  51. rasa/cli/project_templates/basic/domain/general/bot_identity.yml +5 -0
  52. rasa/cli/project_templates/basic/domain/general/cannot_handle.yml +5 -0
  53. rasa/cli/project_templates/basic/domain/general/feedback.yml +28 -0
  54. rasa/cli/project_templates/basic/domain/general/goodbye.yml +7 -0
  55. rasa/cli/project_templates/basic/domain/general/help.yml +5 -0
  56. rasa/cli/project_templates/basic/domain/general/human_handoff_domain.yml +35 -0
  57. rasa/cli/project_templates/{finance/domain/default_actions.yml → basic/domain/general/utils.yml} +0 -3
  58. rasa/cli/project_templates/basic/domain/general/welcome.yml +7 -0
  59. rasa/cli/project_templates/{plain → basic}/endpoints.yml +42 -27
  60. rasa/cli/project_templates/basic/prompts/rephraser_demo_personality_prompt.jinja2 +19 -0
  61. rasa/cli/project_templates/defaults.py +25 -3
  62. rasa/cli/project_templates/finance/actions/__init__.py +46 -0
  63. rasa/cli/project_templates/finance/actions/accounts/__init__.py +0 -0
  64. rasa/cli/project_templates/finance/actions/{action_ask_account.py → accounts/action_ask_account.py} +6 -9
  65. rasa/cli/project_templates/finance/actions/{action_check_balance.py → accounts/action_check_balance.py} +4 -4
  66. rasa/cli/project_templates/finance/actions/action_session_start.py +11 -6
  67. rasa/cli/project_templates/finance/actions/cards/__init__.py +0 -0
  68. rasa/cli/project_templates/finance/actions/{action_ask_card.py → cards/action_ask_card.py} +4 -3
  69. rasa/cli/project_templates/finance/actions/{action_check_card_existence.py → cards/action_check_card_existence.py} +4 -3
  70. rasa/cli/project_templates/finance/actions/{action_update_card_status.py → cards/action_update_card_status.py} +18 -9
  71. rasa/cli/project_templates/finance/actions/database.py +1 -0
  72. rasa/cli/project_templates/finance/actions/transfers/__init__.py +0 -0
  73. rasa/cli/project_templates/finance/actions/{action_add_payee.py → transfers/action_add_payee.py} +8 -3
  74. rasa/cli/project_templates/finance/actions/{action_ask_account_from.py → transfers/action_ask_account_from.py} +5 -4
  75. rasa/cli/project_templates/finance/actions/{action_check_payee_existence.py → transfers/action_check_payee_existence.py} +3 -3
  76. rasa/cli/project_templates/finance/actions/{action_check_sufficient_funds.py → transfers/action_check_sufficient_funds.py} +3 -4
  77. rasa/cli/project_templates/finance/actions/{action_list_payees.py → transfers/action_list_payees.py} +4 -3
  78. rasa/cli/project_templates/finance/actions/{action_remove_payee.py → transfers/action_remove_payee.py} +4 -4
  79. rasa/cli/project_templates/finance/config.yml +8 -19
  80. rasa/cli/project_templates/finance/credentials.yml +6 -7
  81. rasa/cli/project_templates/finance/csvs/cards.csv +10 -10
  82. rasa/cli/project_templates/finance/csvs/payees.csv +10 -9
  83. rasa/cli/project_templates/finance/data/{flows → accounts}/check_balance.yml +2 -1
  84. rasa/cli/project_templates/finance/data/general/bot_identity.yml +6 -0
  85. rasa/cli/project_templates/finance/data/general/feedback.yml +20 -0
  86. rasa/cli/project_templates/finance/data/general/goodbye.yml +6 -0
  87. rasa/cli/project_templates/finance/data/general/hello.yml +7 -0
  88. rasa/cli/project_templates/finance/data/{flows/welcome.yml → general/help.yml} +2 -7
  89. rasa/cli/project_templates/finance/data/general/human_handoff.yml +16 -0
  90. rasa/cli/project_templates/finance/data/general/welcome.yml +9 -0
  91. rasa/cli/project_templates/finance/data/{patterns → system/patterns}/pattern_chitchat.yml +0 -2
  92. rasa/cli/project_templates/finance/data/system/patterns/pattern_completed.yml +7 -0
  93. rasa/cli/project_templates/finance/data/system/patterns/pattern_correction.yml +7 -0
  94. rasa/cli/project_templates/finance/data/system/patterns/pattern_search.yml +8 -0
  95. rasa/cli/project_templates/finance/data/{patterns → system/patterns}/pattern_session_start.yml +0 -1
  96. rasa/cli/project_templates/finance/domain/{check_balance.yml → accounts/check_balance.yml} +2 -0
  97. rasa/cli/project_templates/finance/domain/general/assistant_details.yml +12 -0
  98. rasa/cli/project_templates/finance/domain/general/bot_identity.yml +5 -0
  99. rasa/cli/project_templates/finance/domain/general/cannot_handle.yml +5 -0
  100. rasa/cli/project_templates/finance/domain/general/defaults.yml +24 -0
  101. rasa/cli/project_templates/finance/domain/general/feedback.yml +28 -0
  102. rasa/cli/project_templates/finance/domain/general/goodbye.yml +7 -0
  103. rasa/cli/project_templates/finance/domain/general/help.yml +5 -0
  104. rasa/cli/project_templates/finance/domain/general/human_handoff.yml +30 -0
  105. rasa/cli/project_templates/finance/domain/general/utils.yml +13 -0
  106. rasa/cli/project_templates/finance/domain/general/welcome.yml +8 -0
  107. rasa/cli/project_templates/finance/endpoints.yml +1 -0
  108. rasa/cli/project_templates/finance/prompts/rephraser_demo_personality_prompt.jinja2 +3 -3
  109. rasa/cli/project_templates/telco/actions/actions_billing.py +24 -17
  110. rasa/cli/project_templates/telco/actions/actions_get_data_from_db.py +6 -1
  111. rasa/cli/project_templates/telco/actions/actions_run_diagnostics.py +6 -1
  112. rasa/cli/project_templates/telco/actions/actions_session_start.py +6 -1
  113. rasa/cli/project_templates/tutorial/config.yml +2 -1
  114. rasa/cli/scaffold.py +27 -2
  115. rasa/cli/train.py +8 -0
  116. rasa/cli/utils.py +31 -15
  117. rasa/core/actions/action.py +28 -41
  118. rasa/core/actions/action_run_slot_rejections.py +1 -1
  119. rasa/core/channels/development_inspector.py +47 -14
  120. rasa/core/channels/inspector/dist/assets/{arc-371401b1.js → arc-1ddec37b.js} +1 -1
  121. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-3f126156.js → blockDiagram-38ab4fdb-18af387c.js} +1 -1
  122. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-12f22eb7.js → c4Diagram-3d4e48cf-250127a3.js} +1 -1
  123. rasa/core/channels/inspector/dist/assets/channel-59f6d54b.js +1 -0
  124. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-03b1d386.js → classDiagram-70f12bd4-c3388b34.js} +1 -1
  125. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-84f69d63.js → classDiagram-v2-f2320105-9c893a82.js} +1 -1
  126. rasa/core/channels/inspector/dist/assets/clone-26177ddb.js +1 -0
  127. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-ca47fd38.js → createText-2e5e7dd3-c111213b.js} +1 -1
  128. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-f837ca8a.js → edges-e0da2a9e-812a729d.js} +1 -1
  129. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-8717ac54.js → erDiagram-9861fffd-fd5051bc.js} +1 -1
  130. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-94f38b83.js → flowDb-956e92f1-3287ac02.js} +1 -1
  131. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-b616f9fb.js → flowDiagram-66a62f08-692fb0b2.js} +1 -1
  132. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-29c03f5a.js +1 -0
  133. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-f5d24bb8.js → flowchart-elk-definition-4a651766-008376f1.js} +1 -1
  134. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-b43ba8d9.js → ganttDiagram-c361ad54-df330a69.js} +1 -1
  135. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-c3aafaa5.js → gitGraphDiagram-72cf32ee-e03676fb.js} +1 -1
  136. rasa/core/channels/inspector/dist/assets/{graph-0d0a2c10.js → graph-46fad2ba.js} +1 -1
  137. rasa/core/channels/inspector/dist/assets/{index-3862675e-58ea0305.js → index-3862675e-a484ac55.js} +1 -1
  138. rasa/core/channels/inspector/dist/assets/{index-cce6f8a1.js → index-a003633f.js} +179 -179
  139. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-b8f60461.js → infoDiagram-f8f76790-3f9e6ec2.js} +1 -1
  140. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-95be5545.js → journeyDiagram-49397b02-79f72383.js} +1 -1
  141. rasa/core/channels/inspector/dist/assets/{layout-da885b9b.js → layout-aad098e5.js} +1 -1
  142. rasa/core/channels/inspector/dist/assets/{line-f1c817d3.js → line-219ab7ae.js} +1 -1
  143. rasa/core/channels/inspector/dist/assets/{linear-d42801e6.js → linear-2cddbe62.js} +1 -1
  144. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-a38923a6.js → mindmap-definition-fc14e90a-1d41ed99.js} +1 -1
  145. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-ca6e71e9.js → pieDiagram-8a3498a8-cc496ee8.js} +1 -1
  146. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-b290dae9.js → quadrantDiagram-120e2f19-84d32884.js} +1 -1
  147. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-03f02ceb.js → requirementDiagram-deff3bca-c0deb984.js} +1 -1
  148. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-c49eee40.js → sankeyDiagram-04a897e0-b9d7fd62.js} +1 -1
  149. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-b2cd6a3d.js → sequenceDiagram-704730f1-7d517565.js} +1 -1
  150. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-e53a2028.js → stateDiagram-587899a1-98ef9b27.js} +1 -1
  151. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-e1982a03.js → stateDiagram-v2-d93cdb3a-cee70748.js} +1 -1
  152. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-d0226ca5.js → styles-6aaf32cf-3f9d1c96.js} +1 -1
  153. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-0e21dc00.js → styles-9a916d00-67471923.js} +1 -1
  154. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-9588494e.js → styles-c10674c1-bd093fb7.js} +1 -1
  155. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-be478d4f.js → svgDrawCommon-08f97a94-675794e8.js} +1 -1
  156. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-74631749.js → timeline-definition-85554ec2-0ac67617.js} +1 -1
  157. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-a043552f.js → xychartDiagram-e933f94c-c018dc37.js} +1 -1
  158. rasa/core/channels/inspector/dist/index.html +2 -2
  159. rasa/core/channels/inspector/index.html +1 -1
  160. rasa/core/channels/inspector/package.json +4 -3
  161. rasa/core/channels/inspector/src/App.tsx +53 -7
  162. rasa/core/channels/inspector/src/components/Chat.tsx +3 -2
  163. rasa/core/channels/inspector/src/components/DiagramFlow.tsx +1 -1
  164. rasa/core/channels/inspector/src/components/LatencyDisplay.tsx +268 -0
  165. rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +6 -2
  166. rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +8 -3
  167. rasa/core/channels/inspector/src/types.ts +8 -0
  168. rasa/core/channels/inspector/yarn.lock +12 -12
  169. rasa/core/channels/studio_chat.py +119 -34
  170. rasa/core/channels/voice_ready/twilio_voice.py +1 -1
  171. rasa/core/channels/voice_stream/asr/asr_engine.py +5 -1
  172. rasa/core/channels/voice_stream/asr/deepgram.py +5 -0
  173. rasa/core/channels/voice_stream/audiocodes.py +16 -8
  174. rasa/core/channels/voice_stream/browser_audio.py +39 -4
  175. rasa/core/channels/voice_stream/call_state.py +13 -2
  176. rasa/core/channels/voice_stream/genesys.py +16 -13
  177. rasa/core/channels/voice_stream/jambonz.py +14 -12
  178. rasa/core/channels/voice_stream/twilio_media_streams.py +14 -13
  179. rasa/core/channels/voice_stream/util.py +11 -1
  180. rasa/core/channels/voice_stream/voice_channel.py +108 -29
  181. rasa/core/nlg/callback.py +1 -1
  182. rasa/core/nlg/contextual_response_rephraser.py +19 -9
  183. rasa/core/nlg/generator.py +21 -5
  184. rasa/core/nlg/response.py +43 -6
  185. rasa/core/nlg/translate.py +8 -0
  186. rasa/core/policies/enterprise_search_policy.py +16 -21
  187. rasa/dialogue_understanding/commands/correct_slots_command.py +38 -10
  188. rasa/dialogue_understanding/generator/command_generator.py +5 -5
  189. rasa/dialogue_understanding/generator/command_parser.py +9 -13
  190. rasa/dialogue_understanding/processor/command_processor.py +149 -55
  191. rasa/dialogue_understanding/stack/utils.py +13 -3
  192. rasa/dialogue_understanding_test/du_test_schema.yml +3 -3
  193. rasa/dialogue_understanding_test/validation.py +9 -10
  194. rasa/e2e_test/e2e_config.py +18 -11
  195. rasa/e2e_test/e2e_test_schema.yml +3 -3
  196. rasa/e2e_test/utils/validation.py +17 -19
  197. rasa/engine/validation.py +86 -91
  198. rasa/exceptions.py +26 -1
  199. rasa/model_manager/model_api.py +2 -2
  200. rasa/model_manager/socket_bridge.py +8 -2
  201. rasa/shared/providers/_configs/default_litellm_client_config.py +3 -7
  202. rasa/shared/utils/cli.py +2 -0
  203. rasa/shared/utils/common.py +2 -1
  204. rasa/shared/utils/health_check/health_check.py +10 -14
  205. rasa/studio/upload.py +6 -2
  206. rasa/studio/utils.py +33 -22
  207. rasa/telemetry.py +95 -22
  208. rasa/utils/licensing.py +21 -10
  209. rasa/utils/log_utils.py +1 -1
  210. rasa/utils/tensorflow/transformer.py +3 -3
  211. rasa/validator.py +7 -5
  212. rasa/version.py +1 -1
  213. {rasa_pro-3.13.1a18.dist-info → rasa_pro-3.13.1a20.dist-info}/METADATA +7 -7
  214. {rasa_pro-3.13.1a18.dist-info → rasa_pro-3.13.1a20.dist-info}/RECORD +242 -203
  215. rasa/builder/create_openai_vector_store.py +0 -228
  216. rasa/builder/llm-helper-schema.json +0 -69
  217. rasa/builder/llm_context.py +0 -81
  218. rasa/builder/llm_helper_prompt.jinja2 +0 -245
  219. rasa/cli/project_templates/finance/data/nlu.yml +0 -29
  220. rasa/cli/project_templates/finance/data/patterns/pattern_search.yml +0 -5
  221. rasa/cli/project_templates/finance/domain/default_flows.yml +0 -33
  222. rasa/cli/project_templates/finance/prompts/command-generator.jinja2 +0 -57
  223. rasa/cli/project_templates/finance/tests/conversation_repair/cancellations.yml +0 -12
  224. rasa/cli/project_templates/finance/tests/conversation_repair/cannot_handle.yml +0 -7
  225. rasa/cli/project_templates/finance/tests/conversation_repair/chitchat.yml +0 -7
  226. rasa/cli/project_templates/finance/tests/conversation_repair/clarification.yml +0 -9
  227. rasa/cli/project_templates/finance/tests/conversation_repair/completion.yml +0 -18
  228. rasa/cli/project_templates/finance/tests/conversation_repair/corrections.yml +0 -17
  229. rasa/cli/project_templates/finance/tests/conversation_repair/digressions.yml +0 -32
  230. rasa/cli/project_templates/finance/tests/conversation_repair/human_handoff.yml +0 -21
  231. rasa/cli/project_templates/finance/tests/conversation_repair/skipping_collect_steps.yml +0 -16
  232. rasa/cli/project_templates/finance/tests/demo_scripts/main.yml +0 -16
  233. rasa/cli/project_templates/finance/tests/happy_paths/balance_verification.yml +0 -15
  234. rasa/cli/project_templates/finance/tests/happy_paths/banking_questions.yml +0 -12
  235. rasa/cli/project_templates/finance/tests/happy_paths/card_blocking.yml +0 -52
  236. rasa/cli/project_templates/finance/tests/happy_paths/money_transfer.yml +0 -136
  237. rasa/cli/project_templates/finance/tests/happy_paths/payee_management.yml +0 -27
  238. rasa/cli/project_templates/finance/tests/happy_paths/user_greeted.yml +0 -5
  239. rasa/cli/project_templates/plain/config.yml +0 -17
  240. rasa/cli/project_templates/plain/data/patterns/pattern_session_start.yml +0 -7
  241. rasa/cli/project_templates/plain/domain.yml +0 -5
  242. rasa/core/channels/inspector/dist/assets/channel-f1efda17.js +0 -1
  243. rasa/core/channels/inspector/dist/assets/clone-fdf164e2.js +0 -1
  244. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-7d7a1629.js +0 -1
  245. rasa/shared/importers/static.py +0 -63
  246. /rasa/{cli/project_templates/plain/actions → builder/copilot}/__init__.py +0 -0
  247. /rasa/builder/{inkeep-rag-response-schema.json → document_retrieval/inkeep-rag-response-schema.json} +0 -0
  248. /rasa/cli/project_templates/finance/actions/{action_process_immediate_payment.py → transfers/action_process_immediate_payment.py} +0 -0
  249. /rasa/cli/project_templates/finance/actions/{action_schedule_payment.py → transfers/action_schedule_payment.py} +0 -0
  250. /rasa/cli/project_templates/finance/actions/{action_validate_payment_date.py → transfers/action_validate_payment_date.py} +0 -0
  251. /rasa/cli/project_templates/finance/data/{flows → cards}/block_card.yml +0 -0
  252. /rasa/cli/project_templates/finance/data/{flows → cards}/select_card.yml +0 -0
  253. /rasa/cli/project_templates/finance/data/{source → system/source}/accounts.json +0 -0
  254. /rasa/cli/project_templates/finance/data/{source → system/source}/advisors.json +0 -0
  255. /rasa/cli/project_templates/finance/data/{source → system/source}/appointments.json +0 -0
  256. /rasa/cli/project_templates/finance/data/{source → system/source}/branches.json +0 -0
  257. /rasa/cli/project_templates/finance/data/{source → system/source}/cards.json +0 -0
  258. /rasa/cli/project_templates/finance/data/{source → system/source}/payees.json +0 -0
  259. /rasa/cli/project_templates/finance/data/{source → system/source}/transactions.json +0 -0
  260. /rasa/cli/project_templates/finance/data/{source → system/source}/users.json +0 -0
  261. /rasa/cli/project_templates/finance/data/{flows → transfers}/add_payee.yml +0 -0
  262. /rasa/cli/project_templates/finance/data/{flows → transfers}/list_payees.yml +0 -0
  263. /rasa/cli/project_templates/finance/data/{flows → transfers}/remove_payee.yml +0 -0
  264. /rasa/cli/project_templates/finance/data/{flows → transfers}/transfer_money.yml +0 -0
  265. /rasa/cli/project_templates/finance/domain/{block_card.yml → cards/block_card.yml} +0 -0
  266. /rasa/cli/project_templates/finance/domain/{select_card.yml → cards/select_card.yml} +0 -0
  267. /rasa/cli/project_templates/finance/domain/{add_payee.yml → transfers/add_payee.yml} +0 -0
  268. /rasa/cli/project_templates/finance/domain/{list_payees.yml → transfers/list_payees.yml} +0 -0
  269. /rasa/cli/project_templates/finance/domain/{remove_payee.yml → transfers/remove_payee.yml} +0 -0
  270. /rasa/cli/project_templates/finance/domain/{transfer_money.yml → transfers/transfer_money.yml} +0 -0
  271. {rasa_pro-3.13.1a18.dist-info → rasa_pro-3.13.1a20.dist-info}/NOTICE +0 -0
  272. {rasa_pro-3.13.1a18.dist-info → rasa_pro-3.13.1a20.dist-info}/WHEEL +0 -0
  273. {rasa_pro-3.13.1a18.dist-info → rasa_pro-3.13.1a20.dist-info}/entry_points.txt +0 -0
@@ -26,6 +26,7 @@ from rasa.core.channels.voice_ready.utils import (
26
26
  from rasa.core.channels.voice_stream.audio_bytes import RasaAudioBytes
27
27
  from rasa.core.channels.voice_stream.call_state import call_state
28
28
  from rasa.core.channels.voice_stream.tts.tts_engine import TTSEngine
29
+ from rasa.core.channels.voice_stream.util import repack_voice_credentials
29
30
  from rasa.core.channels.voice_stream.voice_channel import (
30
31
  ContinueConversationAction,
31
32
  EndConversationAction,
@@ -120,20 +121,20 @@ class TwilioMediaStreamsInputChannel(VoiceInputChannel):
120
121
  cls,
121
122
  credentials: Optional[Dict[str, Any]],
122
123
  ) -> VoiceInputChannel:
123
- credentials = credentials or {}
124
+ cls.validate_credentials(credentials)
125
+ new_creds = repack_voice_credentials(credentials)
126
+ return cls(**new_creds)
124
127
 
125
- username = credentials.get("username")
126
- password = credentials.get("password")
128
+ @classmethod
129
+ def validate_credentials(
130
+ cls,
131
+ credentials: Optional[Dict[str, Any]],
132
+ ) -> None:
133
+ cls.validate_basic_credentials(credentials)
134
+ username = credentials.get("username") if credentials else None
135
+ password = credentials.get("password") if credentials else None
127
136
  validate_username_password_credentials(username, password, "TwilioMediaStreams")
128
137
 
129
- return cls(
130
- credentials["server_url"],
131
- credentials["asr"],
132
- credentials["tts"],
133
- username=username,
134
- password=password,
135
- )
136
-
137
138
  @classmethod
138
139
  def name(cls) -> str:
139
140
  return "twilio_media_streams"
@@ -175,14 +176,14 @@ class TwilioMediaStreamsInputChannel(VoiceInputChannel):
175
176
  elif data["event"] == "mark":
176
177
  if data["mark"]["name"] == call_state.latest_bot_audio_id:
177
178
  # Just finished streaming last audio bytes
178
- call_state.is_bot_speaking = False # type: ignore[attr-defined]
179
+ call_state.is_bot_speaking = False
179
180
  if call_state.should_hangup:
180
181
  logger.debug(
181
182
  "twilio_streams.hangup", marker=call_state.latest_bot_audio_id
182
183
  )
183
184
  return EndConversationAction()
184
185
  else:
185
- call_state.is_bot_speaking = True # type: ignore[attr-defined]
186
+ call_state.is_bot_speaking = True
186
187
  return ContinueConversationAction()
187
188
 
188
189
  def create_output_channel(
@@ -1,7 +1,7 @@
1
1
  import audioop
2
2
  import wave
3
3
  from dataclasses import asdict, dataclass
4
- from typing import Optional, Type, TypeVar
4
+ from typing import Dict, Optional, Type, TypeVar
5
5
 
6
6
  import structlog
7
7
 
@@ -55,3 +55,13 @@ class MergeableConfig:
55
55
  @classmethod
56
56
  def from_dict(cls: Type[T], data: dict[str, Optional[str]]) -> T:
57
57
  return cls(**data)
58
+
59
+
60
+ def repack_voice_credentials(
61
+ credentials: Dict[str, str],
62
+ ) -> Dict[str, str]:
63
+ """Repack voice credentials to ensure they are in the correct format."""
64
+ new_creds = {**credentials}
65
+ new_creds["asr_config"] = new_creds.pop("asr", None)
66
+ new_creds["tts_config"] = new_creds.pop("tts", None)
67
+ return new_creds
@@ -1,5 +1,8 @@
1
+ from __future__ import annotations
2
+
1
3
  import asyncio
2
4
  import copy
5
+ import time
3
6
  from dataclasses import asdict, dataclass
4
7
  from typing import Any, AsyncIterator, Awaitable, Callable, Dict, List, Optional, Tuple
5
8
 
@@ -189,7 +192,7 @@ class VoiceOutputChannel(OutputChannel):
189
192
  def update_silence_timeout(self) -> None:
190
193
  """Updates the silence timeout for the session."""
191
194
  if self.tracker_state:
192
- call_state.silence_timeout = self.tracker_state["slots"][ # type: ignore[attr-defined]
195
+ call_state.silence_timeout = self.tracker_state["slots"][
193
196
  SILENCE_TIMEOUT_SLOT
194
197
  ]
195
198
  logger.debug(
@@ -207,22 +210,63 @@ class VoiceOutputChannel(OutputChannel):
207
210
  """Uses the concise button output format for voice channels."""
208
211
  await self.send_text_with_buttons_concise(recipient_id, text, buttons, **kwargs)
209
212
 
213
+ def _track_rasa_processing_latency(self) -> None:
214
+ """Track and log Rasa processing completion latency."""
215
+ if call_state.rasa_processing_start_time:
216
+ call_state.rasa_processing_latency_ms = (
217
+ time.time() - call_state.rasa_processing_start_time
218
+ ) * 1000
219
+ logger.debug(
220
+ "voice_channel.rasa_processing_latency",
221
+ latency_ms=call_state.rasa_processing_latency_ms,
222
+ )
223
+
224
+ def _track_tts_first_byte_latency(self) -> None:
225
+ """Track and log TTS first byte latency."""
226
+ if call_state.tts_start_time:
227
+ call_state.tts_first_byte_latency_ms = (
228
+ time.time() - call_state.tts_start_time
229
+ ) * 1000
230
+ logger.debug(
231
+ "voice_channel.tts_first_byte_latency",
232
+ latency_ms=call_state.tts_first_byte_latency_ms,
233
+ )
234
+
235
+ def _track_tts_complete_latency(self) -> None:
236
+ """Track and log TTS completion latency."""
237
+ if call_state.tts_start_time:
238
+ call_state.tts_complete_latency_ms = (
239
+ time.time() - call_state.tts_start_time
240
+ ) * 1000
241
+ logger.debug(
242
+ "voice_channel.tts_complete_latency",
243
+ latency_ms=call_state.tts_complete_latency_ms,
244
+ )
245
+
210
246
  async def send_text_message(
211
247
  self, recipient_id: str, text: str, **kwargs: Any
212
248
  ) -> None:
213
249
  text = remove_emojis(text)
214
250
  self.update_silence_timeout()
251
+
252
+ # Track Rasa processing completion
253
+ self._track_rasa_processing_latency()
254
+
255
+ # Track TTS start time
256
+ call_state.tts_start_time = time.time()
257
+
215
258
  cached_audio_bytes = self.tts_cache.get(text)
216
259
  collected_audio_bytes = RasaAudioBytes(b"")
217
260
  seconds_marker = -1
218
261
  last_sent_offset = 0
262
+ first_audio_sent = False
219
263
  logger.debug("voice_channel.sending_audio", text=text)
220
264
 
221
265
  # Send start marker before first chunk
222
266
  try:
223
267
  await self.send_start_marker(recipient_id)
224
268
  except (WebsocketClosed, ServerError):
225
- call_state.connection_failed = True # type: ignore[attr-defined]
269
+ call_state.connection_failed = True
226
270
 
227
271
  if cached_audio_bytes:
228
272
  audio_stream = self.chunk_audio(cached_audio_bytes)
@@ -244,6 +288,11 @@ class VoiceOutputChannel(OutputChannel):
244
288
 
245
289
  if should_send:
246
290
  try:
291
+ # Track TTS first byte time
292
+ if not first_audio_sent:
293
+ self._track_tts_first_byte_latency()
294
+ first_audio_sent = True
295
+
247
296
  # Send only the new bytes since last send
248
297
  new_bytes = RasaAudioBytes(collected_audio_bytes[last_sent_offset:])
249
298
  await self.send_audio_bytes(recipient_id, new_bytes)
@@ -256,24 +305,31 @@ class VoiceOutputChannel(OutputChannel):
256
305
 
257
306
  except (WebsocketClosed, ServerError):
258
307
  # ignore sending error, and keep collecting and caching audio bytes
259
- call_state.connection_failed = True # type: ignore[attr-defined]
308
+ call_state.connection_failed = True
260
309
 
261
310
  # Send any remaining audio not yet sent
262
311
  remaining_bytes = len(collected_audio_bytes) - last_sent_offset
263
312
  if remaining_bytes > 0:
264
313
  try:
314
+ # Track TTS first byte time if not already tracked
315
+ if not first_audio_sent:
316
+ self._track_tts_first_byte_latency()
317
+
265
318
  new_bytes = RasaAudioBytes(collected_audio_bytes[last_sent_offset:])
266
319
  await self.send_audio_bytes(recipient_id, new_bytes)
267
320
  except (WebsocketClosed, ServerError):
268
321
  # ignore sending error
269
- call_state.connection_failed = True # type: ignore[attr-defined]
322
+ call_state.connection_failed = True
323
+
324
+ # Track TTS completion time
325
+ self._track_tts_complete_latency()
270
326
 
271
327
  try:
272
328
  await self.send_end_marker(recipient_id)
273
329
  except (WebsocketClosed, ServerError):
274
330
  # ignore sending error
275
331
  pass
276
- call_state.latest_bot_audio_id = self.latest_message_id # type: ignore[attr-defined]
332
+ call_state.latest_bot_audio_id = self.latest_message_id
277
333
 
278
334
  if not cached_audio_bytes:
279
335
  self.tts_cache.put(text, collected_audio_bytes)
@@ -298,7 +354,7 @@ class VoiceOutputChannel(OutputChannel):
298
354
  return
299
355
 
300
356
  async def hangup(self, recipient_id: str, **kwargs: Any) -> None:
301
- call_state.should_hangup = True # type: ignore[attr-defined]
357
+ call_state.should_hangup = True
302
358
 
303
359
 
304
360
  class VoiceInputChannel(InputChannel):
@@ -345,32 +401,32 @@ class VoiceInputChannel(InputChannel):
345
401
  if call_state.silence_timeout_watcher:
346
402
  logger.debug("voice_channel.cancelling_current_timeout_watcher_task")
347
403
  call_state.silence_timeout_watcher.cancel()
348
- call_state.silence_timeout_watcher = None # type: ignore[attr-defined]
404
+ call_state.silence_timeout_watcher = None
349
405
 
350
406
  @classmethod
351
- def from_credentials(
352
- cls,
353
- credentials: Optional[Dict[str, Any]],
354
- ) -> InputChannel:
407
+ def validate_basic_credentials(cls, credentials: Optional[Dict[str, Any]]) -> None:
408
+ """Validate the basic credentials for the voice channel."""
355
409
  if not credentials:
356
410
  cls.raise_missing_credentials_exception()
357
-
358
- if not credentials.get("server_url"):
359
- raise InvalidConfigException("No server_url provided in credentials.")
360
- if not credentials.get("asr"):
411
+ if not isinstance(credentials, dict):
361
412
  raise InvalidConfigException(
362
- "No ASR configuration provided in credentials."
413
+ "Credentials must be a dictionary for voice channel."
363
414
  )
364
- if not credentials.get("tts"):
415
+
416
+ required_keys = {"server_url", "asr", "tts"}
417
+ credentials_keys = set(credentials.keys())
418
+ if not required_keys.issubset(credentials_keys):
419
+ missing_fields = required_keys - credentials_keys
365
420
  raise InvalidConfigException(
366
- "No TTS configuration provided in credentials."
421
+ f"Missing required fields in credentials: {', '.join(missing_fields)} "
422
+ f"for channel {cls.name()}"
367
423
  )
368
424
 
369
- return cls(
370
- server_url=credentials["server_url"],
371
- asr_config=credentials["asr"],
372
- tts_config=credentials["tts"],
373
- )
425
+ @classmethod
426
+ def from_credentials(
427
+ cls, credentials: Optional[Dict[str, Any]]
428
+ ) -> VoiceInputChannel:
429
+ raise NotImplementedError
374
430
 
375
431
  def channel_bytes_to_rasa_audio_bytes(self, input_bytes: bytes) -> RasaAudioBytes:
376
432
  raise NotImplementedError
@@ -439,10 +495,8 @@ class VoiceInputChannel(InputChannel):
439
495
  if was_bot_speaking_before and not is_bot_speaking_after:
440
496
  logger.debug("voice_channel.bot_stopped_speaking")
441
497
  self._cancel_silence_timeout_watcher()
442
- call_state.silence_timeout_watcher = ( # type: ignore[attr-defined]
443
- asyncio.create_task(
444
- self.monitor_silence_timeout(asr_event_queue)
445
- )
498
+ call_state.silence_timeout_watcher = asyncio.create_task(
499
+ self.monitor_silence_timeout(asr_event_queue)
446
500
  )
447
501
  if isinstance(channel_action, NewAudioAction):
448
502
  await asr_engine.send_audio_chunks(channel_action.audio_bytes)
@@ -468,10 +522,17 @@ class VoiceInputChannel(InputChannel):
468
522
  call_parameters,
469
523
  )
470
524
 
525
+ async def asr_keep_alive_task() -> None:
526
+ interval = getattr(asr_engine.config, "keep_alive_interval", 5)
527
+ while True:
528
+ await asyncio.sleep(interval)
529
+ await asr_engine.send_keep_alive()
530
+
471
531
  tasks = [
472
532
  asyncio.create_task(consume_audio_bytes()),
473
533
  asyncio.create_task(receive_asr_events()),
474
534
  asyncio.create_task(handle_asr_events()),
535
+ asyncio.create_task(asr_keep_alive_task()),
475
536
  ]
476
537
  await asyncio.wait(
477
538
  tasks,
@@ -491,6 +552,16 @@ class VoiceInputChannel(InputChannel):
491
552
  """Create a matching voice output channel for this voice input channel."""
492
553
  raise NotImplementedError
493
554
 
555
+ def _track_asr_latency(self) -> None:
556
+ """Track and log ASR processing latency."""
557
+ if call_state.user_speech_start_time:
558
+ call_state.asr_latency_ms = (
559
+ time.time() - call_state.user_speech_start_time
560
+ ) * 1000
561
+ logger.debug(
562
+ "voice_channel.asr_latency", latency_ms=call_state.asr_latency_ms
563
+ )
564
+
494
565
  async def handle_asr_event(
495
566
  self,
496
567
  e: ASREvent,
@@ -504,7 +575,12 @@ class VoiceInputChannel(InputChannel):
504
575
  logger.debug(
505
576
  "VoiceInputChannel.handle_asr_event.new_transcript", transcript=e.text
506
577
  )
507
- call_state.is_user_speaking = False # type: ignore[attr-defined]
578
+ call_state.is_user_speaking = False
579
+
580
+ # Track ASR and Rasa latencies
581
+ self._track_asr_latency()
582
+ call_state.rasa_processing_start_time = time.time()
583
+
508
584
  output_channel = self.create_output_channel(voice_websocket, tts_engine)
509
585
  message = UserMessage(
510
586
  text=e.text,
@@ -515,8 +591,11 @@ class VoiceInputChannel(InputChannel):
515
591
  )
516
592
  await on_new_message(message)
517
593
  elif isinstance(e, UserIsSpeaking):
594
+ # Track when user starts speaking for ASR latency calculation
595
+ if not call_state.is_user_speaking:
596
+ call_state.user_speech_start_time = time.time()
518
597
  self._cancel_silence_timeout_watcher()
519
- call_state.is_user_speaking = True # type: ignore[attr-defined]
598
+ call_state.is_user_speaking = True
520
599
  elif isinstance(e, UserSilence):
521
600
  output_channel = self.create_output_channel(voice_websocket, tts_engine)
522
601
  message = UserMessage(
rasa/core/nlg/callback.py CHANGED
@@ -19,7 +19,7 @@ def nlg_response_format_spec() -> Dict[Text, Any]:
19
19
  return {
20
20
  "type": "object",
21
21
  "properties": {
22
- "text": {"type": "string"},
22
+ "text": {"type": ["string", "null"]},
23
23
  "id": {"type": ["string", "null"]},
24
24
  "buttons": {"type": ["array", "null"], "items": {"type": "object"}},
25
25
  "elements": {"type": ["array", "null"], "items": {"type": "object"}},
@@ -24,6 +24,7 @@ from rasa.shared.constants import (
24
24
  )
25
25
  from rasa.shared.core.domain import KEY_RESPONSES_TEXT, Domain
26
26
  from rasa.shared.core.events import BotUttered, UserUttered
27
+ from rasa.shared.core.flows.constants import KEY_TRANSLATION
27
28
  from rasa.shared.core.trackers import DialogueStateTracker
28
29
  from rasa.shared.nlu.constants import (
29
30
  KEY_COMPONENT_NAME,
@@ -224,8 +225,10 @@ class ContextualResponseRephraser(
224
225
 
225
226
  @measure_llm_latency
226
227
  async def _generate_llm_response(self, prompt: str) -> Optional[LLMResponse]:
227
- """Use LLM to generate a response, returning an LLMResponse object
228
- containing both the generated text (choices) and metadata.
228
+ """Use LLM to generate a response.
229
+
230
+ Returns an LLMResponse object containing both the generated text
231
+ (choices) and metadata.
229
232
 
230
233
  Args:
231
234
  prompt: The prompt to send to the LLM.
@@ -305,7 +308,12 @@ class ContextualResponseRephraser(
305
308
  Returns:
306
309
  The response with the rephrased text.
307
310
  """
308
- if not (response_text := response.get(KEY_RESPONSES_TEXT)):
311
+ translation_response = response.get(KEY_TRANSLATION) or {}
312
+ lang_code = getattr(tracker.current_language, "code", None)
313
+ response_text = translation_response.get(
314
+ lang_code, response.get(KEY_RESPONSES_TEXT)
315
+ )
316
+ if not response_text:
309
317
  return response
310
318
 
311
319
  prompt_template_text = self._template_for_response_rephrasing(response)
@@ -367,12 +375,17 @@ class ContextualResponseRephraser(
367
375
  return response
368
376
 
369
377
  updated_text = llm_response.choices[0]
378
+
379
+ if lang_code in translation_response:
380
+ response[KEY_TRANSLATION][lang_code] = updated_text
381
+ else:
382
+ response[KEY_RESPONSES_TEXT] = updated_text
383
+
370
384
  structlogger.debug(
371
385
  "nlg.rewrite.complete",
372
386
  response_text=response_text,
373
387
  updated_text=updated_text,
374
388
  )
375
- response[KEY_RESPONSES_TEXT] = updated_text
376
389
  return response
377
390
 
378
391
  def does_response_allow_rephrasing(self, template: Dict[Text, Any]) -> bool:
@@ -406,12 +419,9 @@ class ContextualResponseRephraser(
406
419
  Returns:
407
420
  The generated response.
408
421
  """
409
- filled_slots = tracker.current_slot_values()
410
- stack_context = tracker.stack.current_context()
411
- templated_response = self.generate_from_slots(
422
+ templated_response = await super().generate(
412
423
  utter_action=utter_action,
413
- filled_slots=filled_slots,
414
- stack_context=stack_context,
424
+ tracker=tracker,
415
425
  output_channel=output_channel,
416
426
  **kwargs,
417
427
  )
@@ -6,6 +6,8 @@ from pypred import Predicate
6
6
 
7
7
  import rasa.shared.utils.common
8
8
  import rasa.shared.utils.io
9
+ from rasa.core.nlg.translate import has_translation
10
+ from rasa.engine.language import Language
9
11
  from rasa.shared.constants import CHANNEL, RESPONSE_CONDITION
10
12
  from rasa.shared.core.domain import Domain
11
13
  from rasa.shared.core.trackers import DialogueStateTracker
@@ -131,11 +133,23 @@ class ResponseVariationFilter:
131
133
 
132
134
  return True
133
135
 
136
+ def _filter_by_language(
137
+ self, responses: List[Dict[Text, Any]], language: Optional[Language] = None
138
+ ) -> List[Dict[Text, Any]]:
139
+ if not language:
140
+ return responses
141
+
142
+ if filtered := [r for r in responses if has_translation(r, language)]:
143
+ return filtered
144
+ # if no translation is found, return the original response variations
145
+ return responses
146
+
134
147
  def responses_for_utter_action(
135
148
  self,
136
149
  utter_action: Text,
137
150
  output_channel: Text,
138
151
  filled_slots: Dict[Text, Any],
152
+ language: Optional[Language] = None,
139
153
  ) -> List[Dict[Text, Any]]:
140
154
  """Returns array of responses that fit the channel, action and condition."""
141
155
  # filter responses without a condition
@@ -176,16 +190,16 @@ class ResponseVariationFilter:
176
190
  )
177
191
 
178
192
  if conditional_channel:
179
- return conditional_channel
193
+ return self._filter_by_language(conditional_channel, language)
180
194
 
181
195
  if default_channel:
182
- return default_channel
196
+ return self._filter_by_language(default_channel, language)
183
197
 
184
198
  if conditional_no_channel:
185
- return conditional_no_channel
199
+ return self._filter_by_language(conditional_no_channel, language)
186
200
 
187
201
  if default_no_channel:
188
- return default_no_channel
202
+ return self._filter_by_language(default_no_channel, language)
189
203
 
190
204
  # if there is no response variation selected,
191
205
  # return the internal error response to prevent
@@ -198,7 +212,9 @@ class ResponseVariationFilter:
198
212
  f"a default variation and that all the conditions are valid. "
199
213
  f"Returning the internal error response.",
200
214
  )
201
- return self.responses.get("utter_internal_error_rasa", [])
215
+ return self._filter_by_language(
216
+ self.responses.get("utter_internal_error_rasa", []), language
217
+ )
202
218
 
203
219
  def get_response_variation_id(
204
220
  self,
rasa/core/nlg/response.py CHANGED
@@ -5,8 +5,11 @@ from typing import Any, Dict, List, Optional, Text
5
5
  from rasa.core.constants import DEFAULT_TEMPLATE_ENGINE, TEMPLATE_ENGINE_CONFIG_KEY
6
6
  from rasa.core.nlg import interpolator
7
7
  from rasa.core.nlg.generator import NaturalLanguageGenerator, ResponseVariationFilter
8
- from rasa.shared.constants import RESPONSE_CONDITION
8
+ from rasa.core.nlg.translate import get_translated_buttons, get_translated_text
9
+ from rasa.engine.language import Language
10
+ from rasa.shared.constants import BUTTONS, RESPONSE_CONDITION, TEXT
9
11
  from rasa.shared.core.domain import RESPONSE_KEYS_TO_INTERPOLATE
12
+ from rasa.shared.core.flows.constants import KEY_TRANSLATION
10
13
  from rasa.shared.core.trackers import DialogueStateTracker
11
14
  from rasa.shared.nlu.constants import METADATA
12
15
 
@@ -30,7 +33,11 @@ class TemplatedNaturalLanguageGenerator(NaturalLanguageGenerator):
30
33
 
31
34
  # noinspection PyUnusedLocal
32
35
  def _random_response_for(
33
- self, utter_action: Text, output_channel: Text, filled_slots: Dict[Text, Any]
36
+ self,
37
+ utter_action: Text,
38
+ output_channel: Text,
39
+ filled_slots: Dict[Text, Any],
40
+ language: Optional[Language] = None,
34
41
  ) -> Optional[Dict[Text, Any]]:
35
42
  """Select random response for the utter action from available ones.
36
43
 
@@ -42,7 +49,7 @@ class TemplatedNaturalLanguageGenerator(NaturalLanguageGenerator):
42
49
  if utter_action in self.responses:
43
50
  response_filter = ResponseVariationFilter(self.responses)
44
51
  suitable_responses = response_filter.responses_for_utter_action(
45
- utter_action, output_channel, filled_slots
52
+ utter_action, output_channel, filled_slots, language
46
53
  )
47
54
 
48
55
  if suitable_responses:
@@ -75,9 +82,36 @@ class TemplatedNaturalLanguageGenerator(NaturalLanguageGenerator):
75
82
  """Generate a response for the requested utter action."""
76
83
  filled_slots = tracker.current_slot_values()
77
84
  stack_context = tracker.stack.current_context()
78
- return self.generate_from_slots(
79
- utter_action, filled_slots, stack_context, output_channel, **kwargs
85
+ response = self.generate_from_slots(
86
+ utter_action,
87
+ filled_slots,
88
+ stack_context,
89
+ output_channel,
90
+ tracker.current_language,
91
+ **kwargs,
80
92
  )
93
+ if response is not None:
94
+ return self.translate_response(response, tracker.current_language)
95
+ return None
96
+
97
+ def translate_response(
98
+ self, response: Dict[Text, Any], language: Optional[Language] = None
99
+ ) -> Dict[Text, Any]:
100
+ message_copy = copy.deepcopy(response)
101
+
102
+ text = get_translated_text(
103
+ text=message_copy.pop(TEXT, None),
104
+ translation=message_copy.pop(KEY_TRANSLATION, {}),
105
+ language=language,
106
+ )
107
+
108
+ buttons = get_translated_buttons(
109
+ buttons=message_copy.pop(BUTTONS, None), language=language
110
+ )
111
+ message_copy[TEXT] = text
112
+ if buttons:
113
+ message_copy[BUTTONS] = buttons
114
+ return message_copy
81
115
 
82
116
  def generate_from_slots(
83
117
  self,
@@ -85,12 +119,15 @@ class TemplatedNaturalLanguageGenerator(NaturalLanguageGenerator):
85
119
  filled_slots: Dict[Text, Any],
86
120
  stack_context: Dict[Text, Any],
87
121
  output_channel: Text,
122
+ language: Optional[Language] = None,
88
123
  **kwargs: Any,
89
124
  ) -> Optional[Dict[Text, Any]]:
90
125
  """Generate a response for the requested utter action."""
91
126
  # Fetching a random response for the passed utter action
92
127
  r = copy.deepcopy(
93
- self._random_response_for(utter_action, output_channel, filled_slots)
128
+ self._random_response_for(
129
+ utter_action, output_channel, filled_slots, language
130
+ )
94
131
  )
95
132
  # Filling the slots in the response with placeholders and returning the response
96
133
  if r is not None:
@@ -23,6 +23,14 @@ def get_translated_text(
23
23
  return translation.get(language_code, text)
24
24
 
25
25
 
26
+ def has_translation(
27
+ message: Dict[Text, Any], language: Optional[Language] = None
28
+ ) -> bool:
29
+ """Check if the message has a translation for the given language."""
30
+ language_code = language.code if language else None
31
+ return language_code in message.get(KEY_TRANSLATION, {})
32
+
33
+
26
34
  def get_translated_buttons(
27
35
  buttons: Optional[List[Dict[Text, Any]]], language: Optional[Language] = None
28
36
  ) -> Optional[List[Dict[Text, Any]]]:
@@ -50,6 +50,7 @@ from rasa.engine.graph import ExecutionContext
50
50
  from rasa.engine.recipes.default_recipe import DefaultV1Recipe
51
51
  from rasa.engine.storage.resource import Resource
52
52
  from rasa.engine.storage.storage import ModelStorage
53
+ from rasa.exceptions import EnterpriseSearchPolicyError
53
54
  from rasa.graph_components.providers.forms_provider import Forms
54
55
  from rasa.graph_components.providers.responses_provider import Responses
55
56
  from rasa.shared.constants import (
@@ -82,7 +83,6 @@ from rasa.shared.providers.embedding._langchain_embedding_client_adapter import
82
83
  _LangchainEmbeddingClientAdapter,
83
84
  )
84
85
  from rasa.shared.providers.llm.llm_response import LLMResponse, measure_llm_latency
85
- from rasa.shared.utils.cli import print_error_and_exit
86
86
  from rasa.shared.utils.constants import (
87
87
  LOG_COMPONENT_SOURCE_METHOD_FINGERPRINT_ADDON,
88
88
  LOG_COMPONENT_SOURCE_METHOD_INIT,
@@ -343,14 +343,11 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
343
343
  try:
344
344
  embeddings = self._create_plain_embedder(self.embeddings_config)
345
345
  except (ValidationError, Exception) as e:
346
- structlogger.error(
347
- "enterprise_search_policy.train.embedder_instantiation_failed",
348
- message="Unable to instantiate the embedding client.",
349
- error=e,
350
- )
351
- print_error_and_exit(
352
- "Unable to create embedder. Please make sure you specified the "
353
- f"required environment variables. Error: {e}"
346
+ raise EnterpriseSearchPolicyError(
347
+ code="core.policies.enterprise_search_policy.train"
348
+ ".embedder_instantiation_failed",
349
+ event_info=f"Unable to create embedder. Please make sure you "
350
+ f"specified the required environment variables. Error: {e}",
354
351
  )
355
352
 
356
353
  if self.vector_store_type == DEFAULT_VECTOR_STORE_TYPE:
@@ -679,7 +676,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
679
676
  answer_relevant = not _ENTERPRISE_SEARCH_ANSWER_NOT_RELEVANT_PATTERN.search(
680
677
  llm_answer
681
678
  )
682
- structlogger.debug("")
679
+
683
680
  return _RelevancyCheckResponse(
684
681
  answer=llm_answer if answer_relevant else None,
685
682
  relevant=answer_relevant,
@@ -788,25 +785,23 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
788
785
  "Please specify a valid path to the documents source directory in the "
789
786
  "vector_store configuration."
790
787
  )
791
- structlogger.error(
792
- "enterprise_search_policy.train.faiss.invalid_source_directory",
793
- message=error_message,
794
- docs_folder={os.path.abspath(docs_folder)},
795
- configuration_value=docs_folder,
788
+ error_code = (
789
+ "core.policies.enterprise_search_policy.train"
790
+ ".faiss.invalid_source_directory"
796
791
  )
797
- print_error_and_exit(error_message)
792
+ raise EnterpriseSearchPolicyError(code=error_code, event_info=error_message)
798
793
 
799
- docs = glob.glob(os.path.join(docs_folder, "**/*.txt"), recursive=True)
794
+ docs = glob.glob(os.path.join(docs_folder, "**", "*.txt"), recursive=True)
800
795
  if not docs or len(docs) < 1:
801
796
  error_message = (
802
797
  f"Document source directory is empty: '{docs_folder}'. "
803
798
  "Please add documents to this directory or specify a different one."
804
799
  )
805
- structlogger.error(
806
- "enterprise_search_policy.train.faiss.source_directory_empty",
807
- message=error_message,
800
+ error_code = (
801
+ "core.policies.enterprise_search_policy.train"
802
+ ".faiss.source_directory_empty"
808
803
  )
809
- print_error_and_exit(error_message)
804
+ raise EnterpriseSearchPolicyError(code=error_code, event_info=error_message)
810
805
 
811
806
  @classmethod
812
807
  def load(