rasa-pro 3.13.12__py3-none-any.whl → 3.14.0__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/__main__.py +15 -3
- rasa/agents/__init__.py +0 -0
- rasa/agents/agent_factory.py +122 -0
- rasa/agents/agent_manager.py +213 -0
- rasa/agents/constants.py +43 -0
- rasa/agents/core/__init__.py +0 -0
- rasa/agents/core/agent_protocol.py +107 -0
- rasa/agents/core/types.py +81 -0
- rasa/agents/exceptions.py +38 -0
- rasa/agents/protocol/__init__.py +5 -0
- rasa/agents/protocol/a2a/__init__.py +0 -0
- rasa/agents/protocol/a2a/a2a_agent.py +889 -0
- rasa/agents/protocol/mcp/__init__.py +0 -0
- rasa/agents/protocol/mcp/mcp_base_agent.py +778 -0
- rasa/agents/protocol/mcp/mcp_open_agent.py +327 -0
- rasa/agents/protocol/mcp/mcp_task_agent.py +522 -0
- rasa/agents/schemas/__init__.py +13 -0
- rasa/agents/schemas/agent_input.py +38 -0
- rasa/agents/schemas/agent_output.py +26 -0
- rasa/agents/schemas/agent_tool_result.py +65 -0
- rasa/agents/schemas/agent_tool_schema.py +186 -0
- rasa/agents/templates/__init__.py +0 -0
- rasa/agents/templates/mcp_open_agent_prompt_template.jinja2 +20 -0
- rasa/agents/templates/mcp_task_agent_prompt_template.jinja2 +22 -0
- rasa/agents/utils.py +228 -0
- rasa/agents/validation.py +538 -0
- rasa/api.py +23 -9
- rasa/builder/README.md +120 -0
- rasa/builder/__init__.py +0 -0
- rasa/builder/auth.py +176 -0
- rasa/builder/config.py +96 -0
- rasa/builder/copilot/__init__.py +0 -0
- rasa/builder/copilot/constants.py +38 -0
- rasa/builder/copilot/copilot.py +562 -0
- rasa/builder/copilot/copilot_response_handler.py +522 -0
- rasa/builder/copilot/copilot_templated_message_provider.py +81 -0
- rasa/builder/copilot/exceptions.py +32 -0
- rasa/builder/copilot/models.py +690 -0
- rasa/builder/copilot/prompts/__init__.py +0 -0
- rasa/builder/copilot/prompts/copilot_system_prompt.jinja2 +787 -0
- rasa/builder/copilot/prompts/copilot_training_error_handler_prompt.jinja2 +53 -0
- rasa/builder/copilot/prompts/latest_user_message_context_prompt.jinja2 +91 -0
- rasa/builder/copilot/signing.py +305 -0
- rasa/builder/copilot/telemetry.py +234 -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 +41 -0
- rasa/builder/copilot/templated_messages/copilot_welcome_messages.yml +56 -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/clients.py +256 -0
- rasa/builder/guardrails/constants.py +12 -0
- rasa/builder/guardrails/exceptions.py +4 -0
- rasa/builder/guardrails/models.py +266 -0
- rasa/builder/guardrails/policy_checker.py +324 -0
- rasa/builder/guardrails/store.py +238 -0
- rasa/builder/guardrails/utils.py +94 -0
- rasa/builder/job_manager.py +87 -0
- rasa/builder/jobs.py +609 -0
- rasa/builder/llm_service.py +273 -0
- rasa/builder/logging_utils.py +265 -0
- rasa/builder/main.py +234 -0
- rasa/builder/models.py +229 -0
- rasa/builder/project_generator.py +463 -0
- rasa/builder/project_info.py +72 -0
- rasa/builder/service.py +1367 -0
- rasa/builder/shared/tracker_context.py +212 -0
- rasa/builder/skill_to_bot_prompt.jinja2 +164 -0
- rasa/builder/template_cache.py +69 -0
- rasa/builder/training_service.py +188 -0
- rasa/builder/validation_service.py +101 -0
- rasa/cli/arguments/data.py +9 -0
- rasa/cli/arguments/default_arguments.py +12 -0
- rasa/cli/arguments/run.py +2 -0
- rasa/cli/arguments/train.py +2 -0
- rasa/cli/data.py +78 -10
- rasa/cli/dialogue_understanding_test.py +11 -7
- rasa/cli/e2e_test.py +10 -6
- rasa/cli/evaluate.py +4 -2
- rasa/cli/export.py +5 -2
- rasa/cli/inspect.py +9 -4
- rasa/cli/interactive.py +8 -4
- rasa/cli/llm_fine_tuning.py +12 -6
- 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 +8 -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 +11 -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/basic/tests/e2e_test_cases/without_stub/general/feedback.yml +46 -0
- rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/goodbye.yml +9 -0
- rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/hello.yml +8 -0
- rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/help.yml +8 -0
- rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/human_handoff.yml +41 -0
- rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/patterns.yml +32 -0
- rasa/cli/project_templates/basic/tests/e2e_test_cases/without_stub/general/show_faqs.yml +8 -0
- rasa/cli/project_templates/default/config.yml +4 -0
- rasa/cli/project_templates/default/endpoints.yml +4 -0
- rasa/cli/project_templates/defaults.py +1 -0
- rasa/cli/project_templates/finance/README.md +26 -0
- rasa/cli/project_templates/finance/actions/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/accounts/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/accounts/check_balance.py +18 -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/check_that_card_exists.py +21 -0
- rasa/cli/project_templates/finance/actions/cards/list_cards.py +22 -0
- rasa/cli/project_templates/finance/actions/contacts/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/contacts/add_contact.py +30 -0
- rasa/cli/project_templates/finance/actions/contacts/list_contacts.py +22 -0
- rasa/cli/project_templates/finance/actions/contacts/remove_contact.py +35 -0
- rasa/cli/project_templates/finance/actions/db.py +117 -0
- rasa/cli/project_templates/finance/actions/general/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/general/action_human_handoff.py +49 -0
- rasa/cli/project_templates/finance/actions/transfers/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/transfers/check_transfer_funds.py +27 -0
- rasa/cli/project_templates/finance/actions/transfers/check_transfer_limit.py +36 -0
- rasa/cli/project_templates/finance/actions/transfers/execute_recurrent_payment.py +20 -0
- rasa/cli/project_templates/finance/actions/transfers/execute_transfer.py +45 -0
- rasa/cli/project_templates/finance/actions/transfers/list_transactions.py +32 -0
- rasa/cli/project_templates/finance/config.yml +29 -0
- rasa/cli/project_templates/finance/credentials.yml +33 -0
- rasa/cli/project_templates/finance/data/accounts/check_balance.yml +9 -0
- rasa/cli/project_templates/finance/data/accounts/download_statements.yml +26 -0
- rasa/cli/project_templates/finance/data/bills/bill_pay_reminder.yml +25 -0
- rasa/cli/project_templates/finance/data/cards/activate_card.yml +35 -0
- rasa/cli/project_templates/finance/data/cards/block_card.yml +45 -0
- rasa/cli/project_templates/finance/data/cards/list_cards.yml +14 -0
- rasa/cli/project_templates/finance/data/cards/replace_card.yml +16 -0
- rasa/cli/project_templates/finance/data/cards/replace_eligible_card.yml +29 -0
- rasa/cli/project_templates/finance/data/contacts/add_contact.yml +33 -0
- rasa/cli/project_templates/finance/data/contacts/list_contacts.yml +14 -0
- rasa/cli/project_templates/finance/data/contacts/remove_contact.yml +31 -0
- rasa/cli/project_templates/finance/data/data.md +14 -0
- rasa/cli/project_templates/finance/data/general/bot_challenge.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 +6 -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_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/transfers/check_transfer_limit.yml +18 -0
- rasa/cli/project_templates/finance/data/transfers/list_transactions.yml +46 -0
- rasa/cli/project_templates/finance/data/transfers/move_money_between_accounts.yml +51 -0
- rasa/cli/project_templates/finance/data/transfers/transfer_money.yml +34 -0
- rasa/cli/project_templates/finance/data/transfers/transfer_money_to_a_third_party.yml +175 -0
- rasa/cli/project_templates/finance/db/cards.json +18 -0
- rasa/cli/project_templates/finance/db/contacts.json +10 -0
- rasa/cli/project_templates/finance/db/my_account.json +6 -0
- rasa/cli/project_templates/finance/db/transactions.json +22 -0
- rasa/cli/project_templates/finance/docs/docs.md +8 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/account_features/budgeting_analytics.txt +22 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/account_features/multi_currency_accounts.txt +19 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/account_features/premium_benefits.txt +19 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/card_management/contactless_limits.txt +16 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/card_management/freeze_unfreeze_card.txt +16 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/card_management/lost_stolen_card.txt +19 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/money_transfers/instant_payments.txt +19 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/money_transfers/international_transfers.txt +19 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/security_fraud/fraud_protection.txt +22 -0
- rasa/cli/project_templates/finance/docs/fenlo_banking_faq/security_fraud/secure_payments.txt +22 -0
- rasa/cli/project_templates/finance/domain/accounts/check_balance.yml +15 -0
- rasa/cli/project_templates/finance/domain/accounts/download_statements.yml +40 -0
- rasa/cli/project_templates/finance/domain/bills/bill_pay_reminder.yml +49 -0
- rasa/cli/project_templates/finance/domain/cards/activate_card.yml +24 -0
- rasa/cli/project_templates/finance/domain/cards/block_card.yml +44 -0
- rasa/cli/project_templates/finance/domain/cards/list_cards.yml +16 -0
- rasa/cli/project_templates/finance/domain/cards/replace_card.yml +43 -0
- rasa/cli/project_templates/finance/domain/cards/shared.yml +15 -0
- rasa/cli/project_templates/finance/domain/contacts/add_contact.yml +37 -0
- rasa/cli/project_templates/finance/domain/contacts/list_contacts.yml +16 -0
- rasa/cli/project_templates/finance/domain/contacts/remove_contact.yml +32 -0
- rasa/cli/project_templates/finance/domain/domain.md +18 -0
- rasa/cli/project_templates/finance/domain/general/_shared.yml +39 -0
- rasa/cli/project_templates/finance/domain/general/bot_challenge.yml +4 -0
- rasa/cli/project_templates/finance/domain/general/cannot_handle.yml +8 -0
- rasa/cli/project_templates/finance/domain/general/feedback.yml +25 -0
- rasa/cli/project_templates/finance/domain/general/goodbye.yml +7 -0
- rasa/cli/project_templates/finance/domain/general/help.yml +0 -0
- rasa/cli/project_templates/finance/domain/general/human_handoff.yml +31 -0
- rasa/cli/project_templates/finance/domain/general/welcome.yml +39 -0
- rasa/cli/project_templates/finance/domain/transfers/check_transfer_limit.yml +32 -0
- rasa/cli/project_templates/finance/domain/transfers/list_transactions.yml +44 -0
- rasa/cli/project_templates/finance/domain/transfers/shared.yml +17 -0
- rasa/cli/project_templates/finance/domain/transfers/transfer_money.yml +221 -0
- rasa/cli/project_templates/finance/endpoints.yml +67 -0
- rasa/cli/project_templates/finance/prompts/rephraser_demo_personality_prompt.jinja2 +38 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/accounts/check_balance.yml +9 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/accounts/download_statements.yml +43 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/cards/block_card.yml +55 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/general/bot_challenge.yml +8 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/general/feedback.yml +46 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/general/goodbye.yml +9 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/general/hello.yml +8 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/general/human_handoff.yml +35 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/general/patterns.yml +22 -0
- rasa/cli/project_templates/finance/tests/e2e_test_cases/without_stub/transfers/transfer_money.yml +56 -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 +8 -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 +13 -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 +74 -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/with_stub/network/solve_internet_not_slow.yml +33 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/with_stub/network/solve_internet_slow.yml +47 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/without_stub/billing/understand_bill.yml +67 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/without_stub/general/bot_challenge.yml +8 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/without_stub/general/feedback.yml +46 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/without_stub/general/goodbye.yml +9 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/without_stub/general/hello.yml +8 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/without_stub/general/human_handoff.yml +35 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/without_stub/general/patterns.yml +23 -0
- rasa/cli/project_templates/tutorial/config.yml +2 -1
- rasa/cli/project_templates/tutorial/credentials.yml +10 -0
- rasa/cli/run.py +8 -10
- rasa/cli/scaffold.py +50 -6
- rasa/cli/shell.py +10 -5
- rasa/cli/studio/studio.py +1 -1
- rasa/cli/test.py +34 -14
- rasa/cli/train.py +44 -30
- rasa/cli/utils.py +1 -393
- rasa/cli/validation/__init__.py +0 -0
- rasa/cli/validation/bot_config.py +232 -0
- rasa/cli/validation/config_path_validation.py +257 -0
- rasa/cli/x.py +8 -4
- rasa/constants.py +7 -1
- rasa/core/actions/action.py +53 -13
- rasa/core/actions/action_exceptions.py +1 -1
- rasa/core/actions/action_run_slot_rejections.py +1 -1
- rasa/core/actions/grpc_custom_action_executor.py +1 -1
- rasa/core/agent.py +22 -2
- rasa/core/available_agents.py +239 -0
- rasa/core/brokers/broker.py +1 -1
- rasa/core/brokers/kafka.py +56 -8
- rasa/core/channels/__init__.py +82 -35
- rasa/core/channels/channel.py +4 -3
- rasa/core/channels/constants.py +3 -0
- rasa/core/channels/development_inspector.py +29 -16
- rasa/core/channels/hangouts.py +2 -2
- rasa/core/channels/inspector/README.md +25 -13
- rasa/core/channels/inspector/dist/assets/{arc-0b11fe30.js → arc-6177260a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-9eef30a7.js → blockDiagram-38ab4fdb-b054f038.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-03e94f28.js → c4Diagram-3d4e48cf-f25427d5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/channel-bf9cbb34.js +1 -0
- rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-95c09eba.js → classDiagram-70f12bd4-c7a2af53.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-38e8446c.js → classDiagram-v2-f2320105-58db65c0.js} +1 -1
- rasa/core/channels/inspector/dist/assets/clone-8f9083bb.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-57dc3038.js → createText-2e5e7dd3-088372e2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-4bac0545.js → edges-e0da2a9e-58676240.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-81795c90.js → erDiagram-9861fffd-0c14d7c6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-89489ae6.js → flowDb-956e92f1-ea63f85c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-cd152627.js → flowDiagram-66a62f08-a2af48cd.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-9ecd5b59.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-3da369bc.js → flowchart-elk-definition-4a651766-6937abe7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-85ec16f8.js → ganttDiagram-c361ad54-7473f357.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-495bc140.js → gitGraphDiagram-72cf32ee-d0c9405e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-1ec4d266.js → graph-0a6f8466.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3862675e-0a0e97c9.js → index-3862675e-7610671a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/index-74e01d94.js +1354 -0
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-4d54bcde.js → infoDiagram-f8f76790-be397dc7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-dc097114.js → journeyDiagram-49397b02-4cefbf62.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-1a08981e.js → layout-e7fbc2bf.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-95f7f1d3.js → line-a8aa457c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-97e69543.js → linear-3351e0d2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-8c71ff03.js → mindmap-definition-fc14e90a-b8cbf605.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-f14c71c7.js → pieDiagram-8a3498a8-f327f774.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-f1d3c9ff.js → quadrantDiagram-120e2f19-2854c591.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-bfa2412f.js → requirementDiagram-deff3bca-964985d5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-53f2c97b.js → sankeyDiagram-04a897e0-edeb4f33.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-319d7c0e.js → sequenceDiagram-704730f1-fcf70125.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-76a09418.js → stateDiagram-587899a1-0e770395.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-a67f15d4.js → stateDiagram-v2-d93cdb3a-af8dcd22.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-0654e7c3.js → styles-6aaf32cf-36a9e70d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-1394bb9d.js → styles-9a916d00-884a8b5b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-e4c5bdae.js → styles-c10674c1-dc097813.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-50957104.js → svgDrawCommon-08f97a94-5a2c7eed.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-b0885a6a.js → timeline-definition-85554ec2-e89c4f6e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-79e6541a.js → xychartDiagram-e933f94c-afb6fe56.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +1 -1
- rasa/core/channels/inspector/package.json +18 -18
- rasa/core/channels/inspector/src/App.tsx +56 -12
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +1 -1
- rasa/core/channels/inspector/src/components/DialogueAgentStack.tsx +108 -0
- rasa/core/channels/inspector/src/components/{DialogueStack.tsx → DialogueHistoryStack.tsx} +4 -2
- rasa/core/channels/inspector/src/components/DialogueInformation.tsx +20 -3
- rasa/core/channels/inspector/src/components/LatencyDisplay.tsx +296 -0
- rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +6 -2
- rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +26 -4
- rasa/core/channels/inspector/src/helpers/formatters.test.ts +4 -0
- rasa/core/channels/inspector/src/helpers/formatters.ts +24 -3
- rasa/core/channels/inspector/src/helpers/utils.test.ts +127 -0
- rasa/core/channels/inspector/src/helpers/utils.ts +66 -1
- rasa/core/channels/inspector/src/theme/base/styles.ts +19 -1
- rasa/core/channels/inspector/src/types.ts +55 -1
- rasa/core/channels/inspector/yarn.lock +336 -189
- rasa/core/channels/socketio.py +212 -51
- rasa/core/channels/studio_chat.py +82 -32
- rasa/core/channels/telegram.py +4 -9
- rasa/core/channels/voice_ready/twilio_voice.py +1 -1
- 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 +11 -6
- rasa/core/channels/voice_stream/browser_audio.py +91 -4
- rasa/core/channels/voice_stream/call_state.py +13 -2
- rasa/core/channels/voice_stream/genesys.py +19 -15
- rasa/core/channels/voice_stream/jambonz.py +22 -12
- rasa/core/channels/voice_stream/tts/deepgram.py +140 -0
- rasa/core/channels/voice_stream/twilio_media_streams.py +35 -14
- rasa/core/channels/voice_stream/util.py +11 -1
- rasa/core/channels/voice_stream/voice_channel.py +170 -32
- rasa/core/concurrent_lock_store.py +83 -16
- rasa/core/config/__init__.py +0 -0
- rasa/core/{available_endpoints.py → config/available_endpoints.py} +56 -18
- rasa/core/config/configuration.py +295 -0
- rasa/core/config/credentials.py +19 -0
- rasa/core/config/message_procesing_config.py +34 -0
- rasa/core/constants.py +17 -0
- rasa/core/exceptions.py +1 -1
- rasa/core/featurizers/tracker_featurizers.py +3 -2
- rasa/core/iam_credentials_providers/__init__.py +0 -0
- rasa/core/iam_credentials_providers/aws_iam_credentials_providers.py +291 -0
- rasa/core/iam_credentials_providers/credentials_provider_protocol.py +91 -0
- rasa/core/lock_store.py +50 -10
- rasa/core/nlg/contextual_response_rephraser.py +5 -0
- rasa/core/nlg/generator.py +1 -1
- rasa/core/persistor.py +7 -7
- rasa/core/policies/enterprise_search_policy.py +9 -10
- rasa/core/policies/flow_policy.py +4 -4
- rasa/core/policies/flows/agent_executor.py +720 -0
- rasa/core/policies/flows/flow_exceptions.py +5 -2
- rasa/core/policies/flows/flow_executor.py +146 -77
- rasa/core/policies/flows/mcp_tool_executor.py +304 -0
- rasa/core/policies/intentless_policy.py +1 -1
- rasa/core/policies/rule_policy.py +1 -1
- rasa/core/policies/ted_policy.py +20 -12
- rasa/core/policies/unexpected_intent_policy.py +6 -0
- rasa/core/processor.py +100 -44
- rasa/core/redis_connection_factory.py +474 -0
- rasa/core/run.py +49 -10
- rasa/core/test.py +4 -0
- rasa/core/tracker_stores/redis_tracker_store.py +36 -14
- rasa/core/tracker_stores/sql_tracker_store.py +59 -1
- rasa/core/tracker_stores/tracker_store.py +3 -7
- rasa/core/train.py +1 -1
- rasa/core/training/interactive.py +20 -18
- rasa/core/training/story_conflict.py +5 -5
- rasa/core/utils.py +22 -23
- rasa/dialogue_understanding/commands/__init__.py +8 -0
- rasa/dialogue_understanding/commands/cancel_flow_command.py +20 -6
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +21 -2
- rasa/dialogue_understanding/commands/clarify_command.py +20 -2
- rasa/dialogue_understanding/commands/continue_agent_command.py +91 -0
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +21 -2
- rasa/dialogue_understanding/commands/restart_agent_command.py +162 -0
- rasa/dialogue_understanding/commands/start_flow_command.py +75 -7
- rasa/dialogue_understanding/commands/utils.py +135 -2
- rasa/dialogue_understanding/generator/command_parser.py +4 -0
- rasa/dialogue_understanding/generator/flow_retrieval.py +0 -9
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +52 -12
- rasa/dialogue_understanding/generator/llm_command_generator.py +1 -1
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +1 -1
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_claude_3_5_sonnet_20240620_template.jinja2 +66 -0
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v2_gpt_4o_2024_11_20_template.jinja2 +66 -0
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_claude_3_5_sonnet_20240620_template.jinja2 +89 -0
- rasa/dialogue_understanding/generator/prompt_templates/agent_command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +88 -0
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +42 -7
- rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +40 -3
- rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +20 -3
- rasa/dialogue_understanding/patterns/cancel.py +27 -6
- rasa/dialogue_understanding/patterns/clarify.py +3 -14
- rasa/dialogue_understanding/patterns/continue_interrupted.py +239 -6
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +49 -9
- rasa/dialogue_understanding/processor/command_processor.py +136 -15
- rasa/dialogue_understanding/stack/dialogue_stack.py +98 -2
- rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +57 -0
- rasa/dialogue_understanding/stack/utils.py +57 -3
- rasa/dialogue_understanding/utils.py +24 -4
- rasa/dialogue_understanding_test/du_test_runner.py +8 -3
- rasa/e2e_test/e2e_test_runner.py +13 -3
- rasa/engine/caching.py +2 -2
- rasa/engine/constants.py +1 -1
- rasa/engine/graph.py +5 -1
- rasa/engine/loader.py +12 -0
- rasa/engine/recipes/default_components.py +138 -49
- rasa/engine/recipes/default_recipe.py +108 -11
- rasa/engine/runner/dask.py +8 -5
- rasa/engine/validation.py +25 -8
- rasa/graph_components/validators/default_recipe_validator.py +86 -28
- rasa/hooks.py +5 -5
- rasa/llm_fine_tuning/utils.py +2 -2
- rasa/model_manager/model_api.py +4 -5
- rasa/model_manager/runner_service.py +2 -2
- rasa/model_manager/socket_bridge.py +21 -17
- rasa/model_manager/trainer_service.py +12 -9
- rasa/model_manager/utils.py +1 -29
- rasa/model_manager/warm_rasa_process.py +13 -3
- rasa/model_training.py +60 -47
- rasa/nlu/classifiers/diet_classifier.py +198 -98
- rasa/nlu/classifiers/logistic_regression_classifier.py +1 -4
- rasa/nlu/classifiers/mitie_intent_classifier.py +3 -0
- rasa/nlu/classifiers/sklearn_intent_classifier.py +1 -3
- rasa/nlu/extractors/crf_entity_extractor.py +9 -10
- rasa/nlu/extractors/mitie_entity_extractor.py +3 -0
- rasa/nlu/extractors/spacy_entity_extractor.py +3 -0
- rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +4 -0
- rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +5 -0
- rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +2 -0
- rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +3 -0
- rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +4 -2
- rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +4 -0
- rasa/nlu/selectors/response_selector.py +10 -2
- rasa/nlu/tokenizers/jieba_tokenizer.py +3 -4
- rasa/nlu/tokenizers/mitie_tokenizer.py +3 -2
- rasa/nlu/tokenizers/spacy_tokenizer.py +3 -2
- rasa/nlu/utils/mitie_utils.py +3 -0
- rasa/nlu/utils/spacy_utils.py +3 -2
- rasa/plugin.py +8 -8
- rasa/privacy/privacy_config.py +1 -1
- rasa/privacy/privacy_manager.py +12 -3
- rasa/server.py +15 -3
- rasa/shared/agents/__init__.py +0 -0
- rasa/shared/agents/auth/__init__.py +0 -0
- rasa/shared/agents/auth/agent_auth_factory.py +105 -0
- rasa/shared/agents/auth/agent_auth_manager.py +92 -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 +170 -0
- rasa/shared/agents/auth/constants.py +13 -0
- rasa/shared/agents/auth/types.py +12 -0
- rasa/shared/agents/auth/utils.py +85 -0
- rasa/shared/agents/utils.py +35 -0
- rasa/shared/constants.py +11 -0
- rasa/shared/core/constants.py +17 -1
- rasa/shared/core/domain.py +62 -22
- rasa/shared/core/events.py +329 -0
- rasa/shared/core/flows/constants.py +5 -0
- rasa/shared/core/flows/flow.py +1 -1
- rasa/shared/core/flows/flow_step.py +7 -1
- rasa/shared/core/flows/flows_list.py +21 -5
- rasa/shared/core/flows/flows_yaml_schema.json +119 -184
- rasa/shared/core/flows/steps/call.py +57 -6
- rasa/shared/core/flows/steps/collect.py +98 -13
- rasa/shared/core/flows/validation.py +372 -8
- rasa/shared/core/flows/yaml_flows_io.py +19 -10
- rasa/shared/core/slots.py +6 -2
- rasa/shared/core/trackers.py +5 -2
- rasa/shared/core/training_data/story_reader/story_reader.py +1 -1
- rasa/shared/exceptions.py +39 -2
- rasa/shared/importers/importer.py +6 -0
- rasa/shared/importers/rasa.py +1 -1
- rasa/shared/importers/utils.py +86 -4
- rasa/shared/nlu/training_data/schemas/responses.yml +3 -0
- rasa/shared/providers/llm/_base_litellm_client.py +41 -9
- rasa/shared/providers/llm/litellm_router_llm_client.py +10 -6
- rasa/shared/providers/llm/llm_client.py +7 -3
- rasa/shared/providers/llm/llm_response.py +66 -0
- rasa/shared/providers/llm/self_hosted_llm_client.py +8 -4
- rasa/shared/utils/common.py +26 -1
- rasa/shared/utils/health_check/health_check.py +7 -3
- rasa/shared/utils/llm.py +92 -19
- rasa/shared/utils/mcp/__init__.py +0 -0
- rasa/shared/utils/mcp/server_connection.py +250 -0
- rasa/shared/utils/mcp/utils.py +20 -0
- rasa/shared/utils/schemas/events.py +42 -0
- rasa/shared/utils/yaml.py +3 -1
- rasa/studio/download.py +3 -0
- rasa/studio/prompts.py +1 -0
- rasa/studio/pull/pull.py +3 -2
- rasa/studio/train.py +8 -7
- rasa/studio/upload.py +19 -52
- rasa/telemetry.py +166 -28
- rasa/tracing/config.py +45 -12
- rasa/tracing/constants.py +14 -0
- rasa/tracing/instrumentation/attribute_extractors.py +142 -9
- rasa/tracing/instrumentation/instrumentation.py +626 -21
- rasa/tracing/instrumentation/intentless_policy_instrumentation.py +4 -4
- rasa/tracing/instrumentation/metrics.py +32 -0
- rasa/tracing/metric_instrument_provider.py +68 -0
- rasa/utils/common.py +92 -1
- rasa/utils/endpoints.py +11 -2
- rasa/utils/io.py +27 -9
- rasa/utils/json_utils.py +6 -1
- rasa/utils/log_utils.py +121 -7
- rasa/utils/ml_utils.py +1 -1
- rasa/utils/openapi.py +144 -0
- rasa/utils/plotting.py +1 -1
- rasa/utils/pypred.py +45 -0
- rasa/utils/tensorflow/__init__.py +7 -0
- rasa/utils/tensorflow/callback.py +136 -101
- rasa/utils/tensorflow/crf.py +1 -1
- rasa/utils/tensorflow/data_generator.py +21 -8
- rasa/utils/tensorflow/layers.py +21 -11
- rasa/utils/tensorflow/metrics.py +7 -3
- rasa/utils/tensorflow/models.py +56 -8
- rasa/utils/tensorflow/rasa_layers.py +8 -6
- rasa/utils/tensorflow/transformer.py +2 -3
- rasa/utils/train_utils.py +54 -24
- rasa/validator.py +149 -16
- rasa/version.py +1 -1
- rasa_pro-3.14.0.dist-info/METADATA +212 -0
- {rasa_pro-3.13.12.dist-info → rasa_pro-3.14.0.dist-info}/RECORD +581 -269
- rasa/core/channels/inspector/dist/assets/channel-51d02e9e.js +0 -1
- rasa/core/channels/inspector/dist/assets/clone-cc738fa6.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-0c716443.js +0 -1
- rasa/core/channels/inspector/dist/assets/index-c804b295.js +0 -1335
- rasa_pro-3.13.12.dist-info/METADATA +0 -192
- {rasa_pro-3.13.12.dist-info → rasa_pro-3.14.0.dist-info}/NOTICE +0 -0
- {rasa_pro-3.13.12.dist-info → rasa_pro-3.14.0.dist-info}/WHEEL +0 -0
- {rasa_pro-3.13.12.dist-info → rasa_pro-3.14.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import asyncio
|
|
2
4
|
import copy
|
|
5
|
+
import string
|
|
6
|
+
import time
|
|
3
7
|
from dataclasses import asdict, dataclass
|
|
4
8
|
from typing import Any, AsyncIterator, Awaitable, Callable, Dict, List, Optional, Tuple
|
|
5
9
|
|
|
@@ -8,6 +12,11 @@ from sanic import Websocket # type: ignore
|
|
|
8
12
|
from sanic.exceptions import ServerError, WebsocketClosed
|
|
9
13
|
|
|
10
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
|
+
)
|
|
11
20
|
from rasa.core.channels.voice_ready.utils import (
|
|
12
21
|
CallParameters,
|
|
13
22
|
validate_voice_license_scope,
|
|
@@ -29,6 +38,7 @@ from rasa.core.channels.voice_stream.call_state import (
|
|
|
29
38
|
)
|
|
30
39
|
from rasa.core.channels.voice_stream.tts.azure import AzureTTS
|
|
31
40
|
from rasa.core.channels.voice_stream.tts.cartesia import CartesiaTTS
|
|
41
|
+
from rasa.core.channels.voice_stream.tts.deepgram import DeepgramTTS
|
|
32
42
|
from rasa.core.channels.voice_stream.tts.tts_cache import TTSCache
|
|
33
43
|
from rasa.core.channels.voice_stream.tts.tts_engine import TTSEngine, TTSError
|
|
34
44
|
from rasa.core.channels.voice_stream.util import (
|
|
@@ -45,9 +55,13 @@ from rasa.utils.io import remove_emojis
|
|
|
45
55
|
logger = structlog.get_logger(__name__)
|
|
46
56
|
|
|
47
57
|
# define constants for the voice channel
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
58
|
+
DEFAULT_INTERRUPTION_MIN_WORDS = 3
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass
|
|
62
|
+
class InterruptionConfig:
|
|
63
|
+
enabled: bool = False
|
|
64
|
+
min_words: int = DEFAULT_INTERRUPTION_MIN_WORDS
|
|
51
65
|
|
|
52
66
|
|
|
53
67
|
@dataclass
|
|
@@ -120,6 +134,8 @@ def tts_engine_from_config(tts_config: Dict) -> TTSEngine:
|
|
|
120
134
|
return AzureTTS.from_config_dict(tts_config)
|
|
121
135
|
elif name.lower() == "cartesia":
|
|
122
136
|
return CartesiaTTS.from_config_dict(tts_config)
|
|
137
|
+
elif name.lower() == "deepgram":
|
|
138
|
+
return DeepgramTTS.from_config_dict(tts_config)
|
|
123
139
|
else:
|
|
124
140
|
mark_as_beta_feature("Custom TTS Engine")
|
|
125
141
|
try:
|
|
@@ -189,7 +205,7 @@ class VoiceOutputChannel(OutputChannel):
|
|
|
189
205
|
def update_silence_timeout(self) -> None:
|
|
190
206
|
"""Updates the silence timeout for the session."""
|
|
191
207
|
if self.tracker_state:
|
|
192
|
-
call_state.silence_timeout = self.tracker_state["slots"][
|
|
208
|
+
call_state.silence_timeout = self.tracker_state["slots"][
|
|
193
209
|
SILENCE_TIMEOUT_SLOT
|
|
194
210
|
]
|
|
195
211
|
logger.debug(
|
|
@@ -207,22 +223,67 @@ class VoiceOutputChannel(OutputChannel):
|
|
|
207
223
|
"""Uses the concise button output format for voice channels."""
|
|
208
224
|
await self.send_text_with_buttons_concise(recipient_id, text, buttons, **kwargs)
|
|
209
225
|
|
|
226
|
+
def _track_rasa_processing_latency(self) -> None:
|
|
227
|
+
"""Track and log Rasa processing completion latency."""
|
|
228
|
+
if call_state.rasa_processing_start_time:
|
|
229
|
+
call_state.rasa_processing_latency_ms = (
|
|
230
|
+
time.time() - call_state.rasa_processing_start_time
|
|
231
|
+
) * 1000
|
|
232
|
+
logger.debug(
|
|
233
|
+
"voice_channel.rasa_processing_latency",
|
|
234
|
+
latency_ms=call_state.rasa_processing_latency_ms,
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
def _track_tts_first_byte_latency(self) -> None:
|
|
238
|
+
"""Track and log TTS first byte latency."""
|
|
239
|
+
if call_state.tts_start_time:
|
|
240
|
+
call_state.tts_first_byte_latency_ms = (
|
|
241
|
+
time.time() - call_state.tts_start_time
|
|
242
|
+
) * 1000
|
|
243
|
+
logger.debug(
|
|
244
|
+
"voice_channel.tts_first_byte_latency",
|
|
245
|
+
latency_ms=call_state.tts_first_byte_latency_ms,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
def _track_tts_complete_latency(self) -> None:
|
|
249
|
+
"""Track and log TTS completion latency."""
|
|
250
|
+
if call_state.tts_start_time:
|
|
251
|
+
call_state.tts_complete_latency_ms = (
|
|
252
|
+
time.time() - call_state.tts_start_time
|
|
253
|
+
) * 1000
|
|
254
|
+
logger.debug(
|
|
255
|
+
"voice_channel.tts_complete_latency",
|
|
256
|
+
latency_ms=call_state.tts_complete_latency_ms,
|
|
257
|
+
)
|
|
258
|
+
|
|
210
259
|
async def send_text_message(
|
|
211
260
|
self, recipient_id: str, text: str, **kwargs: Any
|
|
212
261
|
) -> None:
|
|
213
262
|
text = remove_emojis(text)
|
|
214
263
|
self.update_silence_timeout()
|
|
264
|
+
|
|
265
|
+
# Track Rasa processing completion
|
|
266
|
+
self._track_rasa_processing_latency()
|
|
267
|
+
|
|
268
|
+
# Track TTS start time
|
|
269
|
+
call_state.tts_start_time = time.time()
|
|
270
|
+
|
|
215
271
|
cached_audio_bytes = self.tts_cache.get(text)
|
|
216
272
|
collected_audio_bytes = RasaAudioBytes(b"")
|
|
217
273
|
seconds_marker = -1
|
|
218
274
|
last_sent_offset = 0
|
|
275
|
+
first_audio_sent = False
|
|
219
276
|
logger.debug("voice_channel.sending_audio", text=text)
|
|
220
277
|
|
|
221
278
|
# Send start marker before first chunk
|
|
222
279
|
try:
|
|
223
280
|
await self.send_start_marker(recipient_id)
|
|
224
281
|
except (WebsocketClosed, ServerError):
|
|
225
|
-
call_state.connection_failed = True
|
|
282
|
+
call_state.connection_failed = True
|
|
283
|
+
|
|
284
|
+
# Is the response interruptible?
|
|
285
|
+
allow_interruptions = kwargs.get("allow_interruptions", True)
|
|
286
|
+
call_state.channel_data["allow_interruptions"] = allow_interruptions
|
|
226
287
|
|
|
227
288
|
if cached_audio_bytes:
|
|
228
289
|
audio_stream = self.chunk_audio(cached_audio_bytes)
|
|
@@ -244,6 +305,11 @@ class VoiceOutputChannel(OutputChannel):
|
|
|
244
305
|
|
|
245
306
|
if should_send:
|
|
246
307
|
try:
|
|
308
|
+
# Track TTS first byte time
|
|
309
|
+
if not first_audio_sent:
|
|
310
|
+
self._track_tts_first_byte_latency()
|
|
311
|
+
first_audio_sent = True
|
|
312
|
+
|
|
247
313
|
# Send only the new bytes since last send
|
|
248
314
|
new_bytes = RasaAudioBytes(collected_audio_bytes[last_sent_offset:])
|
|
249
315
|
await self.send_audio_bytes(recipient_id, new_bytes)
|
|
@@ -256,24 +322,31 @@ class VoiceOutputChannel(OutputChannel):
|
|
|
256
322
|
|
|
257
323
|
except (WebsocketClosed, ServerError):
|
|
258
324
|
# ignore sending error, and keep collecting and caching audio bytes
|
|
259
|
-
call_state.connection_failed = True
|
|
325
|
+
call_state.connection_failed = True
|
|
260
326
|
|
|
261
327
|
# Send any remaining audio not yet sent
|
|
262
328
|
remaining_bytes = len(collected_audio_bytes) - last_sent_offset
|
|
263
329
|
if remaining_bytes > 0:
|
|
264
330
|
try:
|
|
331
|
+
# Track TTS first byte time if not already tracked
|
|
332
|
+
if not first_audio_sent:
|
|
333
|
+
self._track_tts_first_byte_latency()
|
|
334
|
+
|
|
265
335
|
new_bytes = RasaAudioBytes(collected_audio_bytes[last_sent_offset:])
|
|
266
336
|
await self.send_audio_bytes(recipient_id, new_bytes)
|
|
267
337
|
except (WebsocketClosed, ServerError):
|
|
268
338
|
# ignore sending error
|
|
269
|
-
call_state.connection_failed = True
|
|
339
|
+
call_state.connection_failed = True
|
|
340
|
+
|
|
341
|
+
# Track TTS completion time
|
|
342
|
+
self._track_tts_complete_latency()
|
|
270
343
|
|
|
271
344
|
try:
|
|
272
345
|
await self.send_end_marker(recipient_id)
|
|
273
346
|
except (WebsocketClosed, ServerError):
|
|
274
347
|
# ignore sending error
|
|
275
348
|
pass
|
|
276
|
-
call_state.latest_bot_audio_id = self.latest_message_id
|
|
349
|
+
call_state.latest_bot_audio_id = self.latest_message_id
|
|
277
350
|
|
|
278
351
|
if not cached_audio_bytes:
|
|
279
352
|
self.tts_cache.put(text, collected_audio_bytes)
|
|
@@ -298,7 +371,7 @@ class VoiceOutputChannel(OutputChannel):
|
|
|
298
371
|
return
|
|
299
372
|
|
|
300
373
|
async def hangup(self, recipient_id: str, **kwargs: Any) -> None:
|
|
301
|
-
call_state.should_hangup = True
|
|
374
|
+
call_state.should_hangup = True
|
|
302
375
|
|
|
303
376
|
|
|
304
377
|
class VoiceInputChannel(InputChannel):
|
|
@@ -310,6 +383,7 @@ class VoiceInputChannel(InputChannel):
|
|
|
310
383
|
server_url: str,
|
|
311
384
|
asr_config: Dict,
|
|
312
385
|
tts_config: Dict,
|
|
386
|
+
interruptions: Optional[Dict[str, Any]] = None,
|
|
313
387
|
):
|
|
314
388
|
if self.requires_voice_license:
|
|
315
389
|
validate_voice_license_scope()
|
|
@@ -318,12 +392,21 @@ class VoiceInputChannel(InputChannel):
|
|
|
318
392
|
self.asr_config = asr_config
|
|
319
393
|
self.tts_config = tts_config
|
|
320
394
|
self.tts_cache = TTSCache(tts_config.get("cache_size", 1000))
|
|
395
|
+
if interruptions:
|
|
396
|
+
self.interruption_config = InterruptionConfig(**interruptions)
|
|
397
|
+
else:
|
|
398
|
+
self.interruption_config = InterruptionConfig()
|
|
399
|
+
|
|
400
|
+
if self.interruption_config.enabled:
|
|
401
|
+
mark_as_beta_feature(f"Interruption Handling in {self.name()}")
|
|
321
402
|
|
|
322
403
|
logger.info(
|
|
323
404
|
"voice_channel.initialized",
|
|
405
|
+
name=self.name(),
|
|
324
406
|
server_url=self.server_url,
|
|
325
407
|
asr_config=self.asr_config,
|
|
326
408
|
tts_config=self.tts_config,
|
|
409
|
+
interruption_config=self.interruption_config,
|
|
327
410
|
)
|
|
328
411
|
|
|
329
412
|
def get_sender_id(self, call_parameters: CallParameters) -> str:
|
|
@@ -345,32 +428,32 @@ class VoiceInputChannel(InputChannel):
|
|
|
345
428
|
if call_state.silence_timeout_watcher:
|
|
346
429
|
logger.debug("voice_channel.cancelling_current_timeout_watcher_task")
|
|
347
430
|
call_state.silence_timeout_watcher.cancel()
|
|
348
|
-
call_state.silence_timeout_watcher = None
|
|
431
|
+
call_state.silence_timeout_watcher = None
|
|
349
432
|
|
|
350
433
|
@classmethod
|
|
351
|
-
def
|
|
352
|
-
|
|
353
|
-
credentials: Optional[Dict[str, Any]],
|
|
354
|
-
) -> InputChannel:
|
|
434
|
+
def validate_basic_credentials(cls, credentials: Optional[Dict[str, Any]]) -> None:
|
|
435
|
+
"""Validate the basic credentials for the voice channel."""
|
|
355
436
|
if not credentials:
|
|
356
437
|
cls.raise_missing_credentials_exception()
|
|
357
|
-
|
|
358
|
-
if not credentials.get("server_url"):
|
|
359
|
-
raise InvalidConfigException("No server_url provided in credentials.")
|
|
360
|
-
if not credentials.get("asr"):
|
|
438
|
+
if not isinstance(credentials, dict):
|
|
361
439
|
raise InvalidConfigException(
|
|
362
|
-
"
|
|
440
|
+
"Credentials must be a dictionary for voice channel."
|
|
363
441
|
)
|
|
364
|
-
|
|
442
|
+
|
|
443
|
+
required_keys = {"server_url", "asr", "tts"}
|
|
444
|
+
credentials_keys = set(credentials.keys())
|
|
445
|
+
if not required_keys.issubset(credentials_keys):
|
|
446
|
+
missing_fields = required_keys - credentials_keys
|
|
365
447
|
raise InvalidConfigException(
|
|
366
|
-
"
|
|
448
|
+
f"Missing required fields in credentials: {', '.join(missing_fields)} "
|
|
449
|
+
f"for channel {cls.name()}"
|
|
367
450
|
)
|
|
368
451
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
452
|
+
@classmethod
|
|
453
|
+
def from_credentials(
|
|
454
|
+
cls, credentials: Optional[Dict[str, Any]]
|
|
455
|
+
) -> VoiceInputChannel:
|
|
456
|
+
raise NotImplementedError
|
|
374
457
|
|
|
375
458
|
def channel_bytes_to_rasa_audio_bytes(self, input_bytes: bytes) -> RasaAudioBytes:
|
|
376
459
|
raise NotImplementedError
|
|
@@ -405,6 +488,43 @@ class VoiceInputChannel(InputChannel):
|
|
|
405
488
|
"""Map a channel input message to a voice channel action."""
|
|
406
489
|
raise NotImplementedError
|
|
407
490
|
|
|
491
|
+
def should_interrupt(self, e: ASREvent) -> bool:
|
|
492
|
+
"""Determine if the current ASR event should interrupt playback.
|
|
493
|
+
Returns True if the bot response is interruptible
|
|
494
|
+
And if the user spoke more than 3 words.
|
|
495
|
+
|
|
496
|
+
Arguments:
|
|
497
|
+
e: The ASR event to evaluate.
|
|
498
|
+
|
|
499
|
+
Returns:
|
|
500
|
+
True if the event should interrupt playback, False otherwise.
|
|
501
|
+
"""
|
|
502
|
+
# Are interruptions are enabled for the channel?
|
|
503
|
+
if not self.interruption_config.enabled:
|
|
504
|
+
return False
|
|
505
|
+
|
|
506
|
+
# Is the bot response interruptible?
|
|
507
|
+
if not call_state.channel_data.get("allow_interruptions", True):
|
|
508
|
+
return False
|
|
509
|
+
|
|
510
|
+
# Did the user speak more than 3 words?
|
|
511
|
+
min_words = self.interruption_config.min_words
|
|
512
|
+
if isinstance(e, UserIsSpeaking):
|
|
513
|
+
translator = str.maketrans("", "", string.punctuation)
|
|
514
|
+
words = e.text.translate(translator).split()
|
|
515
|
+
return len(words) >= min_words
|
|
516
|
+
return False
|
|
517
|
+
|
|
518
|
+
async def interrupt_playback(
|
|
519
|
+
self, ws: Websocket, call_parameters: CallParameters
|
|
520
|
+
) -> None:
|
|
521
|
+
"""Interrupt the current playback of audio.
|
|
522
|
+
|
|
523
|
+
This function is used for interruption handling.
|
|
524
|
+
As not all channels support flushing bot audio buffer,
|
|
525
|
+
if a channel does not implement it. It has no effect."""
|
|
526
|
+
pass
|
|
527
|
+
|
|
408
528
|
async def run_audio_streaming(
|
|
409
529
|
self,
|
|
410
530
|
on_new_message: Callable[[UserMessage], Awaitable[Any]],
|
|
@@ -439,10 +559,8 @@ class VoiceInputChannel(InputChannel):
|
|
|
439
559
|
if was_bot_speaking_before and not is_bot_speaking_after:
|
|
440
560
|
logger.debug("voice_channel.bot_stopped_speaking")
|
|
441
561
|
self._cancel_silence_timeout_watcher()
|
|
442
|
-
call_state.silence_timeout_watcher = (
|
|
443
|
-
|
|
444
|
-
self.monitor_silence_timeout(asr_event_queue)
|
|
445
|
-
)
|
|
562
|
+
call_state.silence_timeout_watcher = asyncio.create_task(
|
|
563
|
+
self.monitor_silence_timeout(asr_event_queue)
|
|
446
564
|
)
|
|
447
565
|
if isinstance(channel_action, NewAudioAction):
|
|
448
566
|
await asr_engine.send_audio_chunks(channel_action.audio_bytes)
|
|
@@ -498,6 +616,16 @@ class VoiceInputChannel(InputChannel):
|
|
|
498
616
|
"""Create a matching voice output channel for this voice input channel."""
|
|
499
617
|
raise NotImplementedError
|
|
500
618
|
|
|
619
|
+
def _track_asr_latency(self) -> None:
|
|
620
|
+
"""Track and log ASR processing latency."""
|
|
621
|
+
if call_state.user_speech_start_time:
|
|
622
|
+
call_state.asr_latency_ms = (
|
|
623
|
+
time.time() - call_state.user_speech_start_time
|
|
624
|
+
) * 1000
|
|
625
|
+
logger.debug(
|
|
626
|
+
"voice_channel.asr_latency", latency_ms=call_state.asr_latency_ms
|
|
627
|
+
)
|
|
628
|
+
|
|
501
629
|
async def handle_asr_event(
|
|
502
630
|
self,
|
|
503
631
|
e: ASREvent,
|
|
@@ -511,7 +639,12 @@ class VoiceInputChannel(InputChannel):
|
|
|
511
639
|
logger.debug(
|
|
512
640
|
"VoiceInputChannel.handle_asr_event.new_transcript", transcript=e.text
|
|
513
641
|
)
|
|
514
|
-
call_state.is_user_speaking = False
|
|
642
|
+
call_state.is_user_speaking = False
|
|
643
|
+
|
|
644
|
+
# Track ASR and Rasa latencies
|
|
645
|
+
self._track_asr_latency()
|
|
646
|
+
call_state.rasa_processing_start_time = time.time()
|
|
647
|
+
|
|
515
648
|
output_channel = self.create_output_channel(voice_websocket, tts_engine)
|
|
516
649
|
message = UserMessage(
|
|
517
650
|
text=e.text,
|
|
@@ -522,8 +655,13 @@ class VoiceInputChannel(InputChannel):
|
|
|
522
655
|
)
|
|
523
656
|
await on_new_message(message)
|
|
524
657
|
elif isinstance(e, UserIsSpeaking):
|
|
658
|
+
# Track when user starts speaking for ASR latency calculation
|
|
659
|
+
if not call_state.is_user_speaking:
|
|
660
|
+
call_state.user_speech_start_time = time.time()
|
|
525
661
|
self._cancel_silence_timeout_watcher()
|
|
526
|
-
call_state.is_user_speaking = True
|
|
662
|
+
call_state.is_user_speaking = True
|
|
663
|
+
if self.should_interrupt(e):
|
|
664
|
+
await self.interrupt_playback(voice_websocket, call_parameters)
|
|
527
665
|
elif isinstance(e, UserSilence):
|
|
528
666
|
output_channel = self.create_output_channel(voice_websocket, tts_engine)
|
|
529
667
|
message = UserMessage(
|
|
@@ -4,7 +4,11 @@ from collections import deque
|
|
|
4
4
|
from typing import Deque, Optional, Text
|
|
5
5
|
|
|
6
6
|
import structlog
|
|
7
|
+
from pydantic import ValidationError
|
|
7
8
|
|
|
9
|
+
from rasa.core.iam_credentials_providers.credentials_provider_protocol import (
|
|
10
|
+
SupportedServiceType,
|
|
11
|
+
)
|
|
8
12
|
from rasa.core.lock import Ticket, TicketLock
|
|
9
13
|
from rasa.core.lock_store import (
|
|
10
14
|
DEFAULT_SOCKET_TIMEOUT_IN_SECONDS,
|
|
@@ -12,6 +16,12 @@ from rasa.core.lock_store import (
|
|
|
12
16
|
LockError,
|
|
13
17
|
LockStore,
|
|
14
18
|
)
|
|
19
|
+
from rasa.core.redis_connection_factory import (
|
|
20
|
+
DeploymentMode,
|
|
21
|
+
RedisConfig,
|
|
22
|
+
RedisConnectionFactory,
|
|
23
|
+
)
|
|
24
|
+
from rasa.shared.exceptions import RasaException
|
|
15
25
|
from rasa.utils.endpoints import EndpointConfig
|
|
16
26
|
|
|
17
27
|
DEFAULT_REDIS_DB = 1
|
|
@@ -74,9 +84,10 @@ class ConcurrentRedisLockStore(LockStore):
|
|
|
74
84
|
alphanumeric.
|
|
75
85
|
socket_timeout - Timeout in seconds after which an exception will be raised
|
|
76
86
|
in case Redis doesn't respond within `socket_timeout` seconds.
|
|
87
|
+
deployment_mode - Redis deployment mode: standard, cluster, or sentinel.
|
|
88
|
+
endpoints - List of endpoints for cluster/sentinel mode in host:port format.
|
|
89
|
+
sentinel_service - Sentinel service name.
|
|
77
90
|
"""
|
|
78
|
-
import redis
|
|
79
|
-
|
|
80
91
|
host = endpoint_config.kwargs.get("host", DEFAULT_HOSTNAME)
|
|
81
92
|
port = endpoint_config.kwargs.get("port", DEFAULT_PORT)
|
|
82
93
|
db = endpoint_config.kwargs.get("db", DEFAULT_REDIS_DB)
|
|
@@ -90,20 +101,34 @@ class ConcurrentRedisLockStore(LockStore):
|
|
|
90
101
|
socket_timeout = endpoint_config.kwargs.get(
|
|
91
102
|
"socket_timeout", DEFAULT_SOCKET_TIMEOUT_IN_SECONDS
|
|
92
103
|
)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
host=host,
|
|
96
|
-
port=int(port),
|
|
97
|
-
db=int(db),
|
|
98
|
-
username=username,
|
|
99
|
-
password=password,
|
|
100
|
-
ssl=use_ssl,
|
|
101
|
-
ssl_certfile=ssl_certfile,
|
|
102
|
-
ssl_keyfile=ssl_keyfile,
|
|
103
|
-
ssl_ca_certs=ssl_ca_certs,
|
|
104
|
-
socket_timeout=socket_timeout,
|
|
104
|
+
deployment_mode = endpoint_config.kwargs.get(
|
|
105
|
+
"deployment_mode", DeploymentMode.STANDARD.value
|
|
105
106
|
)
|
|
107
|
+
endpoints = endpoint_config.kwargs.get("endpoints", [])
|
|
108
|
+
sentinel_service = endpoint_config.kwargs.get("sentinel_service")
|
|
106
109
|
|
|
110
|
+
try:
|
|
111
|
+
redis_config = RedisConfig(
|
|
112
|
+
host=host,
|
|
113
|
+
port=port,
|
|
114
|
+
service_type=SupportedServiceType.LOCK_STORE,
|
|
115
|
+
db=db,
|
|
116
|
+
username=username,
|
|
117
|
+
password=password,
|
|
118
|
+
use_ssl=use_ssl,
|
|
119
|
+
ssl_certfile=ssl_certfile,
|
|
120
|
+
ssl_keyfile=ssl_keyfile,
|
|
121
|
+
ssl_ca_certs=ssl_ca_certs,
|
|
122
|
+
socket_timeout=socket_timeout,
|
|
123
|
+
deployment_mode=deployment_mode,
|
|
124
|
+
endpoints=endpoints,
|
|
125
|
+
sentinel_service=sentinel_service,
|
|
126
|
+
)
|
|
127
|
+
self.red = RedisConnectionFactory.create_connection(redis_config)
|
|
128
|
+
except ValidationError as e:
|
|
129
|
+
raise RasaException(f"Invalid Redis configuration: {e}")
|
|
130
|
+
|
|
131
|
+
self.deployment_mode = deployment_mode
|
|
107
132
|
self.key_prefix = DEFAULT_CONCURRENT_REDIS_LOCK_STORE_KEY_PREFIX
|
|
108
133
|
if key_prefix:
|
|
109
134
|
structlogger.debug(
|
|
@@ -129,6 +154,45 @@ class ConcurrentRedisLockStore(LockStore):
|
|
|
129
154
|
),
|
|
130
155
|
)
|
|
131
156
|
|
|
157
|
+
def _scan_cluster_keys(self, pattern: Text) -> list:
|
|
158
|
+
"""Scan keys in cluster mode with proper cursor handling."""
|
|
159
|
+
keys = []
|
|
160
|
+
cursor = 0
|
|
161
|
+
|
|
162
|
+
while True:
|
|
163
|
+
try:
|
|
164
|
+
cursor, batch_keys = self.red.scan(cursor, match=pattern, count=100)
|
|
165
|
+
keys.extend(batch_keys)
|
|
166
|
+
|
|
167
|
+
if isinstance(cursor, dict):
|
|
168
|
+
# cursor is a dict mapping each node to its scan position. e.g
|
|
169
|
+
# {'127.0.0.1:7000': 0, '127.0.0.1:7001': 5, '127.0.0.1:7002': 0}
|
|
170
|
+
# A cursor value of 0 means that node has finished scanning
|
|
171
|
+
# When all nodes show 0, the entire cluster scan is complete
|
|
172
|
+
if all(v == 0 for v in cursor.values()):
|
|
173
|
+
break
|
|
174
|
+
else:
|
|
175
|
+
# if scan is complete
|
|
176
|
+
if cursor == 0:
|
|
177
|
+
break
|
|
178
|
+
|
|
179
|
+
except Exception as e:
|
|
180
|
+
structlogger.warning(
|
|
181
|
+
"concurrent_redis_lock_store._get_keys_by_pattern.scan_interrupted",
|
|
182
|
+
event_info=f"SCAN interrupted in cluster mode: {e}. "
|
|
183
|
+
f"Returning {len(keys)} keys found so far.",
|
|
184
|
+
)
|
|
185
|
+
break
|
|
186
|
+
|
|
187
|
+
return keys
|
|
188
|
+
|
|
189
|
+
def _get_keys_by_pattern(self, pattern: Text) -> list:
|
|
190
|
+
"""Get keys by pattern, using SCAN for cluster mode and KEYS for others."""
|
|
191
|
+
if self.deployment_mode == DeploymentMode.CLUSTER.value:
|
|
192
|
+
return self._scan_cluster_keys(pattern)
|
|
193
|
+
else:
|
|
194
|
+
return self.red.keys(pattern)
|
|
195
|
+
|
|
132
196
|
def issue_ticket(
|
|
133
197
|
self, conversation_id: Text, lock_lifetime: float = LOCK_LIFETIME
|
|
134
198
|
) -> int:
|
|
@@ -157,11 +221,14 @@ class ConcurrentRedisLockStore(LockStore):
|
|
|
157
221
|
tickets: Deque[Ticket] = deque()
|
|
158
222
|
|
|
159
223
|
pattern = self.key_prefix + conversation_id + ":" + "[0-9]*"
|
|
160
|
-
redis_keys = self.
|
|
224
|
+
redis_keys = self._get_keys_by_pattern(pattern)
|
|
161
225
|
|
|
162
226
|
for key in redis_keys:
|
|
163
227
|
serialised_ticket = self.red.get(key)
|
|
164
228
|
if serialised_ticket:
|
|
229
|
+
# Handle bytes to string conversion for JSON parsing
|
|
230
|
+
if isinstance(serialised_ticket, bytes):
|
|
231
|
+
serialised_ticket = serialised_ticket.decode("utf-8")
|
|
165
232
|
ticket = Ticket.from_dict(json.loads(serialised_ticket))
|
|
166
233
|
tickets.appendleft(ticket)
|
|
167
234
|
|
|
@@ -172,7 +239,7 @@ class ConcurrentRedisLockStore(LockStore):
|
|
|
172
239
|
def delete_lock(self, conversation_id: Text) -> None:
|
|
173
240
|
"""Deletes lock for conversation ID."""
|
|
174
241
|
pattern = self.key_prefix + conversation_id + ":*"
|
|
175
|
-
redis_keys = self.
|
|
242
|
+
redis_keys = self._get_keys_by_pattern(pattern)
|
|
176
243
|
|
|
177
244
|
if not redis_keys:
|
|
178
245
|
structlogger.debug(
|
|
File without changes
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import dataclasses
|
|
4
|
+
from pathlib import Path
|
|
4
5
|
from typing import Any, Dict, List, Optional, Union
|
|
5
6
|
|
|
6
|
-
from
|
|
7
|
+
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
|
8
|
+
|
|
9
|
+
from rasa.core.constants import MCP_SERVERS_KEY
|
|
10
|
+
from rasa.shared.agents.auth.utils import validate_secrets_in_params
|
|
7
11
|
from rasa.shared.core.constants import (
|
|
8
12
|
GLOBAL_SILENCE_TIMEOUT_DEFAULT_VALUE,
|
|
9
13
|
GLOBAL_SILENCE_TIMEOUT_KEY,
|
|
@@ -57,13 +61,47 @@ class InteractionHandlingConfig:
|
|
|
57
61
|
)
|
|
58
62
|
|
|
59
63
|
|
|
64
|
+
class MCPServerConfig(BaseModel):
|
|
65
|
+
model_config = ConfigDict(extra="allow")
|
|
66
|
+
name: str = Field(..., description="The name of the MCP server.")
|
|
67
|
+
url: str = Field(..., description="The URL of the MCP server.")
|
|
68
|
+
type: str = Field(..., description="The type of the MCP server.")
|
|
69
|
+
additional_params: Optional[Dict[str, Any]] = Field(
|
|
70
|
+
default_factory=dict, description="Additional parameters for the MCP server."
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
@model_validator(mode="after")
|
|
74
|
+
def validate_type(self) -> MCPServerConfig:
|
|
75
|
+
# validate that type is "http"
|
|
76
|
+
if self.type not in ["http", "https"]:
|
|
77
|
+
raise ValueError(f"Invalid MCP server type: {self.type}")
|
|
78
|
+
# validate that name and url are not empty
|
|
79
|
+
if not self.name or not self.url:
|
|
80
|
+
raise ValueError("Name and URL cannot be empty")
|
|
81
|
+
# validate secrets in additional_params
|
|
82
|
+
if self.additional_params:
|
|
83
|
+
validate_secrets_in_params(
|
|
84
|
+
self.additional_params, f"MCP server - '{self.name}'"
|
|
85
|
+
)
|
|
86
|
+
return self
|
|
87
|
+
|
|
88
|
+
@model_validator(mode="before")
|
|
89
|
+
def collect_additional_params(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
|
90
|
+
base_fields = {"name", "url", "type"}
|
|
91
|
+
extras = {k: v for k, v in values.items() if k not in base_fields}
|
|
92
|
+
if extras:
|
|
93
|
+
values["additional_params"] = extras
|
|
94
|
+
# remove them from top level so Pydantic doesn’t complain
|
|
95
|
+
for k in extras:
|
|
96
|
+
values.pop(k)
|
|
97
|
+
return values
|
|
98
|
+
|
|
99
|
+
|
|
60
100
|
class AvailableEndpoints:
|
|
61
101
|
"""Collection of configured endpoints."""
|
|
62
102
|
|
|
63
|
-
_instance = None
|
|
64
|
-
|
|
65
103
|
@classmethod
|
|
66
|
-
def read_endpoints(cls, endpoint_file:
|
|
104
|
+
def read_endpoints(cls, endpoint_file: Path) -> AvailableEndpoints:
|
|
67
105
|
"""Read the different endpoints from a yaml file."""
|
|
68
106
|
nlg = read_endpoint_config(endpoint_file, endpoint_type="nlg")
|
|
69
107
|
nlu = read_endpoint_config(endpoint_file, endpoint_type="nlu")
|
|
@@ -75,6 +113,14 @@ class AvailableEndpoints:
|
|
|
75
113
|
lock_store = read_endpoint_config(endpoint_file, endpoint_type="lock_store")
|
|
76
114
|
event_broker = read_endpoint_config(endpoint_file, endpoint_type="event_broker")
|
|
77
115
|
vector_store = read_endpoint_config(endpoint_file, endpoint_type="vector_store")
|
|
116
|
+
raw_mcp_servers = read_property_config_from_endpoints_file(
|
|
117
|
+
endpoint_file, property_name=MCP_SERVERS_KEY
|
|
118
|
+
)
|
|
119
|
+
mcp_servers = (
|
|
120
|
+
[MCPServerConfig(**server) for server in raw_mcp_servers]
|
|
121
|
+
if raw_mcp_servers
|
|
122
|
+
else None
|
|
123
|
+
)
|
|
78
124
|
model_groups = read_property_config_from_endpoints_file(
|
|
79
125
|
endpoint_file, property_name="model_groups"
|
|
80
126
|
)
|
|
@@ -89,6 +135,7 @@ class AvailableEndpoints:
|
|
|
89
135
|
)
|
|
90
136
|
|
|
91
137
|
return cls(
|
|
138
|
+
endpoint_file,
|
|
92
139
|
nlg,
|
|
93
140
|
nlu,
|
|
94
141
|
action,
|
|
@@ -97,6 +144,7 @@ class AvailableEndpoints:
|
|
|
97
144
|
lock_store,
|
|
98
145
|
event_broker,
|
|
99
146
|
vector_store,
|
|
147
|
+
mcp_servers,
|
|
100
148
|
model_groups,
|
|
101
149
|
privacy,
|
|
102
150
|
interaction_handling,
|
|
@@ -104,6 +152,7 @@ class AvailableEndpoints:
|
|
|
104
152
|
|
|
105
153
|
def __init__(
|
|
106
154
|
self,
|
|
155
|
+
config_file_path: Optional[Path] = None,
|
|
107
156
|
nlg: Optional[EndpointConfig] = None,
|
|
108
157
|
nlu: Optional[EndpointConfig] = None,
|
|
109
158
|
action: Optional[EndpointConfig] = None,
|
|
@@ -112,6 +161,7 @@ class AvailableEndpoints:
|
|
|
112
161
|
lock_store: Optional[EndpointConfig] = None,
|
|
113
162
|
event_broker: Optional[EndpointConfig] = None,
|
|
114
163
|
vector_store: Optional[EndpointConfig] = None,
|
|
164
|
+
mcp_servers: Optional[List[MCPServerConfig]] = None,
|
|
115
165
|
model_groups: Optional[List[Dict[str, Any]]] = None,
|
|
116
166
|
privacy: Optional[Dict[str, Any]] = None,
|
|
117
167
|
interaction_handling: InteractionHandlingConfig = InteractionHandlingConfig(
|
|
@@ -119,6 +169,7 @@ class AvailableEndpoints:
|
|
|
119
169
|
),
|
|
120
170
|
) -> None:
|
|
121
171
|
"""Create an `AvailableEndpoints` object."""
|
|
172
|
+
self.config_file_path = config_file_path
|
|
122
173
|
self.model = model
|
|
123
174
|
self.action = action
|
|
124
175
|
self.nlu = nlu
|
|
@@ -127,20 +178,7 @@ class AvailableEndpoints:
|
|
|
127
178
|
self.lock_store = lock_store
|
|
128
179
|
self.event_broker = event_broker
|
|
129
180
|
self.vector_store = vector_store
|
|
181
|
+
self.mcp_servers = mcp_servers
|
|
130
182
|
self.model_groups = model_groups
|
|
131
183
|
self.privacy = privacy
|
|
132
184
|
self.interaction_handling = interaction_handling
|
|
133
|
-
|
|
134
|
-
@classmethod
|
|
135
|
-
def get_instance(
|
|
136
|
-
cls, endpoint_file: Optional[str] = DEFAULT_ENDPOINTS_PATH
|
|
137
|
-
) -> AvailableEndpoints:
|
|
138
|
-
"""Get the singleton instance of AvailableEndpoints."""
|
|
139
|
-
# Ensure that the instance is initialized only once.
|
|
140
|
-
if cls._instance is None:
|
|
141
|
-
cls._instance = cls.read_endpoints(endpoint_file)
|
|
142
|
-
return cls._instance
|
|
143
|
-
|
|
144
|
-
@classmethod
|
|
145
|
-
def reset_instance(cls) -> None:
|
|
146
|
-
cls._instance = None
|