rasa-pro 3.13.8__py3-none-any.whl → 3.14.0a1__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 (383) hide show
  1. rasa/builder/README.md +120 -0
  2. rasa/builder/__init__.py +0 -0
  3. rasa/builder/auth.py +176 -0
  4. rasa/builder/config.py +91 -0
  5. rasa/builder/copilot/__init__.py +0 -0
  6. rasa/builder/copilot/constants.py +28 -0
  7. rasa/builder/copilot/copilot.py +376 -0
  8. rasa/builder/copilot/copilot_response_handler.py +522 -0
  9. rasa/builder/copilot/copilot_templated_message_provider.py +58 -0
  10. rasa/builder/copilot/exceptions.py +32 -0
  11. rasa/builder/copilot/models.py +464 -0
  12. rasa/builder/copilot/prompts/__init__.py +0 -0
  13. rasa/builder/copilot/prompts/copilot_system_prompt.jinja2 +771 -0
  14. rasa/builder/copilot/signing.py +305 -0
  15. rasa/builder/copilot/telemetry.py +200 -0
  16. rasa/builder/copilot/templated_messages/__init__.py +0 -0
  17. rasa/builder/copilot/templated_messages/copilot_internal_messages_templates.yml +16 -0
  18. rasa/builder/copilot/templated_messages/copilot_templated_responses.yml +38 -0
  19. rasa/builder/document_retrieval/__init__.py +0 -0
  20. rasa/builder/document_retrieval/constants.py +15 -0
  21. rasa/builder/document_retrieval/inkeep-rag-response-schema.json +64 -0
  22. rasa/builder/document_retrieval/inkeep_document_retrieval.py +238 -0
  23. rasa/builder/document_retrieval/models.py +62 -0
  24. rasa/builder/download.py +147 -0
  25. rasa/builder/exceptions.py +91 -0
  26. rasa/builder/guardrails/__init__.py +1 -0
  27. rasa/builder/guardrails/constants.py +9 -0
  28. rasa/builder/guardrails/exceptions.py +4 -0
  29. rasa/builder/guardrails/lakera.py +206 -0
  30. rasa/builder/guardrails/models.py +231 -0
  31. rasa/builder/guardrails/store.py +238 -0
  32. rasa/builder/guardrails/utils.py +328 -0
  33. rasa/builder/job_manager.py +87 -0
  34. rasa/builder/jobs.py +276 -0
  35. rasa/builder/llm_service.py +246 -0
  36. rasa/builder/logging_utils.py +265 -0
  37. rasa/builder/main.py +199 -0
  38. rasa/builder/models.py +216 -0
  39. rasa/builder/project_generator.py +462 -0
  40. rasa/builder/project_info.py +72 -0
  41. rasa/builder/scrape_rasa_docs.py +97 -0
  42. rasa/builder/service.py +1335 -0
  43. rasa/builder/shared/tracker_context.py +212 -0
  44. rasa/builder/skill_to_bot_prompt.jinja2 +164 -0
  45. rasa/builder/training_service.py +183 -0
  46. rasa/builder/validation_service.py +97 -0
  47. rasa/cli/project_templates/basic/actions/__init__ +0 -0
  48. rasa/cli/project_templates/basic/actions/action_human_handoff.py +40 -0
  49. rasa/cli/project_templates/basic/config.yml +30 -0
  50. rasa/cli/project_templates/basic/credentials.yml +33 -0
  51. rasa/cli/project_templates/basic/data/data.md +9 -0
  52. rasa/cli/project_templates/basic/data/general/feedback.yml +21 -0
  53. rasa/cli/project_templates/basic/data/general/goodbye.yml +6 -0
  54. rasa/cli/project_templates/basic/data/general/hello.yml +6 -0
  55. rasa/cli/project_templates/basic/data/general/help.yml +6 -0
  56. rasa/cli/project_templates/basic/data/general/human_handoff.yml +16 -0
  57. rasa/cli/project_templates/basic/data/general/show_faqs.yml +6 -0
  58. rasa/cli/project_templates/basic/data/system/patterns/pattern_cannot_handle.yml +7 -0
  59. rasa/cli/project_templates/basic/data/system/patterns/pattern_completed.yml +7 -0
  60. rasa/cli/project_templates/basic/data/system/patterns/pattern_correction.yml +7 -0
  61. rasa/cli/project_templates/basic/data/system/patterns/pattern_search.yml +8 -0
  62. rasa/cli/project_templates/basic/data/system/patterns/pattern_session_start.yml +8 -0
  63. rasa/cli/project_templates/basic/docs/docs.md +5 -0
  64. rasa/cli/project_templates/basic/docs/template.txt +28 -0
  65. rasa/cli/project_templates/basic/domain/domain.md +9 -0
  66. rasa/cli/project_templates/basic/domain/general/feedback.yml +25 -0
  67. rasa/cli/project_templates/basic/domain/general/goodbye.yml +9 -0
  68. rasa/cli/project_templates/basic/domain/general/hello.yml +7 -0
  69. rasa/cli/project_templates/basic/domain/general/help.yml +21 -0
  70. rasa/cli/project_templates/basic/domain/general/human_handoff.yml +32 -0
  71. rasa/cli/project_templates/basic/domain/general/show_faqs.yml +14 -0
  72. rasa/cli/project_templates/basic/domain/system/patterns/pattern_cannot_handle.yml +5 -0
  73. rasa/cli/project_templates/basic/domain/system/patterns/pattern_session_start.yml +19 -0
  74. rasa/cli/project_templates/basic/endpoints.yml +77 -0
  75. rasa/cli/project_templates/basic/prompts/rephraser_demo_personality_prompt.jinja2 +38 -0
  76. rasa/cli/project_templates/default/config.yml +5 -1
  77. rasa/cli/project_templates/default/endpoints.yml +15 -0
  78. rasa/cli/project_templates/finance/actions/__init__.py +46 -0
  79. rasa/cli/project_templates/finance/actions/accounts/__init__.py +0 -0
  80. rasa/cli/project_templates/finance/actions/accounts/action_ask_account.py +47 -0
  81. rasa/cli/project_templates/finance/actions/accounts/action_check_balance.py +40 -0
  82. rasa/cli/project_templates/finance/actions/action_session_start.py +74 -0
  83. rasa/cli/project_templates/finance/actions/cards/__init__.py +0 -0
  84. rasa/cli/project_templates/finance/actions/cards/action_ask_card.py +48 -0
  85. rasa/cli/project_templates/finance/actions/cards/action_check_card_existence.py +36 -0
  86. rasa/cli/project_templates/finance/actions/cards/action_update_card_status.py +54 -0
  87. rasa/cli/project_templates/finance/actions/database.py +277 -0
  88. rasa/cli/project_templates/finance/actions/transfers/__init__.py +0 -0
  89. rasa/cli/project_templates/finance/actions/transfers/action_add_payee.py +52 -0
  90. rasa/cli/project_templates/finance/actions/transfers/action_ask_account_from.py +51 -0
  91. rasa/cli/project_templates/finance/actions/transfers/action_check_payee_existence.py +40 -0
  92. rasa/cli/project_templates/finance/actions/transfers/action_check_sufficient_funds.py +40 -0
  93. rasa/cli/project_templates/finance/actions/transfers/action_list_payees.py +46 -0
  94. rasa/cli/project_templates/finance/actions/transfers/action_process_immediate_payment.py +18 -0
  95. rasa/cli/project_templates/finance/actions/transfers/action_remove_payee.py +49 -0
  96. rasa/cli/project_templates/finance/actions/transfers/action_schedule_payment.py +19 -0
  97. rasa/cli/project_templates/finance/actions/transfers/action_validate_payment_date.py +36 -0
  98. rasa/cli/project_templates/finance/config.yml +23 -0
  99. rasa/cli/project_templates/finance/credentials.yml +32 -0
  100. rasa/cli/project_templates/finance/csvs/accounts.csv +8 -0
  101. rasa/cli/project_templates/finance/csvs/advisors.csv +7 -0
  102. rasa/cli/project_templates/finance/csvs/appointments.csv +211 -0
  103. rasa/cli/project_templates/finance/csvs/branches.csv +10 -0
  104. rasa/cli/project_templates/finance/csvs/cards.csv +11 -0
  105. rasa/cli/project_templates/finance/csvs/payees.csv +11 -0
  106. rasa/cli/project_templates/finance/csvs/transactions.csv +71 -0
  107. rasa/cli/project_templates/finance/csvs/users.csv +4 -0
  108. rasa/cli/project_templates/finance/data/accounts/check_balance.yml +10 -0
  109. rasa/cli/project_templates/finance/data/cards/block_card.yml +66 -0
  110. rasa/cli/project_templates/finance/data/cards/select_card.yml +12 -0
  111. rasa/cli/project_templates/finance/data/general/bot_identity.yml +6 -0
  112. rasa/cli/project_templates/finance/data/general/feedback.yml +20 -0
  113. rasa/cli/project_templates/finance/data/general/goodbye.yml +6 -0
  114. rasa/cli/project_templates/finance/data/general/hello.yml +7 -0
  115. rasa/cli/project_templates/finance/data/general/help.yml +9 -0
  116. rasa/cli/project_templates/finance/data/general/human_handoff.yml +16 -0
  117. rasa/cli/project_templates/finance/data/general/welcome.yml +9 -0
  118. rasa/cli/project_templates/finance/data/system/patterns/pattern_chitchat.yml +5 -0
  119. rasa/cli/project_templates/finance/data/system/patterns/pattern_completed.yml +7 -0
  120. rasa/cli/project_templates/finance/data/system/patterns/pattern_correction.yml +7 -0
  121. rasa/cli/project_templates/finance/data/system/patterns/pattern_search.yml +8 -0
  122. rasa/cli/project_templates/finance/data/system/patterns/pattern_session_start.yml +8 -0
  123. rasa/cli/project_templates/finance/data/system/source/accounts.json +51 -0
  124. rasa/cli/project_templates/finance/data/system/source/advisors.json +44 -0
  125. rasa/cli/project_templates/finance/data/system/source/appointments.json +1474 -0
  126. rasa/cli/project_templates/finance/data/system/source/branches.json +47 -0
  127. rasa/cli/project_templates/finance/data/system/source/cards.json +72 -0
  128. rasa/cli/project_templates/finance/data/system/source/payees.json +74 -0
  129. rasa/cli/project_templates/finance/data/system/source/transactions.json +492 -0
  130. rasa/cli/project_templates/finance/data/system/source/users.json +29 -0
  131. rasa/cli/project_templates/finance/data/transfers/add_payee.yml +29 -0
  132. rasa/cli/project_templates/finance/data/transfers/list_payees.yml +5 -0
  133. rasa/cli/project_templates/finance/data/transfers/remove_payee.yml +21 -0
  134. rasa/cli/project_templates/finance/data/transfers/transfer_money.yml +67 -0
  135. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/consequences_of_blocking_card.txt +8 -0
  136. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/reasons_to_block_card.txt +8 -0
  137. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/recovering_from_card_fraud.txt +8 -0
  138. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/tips_for_card_security.txt +8 -0
  139. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/what_to_do_if_card_is_lost.txt +8 -0
  140. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/account_balance_security.txt +7 -0
  141. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/common_balance_inquiries.txt +8 -0
  142. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/methods_to_check_balance.txt +8 -0
  143. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/understanding_balance_updates.txt +8 -0
  144. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/what_to_do_if_balance_is_incorrect.txt +8 -0
  145. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/benefits_of_authorised_payees.txt +8 -0
  146. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/common_issues_with_payees.txt +8 -0
  147. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/general_payee_information.txt +8 -0
  148. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/payee_management_tips.txt +8 -0
  149. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/understanding_payee_types.txt +8 -0
  150. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/common_transfer_errors.txt +8 -0
  151. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/fees_for_transfers.txt +8 -0
  152. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/general_transfer_information.txt +8 -0
  153. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/security_tips_for_transfers.txt +8 -0
  154. rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/transfer_processing_times.txt +8 -0
  155. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part1.txt +50 -0
  156. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part10.txt +50 -0
  157. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part11.txt +48 -0
  158. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part12.txt +50 -0
  159. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part13.txt +50 -0
  160. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part14.txt +47 -0
  161. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part15.txt +50 -0
  162. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part16.txt +50 -0
  163. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part17.txt +47 -0
  164. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part18.txt +50 -0
  165. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part19.txt +50 -0
  166. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part2.txt +50 -0
  167. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part20.txt +47 -0
  168. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part21.txt +50 -0
  169. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part22.txt +50 -0
  170. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part23.txt +47 -0
  171. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part24.txt +50 -0
  172. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part25.txt +50 -0
  173. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part26.txt +47 -0
  174. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part27.txt +50 -0
  175. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part28.txt +50 -0
  176. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part29.txt +47 -0
  177. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part3.txt +47 -0
  178. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part30.txt +50 -0
  179. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part31.txt +50 -0
  180. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part32.txt +47 -0
  181. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part33.txt +50 -0
  182. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part34.txt +50 -0
  183. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part35.txt +47 -0
  184. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part36.txt +50 -0
  185. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part37.txt +50 -0
  186. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part38.txt +47 -0
  187. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part39.txt +50 -0
  188. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part4.txt +50 -0
  189. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part40.txt +50 -0
  190. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part41.txt +47 -0
  191. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part42.txt +50 -0
  192. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part43.txt +50 -0
  193. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part44.txt +47 -0
  194. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part45.txt +50 -0
  195. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part46.txt +50 -0
  196. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part47.txt +47 -0
  197. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part48.txt +50 -0
  198. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part49.txt +50 -0
  199. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part5.txt +50 -0
  200. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part50.txt +47 -0
  201. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part51.txt +50 -0
  202. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part52.txt +50 -0
  203. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part53.txt +47 -0
  204. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part54.txt +50 -0
  205. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part55.txt +50 -0
  206. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part56.txt +47 -0
  207. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part57.txt +50 -0
  208. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part58.txt +50 -0
  209. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part59.txt +47 -0
  210. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part6.txt +47 -0
  211. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part60.txt +50 -0
  212. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part61.txt +50 -0
  213. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part7.txt +50 -0
  214. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part8.txt +50 -0
  215. rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part9.txt +47 -0
  216. rasa/cli/project_templates/finance/domain/accounts/check_balance.yml +11 -0
  217. rasa/cli/project_templates/finance/domain/cards/block_card.yml +101 -0
  218. rasa/cli/project_templates/finance/domain/cards/select_card.yml +12 -0
  219. rasa/cli/project_templates/finance/domain/general/assistant_details.yml +12 -0
  220. rasa/cli/project_templates/finance/domain/general/bot_identity.yml +5 -0
  221. rasa/cli/project_templates/finance/domain/general/cannot_handle.yml +5 -0
  222. rasa/cli/project_templates/finance/domain/general/defaults.yml +24 -0
  223. rasa/cli/project_templates/finance/domain/general/feedback.yml +28 -0
  224. rasa/cli/project_templates/finance/domain/general/goodbye.yml +7 -0
  225. rasa/cli/project_templates/finance/domain/general/help.yml +5 -0
  226. rasa/cli/project_templates/finance/domain/general/human_handoff.yml +30 -0
  227. rasa/cli/project_templates/finance/domain/general/utils.yml +13 -0
  228. rasa/cli/project_templates/finance/domain/general/welcome.yml +8 -0
  229. rasa/cli/project_templates/finance/domain/transfers/add_payee.yml +47 -0
  230. rasa/cli/project_templates/finance/domain/transfers/list_payees.yml +4 -0
  231. rasa/cli/project_templates/finance/domain/transfers/remove_payee.yml +16 -0
  232. rasa/cli/project_templates/finance/domain/transfers/transfer_money.yml +79 -0
  233. rasa/cli/project_templates/finance/endpoints.yml +76 -0
  234. rasa/cli/project_templates/finance/prompts/rephraser_demo_personality_prompt.jinja2 +19 -0
  235. rasa/cli/project_templates/telco/actions/__init__.py +0 -0
  236. rasa/cli/project_templates/telco/actions/billing/__init__.py +0 -0
  237. rasa/cli/project_templates/telco/actions/billing/actions_billing.py +204 -0
  238. rasa/cli/project_templates/telco/actions/general/__init__.py +0 -0
  239. rasa/cli/project_templates/telco/actions/general/action_human_handoff.py +49 -0
  240. rasa/cli/project_templates/telco/actions/network/__init__.py +0 -0
  241. rasa/cli/project_templates/telco/actions/network/actions_get_data_from_db.py +48 -0
  242. rasa/cli/project_templates/telco/actions/network/actions_run_diagnostics.py +28 -0
  243. rasa/cli/project_templates/telco/actions/network/actions_session_start.py +18 -0
  244. rasa/cli/project_templates/telco/config.yml +29 -0
  245. rasa/cli/project_templates/telco/credentials.yml +33 -0
  246. rasa/cli/project_templates/telco/csvs/billing.csv +19 -0
  247. rasa/cli/project_templates/telco/csvs/customers.csv +5 -0
  248. rasa/cli/project_templates/telco/data/billing/flow_understand_bill.yml +45 -0
  249. rasa/cli/project_templates/telco/data/general/bot_challenge.yml +6 -0
  250. rasa/cli/project_templates/telco/data/general/feedback.yml +20 -0
  251. rasa/cli/project_templates/telco/data/general/goodbye.yml +6 -0
  252. rasa/cli/project_templates/telco/data/general/hello.yml +6 -0
  253. rasa/cli/project_templates/telco/data/general/human_handoff.yml +16 -0
  254. rasa/cli/project_templates/telco/data/general/patterns.yml +30 -0
  255. rasa/cli/project_templates/telco/data/network/flow_reboot_router.yml +8 -0
  256. rasa/cli/project_templates/telco/data/network/flow_reset_router.yml +7 -0
  257. rasa/cli/project_templates/telco/data/network/flow_solve_internet_issue.yml +73 -0
  258. rasa/cli/project_templates/telco/docs/docs.md +5 -0
  259. rasa/cli/project_templates/telco/docs/network/reset_vs_rboot_router.txt +1 -0
  260. rasa/cli/project_templates/telco/docs/network/restart_router.txt +6 -0
  261. rasa/cli/project_templates/telco/docs/network/run_speed_test.txt +6 -0
  262. rasa/cli/project_templates/telco/domain/billing/domain_undertand_bill.yml +102 -0
  263. rasa/cli/project_templates/telco/domain/general/bot_challenge.yml +4 -0
  264. rasa/cli/project_templates/telco/domain/general/feedback.yml +25 -0
  265. rasa/cli/project_templates/telco/domain/general/goodbye.yml +7 -0
  266. rasa/cli/project_templates/telco/domain/general/hello.yml +5 -0
  267. rasa/cli/project_templates/telco/domain/general/human_handoff.yml +29 -0
  268. rasa/cli/project_templates/telco/domain/general/patterns.yml +33 -0
  269. rasa/cli/project_templates/telco/domain/network/domain_reboot_router.yml +21 -0
  270. rasa/cli/project_templates/telco/domain/network/domain_reset_router.yml +12 -0
  271. rasa/cli/project_templates/telco/domain/network/domain_run_speed_test.yml +25 -0
  272. rasa/cli/project_templates/telco/domain/network/domain_solve_internet_issue.yml +75 -0
  273. rasa/cli/project_templates/telco/domain/shared.yml +129 -0
  274. rasa/cli/project_templates/telco/endpoints.yml +77 -0
  275. rasa/cli/project_templates/telco/prompts/rephraser_demo_personality_prompt.jinja2 +40 -0
  276. rasa/cli/project_templates/tutorial/config.yml +2 -1
  277. rasa/cli/scaffold.py +46 -2
  278. rasa/cli/train.py +2 -2
  279. rasa/core/actions/action.py +27 -38
  280. rasa/core/actions/action_run_slot_rejections.py +1 -1
  281. rasa/core/channels/channel.py +4 -3
  282. rasa/core/channels/constants.py +3 -0
  283. rasa/core/channels/development_inspector.py +48 -15
  284. rasa/core/channels/inspector/dist/assets/{arc-0b11fe30.js → arc-18042c22.js} +1 -1
  285. rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-9eef30a7.js → blockDiagram-38ab4fdb-fdd6bcfa.js} +1 -1
  286. rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-03e94f28.js → c4Diagram-3d4e48cf-f5ae6786.js} +1 -1
  287. rasa/core/channels/inspector/dist/assets/channel-b9b536fc.js +1 -0
  288. rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-95c09eba.js → classDiagram-70f12bd4-81efba3e.js} +1 -1
  289. rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-38e8446c.js → classDiagram-v2-f2320105-3b6b6a92.js} +1 -1
  290. rasa/core/channels/inspector/dist/assets/clone-78d2ddcf.js +1 -0
  291. rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-57dc3038.js → createText-2e5e7dd3-31422447.js} +1 -1
  292. rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-4bac0545.js → edges-e0da2a9e-518a90db.js} +1 -1
  293. rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-81795c90.js → erDiagram-9861fffd-a6d3c25a.js} +1 -1
  294. rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-89489ae6.js → flowDb-956e92f1-e048c2be.js} +1 -1
  295. rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-cd152627.js → flowDiagram-66a62f08-c7474c91.js} +1 -1
  296. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-8b09c060.js +1 -0
  297. rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-3da369bc.js → flowchart-elk-definition-4a651766-cb4d8723.js} +1 -1
  298. rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-85ec16f8.js → ganttDiagram-c361ad54-346636a2.js} +1 -1
  299. rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-495bc140.js → gitGraphDiagram-72cf32ee-7c508874.js} +1 -1
  300. rasa/core/channels/inspector/dist/assets/{graph-1ec4d266.js → graph-14702d8a.js} +1 -1
  301. rasa/core/channels/inspector/dist/assets/{index-3862675e-0a0e97c9.js → index-3862675e-f18b534b.js} +1 -1
  302. rasa/core/channels/inspector/dist/assets/{index-c804b295.js → index-4d4bdf3a.js} +254 -254
  303. rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-4d54bcde.js → infoDiagram-f8f76790-64154b83.js} +1 -1
  304. rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-dc097114.js → journeyDiagram-49397b02-833a5f95.js} +1 -1
  305. rasa/core/channels/inspector/dist/assets/{layout-1a08981e.js → layout-5a3b2123.js} +1 -1
  306. rasa/core/channels/inspector/dist/assets/{line-95f7f1d3.js → line-2272a8c7.js} +1 -1
  307. rasa/core/channels/inspector/dist/assets/{linear-97e69543.js → linear-35bcf273.js} +1 -1
  308. rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-8c71ff03.js → mindmap-definition-fc14e90a-92dcb0e9.js} +1 -1
  309. rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-f14c71c7.js → pieDiagram-8a3498a8-94dbc900.js} +1 -1
  310. rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-f1d3c9ff.js → quadrantDiagram-120e2f19-8b7a9c33.js} +1 -1
  311. rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-bfa2412f.js → requirementDiagram-deff3bca-6f7eab81.js} +1 -1
  312. rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-53f2c97b.js → sankeyDiagram-04a897e0-f43e581d.js} +1 -1
  313. rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-319d7c0e.js → sequenceDiagram-704730f1-0bcbefc3.js} +1 -1
  314. rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-76a09418.js → stateDiagram-587899a1-b8a74083.js} +1 -1
  315. rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-a67f15d4.js → stateDiagram-v2-d93cdb3a-2070218f.js} +1 -1
  316. rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-0654e7c3.js → styles-6aaf32cf-f1d54e34.js} +1 -1
  317. rasa/core/channels/inspector/dist/assets/{styles-9a916d00-1394bb9d.js → styles-9a916d00-980de489.js} +1 -1
  318. rasa/core/channels/inspector/dist/assets/{styles-c10674c1-e4c5bdae.js → styles-c10674c1-3c03abde.js} +1 -1
  319. rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-50957104.js → svgDrawCommon-08f97a94-46ba068f.js} +1 -1
  320. rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-b0885a6a.js → timeline-definition-85554ec2-901f5e3d.js} +1 -1
  321. rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-79e6541a.js → xychartDiagram-e933f94c-acbc628a.js} +1 -1
  322. rasa/core/channels/inspector/dist/index.html +1 -1
  323. rasa/core/channels/inspector/src/App.tsx +60 -15
  324. rasa/core/channels/inspector/src/components/Chat.tsx +3 -2
  325. rasa/core/channels/inspector/src/components/DiagramFlow.tsx +1 -1
  326. rasa/core/channels/inspector/src/components/DialogueInformation.tsx +12 -3
  327. rasa/core/channels/inspector/src/components/LatencyDisplay.tsx +268 -0
  328. rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +6 -2
  329. rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +8 -3
  330. rasa/core/channels/inspector/src/types.ts +8 -0
  331. rasa/core/channels/socketio.py +212 -51
  332. rasa/core/channels/studio_chat.py +161 -50
  333. rasa/core/channels/voice_ready/twilio_voice.py +1 -1
  334. rasa/core/channels/voice_stream/audiocodes.py +9 -6
  335. rasa/core/channels/voice_stream/browser_audio.py +39 -4
  336. rasa/core/channels/voice_stream/call_state.py +13 -2
  337. rasa/core/channels/voice_stream/genesys.py +16 -13
  338. rasa/core/channels/voice_stream/jambonz.py +13 -11
  339. rasa/core/channels/voice_stream/twilio_media_streams.py +14 -13
  340. rasa/core/channels/voice_stream/util.py +11 -1
  341. rasa/core/channels/voice_stream/voice_channel.py +106 -32
  342. rasa/core/nlg/contextual_response_rephraser.py +11 -7
  343. rasa/core/nlg/generator.py +21 -5
  344. rasa/core/nlg/response.py +43 -6
  345. rasa/core/nlg/translate.py +8 -0
  346. rasa/core/policies/enterprise_search_policy.py +4 -7
  347. rasa/core/policies/flows/flow_executor.py +8 -1
  348. rasa/core/run.py +13 -3
  349. rasa/dialogue_understanding/generator/flow_retrieval.py +10 -9
  350. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +1 -1
  351. rasa/dialogue_understanding_test/du_test_schema.yml +3 -3
  352. rasa/e2e_test/e2e_test_schema.yml +3 -3
  353. rasa/model_manager/model_api.py +4 -5
  354. rasa/model_manager/runner_service.py +1 -1
  355. rasa/model_manager/socket_bridge.py +27 -15
  356. rasa/model_manager/trainer_service.py +12 -9
  357. rasa/model_manager/utils.py +1 -29
  358. rasa/shared/core/domain.py +62 -15
  359. rasa/shared/core/flows/flow_step.py +7 -1
  360. rasa/shared/core/flows/steps/call.py +8 -1
  361. rasa/shared/core/flows/yaml_flows_io.py +16 -8
  362. rasa/shared/core/slots.py +4 -0
  363. rasa/shared/importers/importer.py +6 -0
  364. rasa/shared/importers/utils.py +77 -1
  365. rasa/shared/utils/common.py +2 -1
  366. rasa/studio/upload.py +12 -46
  367. rasa/telemetry.py +97 -23
  368. rasa/utils/io.py +27 -9
  369. rasa/utils/json_utils.py +6 -1
  370. rasa/utils/licensing.py +21 -10
  371. rasa/utils/log_utils.py +5 -1
  372. rasa/utils/openapi.py +144 -0
  373. rasa/utils/plotting.py +1 -1
  374. rasa/validator.py +7 -3
  375. rasa/version.py +1 -1
  376. {rasa_pro-3.13.8.dist-info → rasa_pro-3.14.0a1.dist-info}/METADATA +22 -23
  377. {rasa_pro-3.13.8.dist-info → rasa_pro-3.14.0a1.dist-info}/RECORD +380 -104
  378. rasa/core/channels/inspector/dist/assets/channel-51d02e9e.js +0 -1
  379. rasa/core/channels/inspector/dist/assets/clone-cc738fa6.js +0 -1
  380. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-0c716443.js +0 -1
  381. {rasa_pro-3.13.8.dist-info → rasa_pro-3.14.0a1.dist-info}/NOTICE +0 -0
  382. {rasa_pro-3.13.8.dist-info → rasa_pro-3.14.0a1.dist-info}/WHEEL +0 -0
  383. {rasa_pro-3.13.8.dist-info → rasa_pro-3.14.0a1.dist-info}/entry_points.txt +0 -0
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import audioop
2
4
  import json
3
5
  import uuid
@@ -20,6 +22,7 @@ from rasa.core.channels.voice_ready.utils import (
20
22
  from rasa.core.channels.voice_stream.audio_bytes import RasaAudioBytes
21
23
  from rasa.core.channels.voice_stream.call_state import call_state
22
24
  from rasa.core.channels.voice_stream.tts.tts_engine import TTSEngine
25
+ from rasa.core.channels.voice_stream.util import repack_voice_credentials
23
26
  from rasa.core.channels.voice_stream.voice_channel import (
24
27
  ContinueConversationAction,
25
28
  EndConversationAction,
@@ -35,7 +38,7 @@ JAMBONZ_STREAMS_WEBSOCKET_PATH = "webhooks/jambonz_stream/websocket"
35
38
 
36
39
 
37
40
  def map_call_params(data: Dict[Text, str]) -> CallParameters:
38
- """Map the twilio stream parameters to the CallParameters dataclass."""
41
+ """Map the Jambonz stream parameters to the CallParameters dataclass."""
39
42
  call_sid = data.get("callSid", "None")
40
43
  from_number = data.get("from", "Unknown")
41
44
  to_number = data.get("to")
@@ -94,7 +97,7 @@ class JambonzStreamInputChannel(VoiceInputChannel):
94
97
  @classmethod
95
98
  def from_credentials(
96
99
  cls, credentials: Optional[Dict[Text, Any]]
97
- ) -> "JambonzStreamInputChannel":
100
+ ) -> JambonzStreamInputChannel:
98
101
  """Create a channel from credentials dictionary.
99
102
 
100
103
  Args:
@@ -109,19 +112,18 @@ class JambonzStreamInputChannel(VoiceInputChannel):
109
112
  JambonzStreamInputChannel instance
110
113
  """
111
114
  # Get common credentials from parent
112
- channel = super().from_credentials(credentials)
115
+ cls.validate_credentials(credentials)
116
+ new_creds = repack_voice_credentials(credentials)
117
+ return cls(**new_creds)
113
118
 
119
+ @classmethod
120
+ def validate_credentials(cls, credentials: Optional[Dict[Text, Any]]) -> None:
121
+ cls.validate_basic_credentials(credentials)
114
122
  # Check optional basic auth credentials
115
123
  username = credentials.get("username") # type: ignore[union-attr]
116
124
  password = credentials.get("password") # type: ignore[union-attr]
117
125
  validate_username_password_credentials(username, password, "Jambonz Stream")
118
126
 
119
- # Update channel with auth credentials
120
- channel.username = username # type: ignore[attr-defined]
121
- channel.password = password # type: ignore[attr-defined]
122
-
123
- return channel # type: ignore[return-value]
124
-
125
127
  def _websocket_stream_url(self) -> str:
126
128
  """Returns the websocket stream URL."""
127
129
  # depending on the config value, the url might contain http as a
@@ -158,14 +160,14 @@ class JambonzStreamInputChannel(VoiceInputChannel):
158
160
  if data["type"] == "mark":
159
161
  if data["data"]["name"] == call_state.latest_bot_audio_id:
160
162
  # Just finished streaming last audio bytes
161
- call_state.is_bot_speaking = False # type: ignore[attr-defined]
163
+ call_state.is_bot_speaking = False
162
164
  if call_state.should_hangup:
163
165
  logger.debug(
164
166
  "jambonz.hangup", marker=call_state.latest_bot_audio_id
165
167
  )
166
168
  return EndConversationAction()
167
169
  else:
168
- call_state.is_bot_speaking = True # type: ignore[attr-defined]
170
+ call_state.is_bot_speaking = True
169
171
  elif data["event"] == "dtmf":
170
172
  # TODO: handle DTMF input
171
173
  logger.debug("jambonz.dtmf.received", dtmf=data["dtmf"])
@@ -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
 
@@ -8,6 +11,11 @@ from sanic import Websocket # type: ignore
8
11
  from sanic.exceptions import ServerError, WebsocketClosed
9
12
 
10
13
  from rasa.core.channels import InputChannel, OutputChannel, UserMessage
14
+ from rasa.core.channels.constants import (
15
+ USER_CONVERSATION_SESSION_END,
16
+ USER_CONVERSATION_SESSION_START,
17
+ USER_CONVERSATION_SILENCE_TIMEOUT,
18
+ )
11
19
  from rasa.core.channels.voice_ready.utils import (
12
20
  CallParameters,
13
21
  validate_voice_license_scope,
@@ -45,9 +53,6 @@ from rasa.utils.io import remove_emojis
45
53
  logger = structlog.get_logger(__name__)
46
54
 
47
55
  # define constants for the voice channel
48
- USER_CONVERSATION_SESSION_END = "/session_end"
49
- USER_CONVERSATION_SESSION_START = "/session_start"
50
- USER_CONVERSATION_SILENCE_TIMEOUT = "/silence_timeout"
51
56
 
52
57
 
53
58
  @dataclass
@@ -189,7 +194,7 @@ class VoiceOutputChannel(OutputChannel):
189
194
  def update_silence_timeout(self) -> None:
190
195
  """Updates the silence timeout for the session."""
191
196
  if self.tracker_state:
192
- call_state.silence_timeout = self.tracker_state["slots"][ # type: ignore[attr-defined]
197
+ call_state.silence_timeout = self.tracker_state["slots"][
193
198
  SILENCE_TIMEOUT_SLOT
194
199
  ]
195
200
  logger.debug(
@@ -207,22 +212,63 @@ class VoiceOutputChannel(OutputChannel):
207
212
  """Uses the concise button output format for voice channels."""
208
213
  await self.send_text_with_buttons_concise(recipient_id, text, buttons, **kwargs)
209
214
 
215
+ def _track_rasa_processing_latency(self) -> None:
216
+ """Track and log Rasa processing completion latency."""
217
+ if call_state.rasa_processing_start_time:
218
+ call_state.rasa_processing_latency_ms = (
219
+ time.time() - call_state.rasa_processing_start_time
220
+ ) * 1000
221
+ logger.debug(
222
+ "voice_channel.rasa_processing_latency",
223
+ latency_ms=call_state.rasa_processing_latency_ms,
224
+ )
225
+
226
+ def _track_tts_first_byte_latency(self) -> None:
227
+ """Track and log TTS first byte latency."""
228
+ if call_state.tts_start_time:
229
+ call_state.tts_first_byte_latency_ms = (
230
+ time.time() - call_state.tts_start_time
231
+ ) * 1000
232
+ logger.debug(
233
+ "voice_channel.tts_first_byte_latency",
234
+ latency_ms=call_state.tts_first_byte_latency_ms,
235
+ )
236
+
237
+ def _track_tts_complete_latency(self) -> None:
238
+ """Track and log TTS completion latency."""
239
+ if call_state.tts_start_time:
240
+ call_state.tts_complete_latency_ms = (
241
+ time.time() - call_state.tts_start_time
242
+ ) * 1000
243
+ logger.debug(
244
+ "voice_channel.tts_complete_latency",
245
+ latency_ms=call_state.tts_complete_latency_ms,
246
+ )
247
+
210
248
  async def send_text_message(
211
249
  self, recipient_id: str, text: str, **kwargs: Any
212
250
  ) -> None:
213
251
  text = remove_emojis(text)
214
252
  self.update_silence_timeout()
253
+
254
+ # Track Rasa processing completion
255
+ self._track_rasa_processing_latency()
256
+
257
+ # Track TTS start time
258
+ call_state.tts_start_time = time.time()
259
+
215
260
  cached_audio_bytes = self.tts_cache.get(text)
216
261
  collected_audio_bytes = RasaAudioBytes(b"")
217
262
  seconds_marker = -1
218
263
  last_sent_offset = 0
264
+ first_audio_sent = False
219
265
  logger.debug("voice_channel.sending_audio", text=text)
220
266
 
221
267
  # Send start marker before first chunk
222
268
  try:
223
269
  await self.send_start_marker(recipient_id)
224
270
  except (WebsocketClosed, ServerError):
225
- call_state.connection_failed = True # type: ignore[attr-defined]
271
+ call_state.connection_failed = True
226
272
 
227
273
  if cached_audio_bytes:
228
274
  audio_stream = self.chunk_audio(cached_audio_bytes)
@@ -244,6 +290,11 @@ class VoiceOutputChannel(OutputChannel):
244
290
 
245
291
  if should_send:
246
292
  try:
293
+ # Track TTS first byte time
294
+ if not first_audio_sent:
295
+ self._track_tts_first_byte_latency()
296
+ first_audio_sent = True
297
+
247
298
  # Send only the new bytes since last send
248
299
  new_bytes = RasaAudioBytes(collected_audio_bytes[last_sent_offset:])
249
300
  await self.send_audio_bytes(recipient_id, new_bytes)
@@ -256,24 +307,31 @@ class VoiceOutputChannel(OutputChannel):
256
307
 
257
308
  except (WebsocketClosed, ServerError):
258
309
  # ignore sending error, and keep collecting and caching audio bytes
259
- call_state.connection_failed = True # type: ignore[attr-defined]
310
+ call_state.connection_failed = True
260
311
 
261
312
  # Send any remaining audio not yet sent
262
313
  remaining_bytes = len(collected_audio_bytes) - last_sent_offset
263
314
  if remaining_bytes > 0:
264
315
  try:
316
+ # Track TTS first byte time if not already tracked
317
+ if not first_audio_sent:
318
+ self._track_tts_first_byte_latency()
319
+
265
320
  new_bytes = RasaAudioBytes(collected_audio_bytes[last_sent_offset:])
266
321
  await self.send_audio_bytes(recipient_id, new_bytes)
267
322
  except (WebsocketClosed, ServerError):
268
323
  # ignore sending error
269
- call_state.connection_failed = True # type: ignore[attr-defined]
324
+ call_state.connection_failed = True
325
+
326
+ # Track TTS completion time
327
+ self._track_tts_complete_latency()
270
328
 
271
329
  try:
272
330
  await self.send_end_marker(recipient_id)
273
331
  except (WebsocketClosed, ServerError):
274
332
  # ignore sending error
275
333
  pass
276
- call_state.latest_bot_audio_id = self.latest_message_id # type: ignore[attr-defined]
334
+ call_state.latest_bot_audio_id = self.latest_message_id
277
335
 
278
336
  if not cached_audio_bytes:
279
337
  self.tts_cache.put(text, collected_audio_bytes)
@@ -298,7 +356,7 @@ class VoiceOutputChannel(OutputChannel):
298
356
  return
299
357
 
300
358
  async def hangup(self, recipient_id: str, **kwargs: Any) -> None:
301
- call_state.should_hangup = True # type: ignore[attr-defined]
359
+ call_state.should_hangup = True
302
360
 
303
361
 
304
362
  class VoiceInputChannel(InputChannel):
@@ -345,32 +403,32 @@ class VoiceInputChannel(InputChannel):
345
403
  if call_state.silence_timeout_watcher:
346
404
  logger.debug("voice_channel.cancelling_current_timeout_watcher_task")
347
405
  call_state.silence_timeout_watcher.cancel()
348
- call_state.silence_timeout_watcher = None # type: ignore[attr-defined]
406
+ call_state.silence_timeout_watcher = None
349
407
 
350
408
  @classmethod
351
- def from_credentials(
352
- cls,
353
- credentials: Optional[Dict[str, Any]],
354
- ) -> InputChannel:
409
+ def validate_basic_credentials(cls, credentials: Optional[Dict[str, Any]]) -> None:
410
+ """Validate the basic credentials for the voice channel."""
355
411
  if not credentials:
356
412
  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"):
413
+ if not isinstance(credentials, dict):
361
414
  raise InvalidConfigException(
362
- "No ASR configuration provided in credentials."
415
+ "Credentials must be a dictionary for voice channel."
363
416
  )
364
- if not credentials.get("tts"):
417
+
418
+ required_keys = {"server_url", "asr", "tts"}
419
+ credentials_keys = set(credentials.keys())
420
+ if not required_keys.issubset(credentials_keys):
421
+ missing_fields = required_keys - credentials_keys
365
422
  raise InvalidConfigException(
366
- "No TTS configuration provided in credentials."
423
+ f"Missing required fields in credentials: {', '.join(missing_fields)} "
424
+ f"for channel {cls.name()}"
367
425
  )
368
426
 
369
- return cls(
370
- server_url=credentials["server_url"],
371
- asr_config=credentials["asr"],
372
- tts_config=credentials["tts"],
373
- )
427
+ @classmethod
428
+ def from_credentials(
429
+ cls, credentials: Optional[Dict[str, Any]]
430
+ ) -> VoiceInputChannel:
431
+ raise NotImplementedError
374
432
 
375
433
  def channel_bytes_to_rasa_audio_bytes(self, input_bytes: bytes) -> RasaAudioBytes:
376
434
  raise NotImplementedError
@@ -439,10 +497,8 @@ class VoiceInputChannel(InputChannel):
439
497
  if was_bot_speaking_before and not is_bot_speaking_after:
440
498
  logger.debug("voice_channel.bot_stopped_speaking")
441
499
  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
- )
500
+ call_state.silence_timeout_watcher = asyncio.create_task(
501
+ self.monitor_silence_timeout(asr_event_queue)
446
502
  )
447
503
  if isinstance(channel_action, NewAudioAction):
448
504
  await asr_engine.send_audio_chunks(channel_action.audio_bytes)
@@ -498,6 +554,16 @@ class VoiceInputChannel(InputChannel):
498
554
  """Create a matching voice output channel for this voice input channel."""
499
555
  raise NotImplementedError
500
556
 
557
+ def _track_asr_latency(self) -> None:
558
+ """Track and log ASR processing latency."""
559
+ if call_state.user_speech_start_time:
560
+ call_state.asr_latency_ms = (
561
+ time.time() - call_state.user_speech_start_time
562
+ ) * 1000
563
+ logger.debug(
564
+ "voice_channel.asr_latency", latency_ms=call_state.asr_latency_ms
565
+ )
566
+
501
567
  async def handle_asr_event(
502
568
  self,
503
569
  e: ASREvent,
@@ -511,7 +577,12 @@ class VoiceInputChannel(InputChannel):
511
577
  logger.debug(
512
578
  "VoiceInputChannel.handle_asr_event.new_transcript", transcript=e.text
513
579
  )
514
- call_state.is_user_speaking = False # type: ignore[attr-defined]
580
+ call_state.is_user_speaking = False
581
+
582
+ # Track ASR and Rasa latencies
583
+ self._track_asr_latency()
584
+ call_state.rasa_processing_start_time = time.time()
585
+
515
586
  output_channel = self.create_output_channel(voice_websocket, tts_engine)
516
587
  message = UserMessage(
517
588
  text=e.text,
@@ -522,8 +593,11 @@ class VoiceInputChannel(InputChannel):
522
593
  )
523
594
  await on_new_message(message)
524
595
  elif isinstance(e, UserIsSpeaking):
596
+ # Track when user starts speaking for ASR latency calculation
597
+ if not call_state.is_user_speaking:
598
+ call_state.user_speech_start_time = time.time()
525
599
  self._cancel_silence_timeout_watcher()
526
- call_state.is_user_speaking = True # type: ignore[attr-defined]
600
+ call_state.is_user_speaking = True
527
601
  elif isinstance(e, UserSilence):
528
602
  output_channel = self.create_output_channel(voice_websocket, tts_engine)
529
603
  message = UserMessage(
@@ -225,8 +225,10 @@ class ContextualResponseRephraser(
225
225
 
226
226
  @measure_llm_latency
227
227
  async def _generate_llm_response(self, prompt: str) -> Optional[LLMResponse]:
228
- """Use LLM to generate a response, returning an LLMResponse object
229
- 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.
230
232
 
231
233
  Args:
232
234
  prompt: The prompt to send to the LLM.
@@ -315,14 +317,18 @@ class ContextualResponseRephraser(
315
317
  return response
316
318
 
317
319
  prompt_template_text = self._template_for_response_rephrasing(response)
320
+
321
+ # Last user message (=current input) should always be in prompt if available
318
322
  last_message_by_user = getattr(tracker.latest_message, "text", "")
319
323
  current_input = (
320
324
  f"{USER}: {last_message_by_user}" if last_message_by_user else ""
321
325
  )
322
326
 
327
+ # Only summarise conversation history if flagged
323
328
  if self.summarize_history:
324
329
  history = await self._create_history(tracker)
325
330
  else:
331
+ # Count multiple utterances by bot/user as single turn
326
332
  turns_wrapper = (
327
333
  _count_multiple_utterances_as_single_turn
328
334
  if self.count_multiple_utterances_as_single_turn
@@ -365,6 +371,7 @@ class ContextualResponseRephraser(
365
371
  )
366
372
 
367
373
  if not (llm_response and llm_response.choices and llm_response.choices[0]):
374
+ # If the LLM fails to generate a response, return the original response.
368
375
  return response
369
376
 
370
377
  updated_text = llm_response.choices[0]
@@ -412,12 +419,9 @@ class ContextualResponseRephraser(
412
419
  Returns:
413
420
  The generated response.
414
421
  """
415
- filled_slots = tracker.current_slot_values()
416
- stack_context = tracker.stack.current_context()
417
- templated_response = self.generate_from_slots(
422
+ templated_response = await super().generate(
418
423
  utter_action=utter_action,
419
- filled_slots=filled_slots,
420
- stack_context=stack_context,
424
+ tracker=tracker,
421
425
  output_channel=output_channel,
422
426
  **kwargs,
423
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]]]: