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,7 +1,10 @@
1
+ from __future__ import annotations
2
+
1
3
  import asyncio
2
4
  import audioop
3
5
  import base64
4
6
  import json
7
+ import time
5
8
  import uuid
6
9
  from functools import partial
7
10
  from typing import (
@@ -14,6 +17,7 @@ from typing import (
14
17
  Optional,
15
18
  Text,
16
19
  Tuple,
20
+ Union,
17
21
  )
18
22
 
19
23
  import structlog
@@ -32,6 +36,7 @@ from rasa.core.channels.voice_stream.voice_channel import (
32
36
  VoiceInputChannel,
33
37
  VoiceOutputChannel,
34
38
  )
39
+ from rasa.core.exceptions import AgentNotReady
35
40
  from rasa.hooks import hookimpl
36
41
  from rasa.plugin import plugin_manager
37
42
  from rasa.shared.core.constants import ACTION_LISTEN_NAME
@@ -42,14 +47,15 @@ if TYPE_CHECKING:
42
47
  from sanic import Sanic, Websocket # type: ignore[attr-defined]
43
48
  from socketio import AsyncServer
44
49
 
45
- from rasa.core.channels.channel import InputChannel, UserMessage
46
50
  from rasa.shared.core.trackers import DialogueStateTracker
47
51
 
48
52
 
49
53
  structlogger = structlog.get_logger()
50
54
 
51
55
 
52
- def tracker_as_dump(tracker: "DialogueStateTracker") -> str:
56
+ def tracker_as_dump(
57
+ tracker: "DialogueStateTracker", latency: Optional[float] = None
58
+ ) -> Dict[str, Any]:
53
59
  """Create a dump of the tracker state."""
54
60
  from rasa.shared.core.trackers import get_trackers_for_conversation_sessions
55
61
 
@@ -60,8 +66,14 @@ def tracker_as_dump(tracker: "DialogueStateTracker") -> str:
60
66
  else:
61
67
  last_tracker = multiple_tracker_sessions[-1]
62
68
 
69
+ # TODO: this is a bug: the bridge converts this back to json, but it
70
+ # should be json in the first place
63
71
  state = last_tracker.current_state(EventVerbosity.AFTER_RESTART)
64
- return json.dumps(state)
72
+
73
+ if latency is not None:
74
+ state["latency"] = {"rasa_processing_latency_ms": latency}
75
+
76
+ return state
65
77
 
66
78
 
67
79
  def does_need_action_prediction(tracker: "DialogueStateTracker") -> bool:
@@ -143,6 +155,7 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
143
155
  jwt_key: Optional[Text] = None,
144
156
  jwt_method: Optional[Text] = "HS256",
145
157
  metadata_key: Optional[Text] = "metadata",
158
+ enable_silence_timeout: bool = False,
146
159
  ) -> None:
147
160
  """Creates a `StudioChatInput` object."""
148
161
  from rasa.core.agent import Agent
@@ -160,6 +173,7 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
160
173
  jwt_key=jwt_key,
161
174
  jwt_method=jwt_method,
162
175
  metadata_key=metadata_key,
176
+ enable_silence_timeout=enable_silence_timeout,
163
177
  )
164
178
 
165
179
  # Initialize the Voice Input Channel
@@ -175,11 +189,14 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
175
189
  # `background_tasks` holds the asyncio tasks for voice streaming
176
190
  self.active_connections: Dict[str, SocketIOVoiceWebsocketAdapter] = {}
177
191
  self.background_tasks: Dict[str, asyncio.Task] = {}
192
+ self._turn_start_times: Dict[Text, float] = {}
178
193
 
179
194
  self._register_tracker_update_hook()
180
195
 
181
196
  @classmethod
182
- def from_credentials(cls, credentials: Optional[Dict[Text, Any]]) -> "InputChannel":
197
+ def from_credentials(
198
+ cls, credentials: Optional[Dict[Text, Any]]
199
+ ) -> "StudioChatInput":
183
200
  """Creates a StudioChatInput channel from credentials."""
184
201
  credentials = credentials or {}
185
202
 
@@ -197,35 +214,73 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
197
214
  jwt_key=credentials.get("jwt_key"),
198
215
  jwt_method=credentials.get("jwt_method", "HS256"),
199
216
  metadata_key=credentials.get("metadata_key", "metadata"),
217
+ enable_silence_timeout=credentials.get("enable_silence_timeout", False),
200
218
  )
201
219
 
220
+ async def emit(self, event: str, data: Union[Dict, str], room: str) -> None:
221
+ """Emits an event to the websocket."""
222
+ if not self.sio_server:
223
+ structlogger.error("studio_chat.emit.sio_not_initialized")
224
+ return
225
+ await self.sio_server.emit(event, data, room=room)
226
+
202
227
  def _register_tracker_update_hook(self) -> None:
203
228
  plugin_manager().register(StudioTrackerUpdatePlugin(self))
204
229
 
205
- async def on_tracker_updated(self, tracker: "DialogueStateTracker") -> None:
230
+ async def on_tracker_updated(
231
+ self, tracker: "DialogueStateTracker", latency: Optional[float] = None
232
+ ) -> None:
206
233
  """Triggers a tracker update notification after a change to the tracker."""
207
- await self.publish_tracker_update(tracker.sender_id, tracker_as_dump(tracker))
234
+ await self.publish_tracker_update(
235
+ tracker.sender_id, tracker_as_dump(tracker, latency)
236
+ )
208
237
 
209
- async def publish_tracker_update(self, sender_id: str, tracker_dump: Dict) -> None:
238
+ async def publish_tracker_update(self, sender_id: str, tracker_dump: str) -> None:
210
239
  """Publishes a tracker update notification to the websocket."""
211
- if not self.sio:
212
- structlogger.error("studio_chat.on_tracker_updated.sio_not_initialized")
213
- return
214
- await self.sio.emit("tracker", tracker_dump, room=sender_id)
240
+ await self.emit("tracker", tracker_dump, room=sender_id)
241
+
242
+ def _record_turn_start_time(self, sender_id: Text) -> None:
243
+ """Records the start time of a new turn."""
244
+ self._turn_start_times[sender_id] = time.time()
245
+
246
+ def _get_latency(self, sender_id: Text) -> Optional[float]:
247
+ """Returns the latency of the current turn in milliseconds."""
248
+ if sender_id not in self._turn_start_times:
249
+ return None
250
+
251
+ latency = (time.time() - self._turn_start_times[sender_id]) * 1000
252
+ # The turn is over, so we can remove the start time
253
+ del self._turn_start_times[sender_id]
254
+ return latency
215
255
 
216
256
  async def on_message_proxy(
217
257
  self,
218
- on_new_message: Callable[["UserMessage"], Awaitable[Any]],
219
- message: "UserMessage",
258
+ on_new_message: Callable[[UserMessage], Awaitable[Any]],
259
+ message: UserMessage,
220
260
  ) -> None:
221
261
  """Proxies the on_new_message call to the underlying channel.
222
262
 
223
263
  Triggers a tracker update notification after processing the message.
224
264
  """
225
- await on_new_message(message)
265
+ self._record_turn_start_time(message.sender_id)
266
+ try:
267
+ await on_new_message(message)
268
+ except Exception as e:
269
+ structlogger.exception(
270
+ "studio_chat.on_new_message.error",
271
+ error=str(e),
272
+ sender_id=message.sender_id,
273
+ )
226
274
 
227
- if not self.agent:
275
+ if not self.agent or not self.agent.is_ready():
228
276
  structlogger.error("studio_chat.on_message_proxy.agent_not_initialized")
277
+ await self.emit_error(
278
+ "The Rasa Pro model could not be loaded. "
279
+ "Please check the training and deployment logs "
280
+ "for more information.",
281
+ message.sender_id,
282
+ AgentNotReady("The Rasa Pro model could not be loaded."),
283
+ )
229
284
  return
230
285
 
231
286
  tracker = await self.agent.tracker_store.retrieve(message.sender_id)
@@ -233,7 +288,19 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
233
288
  structlogger.error("studio_chat.on_message_proxy.tracker_not_found")
234
289
  return
235
290
 
236
- await self.on_tracker_updated(tracker)
291
+ latency = self._get_latency(message.sender_id)
292
+ await self.on_tracker_updated(tracker, latency)
293
+
294
+ async def emit_error(self, message: str, room: str, e: Exception) -> None:
295
+ await self.emit(
296
+ "error",
297
+ {
298
+ "message": message,
299
+ "error": str(e),
300
+ "exception": str(type(e).__name__),
301
+ },
302
+ room=room,
303
+ )
237
304
 
238
305
  async def handle_tracker_update(self, sid: str, data: Dict) -> None:
239
306
  from rasa.shared.core.trackers import DialogueStateTracker
@@ -251,21 +318,41 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
251
318
  structlogger.error("studio_chat.sio.domain_not_initialized")
252
319
  return None
253
320
 
254
- async with self.agent.lock_store.lock(data["sender_id"]):
255
- tracker = DialogueStateTracker.from_dict(
256
- data["sender_id"], data["events"], domain.slots
257
- )
258
-
259
- # will override an existing tracker with the same id!
260
- await self.agent.tracker_store.save(tracker)
321
+ tracker: Optional[DialogueStateTracker] = None
261
322
 
262
- processor = self.agent.processor
263
- if processor and does_need_action_prediction(tracker):
264
- output_channel = self.get_output_channel()
323
+ async with self.agent.lock_store.lock(data["sender_id"]):
324
+ try:
325
+ tracker = DialogueStateTracker.from_dict(
326
+ data["sender_id"], data["events"], domain.slots
327
+ )
265
328
 
266
- await processor._run_prediction_loop(output_channel, tracker)
329
+ # will override an existing tracker with the same id!
267
330
  await self.agent.tracker_store.save(tracker)
268
331
 
332
+ processor = self.agent.processor
333
+ if processor and does_need_action_prediction(tracker):
334
+ output_channel = self.get_output_channel()
335
+
336
+ await processor._run_prediction_loop(output_channel, tracker)
337
+ await self.agent.tracker_store.save(tracker)
338
+ except Exception as e:
339
+ structlogger.error(
340
+ "studio_chat.sio.handle_tracker_update.error",
341
+ error=e,
342
+ sender_id=data["sender_id"],
343
+ )
344
+ await self.emit_error(
345
+ "An error occurred while updating the conversation.",
346
+ data["sender_id"],
347
+ e,
348
+ )
349
+
350
+ if not tracker:
351
+ # in case the tracker couldn't be updated, we retrieve the prior
352
+ # version and use that to populate the update
353
+ tracker = await self.agent.tracker_store.get_or_create_tracker(
354
+ data["sender_id"]
355
+ )
269
356
  await self.on_tracker_updated(tracker)
270
357
 
271
358
  def channel_bytes_to_rasa_audio_bytes(self, input_bytes: bytes) -> RasaAudioBytes:
@@ -275,7 +362,7 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
275
362
  async def collect_call_parameters(
276
363
  self, channel_websocket: "Websocket"
277
364
  ) -> Optional[CallParameters]:
278
- """Voice method to collect call parameters"""
365
+ """Voice method to collect call parameters."""
279
366
  session_id = channel_websocket.session_id
280
367
  return CallParameters(session_id, "local", "local", stream_id=session_id)
281
368
 
@@ -292,20 +379,20 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
292
379
  elif "marker" in message:
293
380
  if message["marker"] == call_state.latest_bot_audio_id:
294
381
  # Just finished streaming last audio bytes
295
- call_state.is_bot_speaking = False # type: ignore[attr-defined]
382
+ call_state.is_bot_speaking = False
296
383
  if call_state.should_hangup:
297
384
  structlogger.debug(
298
385
  "studio_chat.hangup", marker=call_state.latest_bot_audio_id
299
386
  )
300
387
  return EndConversationAction()
301
388
  else:
302
- call_state.is_bot_speaking = True # type: ignore[attr-defined]
389
+ call_state.is_bot_speaking = True
303
390
  return ContinueConversationAction()
304
391
 
305
- def create_output_channel(
392
+ def _create_output_channel(
306
393
  self, voice_websocket: "Websocket", tts_engine: TTSEngine
307
394
  ) -> VoiceOutputChannel:
308
- """Create a voice output channel"""
395
+ """Create a voice output channel."""
309
396
  return StudioVoiceOutputChannel(
310
397
  voice_websocket,
311
398
  tts_engine,
@@ -332,7 +419,7 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
332
419
 
333
420
  # Create a websocket adapter for this connection
334
421
  ws_adapter = SocketIOVoiceWebsocketAdapter(
335
- sio=self.sio,
422
+ sio_server=self.sio_server,
336
423
  session_id=session_id,
337
424
  sid=sid,
338
425
  bot_message_evt=self.bot_message_evt,
@@ -380,13 +467,12 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
380
467
  task.cancel()
381
468
 
382
469
  def blueprint(
383
- self, on_new_message: Callable[["UserMessage"], Awaitable[Any]]
470
+ self, on_new_message: Callable[[UserMessage], Awaitable[Any]]
384
471
  ) -> SocketBlueprint:
385
- socket_blueprint = super().blueprint(
386
- partial(self.on_message_proxy, on_new_message)
387
- )
472
+ proxied_on_message = partial(self.on_message_proxy, on_new_message)
473
+ socket_blueprint = super().blueprint(proxied_on_message)
388
474
 
389
- if not self.sio:
475
+ if not self.sio_server:
390
476
  structlogger.error("studio_chat.blueprint.sio_not_initialized")
391
477
  return socket_blueprint
392
478
 
@@ -396,12 +482,12 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
396
482
  ) -> None:
397
483
  self.agent = app.ctx.agent
398
484
 
399
- @self.sio.on("disconnect", namespace=self.namespace)
485
+ @self.sio_server.on("disconnect", namespace=self.namespace)
400
486
  async def disconnect(sid: Text) -> None:
401
487
  structlogger.debug("studio_chat.sio.disconnect", sid=sid)
402
488
  self._cleanup_tasks_for_sid(sid)
403
489
 
404
- @self.sio.on("session_request", namespace=self.namespace)
490
+ @self.sio_server.on("session_request", namespace=self.namespace)
405
491
  async def session_request(sid: Text, data: Optional[Dict]) -> None:
406
492
  """Overrides the base SocketIOInput session_request handler.
407
493
 
@@ -419,9 +505,9 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
419
505
 
420
506
  # start a voice session if requested
421
507
  if data and data.get("is_voice", False):
422
- self._start_voice_session(data["session_id"], sid, on_new_message)
508
+ self._start_voice_session(data["session_id"], sid, proxied_on_message)
423
509
 
424
- @self.sio.on(self.user_message_evt, namespace=self.namespace)
510
+ @self.sio_server.on(self.user_message_evt, namespace=self.namespace)
425
511
  async def handle_message(sid: Text, data: Dict) -> None:
426
512
  """Overrides the base SocketIOInput handle_message handler."""
427
513
  # Handle voice messages
@@ -432,10 +518,18 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
432
518
  ws.put_message(data)
433
519
  return
434
520
 
435
- # Handle text messages
436
- await self.handle_user_message(sid, data, on_new_message)
437
-
438
- @self.sio.on("update_tracker", namespace=self.namespace)
521
+ try:
522
+ # Handle text messages
523
+ await self.handle_user_message(sid, data, proxied_on_message)
524
+ except Exception as e:
525
+ structlogger.exception(
526
+ "studio_chat.sio.handle_message.error",
527
+ error=str(e),
528
+ sid=sid,
529
+ )
530
+ await self.emit("error", str(e), room=sid)
531
+
532
+ @self.sio_server.on("update_tracker", namespace=self.namespace)
439
533
  async def on_update_tracker(sid: Text, data: Dict) -> None:
440
534
  await self.handle_tracker_update(sid, data)
441
535
 
@@ -457,16 +551,33 @@ class StudioVoiceOutputChannel(VoiceOutputChannel):
457
551
 
458
552
  def create_marker_message(self, recipient_id: str) -> Tuple[str, str]:
459
553
  message_id = uuid.uuid4().hex
460
- return json.dumps({"marker": message_id}), message_id
554
+ marker_data = {"marker": message_id}
555
+
556
+ # Include comprehensive latency information if available
557
+ latency_data = {
558
+ "asr_latency_ms": call_state.asr_latency_ms,
559
+ "rasa_processing_latency_ms": call_state.rasa_processing_latency_ms,
560
+ "tts_first_byte_latency_ms": call_state.tts_first_byte_latency_ms,
561
+ "tts_complete_latency_ms": call_state.tts_complete_latency_ms,
562
+ }
563
+
564
+ # Filter out None values from latency data
565
+ latency_data = {k: v for k, v in latency_data.items() if v is not None}
566
+
567
+ # Add latency data to marker if any metrics are available
568
+ if latency_data:
569
+ marker_data["latency"] = latency_data # type: ignore[assignment]
570
+
571
+ return json.dumps(marker_data), message_id
461
572
 
462
573
 
463
574
  class SocketIOVoiceWebsocketAdapter:
464
575
  """Adapter to make Socket.IO work like a Sanic WebSocket for voice channels."""
465
576
 
466
577
  def __init__(
467
- self, sio: "AsyncServer", session_id: str, sid: str, bot_message_evt: str
578
+ self, sio_server: "AsyncServer", session_id: str, sid: str, bot_message_evt: str
468
579
  ) -> None:
469
- self.sio = sio
580
+ self.sio_server = sio_server
470
581
  self.bot_message_evt = bot_message_evt
471
582
  self._closed = False
472
583
  self._receive_queue: asyncio.Queue[Any] = asyncio.Queue()
@@ -485,7 +596,7 @@ class SocketIOVoiceWebsocketAdapter:
485
596
  async def send(self, data: Any) -> None:
486
597
  """Send data to the client."""
487
598
  if not self.closed:
488
- await self.sio.emit(self.bot_message_evt, data, room=self.sid)
599
+ await self.sio_server.emit(self.bot_message_evt, data, room=self.sid)
489
600
 
490
601
  async def recv(self) -> Any:
491
602
  """Receive data from the client."""
@@ -30,7 +30,7 @@ TWILIO_VOICE_PATH = "webhooks/twilio_voice/webhook"
30
30
 
31
31
 
32
32
  def map_call_params(form: RequestParameters) -> CallParameters:
33
- """Map the Audiocodes parameters to the CallParameters dataclass."""
33
+ """Map the Twilio Voice parameters to the CallParameters dataclass."""
34
34
  return CallParameters(
35
35
  call_id=form.get("CallSid"),
36
36
  user_phone=form.get("Caller"),
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import asyncio
2
4
  import base64
3
5
  import hmac
@@ -21,6 +23,7 @@ from rasa.core.channels.voice_stream.call_state import (
21
23
  call_state,
22
24
  )
23
25
  from rasa.core.channels.voice_stream.tts.tts_engine import TTSEngine
26
+ from rasa.core.channels.voice_stream.util import repack_voice_credentials
24
27
  from rasa.core.channels.voice_stream.voice_channel import (
25
28
  ContinueConversationAction,
26
29
  EndConversationAction,
@@ -85,7 +88,7 @@ class AudiocodesVoiceOutputChannel(VoiceOutputChannel):
85
88
  # however, Audiocodes does not have an event to indicate that.
86
89
  # This is an approximation, as the bot will be sent the audio chunks next
87
90
  # which are played to the user immediately.
88
- call_state.is_bot_speaking = True # type: ignore[attr-defined]
91
+ call_state.is_bot_speaking = True
89
92
 
90
93
  async def send_intermediate_marker(self, recipient_id: str) -> None:
91
94
  """Audiocodes doesn't need intermediate markers, so do nothing."""
@@ -127,10 +130,10 @@ class AudiocodesVoiceInputChannel(VoiceInputChannel):
127
130
  def from_credentials(
128
131
  cls,
129
132
  credentials: Optional[Dict[str, Any]],
130
- ) -> "AudiocodesVoiceInputChannel":
131
- channel = super().from_credentials(credentials)
132
- channel.token = credentials.get("token") # type: ignore[attr-defined, union-attr]
133
- return channel # type: ignore[return-value]
133
+ ) -> AudiocodesVoiceInputChannel:
134
+ cls.validate_basic_credentials(credentials)
135
+ new_creds = repack_voice_credentials(credentials)
136
+ return cls(**new_creds)
134
137
 
135
138
  def channel_bytes_to_rasa_audio_bytes(self, input_bytes: bytes) -> RasaAudioBytes:
136
139
  return RasaAudioBytes(base64.b64decode(input_bytes))
@@ -184,7 +187,7 @@ class AudiocodesVoiceInputChannel(VoiceInputChannel):
184
187
  pass
185
188
  elif activity["name"] == "playFinished":
186
189
  logger.debug("audiocodes_stream.playFinished", data=activity)
187
- call_state.is_bot_speaking = False # type: ignore[attr-defined]
190
+ call_state.is_bot_speaking = False
188
191
  if call_state.should_hangup:
189
192
  logger.info("audiocodes_stream.hangup")
190
193
  self._send_hangup(ws, data)
@@ -1,8 +1,10 @@
1
+ from __future__ import annotations
2
+
1
3
  import audioop
2
4
  import base64
3
5
  import json
4
6
  import uuid
5
- from typing import Any, Awaitable, Callable, Optional, Tuple
7
+ from typing import Any, Awaitable, Callable, Dict, Optional, Tuple
6
8
 
7
9
  import structlog
8
10
  from sanic import ( # type: ignore[attr-defined]
@@ -18,6 +20,7 @@ from rasa.core.channels.voice_ready.utils import CallParameters
18
20
  from rasa.core.channels.voice_stream.audio_bytes import RasaAudioBytes
19
21
  from rasa.core.channels.voice_stream.call_state import call_state
20
22
  from rasa.core.channels.voice_stream.tts.tts_engine import TTSEngine
23
+ from rasa.core.channels.voice_stream.util import repack_voice_credentials
21
24
  from rasa.core.channels.voice_stream.voice_channel import (
22
25
  ContinueConversationAction,
23
26
  EndConversationAction,
@@ -45,10 +48,33 @@ class BrowserAudioOutputChannel(VoiceOutputChannel):
45
48
 
46
49
  def create_marker_message(self, recipient_id: str) -> Tuple[str, str]:
47
50
  message_id = uuid.uuid4().hex
48
- return json.dumps({"marker": message_id}), message_id
51
+ marker_data = {"marker": message_id}
52
+
53
+ # Include comprehensive latency information if available
54
+ latency_data = {
55
+ "asr_latency_ms": call_state.asr_latency_ms,
56
+ "rasa_processing_latency_ms": call_state.rasa_processing_latency_ms,
57
+ "tts_first_byte_latency_ms": call_state.tts_first_byte_latency_ms,
58
+ "tts_complete_latency_ms": call_state.tts_complete_latency_ms,
59
+ }
60
+
61
+ # Filter out None values from latency data
62
+ latency_data = {k: v for k, v in latency_data.items() if v is not None}
63
+
64
+ # Add latency data to marker if any metrics are available
65
+ if latency_data:
66
+ marker_data["latency"] = latency_data # type: ignore[assignment]
67
+
68
+ return json.dumps(marker_data), message_id
49
69
 
50
70
 
51
71
  class BrowserAudioInputChannel(VoiceInputChannel):
72
+ def __init__(
73
+ self, server_url: str, asr_config: Dict[str, Any], tts_config: Dict[str, Any]
74
+ ) -> None:
75
+ """Initializes the browser audio input channel."""
76
+ super().__init__(server_url, asr_config, tts_config)
77
+
52
78
  @classmethod
53
79
  def name(cls) -> str:
54
80
  return "browser_audio"
@@ -62,6 +88,15 @@ class BrowserAudioInputChannel(VoiceInputChannel):
62
88
  call_id = f"inspect-{uuid.uuid4()}"
63
89
  return CallParameters(call_id, "local", "local", stream_id=call_id)
64
90
 
91
+ @classmethod
92
+ def from_credentials(
93
+ cls,
94
+ credentials: Optional[Dict[str, Any]],
95
+ ) -> BrowserAudioInputChannel:
96
+ cls.validate_basic_credentials(credentials)
97
+ new_creds = repack_voice_credentials(credentials)
98
+ return cls(**new_creds)
99
+
65
100
  def map_input_message(
66
101
  self,
67
102
  message: Any,
@@ -75,14 +110,14 @@ class BrowserAudioInputChannel(VoiceInputChannel):
75
110
  elif "marker" in data:
76
111
  if data["marker"] == call_state.latest_bot_audio_id:
77
112
  # Just finished streaming last audio bytes
78
- call_state.is_bot_speaking = False # type: ignore[attr-defined]
113
+ call_state.is_bot_speaking = False
79
114
  if call_state.should_hangup:
80
115
  logger.debug(
81
116
  "browser_audio.hangup", marker=call_state.latest_bot_audio_id
82
117
  )
83
118
  return EndConversationAction()
84
119
  else:
85
- call_state.is_bot_speaking = True # type: ignore[attr-defined]
120
+ call_state.is_bot_speaking = True
86
121
  return ContinueConversationAction()
87
122
 
88
123
  def create_output_channel(
@@ -1,7 +1,7 @@
1
1
  import asyncio
2
2
  from contextvars import ContextVar
3
3
  from dataclasses import dataclass, field
4
- from typing import Any, Dict, Optional
4
+ from typing import Any, Dict, Optional, cast
5
5
 
6
6
  from werkzeug.local import LocalProxy
7
7
 
@@ -19,9 +19,20 @@ class CallState:
19
19
  should_hangup: bool = False
20
20
  connection_failed: bool = False
21
21
 
22
+ # Latency tracking - start times only
23
+ user_speech_start_time: Optional[float] = None
24
+ rasa_processing_start_time: Optional[float] = None
25
+ tts_start_time: Optional[float] = None
26
+
27
+ # Calculated latencies (used by channels like browser_audio)
28
+ asr_latency_ms: Optional[float] = None
29
+ rasa_processing_latency_ms: Optional[float] = None
30
+ tts_first_byte_latency_ms: Optional[float] = None
31
+ tts_complete_latency_ms: Optional[float] = None
32
+
22
33
  # Generic field for channel-specific state data
23
34
  channel_data: Dict[str, Any] = field(default_factory=dict)
24
35
 
25
36
 
26
37
  _call_state: ContextVar[CallState] = ContextVar("call_state")
27
- call_state = LocalProxy(_call_state)
38
+ call_state: CallState = cast(CallState, LocalProxy(_call_state))
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import asyncio
2
4
  import base64
3
5
  import hashlib
@@ -21,6 +23,7 @@ from rasa.core.channels.voice_stream.call_state import (
21
23
  call_state,
22
24
  )
23
25
  from rasa.core.channels.voice_stream.tts.tts_engine import TTSEngine
26
+ from rasa.core.channels.voice_stream.util import repack_voice_credentials
24
27
  from rasa.core.channels.voice_stream.voice_channel import (
25
28
  ContinueConversationAction,
26
29
  EndConversationAction,
@@ -54,7 +57,7 @@ logger = structlog.get_logger(__name__)
54
57
 
55
58
 
56
59
  def map_call_params(data: Dict[Text, Any]) -> CallParameters:
57
- """Map the twilio stream parameters to the CallParameters dataclass."""
60
+ """Map the Genesys parameters to the CallParameters dataclass."""
58
61
  parameters = data["parameters"]
59
62
  participant = parameters["participant"]
60
63
  # sent as {"ani": "tel:+491604697810"}
@@ -107,7 +110,7 @@ class GenesysInputChannel(VoiceInputChannel):
107
110
  def from_credentials(
108
111
  cls,
109
112
  credentials: Optional[Dict[str, Any]],
110
- ) -> "GenesysInputChannel":
113
+ ) -> GenesysInputChannel:
111
114
  """Create a channel from credentials dictionary.
112
115
 
113
116
  Args:
@@ -121,21 +124,21 @@ class GenesysInputChannel(VoiceInputChannel):
121
124
  Returns:
122
125
  GenesysInputChannel instance
123
126
  """
124
- channel = super().from_credentials(credentials)
127
+ cls.validate_credentials(credentials)
128
+ new_creds = repack_voice_credentials(credentials)
129
+ return cls(**new_creds)
125
130
 
126
- # Check required Genesys-specific credentials
131
+ @classmethod
132
+ def validate_credentials(cls, credentials: Optional[Dict[str, Any]]) -> None:
133
+ """Validate the credentials for the Genesys voice channel."""
134
+ cls.validate_basic_credentials(credentials)
127
135
  if not credentials.get("api_key"): # type: ignore[union-attr]
128
136
  raise InvalidConfigException(
129
137
  "No API key given for Genesys voice channel (api_key)."
130
138
  )
131
139
 
132
- # Update channel with Genesys-specific credentials
133
- channel.api_key = credentials["api_key"] # type: ignore[index,attr-defined]
134
- channel.client_secret = credentials.get("client_secret") # type: ignore[union-attr,attr-defined]
135
-
136
- return channel # type: ignore[return-value]
137
-
138
- def _ensure_channel_data_initialized(self) -> None:
140
+ @staticmethod
141
+ def _ensure_channel_data_initialized() -> None:
139
142
  """Initialize Genesys-specific channel data if not already present.
140
143
 
141
144
  Genesys requires the server and client each maintain a
@@ -216,10 +219,10 @@ class GenesysInputChannel(VoiceInputChannel):
216
219
  self.handle_ping(ws, data)
217
220
  elif msg_type == "playback_started":
218
221
  logger.debug("genesys.handle_playback_started", message=data)
219
- call_state.is_bot_speaking = True # type: ignore[attr-defined]
222
+ call_state.is_bot_speaking = True
220
223
  elif msg_type == "playback_completed":
221
224
  logger.debug("genesys.handle_playback_completed", message=data)
222
- call_state.is_bot_speaking = False # type: ignore[attr-defined]
225
+ call_state.is_bot_speaking = False
223
226
  if call_state.should_hangup:
224
227
  logger.info("genesys.hangup")
225
228
  self.disconnect(ws, data)