rasa-pro 3.13.11__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/direct_custom_actions_executor.py +9 -2
- 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/licensing.py +21 -10
- 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.11.dist-info → rasa_pro-3.14.0.dist-info}/RECORD +583 -271
- 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.11.dist-info/METADATA +0 -192
- {rasa_pro-3.13.11.dist-info → rasa_pro-3.14.0.dist-info}/NOTICE +0 -0
- {rasa_pro-3.13.11.dist-info → rasa_pro-3.14.0.dist-info}/WHEEL +0 -0
- {rasa_pro-3.13.11.dist-info → rasa_pro-3.14.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import copy
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple, cast
|
|
4
|
+
|
|
5
|
+
import structlog
|
|
6
|
+
|
|
7
|
+
from rasa.builder.copilot.constants import ROLE_COPILOT, ROLE_USER
|
|
8
|
+
from rasa.builder.copilot.copilot_response_handler import CopilotResponseHandler
|
|
9
|
+
from rasa.builder.copilot.models import (
|
|
10
|
+
CopilotChatMessage,
|
|
11
|
+
CopilotContext,
|
|
12
|
+
GeneratedContent,
|
|
13
|
+
ResponseCategory,
|
|
14
|
+
)
|
|
15
|
+
from rasa.builder.guardrails.clients import GuardrailsClient
|
|
16
|
+
from rasa.builder.guardrails.models import (
|
|
17
|
+
GuardrailRequestKey,
|
|
18
|
+
GuardrailResponse,
|
|
19
|
+
)
|
|
20
|
+
from rasa.builder.guardrails.utils import (
|
|
21
|
+
create_guardrail_request,
|
|
22
|
+
)
|
|
23
|
+
from rasa.builder.shared.tracker_context import (
|
|
24
|
+
AssistantConversationTurn,
|
|
25
|
+
TrackerContext,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
structlogger = structlog.get_logger()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class GuardrailsPolicyChecker:
|
|
36
|
+
def __init__(self, guardrail_client: GuardrailsClient):
|
|
37
|
+
self.guardrail_client = guardrail_client
|
|
38
|
+
|
|
39
|
+
async def check_assistant_chat_for_policy_violations(
|
|
40
|
+
self,
|
|
41
|
+
tracker_context: TrackerContext,
|
|
42
|
+
hello_rasa_user_id: Optional[str],
|
|
43
|
+
hello_rasa_project_id: Optional[str],
|
|
44
|
+
**kwargs: Any,
|
|
45
|
+
) -> TrackerContext:
|
|
46
|
+
"""Return a sanitised TrackerContext with unsafe turns removed.
|
|
47
|
+
|
|
48
|
+
Only user messages are moderated - assistant messages are assumed safe.
|
|
49
|
+
LRU cache is used, so each unique user text is checked once.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
tracker_context: The TrackerContext containing conversation turns.
|
|
53
|
+
hello_rasa_user_id: The user ID for the conversation.
|
|
54
|
+
hello_rasa_project_id: The project ID for the conversation.
|
|
55
|
+
**kwargs: Additional parameters for the guardrail request.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
TrackerContext with unsafe turns removed.
|
|
59
|
+
"""
|
|
60
|
+
# Collect (turn_index, user_text) for all turns with a user message
|
|
61
|
+
items = self._format_user_messages_to_assistant(
|
|
62
|
+
tracker_context.conversation_turns
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
flagged_turns = await self._check_user_messages_for_violations(
|
|
66
|
+
items,
|
|
67
|
+
hello_rasa_user_id=hello_rasa_user_id,
|
|
68
|
+
hello_rasa_project_id=hello_rasa_project_id,
|
|
69
|
+
log_prefix="assistant_guardrails",
|
|
70
|
+
**kwargs,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
if not flagged_turns:
|
|
74
|
+
return tracker_context
|
|
75
|
+
|
|
76
|
+
structlogger.info(
|
|
77
|
+
"guardrails_policy_checker.assistant_guardrails.turns_flagged",
|
|
78
|
+
count=len(flagged_turns),
|
|
79
|
+
turn_indices=sorted(flagged_turns),
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# Build a TrackerContext with safe turns
|
|
83
|
+
safe_turns: List[AssistantConversationTurn] = [
|
|
84
|
+
turn
|
|
85
|
+
for idx, turn in enumerate(tracker_context.conversation_turns)
|
|
86
|
+
if idx not in flagged_turns
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
new_tracker_context = copy.deepcopy(tracker_context)
|
|
90
|
+
new_tracker_context.conversation_turns = safe_turns
|
|
91
|
+
return new_tracker_context
|
|
92
|
+
|
|
93
|
+
async def check_copilot_chat_for_policy_violations(
|
|
94
|
+
self,
|
|
95
|
+
context: CopilotContext,
|
|
96
|
+
hello_rasa_user_id: Optional[str],
|
|
97
|
+
hello_rasa_project_id: Optional[str],
|
|
98
|
+
**kwargs: Any,
|
|
99
|
+
) -> Optional[GeneratedContent]:
|
|
100
|
+
"""Check the copilot chat history for guardrail policy violations.
|
|
101
|
+
|
|
102
|
+
Only user messages are moderated – assistant messages are assumed safe.
|
|
103
|
+
LRU cache is used, so each unique user text is checked once.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
context: The CopilotContext containing the copilot chat history.
|
|
107
|
+
hello_rasa_user_id: The user ID for the conversation.
|
|
108
|
+
hello_rasa_project_id: The project ID for the conversation.
|
|
109
|
+
**kwargs: Additional parameters for the guardrail request.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
Returns a default violation response if the system flags any user message,
|
|
113
|
+
otherwise return None.
|
|
114
|
+
"""
|
|
115
|
+
# Collect (index, text) for user messages; skip ones already marked as
|
|
116
|
+
# violations
|
|
117
|
+
items = self._format_user_messages_to_copilot(context.copilot_chat_history)
|
|
118
|
+
|
|
119
|
+
flagged_user_indices = await self._check_user_messages_for_violations(
|
|
120
|
+
items,
|
|
121
|
+
hello_rasa_user_id=hello_rasa_user_id,
|
|
122
|
+
hello_rasa_project_id=hello_rasa_project_id,
|
|
123
|
+
log_prefix="copilot_guardrails",
|
|
124
|
+
**kwargs,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
self._annotate_flagged_user_messages(
|
|
128
|
+
context.copilot_chat_history, flagged_user_indices
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
if not flagged_user_indices:
|
|
132
|
+
return None
|
|
133
|
+
|
|
134
|
+
# Identify the latest user message index in the current request
|
|
135
|
+
last_user_idx: Optional[int] = None
|
|
136
|
+
for i in range(len(context.copilot_chat_history) - 1, -1, -1):
|
|
137
|
+
if getattr(context.copilot_chat_history[i], "role", None) == ROLE_USER:
|
|
138
|
+
last_user_idx = i
|
|
139
|
+
break
|
|
140
|
+
|
|
141
|
+
# Remove flagged user messages and their next copilot messages
|
|
142
|
+
indices_to_remove: Set[int] = set()
|
|
143
|
+
total = len(context.copilot_chat_history)
|
|
144
|
+
for uidx in flagged_user_indices:
|
|
145
|
+
indices_to_remove.add(uidx)
|
|
146
|
+
next_idx = uidx + 1
|
|
147
|
+
if (
|
|
148
|
+
next_idx < total
|
|
149
|
+
and getattr(context.copilot_chat_history[next_idx], "role", None)
|
|
150
|
+
== ROLE_COPILOT
|
|
151
|
+
):
|
|
152
|
+
indices_to_remove.add(next_idx)
|
|
153
|
+
|
|
154
|
+
# Apply sanitization
|
|
155
|
+
filtered_copilot_chat_history = [
|
|
156
|
+
msg
|
|
157
|
+
for i, msg in enumerate(context.copilot_chat_history)
|
|
158
|
+
if i not in indices_to_remove
|
|
159
|
+
]
|
|
160
|
+
if len(filtered_copilot_chat_history) != len(context.copilot_chat_history):
|
|
161
|
+
structlogger.info(
|
|
162
|
+
"guardrails_policy_checker"
|
|
163
|
+
".copilot_guardrails"
|
|
164
|
+
".copilot_chat_history_sanitized",
|
|
165
|
+
removed_indices=sorted(indices_to_remove),
|
|
166
|
+
removed_messages=(
|
|
167
|
+
len(context.copilot_chat_history)
|
|
168
|
+
- len(filtered_copilot_chat_history)
|
|
169
|
+
),
|
|
170
|
+
kept_messages=len(filtered_copilot_chat_history),
|
|
171
|
+
)
|
|
172
|
+
context.copilot_chat_history = filtered_copilot_chat_history
|
|
173
|
+
|
|
174
|
+
# Block only if the latest user message in this request was flagged
|
|
175
|
+
if last_user_idx is not None and last_user_idx in flagged_user_indices:
|
|
176
|
+
return CopilotResponseHandler.respond_to_guardrail_policy_violations()
|
|
177
|
+
|
|
178
|
+
# Otherwise proceed (following messages are respected)
|
|
179
|
+
return None
|
|
180
|
+
|
|
181
|
+
async def _check_user_messages_for_violations(
|
|
182
|
+
self,
|
|
183
|
+
items: List[Tuple[int, str]],
|
|
184
|
+
hello_rasa_user_id: Optional[str],
|
|
185
|
+
hello_rasa_project_id: Optional[str],
|
|
186
|
+
log_prefix: str,
|
|
187
|
+
**kwargs: Any,
|
|
188
|
+
) -> Set[int]:
|
|
189
|
+
"""Run guardrail checks for provided (index, user_text) pairs.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
items: List of tuples containing (index, user_text) to check.
|
|
193
|
+
hello_rasa_user_id: The user ID for the conversation.
|
|
194
|
+
hello_rasa_project_id: The project ID for the conversation.
|
|
195
|
+
log_prefix: Prefix for logging messages.
|
|
196
|
+
**kwargs: Additional parameters for the guardrail request.
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
A set of indices that were flagged by the guardrails.
|
|
200
|
+
"""
|
|
201
|
+
if not items:
|
|
202
|
+
return set()
|
|
203
|
+
|
|
204
|
+
# 1) Group indices by logical request key (hashable by value)
|
|
205
|
+
indices_by_key: Dict[GuardrailRequestKey, List[int]] = {}
|
|
206
|
+
for idx, text in items:
|
|
207
|
+
key = GuardrailRequestKey(
|
|
208
|
+
user_text=text,
|
|
209
|
+
hello_rasa_user_id=hello_rasa_user_id or "",
|
|
210
|
+
hello_rasa_project_id=hello_rasa_project_id or "",
|
|
211
|
+
# The client-specific request parameters go in the metadata
|
|
212
|
+
# so that they can be used to create the request
|
|
213
|
+
metadata=kwargs,
|
|
214
|
+
)
|
|
215
|
+
if not key.user_text:
|
|
216
|
+
continue
|
|
217
|
+
indices_by_key.setdefault(key, []).append(idx)
|
|
218
|
+
|
|
219
|
+
if not indices_by_key:
|
|
220
|
+
return set()
|
|
221
|
+
|
|
222
|
+
# 2) Create one task per logical key
|
|
223
|
+
tasks_by_key: Dict[GuardrailRequestKey, asyncio.Task[GuardrailResponse]] = {}
|
|
224
|
+
for key in indices_by_key:
|
|
225
|
+
request = create_guardrail_request(
|
|
226
|
+
client_type=type(self.guardrail_client),
|
|
227
|
+
user_text=key.user_text,
|
|
228
|
+
hello_rasa_user_id=key.hello_rasa_user_id,
|
|
229
|
+
hello_rasa_project_id=key.hello_rasa_project_id,
|
|
230
|
+
**kwargs,
|
|
231
|
+
)
|
|
232
|
+
tasks_by_key[key] = self.guardrail_client.schedule_check(request)
|
|
233
|
+
|
|
234
|
+
# 3) Await unique tasks once
|
|
235
|
+
keys = list(tasks_by_key.keys())
|
|
236
|
+
tasks = [tasks_by_key[k] for k in keys]
|
|
237
|
+
responses = await asyncio.gather(*tasks, return_exceptions=True)
|
|
238
|
+
|
|
239
|
+
# 4) Map results back to all corresponding indices
|
|
240
|
+
flagged: Set[int] = set()
|
|
241
|
+
for key, response in zip(keys, responses):
|
|
242
|
+
if isinstance(response, Exception):
|
|
243
|
+
structlogger.warning(
|
|
244
|
+
f"{log_prefix}.request_failed", error=str(response)
|
|
245
|
+
)
|
|
246
|
+
continue
|
|
247
|
+
# At this point, response is guaranteed to be GuardrailResponse
|
|
248
|
+
# Use typing.cast to explicitly cast the type
|
|
249
|
+
guardrail_response = cast(GuardrailResponse, response)
|
|
250
|
+
if guardrail_response.flagged:
|
|
251
|
+
flagged.update(indices_by_key.get(key, []))
|
|
252
|
+
|
|
253
|
+
return flagged
|
|
254
|
+
|
|
255
|
+
def _annotate_flagged_user_messages(
|
|
256
|
+
self,
|
|
257
|
+
copilot_chat_history: List[CopilotChatMessage],
|
|
258
|
+
flagged_user_indices: Set[int],
|
|
259
|
+
) -> None:
|
|
260
|
+
"""Mark flagged user messages in-place on the original copilot chat history.
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
copilot_chat_history: The copilot chat history containing messages.
|
|
264
|
+
flagged_user_indices: Set of indices of user messages that were flagged.
|
|
265
|
+
"""
|
|
266
|
+
if not flagged_user_indices:
|
|
267
|
+
return
|
|
268
|
+
|
|
269
|
+
total = len(copilot_chat_history)
|
|
270
|
+
for uidx in flagged_user_indices:
|
|
271
|
+
if 0 <= uidx < total and copilot_chat_history[uidx].role == ROLE_USER:
|
|
272
|
+
copilot_chat_history[
|
|
273
|
+
uidx
|
|
274
|
+
].response_category = ResponseCategory.GUARDRAILS_POLICY_VIOLATION
|
|
275
|
+
|
|
276
|
+
def _format_user_messages_to_assistant(
|
|
277
|
+
self, conversation_turns: List[AssistantConversationTurn]
|
|
278
|
+
) -> List[Tuple[int, str]]:
|
|
279
|
+
"""Collect (turn_index, user_text) tuples for all turns with user messages.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
conversation_turns: The list of conversation turns.
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
List of tuples containing (turn_index, user_text) for valid user messages.
|
|
286
|
+
"""
|
|
287
|
+
items: List[Tuple[int, str]] = []
|
|
288
|
+
for idx, turn in enumerate(conversation_turns):
|
|
289
|
+
user_message = turn.user_message
|
|
290
|
+
if not user_message:
|
|
291
|
+
continue
|
|
292
|
+
|
|
293
|
+
text = (user_message.text or "").strip()
|
|
294
|
+
if not text:
|
|
295
|
+
continue
|
|
296
|
+
|
|
297
|
+
items.append((idx, text))
|
|
298
|
+
|
|
299
|
+
return items
|
|
300
|
+
|
|
301
|
+
def _format_user_messages_to_copilot(
|
|
302
|
+
self, copilot_chat_history: List[CopilotChatMessage]
|
|
303
|
+
) -> List[Tuple[int, str]]:
|
|
304
|
+
"""Collect (index, user_text) tuples for all messages with user messages.
|
|
305
|
+
|
|
306
|
+
Args:
|
|
307
|
+
copilot_chat_history: The list of messages.
|
|
308
|
+
"""
|
|
309
|
+
items: List[Tuple[int, str]] = []
|
|
310
|
+
for idx, message in enumerate(copilot_chat_history):
|
|
311
|
+
if (
|
|
312
|
+
message.response_category
|
|
313
|
+
== ResponseCategory.GUARDRAILS_POLICY_VIOLATION
|
|
314
|
+
):
|
|
315
|
+
continue
|
|
316
|
+
if message.role != ROLE_USER:
|
|
317
|
+
continue
|
|
318
|
+
formatted_message = message.build_openai_message()
|
|
319
|
+
text = (formatted_message.get("content") or "").strip()
|
|
320
|
+
if not text:
|
|
321
|
+
continue
|
|
322
|
+
items.append((idx, text))
|
|
323
|
+
|
|
324
|
+
return items
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import time
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
import structlog
|
|
6
|
+
|
|
7
|
+
from rasa.builder import config
|
|
8
|
+
from rasa.builder.guardrails.constants import (
|
|
9
|
+
BLOCK_SCOPE_PROJECT,
|
|
10
|
+
BLOCK_SCOPE_USER,
|
|
11
|
+
BlockScope,
|
|
12
|
+
)
|
|
13
|
+
from rasa.builder.guardrails.models import BlockResult, ProjectState, ScopeState
|
|
14
|
+
|
|
15
|
+
structlogger = structlog.get_logger()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class GuardrailsInMemoryStore:
|
|
19
|
+
"""In-memory strike and block tracking for a single project instance."""
|
|
20
|
+
|
|
21
|
+
def __init__(self) -> None:
|
|
22
|
+
self._state: ProjectState = ProjectState()
|
|
23
|
+
self._lock = asyncio.Lock()
|
|
24
|
+
|
|
25
|
+
@staticmethod
|
|
26
|
+
def _normalize_user_id(user_id: Optional[str]) -> str:
|
|
27
|
+
"""Normalize and validate user_id.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
user_id: User identifier.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
Validated, non-empty user id.
|
|
34
|
+
"""
|
|
35
|
+
uid = (user_id or "").strip()
|
|
36
|
+
if not uid:
|
|
37
|
+
raise ValueError("user_id is required for guardrails tracking.")
|
|
38
|
+
return uid
|
|
39
|
+
|
|
40
|
+
def _get_or_create_user(self, user_id: str) -> ScopeState:
|
|
41
|
+
"""Return (and create if needed) the per-user scope state.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
user_id: User identifier.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
Mutable ScopeState for the user.
|
|
48
|
+
"""
|
|
49
|
+
uid = self._normalize_user_id(user_id)
|
|
50
|
+
return self._state.users.setdefault(uid, ScopeState())
|
|
51
|
+
|
|
52
|
+
def _clear_expired_project_block(self, now: float) -> None:
|
|
53
|
+
"""Clear project-level block if expired.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
now: Current time as a UNIX timestamp.
|
|
57
|
+
"""
|
|
58
|
+
project = self._state.project
|
|
59
|
+
if project.blocked_until and now >= project.blocked_until:
|
|
60
|
+
project.blocked_until = None
|
|
61
|
+
|
|
62
|
+
def _clear_expired_user_block(self, user_id: str, now: float) -> None:
|
|
63
|
+
"""Clear user-level block if expired.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
user_id: User identifier.
|
|
67
|
+
now: Current time as a UNIX timestamp.
|
|
68
|
+
"""
|
|
69
|
+
try:
|
|
70
|
+
uid = self._normalize_user_id(user_id)
|
|
71
|
+
except ValueError:
|
|
72
|
+
return
|
|
73
|
+
|
|
74
|
+
user_state = self._state.users.get(uid)
|
|
75
|
+
if user_state and user_state.blocked_until and now >= user_state.blocked_until:
|
|
76
|
+
user_state.blocked_until = None
|
|
77
|
+
|
|
78
|
+
@staticmethod
|
|
79
|
+
def _apply_user_block_if_needed(user_id: str, user_state: ScopeState) -> bool:
|
|
80
|
+
"""Apply a user-level block if the threshold is reached.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
user_id: User identifier.
|
|
84
|
+
user_state: Current user's scope state.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
True if a block was applied during this call; otherwise False.
|
|
88
|
+
"""
|
|
89
|
+
now = time.time()
|
|
90
|
+
if user_state.is_blocked(now):
|
|
91
|
+
return False
|
|
92
|
+
|
|
93
|
+
if len(user_state.violations) < config.GUARDRAILS_USER_MAX_STRIKES:
|
|
94
|
+
return False
|
|
95
|
+
|
|
96
|
+
duration_seconds = config.GUARDRAILS_BLOCK_DURATION_SECONDS
|
|
97
|
+
block_until = float("inf") if duration_seconds <= 0 else now + duration_seconds
|
|
98
|
+
user_state.blocked_until = block_until
|
|
99
|
+
structlogger.info(
|
|
100
|
+
"guardrails.store.user_blocked",
|
|
101
|
+
project_id=config.HELLO_RASA_PROJECT_ID,
|
|
102
|
+
user_id=user_id,
|
|
103
|
+
strikes=len(user_state.violations),
|
|
104
|
+
duration_sec=duration_seconds,
|
|
105
|
+
)
|
|
106
|
+
return True
|
|
107
|
+
|
|
108
|
+
def _apply_project_block_if_needed(self) -> bool:
|
|
109
|
+
"""Apply a project-level block if the threshold is reached.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
True if a block was applied during this call; otherwise False.
|
|
113
|
+
"""
|
|
114
|
+
now = time.time()
|
|
115
|
+
project_state = self._state.project
|
|
116
|
+
if project_state.is_blocked(now):
|
|
117
|
+
return False
|
|
118
|
+
|
|
119
|
+
if len(project_state.violations) < config.GUARDRAILS_PROJECT_MAX_STRIKES:
|
|
120
|
+
return False
|
|
121
|
+
|
|
122
|
+
duration_seconds = config.GUARDRAILS_BLOCK_DURATION_SECONDS
|
|
123
|
+
block_until = float("inf") if duration_seconds <= 0 else now + duration_seconds
|
|
124
|
+
project_state.blocked_until = block_until
|
|
125
|
+
structlogger.info(
|
|
126
|
+
"guardrails.store.project_blocked",
|
|
127
|
+
project_id=config.HELLO_RASA_PROJECT_ID,
|
|
128
|
+
strikes=len(project_state.violations),
|
|
129
|
+
duration_sec=duration_seconds,
|
|
130
|
+
)
|
|
131
|
+
return True
|
|
132
|
+
|
|
133
|
+
async def check_block_scope(self, user_id: str) -> Optional[BlockScope]:
|
|
134
|
+
"""Return current block scope if blocked.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
user_id: User identifier.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
'user' if user blocked, 'project' if project blocked, otherwise None.
|
|
141
|
+
"""
|
|
142
|
+
uid = self._normalize_user_id(user_id)
|
|
143
|
+
|
|
144
|
+
async with self._lock:
|
|
145
|
+
now = time.time()
|
|
146
|
+
|
|
147
|
+
# Clear expired blocks
|
|
148
|
+
self._clear_expired_project_block(now)
|
|
149
|
+
self._clear_expired_user_block(uid, now)
|
|
150
|
+
|
|
151
|
+
user_state = self._state.users.get(uid)
|
|
152
|
+
|
|
153
|
+
if user_state and user_state.is_blocked(now):
|
|
154
|
+
return BLOCK_SCOPE_USER
|
|
155
|
+
if self._state.project.is_blocked(now):
|
|
156
|
+
return BLOCK_SCOPE_PROJECT
|
|
157
|
+
return None
|
|
158
|
+
|
|
159
|
+
async def record_violation(self, user_id: str) -> BlockResult:
|
|
160
|
+
"""Record a violation and apply thresholds/blocks.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
user_id: User identifier.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
BlockResult indicating whether a new user or project block was applied.
|
|
167
|
+
"""
|
|
168
|
+
uid = self._normalize_user_id(user_id)
|
|
169
|
+
result = BlockResult()
|
|
170
|
+
|
|
171
|
+
async with self._lock:
|
|
172
|
+
now = time.time()
|
|
173
|
+
user_state = self._get_or_create_user(uid)
|
|
174
|
+
|
|
175
|
+
# Accumulate violations (no sliding window)
|
|
176
|
+
self._state.project.violations.append(now)
|
|
177
|
+
user_state.violations.append(now)
|
|
178
|
+
|
|
179
|
+
# Apply user and project blocks
|
|
180
|
+
result.user_blocked_now = self._apply_user_block_if_needed(
|
|
181
|
+
user_id=uid,
|
|
182
|
+
user_state=user_state,
|
|
183
|
+
)
|
|
184
|
+
result.project_blocked_now = self._apply_project_block_if_needed()
|
|
185
|
+
|
|
186
|
+
return result
|
|
187
|
+
|
|
188
|
+
async def unblock_user(self, user_id: str) -> None:
|
|
189
|
+
"""Unblock a user without altering strike history.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
user_id: User identifier.
|
|
193
|
+
"""
|
|
194
|
+
uid = self._normalize_user_id(user_id)
|
|
195
|
+
|
|
196
|
+
async with self._lock:
|
|
197
|
+
if state := self._state.users.get(uid):
|
|
198
|
+
state.blocked_until = None
|
|
199
|
+
|
|
200
|
+
async def reset_user(self, user_id: str) -> None:
|
|
201
|
+
"""Unblock a user and clear their strikes.
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
user_id: User identifier.
|
|
205
|
+
"""
|
|
206
|
+
uid = self._normalize_user_id(user_id)
|
|
207
|
+
|
|
208
|
+
async with self._lock:
|
|
209
|
+
if state := self._state.users.get(uid):
|
|
210
|
+
state.blocked_until = None
|
|
211
|
+
state.violations.clear()
|
|
212
|
+
|
|
213
|
+
async def unblock_project(self) -> None:
|
|
214
|
+
"""Unblock the project without altering strike history."""
|
|
215
|
+
async with self._lock:
|
|
216
|
+
self._state.project.blocked_until = None
|
|
217
|
+
|
|
218
|
+
async def reset_project(self) -> None:
|
|
219
|
+
"""Unblock the project and clear project-wide strikes."""
|
|
220
|
+
async with self._lock:
|
|
221
|
+
self._state.project.blocked_until = None
|
|
222
|
+
self._state.project.violations.clear()
|
|
223
|
+
|
|
224
|
+
async def reset_all(self) -> None:
|
|
225
|
+
"""Reset all guardrail state (project and users)."""
|
|
226
|
+
async with self._lock:
|
|
227
|
+
# Clear project scope
|
|
228
|
+
self._state.project.blocked_until = None
|
|
229
|
+
self._state.project.violations.clear()
|
|
230
|
+
|
|
231
|
+
# Clear all users
|
|
232
|
+
for state in self._state.users.values():
|
|
233
|
+
state.blocked_until = None
|
|
234
|
+
state.violations.clear()
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
# Singleton instance for application-wide use
|
|
238
|
+
guardrails_store = GuardrailsInMemoryStore()
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Type
|
|
2
|
+
|
|
3
|
+
import structlog
|
|
4
|
+
|
|
5
|
+
from rasa.builder.guardrails.clients import GuardrailsClient, LakeraAIGuardrails
|
|
6
|
+
from rasa.builder.guardrails.models import (
|
|
7
|
+
GuardrailRequest,
|
|
8
|
+
LakeraGuardrailRequest,
|
|
9
|
+
)
|
|
10
|
+
from rasa.shared.constants import ROLE_USER
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from rasa.builder.guardrails.models import GuardrailType
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
structlogger = structlog.get_logger()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def map_lakera_detector_type_to_guardrail_type(
|
|
20
|
+
lakera_detector_type: str,
|
|
21
|
+
) -> Optional["GuardrailType"]:
|
|
22
|
+
"""Map a Lakera detector type to a Rasa guardrail type."""
|
|
23
|
+
from rasa.builder.guardrails.models import GuardrailType
|
|
24
|
+
|
|
25
|
+
# Check for exact matches first
|
|
26
|
+
LAKERA_DETECTOR_TYPES_2_RASA_GUARDRAIL_TYPES_MAPPING = {
|
|
27
|
+
"prompt_attack": GuardrailType.PROMPT_ATTACK,
|
|
28
|
+
"unknown_links": GuardrailType.MALICIOUS_LINKS,
|
|
29
|
+
"custom": GuardrailType.CUSTOM,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# Check for exact match first
|
|
33
|
+
if lakera_detector_type in LAKERA_DETECTOR_TYPES_2_RASA_GUARDRAIL_TYPES_MAPPING:
|
|
34
|
+
return LAKERA_DETECTOR_TYPES_2_RASA_GUARDRAIL_TYPES_MAPPING[
|
|
35
|
+
lakera_detector_type
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
# Check for subtypes that start with specific prefixes
|
|
39
|
+
# https://docs.lakera.ai/docs/policies/self-hosted-policies#detectors-section
|
|
40
|
+
if lakera_detector_type.startswith("moderated_content"):
|
|
41
|
+
return GuardrailType.CONTENT_VIOLATION
|
|
42
|
+
if lakera_detector_type.startswith("pii"):
|
|
43
|
+
return GuardrailType.DATA_LEAKAGE
|
|
44
|
+
|
|
45
|
+
# If no match found, return OTHER
|
|
46
|
+
return GuardrailType.OTHER
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def create_guardrail_request(
|
|
50
|
+
client_type: Type[GuardrailsClient],
|
|
51
|
+
user_text: str,
|
|
52
|
+
hello_rasa_user_id: str,
|
|
53
|
+
hello_rasa_project_id: str,
|
|
54
|
+
**kwargs: Any,
|
|
55
|
+
) -> GuardrailRequest:
|
|
56
|
+
"""Create a guardrail request."""
|
|
57
|
+
|
|
58
|
+
def _create_lakera_guardrail_request(
|
|
59
|
+
user_text: str,
|
|
60
|
+
hello_rasa_user_id: str,
|
|
61
|
+
hello_rasa_project_id: str,
|
|
62
|
+
**kwargs: Any,
|
|
63
|
+
) -> LakeraGuardrailRequest:
|
|
64
|
+
"""Create a Lakera guardrail request."""
|
|
65
|
+
return LakeraGuardrailRequest(
|
|
66
|
+
hello_rasa_user_id=hello_rasa_user_id,
|
|
67
|
+
hello_rasa_project_id=hello_rasa_project_id,
|
|
68
|
+
messages=[{"role": ROLE_USER, "content": user_text}],
|
|
69
|
+
**kwargs,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
map_client_to_request: Dict[
|
|
73
|
+
Type[GuardrailsClient], Callable[..., GuardrailRequest]
|
|
74
|
+
] = {
|
|
75
|
+
LakeraAIGuardrails: _create_lakera_guardrail_request,
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if client_type in map_client_to_request:
|
|
79
|
+
return map_client_to_request[client_type](
|
|
80
|
+
user_text,
|
|
81
|
+
hello_rasa_user_id,
|
|
82
|
+
hello_rasa_project_id,
|
|
83
|
+
**kwargs,
|
|
84
|
+
)
|
|
85
|
+
else:
|
|
86
|
+
message = f"Unsupported guardrail client: {type(client_type)}"
|
|
87
|
+
structlogger.error(
|
|
88
|
+
"guardrails_policy_checker"
|
|
89
|
+
".create_guardrail_request"
|
|
90
|
+
".unsupported_guardrail_client",
|
|
91
|
+
message=message,
|
|
92
|
+
guardrail_client=client_type,
|
|
93
|
+
)
|
|
94
|
+
raise ValueError(message)
|