rasa-pro 3.14.0.dev7__py3-none-any.whl → 3.14.0.dev8__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.
- rasa/agents/agent_manager.py +1 -1
- rasa/agents/constants.py +2 -2
- rasa/agents/protocol/a2a/a2a_agent.py +385 -227
- rasa/agents/protocol/mcp/mcp_base_agent.py +30 -13
- rasa/agents/protocol/mcp/mcp_open_agent.py +31 -8
- rasa/agents/protocol/mcp/mcp_task_agent.py +32 -9
- rasa/agents/schemas/agent_output.py +1 -1
- rasa/agents/utils.py +90 -1
- rasa/builder/README.md +120 -0
- rasa/builder/__init__.py +0 -0
- rasa/builder/auth.py +176 -0
- rasa/builder/config.py +92 -0
- rasa/builder/copilot/__init__.py +0 -0
- rasa/builder/copilot/constants.py +31 -0
- rasa/builder/copilot/copilot.py +450 -0
- rasa/builder/copilot/copilot_response_handler.py +522 -0
- rasa/builder/copilot/copilot_templated_message_provider.py +58 -0
- rasa/builder/copilot/exceptions.py +32 -0
- rasa/builder/copilot/models.py +500 -0
- rasa/builder/copilot/prompts/__init__.py +0 -0
- rasa/builder/copilot/prompts/copilot_system_prompt.jinja2 +766 -0
- rasa/builder/copilot/prompts/latest_user_message_context_prompt.jinja2 +61 -0
- rasa/builder/copilot/signing.py +305 -0
- rasa/builder/copilot/telemetry.py +210 -0
- rasa/builder/copilot/templated_messages/__init__.py +0 -0
- rasa/builder/copilot/templated_messages/copilot_internal_messages_templates.yml +16 -0
- rasa/builder/copilot/templated_messages/copilot_templated_responses.yml +38 -0
- rasa/builder/document_retrieval/__init__.py +0 -0
- rasa/builder/document_retrieval/constants.py +15 -0
- rasa/builder/document_retrieval/inkeep-rag-response-schema.json +64 -0
- rasa/builder/document_retrieval/inkeep_document_retrieval.py +238 -0
- rasa/builder/document_retrieval/models.py +62 -0
- rasa/builder/download.py +140 -0
- rasa/builder/exceptions.py +91 -0
- rasa/builder/guardrails/__init__.py +1 -0
- rasa/builder/guardrails/constants.py +9 -0
- rasa/builder/guardrails/exceptions.py +4 -0
- rasa/builder/guardrails/lakera.py +206 -0
- rasa/builder/guardrails/models.py +231 -0
- rasa/builder/guardrails/store.py +238 -0
- rasa/builder/guardrails/utils.py +328 -0
- rasa/builder/job_manager.py +87 -0
- rasa/builder/jobs.py +282 -0
- rasa/builder/llm_service.py +246 -0
- rasa/builder/logging_utils.py +265 -0
- rasa/builder/main.py +243 -0
- rasa/builder/models.py +216 -0
- rasa/builder/project_generator.py +458 -0
- rasa/builder/project_info.py +72 -0
- rasa/builder/scrape_rasa_docs.py +97 -0
- rasa/builder/service.py +1345 -0
- rasa/builder/shared/tracker_context.py +212 -0
- rasa/builder/skill_to_bot_prompt.jinja2 +164 -0
- rasa/builder/template_cache.py +244 -0
- rasa/builder/training_service.py +194 -0
- rasa/builder/validation_service.py +97 -0
- rasa/cli/project_templates/basic/README.md +23 -0
- rasa/cli/project_templates/basic/actions/__init__ +0 -0
- rasa/cli/project_templates/basic/actions/action_human_handoff.py +40 -0
- rasa/cli/project_templates/basic/actions/actions.md +10 -0
- rasa/cli/project_templates/basic/config.yml +29 -0
- rasa/cli/project_templates/basic/credentials.yml +33 -0
- rasa/cli/project_templates/basic/data/data.md +9 -0
- rasa/cli/project_templates/basic/data/general/feedback.yml +21 -0
- rasa/cli/project_templates/basic/data/general/goodbye.yml +6 -0
- rasa/cli/project_templates/basic/data/general/hello.yml +6 -0
- rasa/cli/project_templates/basic/data/general/help.yml +6 -0
- rasa/cli/project_templates/basic/data/general/human_handoff.yml +16 -0
- rasa/cli/project_templates/basic/data/general/show_faqs.yml +6 -0
- rasa/cli/project_templates/basic/data/system/patterns/pattern_cannot_handle.yml +7 -0
- rasa/cli/project_templates/basic/data/system/patterns/pattern_completed.yml +7 -0
- rasa/cli/project_templates/basic/data/system/patterns/pattern_correction.yml +7 -0
- rasa/cli/project_templates/basic/data/system/patterns/pattern_search.yml +8 -0
- rasa/cli/project_templates/basic/data/system/patterns/pattern_session_start.yml +8 -0
- rasa/cli/project_templates/basic/docs/docs.md +5 -0
- rasa/cli/project_templates/basic/docs/template.txt +28 -0
- rasa/cli/project_templates/basic/domain/domain.md +8 -0
- rasa/cli/project_templates/basic/domain/general/feedback.yml +25 -0
- rasa/cli/project_templates/basic/domain/general/goodbye.yml +9 -0
- rasa/cli/project_templates/basic/domain/general/hello.yml +7 -0
- rasa/cli/project_templates/basic/domain/general/help.yml +21 -0
- rasa/cli/project_templates/basic/domain/general/human_handoff.yml +32 -0
- rasa/cli/project_templates/basic/domain/general/show_faqs.yml +14 -0
- rasa/cli/project_templates/basic/domain/system/patterns/pattern_cannot_handle.yml +5 -0
- rasa/cli/project_templates/basic/domain/system/patterns/pattern_session_start.yml +19 -0
- rasa/cli/project_templates/basic/endpoints.yml +67 -0
- rasa/cli/project_templates/basic/prompts/rephraser_demo_personality_prompt.jinja2 +38 -0
- rasa/cli/project_templates/default/config.yml +4 -0
- rasa/cli/project_templates/default/endpoints.yml +4 -0
- rasa/cli/project_templates/finance/README.md +25 -0
- rasa/cli/project_templates/finance/actions/__init__.py +46 -0
- rasa/cli/project_templates/finance/actions/accounts/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/accounts/action_ask_account.py +47 -0
- rasa/cli/project_templates/finance/actions/accounts/action_check_balance.py +40 -0
- rasa/cli/project_templates/finance/actions/action_session_start.py +74 -0
- rasa/cli/project_templates/finance/actions/actions.md +15 -0
- rasa/cli/project_templates/finance/actions/cards/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/cards/action_ask_card.py +48 -0
- rasa/cli/project_templates/finance/actions/cards/action_check_card_existence.py +36 -0
- rasa/cli/project_templates/finance/actions/cards/action_update_card_status.py +54 -0
- rasa/cli/project_templates/finance/actions/database.py +277 -0
- rasa/cli/project_templates/finance/actions/transfers/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/transfers/action_add_payee.py +52 -0
- rasa/cli/project_templates/finance/actions/transfers/action_ask_account_from.py +51 -0
- rasa/cli/project_templates/finance/actions/transfers/action_check_payee_existence.py +40 -0
- rasa/cli/project_templates/finance/actions/transfers/action_check_sufficient_funds.py +40 -0
- rasa/cli/project_templates/finance/actions/transfers/action_list_payees.py +46 -0
- rasa/cli/project_templates/finance/actions/transfers/action_process_immediate_payment.py +18 -0
- rasa/cli/project_templates/finance/actions/transfers/action_remove_payee.py +49 -0
- rasa/cli/project_templates/finance/actions/transfers/action_schedule_payment.py +19 -0
- rasa/cli/project_templates/finance/actions/transfers/action_validate_payment_date.py +36 -0
- rasa/cli/project_templates/finance/config.yml +23 -0
- rasa/cli/project_templates/finance/credentials.yml +32 -0
- rasa/cli/project_templates/finance/csvs/accounts.csv +8 -0
- rasa/cli/project_templates/finance/csvs/advisors.csv +7 -0
- rasa/cli/project_templates/finance/csvs/appointments.csv +211 -0
- rasa/cli/project_templates/finance/csvs/branches.csv +10 -0
- rasa/cli/project_templates/finance/csvs/cards.csv +11 -0
- rasa/cli/project_templates/finance/csvs/payees.csv +11 -0
- rasa/cli/project_templates/finance/csvs/transactions.csv +71 -0
- rasa/cli/project_templates/finance/csvs/users.csv +4 -0
- rasa/cli/project_templates/finance/data/accounts/check_balance.yml +10 -0
- rasa/cli/project_templates/finance/data/cards/block_card.yml +66 -0
- rasa/cli/project_templates/finance/data/cards/select_card.yml +12 -0
- rasa/cli/project_templates/finance/data/data.md +11 -0
- rasa/cli/project_templates/finance/data/general/bot_identity.yml +6 -0
- rasa/cli/project_templates/finance/data/general/feedback.yml +20 -0
- rasa/cli/project_templates/finance/data/general/goodbye.yml +6 -0
- rasa/cli/project_templates/finance/data/general/hello.yml +7 -0
- rasa/cli/project_templates/finance/data/general/help.yml +9 -0
- rasa/cli/project_templates/finance/data/general/human_handoff.yml +16 -0
- rasa/cli/project_templates/finance/data/general/welcome.yml +9 -0
- rasa/cli/project_templates/finance/data/system/patterns/pattern_chitchat.yml +5 -0
- rasa/cli/project_templates/finance/data/system/patterns/pattern_completed.yml +7 -0
- rasa/cli/project_templates/finance/data/system/patterns/pattern_correction.yml +7 -0
- rasa/cli/project_templates/finance/data/system/patterns/pattern_search.yml +8 -0
- rasa/cli/project_templates/finance/data/system/patterns/pattern_session_start.yml +8 -0
- rasa/cli/project_templates/finance/data/system/source/accounts.json +51 -0
- rasa/cli/project_templates/finance/data/system/source/advisors.json +44 -0
- rasa/cli/project_templates/finance/data/system/source/appointments.json +1474 -0
- rasa/cli/project_templates/finance/data/system/source/branches.json +47 -0
- rasa/cli/project_templates/finance/data/system/source/cards.json +72 -0
- rasa/cli/project_templates/finance/data/system/source/payees.json +74 -0
- rasa/cli/project_templates/finance/data/system/source/transactions.json +492 -0
- rasa/cli/project_templates/finance/data/system/source/users.json +29 -0
- rasa/cli/project_templates/finance/data/transfers/add_payee.yml +29 -0
- rasa/cli/project_templates/finance/data/transfers/list_payees.yml +5 -0
- rasa/cli/project_templates/finance/data/transfers/remove_payee.yml +21 -0
- rasa/cli/project_templates/finance/data/transfers/transfer_money.yml +67 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/consequences_of_blocking_card.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/reasons_to_block_card.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/recovering_from_card_fraud.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/tips_for_card_security.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/what_to_do_if_card_is_lost.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/account_balance_security.txt +7 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/common_balance_inquiries.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/methods_to_check_balance.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/understanding_balance_updates.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/what_to_do_if_balance_is_incorrect.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/benefits_of_authorised_payees.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/common_issues_with_payees.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/general_payee_information.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/payee_management_tips.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/understanding_payee_types.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/common_transfer_errors.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/fees_for_transfers.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/general_transfer_information.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/security_tips_for_transfers.txt +8 -0
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/transfer_processing_times.txt +8 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part1.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part10.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part11.txt +48 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part12.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part13.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part14.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part15.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part16.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part17.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part18.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part19.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part2.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part20.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part21.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part22.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part23.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part24.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part25.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part26.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part27.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part28.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part29.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part3.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part30.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part31.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part32.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part33.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part34.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part35.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part36.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part37.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part38.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part39.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part4.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part40.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part41.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part42.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part43.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part44.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part45.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part46.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part47.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part48.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part49.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part5.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part50.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part51.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part52.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part53.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part54.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part55.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part56.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part57.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part58.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part59.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part6.txt +47 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part60.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part61.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part7.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part8.txt +50 -0
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part9.txt +47 -0
- rasa/cli/project_templates/finance/domain/accounts/check_balance.yml +11 -0
- rasa/cli/project_templates/finance/domain/cards/block_card.yml +101 -0
- rasa/cli/project_templates/finance/domain/cards/select_card.yml +12 -0
- rasa/cli/project_templates/finance/domain/domain.md +10 -0
- rasa/cli/project_templates/finance/domain/general/agent_details.yml +12 -0
- rasa/cli/project_templates/finance/domain/general/bot_identity.yml +5 -0
- rasa/cli/project_templates/finance/domain/general/cannot_handle.yml +5 -0
- rasa/cli/project_templates/finance/domain/general/defaults.yml +24 -0
- rasa/cli/project_templates/finance/domain/general/feedback.yml +28 -0
- rasa/cli/project_templates/finance/domain/general/goodbye.yml +7 -0
- rasa/cli/project_templates/finance/domain/general/help.yml +5 -0
- rasa/cli/project_templates/finance/domain/general/human_handoff.yml +30 -0
- rasa/cli/project_templates/finance/domain/general/utils.yml +13 -0
- rasa/cli/project_templates/finance/domain/general/welcome.yml +8 -0
- rasa/cli/project_templates/finance/domain/transfers/add_payee.yml +47 -0
- rasa/cli/project_templates/finance/domain/transfers/list_payees.yml +4 -0
- rasa/cli/project_templates/finance/domain/transfers/remove_payee.yml +16 -0
- rasa/cli/project_templates/finance/domain/transfers/transfer_money.yml +79 -0
- rasa/cli/project_templates/finance/endpoints.yml +66 -0
- rasa/cli/project_templates/finance/prompts/rephraser_demo_personality_prompt.jinja2 +19 -0
- rasa/cli/project_templates/telco/README.md +25 -0
- rasa/cli/project_templates/telco/actions/__init__.py +0 -0
- rasa/cli/project_templates/telco/actions/actions.md +12 -0
- rasa/cli/project_templates/telco/actions/billing/__init__.py +0 -0
- rasa/cli/project_templates/telco/actions/billing/actions_billing.py +204 -0
- rasa/cli/project_templates/telco/actions/general/__init__.py +0 -0
- rasa/cli/project_templates/telco/actions/general/action_human_handoff.py +49 -0
- rasa/cli/project_templates/telco/actions/network/__init__.py +0 -0
- rasa/cli/project_templates/telco/actions/network/actions_get_data_from_db.py +48 -0
- rasa/cli/project_templates/telco/actions/network/actions_run_diagnostics.py +28 -0
- rasa/cli/project_templates/telco/actions/network/actions_session_start.py +18 -0
- rasa/cli/project_templates/telco/config.yml +29 -0
- rasa/cli/project_templates/telco/credentials.yml +33 -0
- rasa/cli/project_templates/telco/csvs/billing.csv +19 -0
- rasa/cli/project_templates/telco/csvs/customers.csv +5 -0
- rasa/cli/project_templates/telco/data/billing/flow_understand_bill.yml +45 -0
- rasa/cli/project_templates/telco/data/data.md +11 -0
- rasa/cli/project_templates/telco/data/general/bot_challenge.yml +6 -0
- rasa/cli/project_templates/telco/data/general/feedback.yml +20 -0
- rasa/cli/project_templates/telco/data/general/goodbye.yml +6 -0
- rasa/cli/project_templates/telco/data/general/hello.yml +6 -0
- rasa/cli/project_templates/telco/data/general/human_handoff.yml +16 -0
- rasa/cli/project_templates/telco/data/general/patterns.yml +30 -0
- rasa/cli/project_templates/telco/data/network/flow_reboot_router.yml +8 -0
- rasa/cli/project_templates/telco/data/network/flow_reset_router.yml +7 -0
- rasa/cli/project_templates/telco/data/network/flow_solve_internet_issue.yml +73 -0
- rasa/cli/project_templates/telco/docs/docs.md +5 -0
- rasa/cli/project_templates/telco/docs/network/reset_vs_rboot_router.txt +1 -0
- rasa/cli/project_templates/telco/docs/network/restart_router.txt +6 -0
- rasa/cli/project_templates/telco/docs/network/run_speed_test.txt +6 -0
- rasa/cli/project_templates/telco/domain/billing/understand_bill.yml +102 -0
- rasa/cli/project_templates/telco/domain/domain.md +14 -0
- rasa/cli/project_templates/telco/domain/general/bot_challenge.yml +4 -0
- rasa/cli/project_templates/telco/domain/general/feedback.yml +25 -0
- rasa/cli/project_templates/telco/domain/general/goodbye.yml +7 -0
- rasa/cli/project_templates/telco/domain/general/hello.yml +5 -0
- rasa/cli/project_templates/telco/domain/general/human_handoff.yml +26 -0
- rasa/cli/project_templates/telco/domain/general/patterns.yml +33 -0
- rasa/cli/project_templates/telco/domain/network/reboot_router.yml +21 -0
- rasa/cli/project_templates/telco/domain/network/reset_router.yml +12 -0
- rasa/cli/project_templates/telco/domain/network/run_speed_test.yml +25 -0
- rasa/cli/project_templates/telco/domain/network/solve_internet_issue.yml +75 -0
- rasa/cli/project_templates/telco/domain/shared.yml +129 -0
- rasa/cli/project_templates/telco/endpoints.yml +67 -0
- rasa/cli/project_templates/telco/prompts/rephraser_demo_personality_prompt.jinja2 +40 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/billing/understand_bill.yml +67 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/bot_challenge.yml +8 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/feedback.yml +46 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/goodbye.yml +9 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/hello.yml +8 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/human_handoff.yml +35 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/patterns.yml +23 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/network/solve_internet_issue.yml +57 -0
- rasa/cli/project_templates/tutorial/config.yml +2 -1
- rasa/cli/scaffold.py +46 -2
- rasa/core/actions/action.py +0 -1
- rasa/core/available_agents.py +2 -0
- rasa/core/available_endpoints.py +17 -2
- rasa/core/channels/channel.py +4 -3
- rasa/core/channels/constants.py +3 -0
- rasa/core/channels/development_inspector.py +2 -22
- rasa/core/channels/inspector/README.md +26 -14
- rasa/core/channels/inspector/dist/assets/{arc-cce7e0a8.js → arc-edef10dd.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-e2a49be7.js → blockDiagram-38ab4fdb-49f6762b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-3def7895.js → c4Diagram-3d4e48cf-313c08e6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/channel-63aa27d1.js +1 -0
- rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-e66fe4df.js → classDiagram-70f12bd4-35e41ce9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-eb874aaa.js → classDiagram-v2-f2320105-f346068d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/clone-5566bae8.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-cf934643.js → createText-2e5e7dd3-7a44bce8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-8fdf9155.js → edges-e0da2a9e-d7cf78c7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-6106fb96.js → erDiagram-9861fffd-9813e81c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-4c2bb040.js → flowDb-956e92f1-d8ba0870.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-f0ff96af.js → flowDiagram-66a62f08-51f0db4d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-32936074.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-a21707ec.js → flowchart-elk-definition-4a651766-ff9ea384.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-c165acb1.js → ganttDiagram-c361ad54-a8e13b6b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-b0564cf1.js → gitGraphDiagram-72cf32ee-3b171c6d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-e557e67a.js → graph-790ef78b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3862675e-1ce60e9e.js → index-3862675e-ecdce073.js} +1 -1
- rasa/core/channels/inspector/dist/assets/index-d705da80.js +1352 -0
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-893569e2.js → infoDiagram-f8f76790-f5a422fe.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-c29c864f.js → journeyDiagram-49397b02-3185b7ac.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-649a5eae.js → layout-837fd3aa.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-0e5685ed.js → line-7e05afcb.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-eaa320bd.js → linear-162eb295.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-f35df9e6.js → mindmap-definition-fc14e90a-f4978aee.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-78339e96.js → pieDiagram-8a3498a8-b25d0a52.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-9b5f2f14.js → quadrantDiagram-120e2f19-63db1afa.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-d05ddb3a.js → requirementDiagram-deff3bca-1b486cc9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-d9be5dfd.js → sankeyDiagram-04a897e0-7e795291.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-0f1c4348.js → sequenceDiagram-704730f1-b8aba159.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-9ddf63b3.js → stateDiagram-587899a1-41529fd5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-bc2b81ed.js → stateDiagram-v2-d93cdb3a-b241043c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-0a287936.js → styles-6aaf32cf-b5b53234.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-e3941990.js → styles-9a916d00-13d138e5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-ce4eca24.js → styles-c10674c1-94cbde3f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-d822b1a8.js → svgDrawCommon-08f97a94-453ae764.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-e144c7a7.js → timeline-definition-85554ec2-8dcb88a4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-ab7f4e14.js → xychartDiagram-e933f94c-376af5f0.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +2 -2
- rasa/core/channels/inspector/index.html +1 -1
- rasa/core/channels/inspector/src/App.tsx +16 -42
- rasa/core/channels/inspector/src/components/Chat.tsx +2 -3
- rasa/core/channels/inspector/src/components/DialogueHistoryStack.tsx +1 -0
- rasa/core/channels/inspector/src/components/DialogueInformation.tsx +20 -3
- rasa/core/channels/inspector/src/components/LatencyDisplay.tsx +63 -35
- rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +14 -0
- rasa/core/channels/inspector/src/types.ts +32 -7
- rasa/core/channels/socketio.py +212 -51
- rasa/core/channels/studio_chat.py +59 -57
- rasa/core/channels/voice_stream/asr/asr_event.py +1 -1
- rasa/core/channels/voice_stream/asr/azure.py +6 -3
- rasa/core/channels/voice_stream/asr/deepgram.py +1 -1
- rasa/core/channels/voice_stream/audiocodes.py +3 -0
- rasa/core/channels/voice_stream/browser_audio.py +53 -3
- rasa/core/channels/voice_stream/genesys.py +2 -1
- rasa/core/channels/voice_stream/jambonz.py +9 -1
- rasa/core/channels/voice_stream/twilio_media_streams.py +16 -0
- rasa/core/channels/voice_stream/voice_channel.py +66 -3
- rasa/core/constants.py +6 -0
- rasa/core/iam_credentials_providers/__init__.py +0 -0
- rasa/core/iam_credentials_providers/aws_iam_credentials_providers.py +66 -0
- rasa/core/iam_credentials_providers/credentials_provider_protocol.py +89 -0
- rasa/core/policies/enterprise_search_policy.py +4 -7
- rasa/core/policies/flows/flow_executor.py +14 -5
- rasa/core/policies/ted_policy.py +7 -5
- rasa/core/processor.py +32 -0
- rasa/core/redis_connection_factory.py +411 -0
- rasa/core/run.py +13 -3
- rasa/core/tracker_stores/redis_tracker_store.py +32 -14
- rasa/core/tracker_stores/sql_tracker_store.py +57 -1
- rasa/dialogue_understanding/generator/flow_retrieval.py +10 -9
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +10 -5
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +10 -5
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +20 -12
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +19 -12
- rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +6 -35
- rasa/dialogue_understanding/patterns/cancel.py +27 -6
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +1 -1
- rasa/dialogue_understanding/processor/command_processor.py +35 -0
- rasa/engine/graph.py +5 -1
- rasa/engine/recipes/default_components.py +78 -10
- rasa/engine/recipes/default_recipe.py +41 -1
- rasa/engine/storage/local_model_storage.py +83 -3
- rasa/graph_components/validators/default_recipe_validator.py +153 -135
- rasa/model_manager/model_api.py +4 -5
- rasa/model_manager/runner_service.py +1 -1
- rasa/model_manager/socket_bridge.py +20 -15
- rasa/model_manager/trainer_service.py +12 -9
- rasa/model_manager/utils.py +1 -29
- rasa/model_manager/warm_rasa_process.py +1 -1
- rasa/model_training.py +14 -0
- rasa/nlu/classifiers/diet_classifier.py +22 -6
- rasa/nlu/classifiers/logistic_regression_classifier.py +18 -0
- rasa/nlu/extractors/extractor.py +1 -2
- rasa/shared/agents/auth/__init__.py +0 -0
- rasa/shared/agents/auth/agent_auth_factory.py +74 -0
- rasa/shared/agents/auth/agent_auth_manager.py +86 -0
- rasa/shared/agents/auth/auth_strategy/__init__.py +19 -0
- rasa/shared/agents/auth/auth_strategy/agent_auth_strategy.py +52 -0
- rasa/shared/agents/auth/auth_strategy/api_key_auth_strategy.py +42 -0
- rasa/shared/agents/auth/auth_strategy/bearer_token_auth_strategy.py +28 -0
- rasa/shared/agents/auth/auth_strategy/oauth2_auth_strategy.py +159 -0
- rasa/shared/agents/auth/constants.py +11 -0
- rasa/shared/agents/auth/types.py +11 -0
- rasa/shared/core/constants.py +1 -0
- rasa/shared/core/domain.py +58 -11
- rasa/shared/core/events.py +2 -0
- rasa/shared/core/flows/constants.py +5 -0
- rasa/shared/core/flows/flow_step.py +7 -1
- rasa/shared/core/flows/flows_list.py +6 -0
- rasa/shared/core/flows/steps/call.py +15 -12
- rasa/shared/core/flows/validation.py +238 -44
- rasa/shared/core/flows/yaml_flows_io.py +15 -6
- rasa/shared/core/slots.py +4 -0
- rasa/shared/exceptions.py +12 -0
- rasa/shared/importers/importer.py +6 -0
- rasa/shared/importers/utils.py +77 -1
- rasa/shared/nlu/training_data/schemas/responses.yml +3 -0
- rasa/shared/providers/_utils.py +60 -44
- rasa/shared/providers/embedding/default_litellm_embedding_client.py +2 -0
- rasa/shared/providers/llm/_base_litellm_client.py +2 -2
- rasa/shared/providers/llm/default_litellm_llm_client.py +2 -0
- rasa/shared/providers/llm/llm_response.py +4 -4
- rasa/shared/utils/common.py +24 -0
- rasa/shared/utils/llm.py +2 -1
- rasa/shared/utils/mcp/server_connection.py +84 -23
- rasa/shared/utils/mcp/utils.py +20 -0
- rasa/studio/upload.py +16 -47
- rasa/telemetry.py +97 -23
- rasa/tracing/config.py +38 -12
- rasa/tracing/instrumentation/attribute_extractors.py +5 -1
- rasa/tracing/instrumentation/instrumentation.py +85 -8
- rasa/utils/common.py +1 -1
- rasa/utils/io.py +27 -9
- rasa/utils/json_utils.py +6 -1
- rasa/utils/log_utils.py +5 -1
- rasa/utils/openapi.py +144 -0
- rasa/utils/tensorflow/__init__.py +29 -0
- rasa/utils/tensorflow/callback.py +1 -1
- rasa/utils/tensorflow/crf.py +1 -1
- rasa/utils/tensorflow/data_generator.py +21 -8
- rasa/utils/tensorflow/layers.py +11 -4
- rasa/utils/tensorflow/metrics.py +7 -3
- rasa/utils/tensorflow/models.py +41 -6
- rasa/utils/tensorflow/rasa_layers.py +6 -4
- rasa/utils/tensorflow/transformer.py +2 -3
- rasa/utils/train_utils.py +68 -38
- rasa/validator.py +18 -16
- rasa/version.py +1 -1
- rasa_pro-3.14.0.dev8.dist-info/METADATA +199 -0
- {rasa_pro-3.14.0.dev7.dist-info → rasa_pro-3.14.0.dev8.dist-info}/RECORD +466 -156
- rasa/core/channels/inspector/dist/assets/channel-858c2c20.js +0 -1
- rasa/core/channels/inspector/dist/assets/clone-4b80996c.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-16f09b7a.js +0 -1
- rasa/core/channels/inspector/dist/assets/index-996fe816.js +0 -1353
- rasa_pro-3.14.0.dev7.dist-info/METADATA +0 -190
- {rasa_pro-3.14.0.dev7.dist-info → rasa_pro-3.14.0.dev8.dist-info}/NOTICE +0 -0
- {rasa_pro-3.14.0.dev7.dist-info → rasa_pro-3.14.0.dev8.dist-info}/WHEEL +0 -0
- {rasa_pro-3.14.0.dev7.dist-info → rasa_pro-3.14.0.dev8.dist-info}/entry_points.txt +0 -0
|
@@ -4,7 +4,6 @@ import asyncio
|
|
|
4
4
|
import audioop
|
|
5
5
|
import base64
|
|
6
6
|
import json
|
|
7
|
-
import time
|
|
8
7
|
import uuid
|
|
9
8
|
from functools import partial
|
|
10
9
|
from typing import (
|
|
@@ -17,9 +16,9 @@ from typing import (
|
|
|
17
16
|
Optional,
|
|
18
17
|
Text,
|
|
19
18
|
Tuple,
|
|
19
|
+
Union,
|
|
20
20
|
)
|
|
21
21
|
|
|
22
|
-
import orjson
|
|
23
22
|
import structlog
|
|
24
23
|
|
|
25
24
|
from rasa.core.channels import UserMessage
|
|
@@ -47,16 +46,13 @@ if TYPE_CHECKING:
|
|
|
47
46
|
from sanic import Sanic, Websocket # type: ignore[attr-defined]
|
|
48
47
|
from socketio import AsyncServer
|
|
49
48
|
|
|
50
|
-
from rasa.core.channels.channel import UserMessage
|
|
51
49
|
from rasa.shared.core.trackers import DialogueStateTracker
|
|
52
50
|
|
|
53
51
|
|
|
54
52
|
structlogger = structlog.get_logger()
|
|
55
53
|
|
|
56
54
|
|
|
57
|
-
def tracker_as_dump(
|
|
58
|
-
tracker: "DialogueStateTracker", latency: Optional[float] = None
|
|
59
|
-
) -> str:
|
|
55
|
+
def tracker_as_dump(tracker: "DialogueStateTracker") -> Dict[str, Any]:
|
|
60
56
|
"""Create a dump of the tracker state."""
|
|
61
57
|
from rasa.shared.core.trackers import get_trackers_for_conversation_sessions
|
|
62
58
|
|
|
@@ -68,10 +64,7 @@ def tracker_as_dump(
|
|
|
68
64
|
last_tracker = multiple_tracker_sessions[-1]
|
|
69
65
|
|
|
70
66
|
state = last_tracker.current_state(EventVerbosity.AFTER_RESTART)
|
|
71
|
-
|
|
72
|
-
if latency is not None:
|
|
73
|
-
state["latency"] = {"rasa_processing_latency_ms": latency}
|
|
74
|
-
return orjson.dumps(state, option=orjson.OPT_SERIALIZE_NUMPY).decode("utf-8")
|
|
67
|
+
return state
|
|
75
68
|
|
|
76
69
|
|
|
77
70
|
def does_need_action_prediction(tracker: "DialogueStateTracker") -> bool:
|
|
@@ -153,6 +146,7 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
153
146
|
jwt_key: Optional[Text] = None,
|
|
154
147
|
jwt_method: Optional[Text] = "HS256",
|
|
155
148
|
metadata_key: Optional[Text] = "metadata",
|
|
149
|
+
enable_silence_timeout: bool = False,
|
|
156
150
|
) -> None:
|
|
157
151
|
"""Creates a `StudioChatInput` object."""
|
|
158
152
|
from rasa.core.agent import Agent
|
|
@@ -170,6 +164,7 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
170
164
|
jwt_key=jwt_key,
|
|
171
165
|
jwt_method=jwt_method,
|
|
172
166
|
metadata_key=metadata_key,
|
|
167
|
+
enable_silence_timeout=enable_silence_timeout,
|
|
173
168
|
)
|
|
174
169
|
|
|
175
170
|
# Initialize the Voice Input Channel
|
|
@@ -210,55 +205,46 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
210
205
|
jwt_key=credentials.get("jwt_key"),
|
|
211
206
|
jwt_method=credentials.get("jwt_method", "HS256"),
|
|
212
207
|
metadata_key=credentials.get("metadata_key", "metadata"),
|
|
208
|
+
enable_silence_timeout=credentials.get("enable_silence_timeout", False),
|
|
213
209
|
)
|
|
214
210
|
|
|
215
|
-
async def emit(self, event: str, data: str, room: str) -> None:
|
|
211
|
+
async def emit(self, event: str, data: Union[Dict, str], room: str) -> None:
|
|
216
212
|
"""Emits an event to the websocket."""
|
|
217
|
-
if not self.
|
|
213
|
+
if not self.sio_server:
|
|
218
214
|
structlogger.error("studio_chat.emit.sio_not_initialized")
|
|
219
215
|
return
|
|
220
|
-
await self.
|
|
216
|
+
await self.sio_server.emit(event, data, room=room)
|
|
221
217
|
|
|
222
218
|
def _register_tracker_update_hook(self) -> None:
|
|
223
219
|
plugin_manager().register(StudioTrackerUpdatePlugin(self))
|
|
224
220
|
|
|
225
|
-
async def on_tracker_updated(
|
|
226
|
-
self, tracker: "DialogueStateTracker", latency: Optional[float] = None
|
|
227
|
-
) -> None:
|
|
221
|
+
async def on_tracker_updated(self, tracker: "DialogueStateTracker") -> None:
|
|
228
222
|
"""Triggers a tracker update notification after a change to the tracker."""
|
|
229
|
-
await self.publish_tracker_update(
|
|
230
|
-
tracker.sender_id, tracker_as_dump(tracker, latency)
|
|
231
|
-
)
|
|
223
|
+
await self.publish_tracker_update(tracker.sender_id, tracker_as_dump(tracker))
|
|
232
224
|
|
|
233
|
-
async def publish_tracker_update(
|
|
225
|
+
async def publish_tracker_update(
|
|
226
|
+
self, sender_id: str, tracker_dump: Dict[str, Any]
|
|
227
|
+
) -> None:
|
|
234
228
|
"""Publishes a tracker update notification to the websocket."""
|
|
235
229
|
await self.emit("tracker", tracker_dump, room=sender_id)
|
|
236
230
|
|
|
237
|
-
def _record_turn_start_time(self, sender_id: Text) -> None:
|
|
238
|
-
"""Records the start time of a new turn."""
|
|
239
|
-
self._turn_start_times[sender_id] = time.time()
|
|
240
|
-
|
|
241
|
-
def _get_latency(self, sender_id: Text) -> Optional[float]:
|
|
242
|
-
"""Returns the latency of the current turn in milliseconds."""
|
|
243
|
-
if sender_id not in self._turn_start_times:
|
|
244
|
-
return None
|
|
245
|
-
|
|
246
|
-
latency = (time.time() - self._turn_start_times[sender_id]) * 1000
|
|
247
|
-
# The turn is over, so we can remove the start time
|
|
248
|
-
del self._turn_start_times[sender_id]
|
|
249
|
-
return latency
|
|
250
|
-
|
|
251
231
|
async def on_message_proxy(
|
|
252
232
|
self,
|
|
253
|
-
on_new_message: Callable[[
|
|
254
|
-
message:
|
|
233
|
+
on_new_message: Callable[[UserMessage], Awaitable[Any]],
|
|
234
|
+
message: UserMessage,
|
|
255
235
|
) -> None:
|
|
256
236
|
"""Proxies the on_new_message call to the underlying channel.
|
|
257
237
|
|
|
258
238
|
Triggers a tracker update notification after processing the message.
|
|
259
239
|
"""
|
|
260
|
-
|
|
261
|
-
|
|
240
|
+
try:
|
|
241
|
+
await on_new_message(message)
|
|
242
|
+
except Exception as e:
|
|
243
|
+
structlogger.exception(
|
|
244
|
+
"studio_chat.on_new_message.error",
|
|
245
|
+
error=str(e),
|
|
246
|
+
sender_id=message.sender_id,
|
|
247
|
+
)
|
|
262
248
|
|
|
263
249
|
if not self.agent or not self.agent.is_ready():
|
|
264
250
|
structlogger.error("studio_chat.on_message_proxy.agent_not_initialized")
|
|
@@ -276,8 +262,7 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
276
262
|
structlogger.error("studio_chat.on_message_proxy.tracker_not_found")
|
|
277
263
|
return
|
|
278
264
|
|
|
279
|
-
|
|
280
|
-
await self.on_tracker_updated(tracker, latency)
|
|
265
|
+
await self.on_tracker_updated(tracker)
|
|
281
266
|
|
|
282
267
|
async def emit_error(self, message: str, room: str, e: Exception) -> None:
|
|
283
268
|
await self.emit(
|
|
@@ -380,13 +365,20 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
380
365
|
def create_output_channel(
|
|
381
366
|
self, voice_websocket: "Websocket", tts_engine: TTSEngine
|
|
382
367
|
) -> VoiceOutputChannel:
|
|
383
|
-
"""Create a voice output channel."""
|
|
368
|
+
"""Create a voice output channel. This is used by VoiceInputChannel."""
|
|
384
369
|
return StudioVoiceOutputChannel(
|
|
385
370
|
voice_websocket,
|
|
386
371
|
tts_engine,
|
|
387
372
|
self.tts_cache,
|
|
388
373
|
)
|
|
389
374
|
|
|
375
|
+
async def interrupt_playback(
|
|
376
|
+
self, ws: Websocket, call_parameters: CallParameters
|
|
377
|
+
) -> None:
|
|
378
|
+
"""Interrupt the current playback of audio."""
|
|
379
|
+
structlogger.debug("studio_chat.interrupt_playback")
|
|
380
|
+
await ws.send(json.dumps({"interruptPlayback": True}))
|
|
381
|
+
|
|
390
382
|
def _start_voice_session(
|
|
391
383
|
self,
|
|
392
384
|
session_id: str,
|
|
@@ -407,7 +399,7 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
407
399
|
|
|
408
400
|
# Create a websocket adapter for this connection
|
|
409
401
|
ws_adapter = SocketIOVoiceWebsocketAdapter(
|
|
410
|
-
|
|
402
|
+
sio_server=self.sio_server,
|
|
411
403
|
session_id=session_id,
|
|
412
404
|
sid=sid,
|
|
413
405
|
bot_message_evt=self.bot_message_evt,
|
|
@@ -455,12 +447,13 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
455
447
|
task.cancel()
|
|
456
448
|
|
|
457
449
|
def blueprint(
|
|
458
|
-
self, on_new_message: Callable[[
|
|
450
|
+
self, on_new_message: Callable[[UserMessage], Awaitable[Any]]
|
|
459
451
|
) -> SocketBlueprint:
|
|
460
|
-
|
|
461
|
-
|
|
452
|
+
socket_blueprint = super().blueprint(
|
|
453
|
+
partial(self.on_message_proxy, on_new_message)
|
|
454
|
+
)
|
|
462
455
|
|
|
463
|
-
if not self.
|
|
456
|
+
if not self.sio_server:
|
|
464
457
|
structlogger.error("studio_chat.blueprint.sio_not_initialized")
|
|
465
458
|
return socket_blueprint
|
|
466
459
|
|
|
@@ -468,14 +461,15 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
468
461
|
async def after_server_start(
|
|
469
462
|
app: "Sanic", _: asyncio.AbstractEventLoop
|
|
470
463
|
) -> None:
|
|
471
|
-
|
|
464
|
+
if hasattr(app.ctx, "agent"):
|
|
465
|
+
self.agent = app.ctx.agent
|
|
472
466
|
|
|
473
|
-
@self.
|
|
467
|
+
@self.sio_server.on("disconnect", namespace=self.namespace)
|
|
474
468
|
async def disconnect(sid: Text) -> None:
|
|
475
469
|
structlogger.debug("studio_chat.sio.disconnect", sid=sid)
|
|
476
470
|
self._cleanup_tasks_for_sid(sid)
|
|
477
471
|
|
|
478
|
-
@self.
|
|
472
|
+
@self.sio_server.on("session_request", namespace=self.namespace)
|
|
479
473
|
async def session_request(sid: Text, data: Optional[Dict]) -> None:
|
|
480
474
|
"""Overrides the base SocketIOInput session_request handler.
|
|
481
475
|
|
|
@@ -493,9 +487,9 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
493
487
|
|
|
494
488
|
# start a voice session if requested
|
|
495
489
|
if data and data.get("is_voice", False):
|
|
496
|
-
self._start_voice_session(data["session_id"], sid,
|
|
490
|
+
self._start_voice_session(data["session_id"], sid, on_new_message)
|
|
497
491
|
|
|
498
|
-
@self.
|
|
492
|
+
@self.sio_server.on(self.user_message_evt, namespace=self.namespace)
|
|
499
493
|
async def handle_message(sid: Text, data: Dict) -> None:
|
|
500
494
|
"""Overrides the base SocketIOInput handle_message handler."""
|
|
501
495
|
# Handle voice messages
|
|
@@ -506,10 +500,18 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
|
|
|
506
500
|
ws.put_message(data)
|
|
507
501
|
return
|
|
508
502
|
|
|
509
|
-
|
|
510
|
-
|
|
503
|
+
try:
|
|
504
|
+
# Handle text messages
|
|
505
|
+
await self.handle_user_message(sid, data, on_new_message)
|
|
506
|
+
except Exception as e:
|
|
507
|
+
structlogger.exception(
|
|
508
|
+
"studio_chat.sio.handle_message.error",
|
|
509
|
+
error=str(e),
|
|
510
|
+
sid=sid,
|
|
511
|
+
)
|
|
512
|
+
await self.emit("error", str(e), room=sid)
|
|
511
513
|
|
|
512
|
-
@self.
|
|
514
|
+
@self.sio_server.on("update_tracker", namespace=self.namespace)
|
|
513
515
|
async def on_update_tracker(sid: Text, data: Dict) -> None:
|
|
514
516
|
await self.handle_tracker_update(sid, data)
|
|
515
517
|
|
|
@@ -555,9 +557,9 @@ class SocketIOVoiceWebsocketAdapter:
|
|
|
555
557
|
"""Adapter to make Socket.IO work like a Sanic WebSocket for voice channels."""
|
|
556
558
|
|
|
557
559
|
def __init__(
|
|
558
|
-
self,
|
|
560
|
+
self, sio_server: "AsyncServer", session_id: str, sid: str, bot_message_evt: str
|
|
559
561
|
) -> None:
|
|
560
|
-
self.
|
|
562
|
+
self.sio_server = sio_server
|
|
561
563
|
self.bot_message_evt = bot_message_evt
|
|
562
564
|
self._closed = False
|
|
563
565
|
self._receive_queue: asyncio.Queue[Any] = asyncio.Queue()
|
|
@@ -576,7 +578,7 @@ class SocketIOVoiceWebsocketAdapter:
|
|
|
576
578
|
async def send(self, data: Any) -> None:
|
|
577
579
|
"""Send data to the client."""
|
|
578
580
|
if not self.closed:
|
|
579
|
-
await self.
|
|
581
|
+
await self.sio_server.emit(self.bot_message_evt, data, room=self.sid)
|
|
580
582
|
|
|
581
583
|
async def recv(self) -> Any:
|
|
582
584
|
"""Receive data from the client."""
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import os
|
|
3
3
|
from dataclasses import dataclass
|
|
4
|
-
from typing import Any, AsyncIterator, Dict, Optional
|
|
4
|
+
from typing import TYPE_CHECKING, Any, AsyncIterator, Dict, Optional
|
|
5
5
|
|
|
6
6
|
import structlog
|
|
7
7
|
|
|
@@ -15,6 +15,9 @@ from rasa.core.channels.voice_stream.audio_bytes import HERTZ, RasaAudioBytes
|
|
|
15
15
|
from rasa.shared.constants import AZURE_SPEECH_API_KEY_ENV_VAR
|
|
16
16
|
from rasa.shared.exceptions import ConnectionException
|
|
17
17
|
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from azure.cognitiveservices.speech import SpeechRecognitionEventArgs
|
|
20
|
+
|
|
18
21
|
logger = structlog.get_logger(__name__)
|
|
19
22
|
|
|
20
23
|
|
|
@@ -43,9 +46,9 @@ class AzureASR(ASREngine[AzureASRConfig]):
|
|
|
43
46
|
)
|
|
44
47
|
self.main_loop = asyncio.get_running_loop()
|
|
45
48
|
|
|
46
|
-
def signal_user_is_speaking(self, event:
|
|
49
|
+
def signal_user_is_speaking(self, event: "SpeechRecognitionEventArgs") -> None:
|
|
47
50
|
"""Replace the azure event with a generic is speaking event."""
|
|
48
|
-
self.fill_queue(UserIsSpeaking())
|
|
51
|
+
self.fill_queue(UserIsSpeaking(event.result.text))
|
|
49
52
|
|
|
50
53
|
def fill_queue(self, event: Any) -> None:
|
|
51
54
|
"""Either puts the event or a dedicated ASR Event into the queue."""
|
|
@@ -117,7 +117,7 @@ class DeepgramASR(ASREngine[DeepgramASRConfig]):
|
|
|
117
117
|
self.accumulated_transcript, transcript
|
|
118
118
|
)
|
|
119
119
|
elif transcript:
|
|
120
|
-
return UserIsSpeaking()
|
|
120
|
+
return UserIsSpeaking(transcript)
|
|
121
121
|
# event that comes after utterance_end_ms of no new transcript
|
|
122
122
|
elif data_type == "UtteranceEnd":
|
|
123
123
|
if self.accumulated_transcript:
|
|
@@ -89,6 +89,7 @@ class AudiocodesVoiceOutputChannel(VoiceOutputChannel):
|
|
|
89
89
|
# This is an approximation, as the bot will be sent the audio chunks next
|
|
90
90
|
# which are played to the user immediately.
|
|
91
91
|
call_state.is_bot_speaking = True
|
|
92
|
+
VoiceInputChannel._cancel_silence_timeout_watcher()
|
|
92
93
|
|
|
93
94
|
async def send_intermediate_marker(self, recipient_id: str) -> None:
|
|
94
95
|
"""Audiocodes doesn't need intermediate markers, so do nothing."""
|
|
@@ -116,6 +117,7 @@ class AudiocodesVoiceInputChannel(VoiceInputChannel):
|
|
|
116
117
|
server_url: str,
|
|
117
118
|
asr_config: Dict,
|
|
118
119
|
tts_config: Dict,
|
|
120
|
+
interruptions: Optional[Dict[str, int]] = None,
|
|
119
121
|
token: Optional[Text] = None,
|
|
120
122
|
):
|
|
121
123
|
mark_as_beta_feature("Audiocodes (audiocodes_stream) Channel")
|
|
@@ -123,6 +125,7 @@ class AudiocodesVoiceInputChannel(VoiceInputChannel):
|
|
|
123
125
|
server_url=server_url,
|
|
124
126
|
asr_config=asr_config,
|
|
125
127
|
tts_config=tts_config,
|
|
128
|
+
interruptions=interruptions,
|
|
126
129
|
)
|
|
127
130
|
self.token = token
|
|
128
131
|
|
|
@@ -3,7 +3,9 @@ from __future__ import annotations
|
|
|
3
3
|
import audioop
|
|
4
4
|
import base64
|
|
5
5
|
import json
|
|
6
|
+
import os
|
|
6
7
|
import uuid
|
|
8
|
+
import wave
|
|
7
9
|
from typing import Any, Awaitable, Callable, Dict, Optional, Tuple
|
|
8
10
|
|
|
9
11
|
import structlog
|
|
@@ -70,10 +72,45 @@ class BrowserAudioOutputChannel(VoiceOutputChannel):
|
|
|
70
72
|
|
|
71
73
|
class BrowserAudioInputChannel(VoiceInputChannel):
|
|
72
74
|
def __init__(
|
|
73
|
-
self,
|
|
75
|
+
self,
|
|
76
|
+
server_url: str,
|
|
77
|
+
asr_config: Dict[str, Any],
|
|
78
|
+
tts_config: Dict[str, Any],
|
|
79
|
+
recording: bool = False,
|
|
80
|
+
interruptions: Optional[Dict[str, int]] = None,
|
|
74
81
|
) -> None:
|
|
75
82
|
"""Initializes the browser audio input channel."""
|
|
76
|
-
super().__init__(server_url, asr_config, tts_config)
|
|
83
|
+
super().__init__(server_url, asr_config, tts_config, interruptions)
|
|
84
|
+
|
|
85
|
+
# For debugging, recording of user audio might be useful
|
|
86
|
+
# to identify audio quality issues or transcription errors
|
|
87
|
+
self._recording_enabled = recording
|
|
88
|
+
self._wav_file: Optional[wave.Wave_write] = None
|
|
89
|
+
|
|
90
|
+
def _start_recording(self, call_id: str, user_id: str) -> None:
|
|
91
|
+
os.makedirs("recordings", exist_ok=True)
|
|
92
|
+
filename = f"{user_id}_{call_id}.wav"
|
|
93
|
+
file_path = os.path.join("recordings", filename)
|
|
94
|
+
|
|
95
|
+
if not self._recording_enabled:
|
|
96
|
+
return
|
|
97
|
+
|
|
98
|
+
self._wav_file = wave.open(file_path, "wb")
|
|
99
|
+
self._wav_file.setnchannels(1) # Mono audio
|
|
100
|
+
self._wav_file.setsampwidth(4) # 32-bit audio (4 bytes)
|
|
101
|
+
self._wav_file.setframerate(8000) # 8kHz sample rate
|
|
102
|
+
logger.info("voice_channel.user_audio_recording.started", file_path=file_path)
|
|
103
|
+
|
|
104
|
+
def _append_audio_to_recording(self, audio_bytes: bytes) -> None:
|
|
105
|
+
if self._wav_file and self._recording_enabled:
|
|
106
|
+
self._wav_file.writeframes(audio_bytes)
|
|
107
|
+
|
|
108
|
+
def _stop_recording(self) -> None:
|
|
109
|
+
"""Close the recording file if it's open."""
|
|
110
|
+
if self._wav_file:
|
|
111
|
+
self._wav_file.close()
|
|
112
|
+
self._wav_file = None
|
|
113
|
+
logger.debug("voice_channel.user_audio_recording.stopped")
|
|
77
114
|
|
|
78
115
|
@classmethod
|
|
79
116
|
def name(cls) -> str:
|
|
@@ -94,7 +131,7 @@ class BrowserAudioInputChannel(VoiceInputChannel):
|
|
|
94
131
|
credentials: Optional[Dict[str, Any]],
|
|
95
132
|
) -> BrowserAudioInputChannel:
|
|
96
133
|
cls.validate_basic_credentials(credentials)
|
|
97
|
-
new_creds = repack_voice_credentials(credentials)
|
|
134
|
+
new_creds = repack_voice_credentials(credentials or {})
|
|
98
135
|
return cls(**new_creds)
|
|
99
136
|
|
|
100
137
|
def map_input_message(
|
|
@@ -105,6 +142,7 @@ class BrowserAudioInputChannel(VoiceInputChannel):
|
|
|
105
142
|
data = json.loads(message)
|
|
106
143
|
if "audio" in data:
|
|
107
144
|
channel_bytes = base64.b64decode(data["audio"])
|
|
145
|
+
self._append_audio_to_recording(channel_bytes)
|
|
108
146
|
audio_bytes = self.channel_bytes_to_rasa_audio_bytes(channel_bytes)
|
|
109
147
|
return NewAudioAction(audio_bytes)
|
|
110
148
|
elif "marker" in data:
|
|
@@ -120,6 +158,13 @@ class BrowserAudioInputChannel(VoiceInputChannel):
|
|
|
120
158
|
call_state.is_bot_speaking = True
|
|
121
159
|
return ContinueConversationAction()
|
|
122
160
|
|
|
161
|
+
async def interrupt_playback(
|
|
162
|
+
self, ws: Websocket, call_parameters: CallParameters
|
|
163
|
+
) -> None:
|
|
164
|
+
"""Interrupt the current playback of audio."""
|
|
165
|
+
logger.debug("browser_audio.interrupt_playback")
|
|
166
|
+
await ws.send(json.dumps({"interruptPlayback": True}))
|
|
167
|
+
|
|
123
168
|
def create_output_channel(
|
|
124
169
|
self, voice_websocket: Websocket, tts_engine: TTSEngine
|
|
125
170
|
) -> VoiceOutputChannel:
|
|
@@ -142,8 +187,13 @@ class BrowserAudioInputChannel(VoiceInputChannel):
|
|
|
142
187
|
@blueprint.websocket("/websocket") # type: ignore
|
|
143
188
|
async def handle_message(request: Request, ws: Websocket) -> None:
|
|
144
189
|
try:
|
|
190
|
+
call_parameters = await self.collect_call_parameters(ws)
|
|
191
|
+
if call_parameters and call_parameters.call_id:
|
|
192
|
+
self._start_recording(call_parameters.call_id, "local")
|
|
145
193
|
await self.run_audio_streaming(on_new_message, ws)
|
|
146
194
|
except Exception as e:
|
|
147
195
|
logger.error("browser_audio.handle_message.error", error=e)
|
|
196
|
+
finally:
|
|
197
|
+
self._stop_recording()
|
|
148
198
|
|
|
149
199
|
return blueprint
|
|
@@ -99,10 +99,11 @@ class GenesysInputChannel(VoiceInputChannel):
|
|
|
99
99
|
server_url: str,
|
|
100
100
|
asr_config: Dict,
|
|
101
101
|
tts_config: Dict,
|
|
102
|
+
interruptions: Optional[Dict[str, int]] = None,
|
|
102
103
|
api_key: Optional[Text] = None,
|
|
103
104
|
client_secret: Optional[Text] = None,
|
|
104
105
|
) -> None:
|
|
105
|
-
super().__init__(server_url, asr_config, tts_config)
|
|
106
|
+
super().__init__(server_url, asr_config, tts_config, interruptions)
|
|
106
107
|
self.api_key = api_key
|
|
107
108
|
self.client_secret = client_secret
|
|
108
109
|
|
|
@@ -81,6 +81,7 @@ class JambonzStreamInputChannel(VoiceInputChannel):
|
|
|
81
81
|
server_url: str,
|
|
82
82
|
asr_config: Dict,
|
|
83
83
|
tts_config: Dict,
|
|
84
|
+
interruptions: Optional[Dict[str, int]] = None,
|
|
84
85
|
username: Optional[Text] = None,
|
|
85
86
|
password: Optional[Text] = None,
|
|
86
87
|
) -> None:
|
|
@@ -90,7 +91,7 @@ class JambonzStreamInputChannel(VoiceInputChannel):
|
|
|
90
91
|
username: Optional username for basic auth
|
|
91
92
|
password: Optional password for basic auth
|
|
92
93
|
"""
|
|
93
|
-
super().__init__(server_url, asr_config, tts_config)
|
|
94
|
+
super().__init__(server_url, asr_config, tts_config, interruptions)
|
|
94
95
|
self.username = username
|
|
95
96
|
self.password = password
|
|
96
97
|
|
|
@@ -185,6 +186,13 @@ class JambonzStreamInputChannel(VoiceInputChannel):
|
|
|
185
186
|
self.tts_cache,
|
|
186
187
|
)
|
|
187
188
|
|
|
189
|
+
async def interrupt_playback(
|
|
190
|
+
self, ws: Websocket, call_parameters: CallParameters
|
|
191
|
+
) -> None:
|
|
192
|
+
"""Interrupt the current playback of audio."""
|
|
193
|
+
logger.debug("jambonz.interrupt_playback")
|
|
194
|
+
await ws.send(json.dumps({"type": "killAudio"}))
|
|
195
|
+
|
|
188
196
|
def blueprint(
|
|
189
197
|
self, on_new_message: Callable[[UserMessage], Awaitable[Any]]
|
|
190
198
|
) -> Blueprint:
|
|
@@ -105,6 +105,7 @@ class TwilioMediaStreamsInputChannel(VoiceInputChannel):
|
|
|
105
105
|
server_url: str,
|
|
106
106
|
asr_config: Dict,
|
|
107
107
|
tts_config: Dict,
|
|
108
|
+
interruptions: Optional[Dict[str, int]] = None,
|
|
108
109
|
username: Optional[Text] = None,
|
|
109
110
|
password: Optional[Text] = None,
|
|
110
111
|
):
|
|
@@ -112,6 +113,7 @@ class TwilioMediaStreamsInputChannel(VoiceInputChannel):
|
|
|
112
113
|
server_url=server_url,
|
|
113
114
|
asr_config=asr_config,
|
|
114
115
|
tts_config=tts_config,
|
|
116
|
+
interruptions=interruptions,
|
|
115
117
|
)
|
|
116
118
|
self.username = username
|
|
117
119
|
self.password = password
|
|
@@ -195,6 +197,20 @@ class TwilioMediaStreamsInputChannel(VoiceInputChannel):
|
|
|
195
197
|
self.tts_cache,
|
|
196
198
|
)
|
|
197
199
|
|
|
200
|
+
async def interrupt_playback(
|
|
201
|
+
self, ws: Websocket, call_parameters: CallParameters
|
|
202
|
+
) -> None:
|
|
203
|
+
"""Interrupt the current playback of audio."""
|
|
204
|
+
logger.debug("twilio_media_streams.interrupt_playback")
|
|
205
|
+
await ws.send(
|
|
206
|
+
json.dumps(
|
|
207
|
+
{
|
|
208
|
+
"event": "clear",
|
|
209
|
+
"streamSid": call_parameters.stream_id,
|
|
210
|
+
}
|
|
211
|
+
)
|
|
212
|
+
)
|
|
213
|
+
|
|
198
214
|
def blueprint(
|
|
199
215
|
self, on_new_message: Callable[[UserMessage], Awaitable[Any]]
|
|
200
216
|
) -> Blueprint:
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import copy
|
|
5
|
+
import string
|
|
5
6
|
import time
|
|
6
7
|
from dataclasses import asdict, dataclass
|
|
7
8
|
from typing import Any, AsyncIterator, Awaitable, Callable, Dict, List, Optional, Tuple
|
|
@@ -11,6 +12,11 @@ from sanic import Websocket # type: ignore
|
|
|
11
12
|
from sanic.exceptions import ServerError, WebsocketClosed
|
|
12
13
|
|
|
13
14
|
from rasa.core.channels import InputChannel, OutputChannel, UserMessage
|
|
15
|
+
from rasa.core.channels.constants import (
|
|
16
|
+
USER_CONVERSATION_SESSION_END,
|
|
17
|
+
USER_CONVERSATION_SESSION_START,
|
|
18
|
+
USER_CONVERSATION_SILENCE_TIMEOUT,
|
|
19
|
+
)
|
|
14
20
|
from rasa.core.channels.voice_ready.utils import (
|
|
15
21
|
CallParameters,
|
|
16
22
|
validate_voice_license_scope,
|
|
@@ -48,9 +54,13 @@ from rasa.utils.io import remove_emojis
|
|
|
48
54
|
logger = structlog.get_logger(__name__)
|
|
49
55
|
|
|
50
56
|
# define constants for the voice channel
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
DEFAULT_INTERRUPTION_MIN_WORDS = 3
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclass
|
|
61
|
+
class InterruptionConfig:
|
|
62
|
+
enabled: bool = False
|
|
63
|
+
min_words: int = DEFAULT_INTERRUPTION_MIN_WORDS
|
|
54
64
|
|
|
55
65
|
|
|
56
66
|
@dataclass
|
|
@@ -268,6 +278,10 @@ class VoiceOutputChannel(OutputChannel):
|
|
|
268
278
|
except (WebsocketClosed, ServerError):
|
|
269
279
|
call_state.connection_failed = True
|
|
270
280
|
|
|
281
|
+
# Is the response interruptible?
|
|
282
|
+
allow_interruptions = kwargs.get("allow_interruptions", True)
|
|
283
|
+
call_state.channel_data["allow_interruptions"] = allow_interruptions
|
|
284
|
+
|
|
271
285
|
if cached_audio_bytes:
|
|
272
286
|
audio_stream = self.chunk_audio(cached_audio_bytes)
|
|
273
287
|
else:
|
|
@@ -366,6 +380,7 @@ class VoiceInputChannel(InputChannel):
|
|
|
366
380
|
server_url: str,
|
|
367
381
|
asr_config: Dict,
|
|
368
382
|
tts_config: Dict,
|
|
383
|
+
interruptions: Optional[Dict[str, Any]] = None,
|
|
369
384
|
):
|
|
370
385
|
if self.requires_voice_license:
|
|
371
386
|
validate_voice_license_scope()
|
|
@@ -374,12 +389,21 @@ class VoiceInputChannel(InputChannel):
|
|
|
374
389
|
self.asr_config = asr_config
|
|
375
390
|
self.tts_config = tts_config
|
|
376
391
|
self.tts_cache = TTSCache(tts_config.get("cache_size", 1000))
|
|
392
|
+
if interruptions:
|
|
393
|
+
self.interruption_config = InterruptionConfig(**interruptions)
|
|
394
|
+
else:
|
|
395
|
+
self.interruption_config = InterruptionConfig()
|
|
396
|
+
|
|
397
|
+
if self.interruption_config.enabled:
|
|
398
|
+
mark_as_beta_feature(f"Interruption Handling in {self.name()}")
|
|
377
399
|
|
|
378
400
|
logger.info(
|
|
379
401
|
"voice_channel.initialized",
|
|
402
|
+
name=self.name(),
|
|
380
403
|
server_url=self.server_url,
|
|
381
404
|
asr_config=self.asr_config,
|
|
382
405
|
tts_config=self.tts_config,
|
|
406
|
+
interruption_config=self.interruption_config,
|
|
383
407
|
)
|
|
384
408
|
|
|
385
409
|
def get_sender_id(self, call_parameters: CallParameters) -> str:
|
|
@@ -461,6 +485,43 @@ class VoiceInputChannel(InputChannel):
|
|
|
461
485
|
"""Map a channel input message to a voice channel action."""
|
|
462
486
|
raise NotImplementedError
|
|
463
487
|
|
|
488
|
+
def should_interrupt(self, e: ASREvent) -> bool:
|
|
489
|
+
"""Determine if the current ASR event should interrupt playback.
|
|
490
|
+
Returns True if the bot response is interruptible
|
|
491
|
+
And if the user spoke more than 3 words.
|
|
492
|
+
|
|
493
|
+
Arguments:
|
|
494
|
+
e: The ASR event to evaluate.
|
|
495
|
+
|
|
496
|
+
Returns:
|
|
497
|
+
True if the event should interrupt playback, False otherwise.
|
|
498
|
+
"""
|
|
499
|
+
# Are interruptions are enabled for the channel?
|
|
500
|
+
if not self.interruption_config.enabled:
|
|
501
|
+
return False
|
|
502
|
+
|
|
503
|
+
# Is the bot response interruptible?
|
|
504
|
+
if not call_state.channel_data.get("allow_interruptions", True):
|
|
505
|
+
return False
|
|
506
|
+
|
|
507
|
+
# Did the user speak more than 3 words?
|
|
508
|
+
min_words = self.interruption_config.min_words
|
|
509
|
+
if isinstance(e, UserIsSpeaking):
|
|
510
|
+
translator = str.maketrans("", "", string.punctuation)
|
|
511
|
+
words = e.text.translate(translator).split()
|
|
512
|
+
return len(words) >= min_words
|
|
513
|
+
return False
|
|
514
|
+
|
|
515
|
+
async def interrupt_playback(
|
|
516
|
+
self, ws: Websocket, call_parameters: CallParameters
|
|
517
|
+
) -> None:
|
|
518
|
+
"""Interrupt the current playback of audio.
|
|
519
|
+
|
|
520
|
+
This function is used for interruption handling.
|
|
521
|
+
As not all channels support flushing bot audio buffer,
|
|
522
|
+
if a channel does not implement it. It has no effect."""
|
|
523
|
+
pass
|
|
524
|
+
|
|
464
525
|
async def run_audio_streaming(
|
|
465
526
|
self,
|
|
466
527
|
on_new_message: Callable[[UserMessage], Awaitable[Any]],
|
|
@@ -596,6 +657,8 @@ class VoiceInputChannel(InputChannel):
|
|
|
596
657
|
call_state.user_speech_start_time = time.time()
|
|
597
658
|
self._cancel_silence_timeout_watcher()
|
|
598
659
|
call_state.is_user_speaking = True
|
|
660
|
+
if self.should_interrupt(e):
|
|
661
|
+
await self.interrupt_playback(voice_websocket, call_parameters)
|
|
599
662
|
elif isinstance(e, UserSilence):
|
|
600
663
|
output_channel = self.create_output_channel(voice_websocket, tts_engine)
|
|
601
664
|
message = UserMessage(
|
rasa/core/constants.py
CHANGED
|
@@ -116,3 +116,9 @@ ACTIVE_FLOW_METADATA_KEY = "active_flow"
|
|
|
116
116
|
STEP_ID_METADATA_KEY = "step_id"
|
|
117
117
|
KEY_IS_CALM_SYSTEM = "is_calm_system"
|
|
118
118
|
KEY_IS_COEXISTENCE_ASSISTANT = "is_coexistence_assistant"
|
|
119
|
+
|
|
120
|
+
IAM_CLOUD_PROVIDER_ENV_VAR_NAME = "IAM_CLOUD_PROVIDER"
|
|
121
|
+
SQL_TRACKER_STORE_SSL_MODE_ENV_VAR_NAME = "SQL_TRACKER_STORE_SSL_MODE"
|
|
122
|
+
SQL_TRACKER_STORE_SSL_ROOT_CERTIFICATE_ENV_VAR_NAME = (
|
|
123
|
+
"SQL_TRACKER_STORE_SSL_ROOT_CERTIFICATE"
|
|
124
|
+
)
|
|
File without changes
|