rasa-pro 3.13.1a19__py3-none-any.whl → 3.13.1a20__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 +8 -0
- rasa/builder/auth.py +71 -0
- rasa/builder/config.py +16 -0
- rasa/builder/copilot/constants.py +15 -0
- rasa/builder/copilot/copilot.py +342 -0
- rasa/builder/copilot/copilot_response_handler.py +471 -0
- rasa/builder/copilot/exceptions.py +20 -0
- rasa/builder/copilot/models.py +344 -0
- rasa/builder/copilot/prompts/copilot_system_prompt.jinja2 +495 -0
- rasa/builder/copilot/telemetry.py +195 -0
- rasa/builder/document_retrieval/__init__.py +0 -0
- rasa/builder/document_retrieval/constants.py +16 -0
- rasa/builder/{inkeep_document_retrieval.py → document_retrieval/inkeep_document_retrieval.py} +24 -30
- rasa/builder/document_retrieval/models.py +62 -0
- rasa/builder/download.py +140 -0
- rasa/builder/guardrails/__init__.py +1 -0
- rasa/builder/guardrails/constants.py +4 -0
- rasa/builder/guardrails/exceptions.py +4 -0
- rasa/builder/guardrails/lakera.py +188 -0
- rasa/builder/guardrails/models.py +199 -0
- rasa/builder/guardrails/utils.py +305 -0
- rasa/builder/job_manager.py +87 -0
- rasa/builder/jobs.py +232 -0
- rasa/builder/llm_service.py +59 -7
- rasa/builder/logging_utils.py +162 -4
- rasa/builder/main.py +29 -16
- rasa/builder/models.py +90 -233
- rasa/builder/project_generator.py +91 -7
- rasa/builder/scrape_rasa_docs.py +1 -1
- rasa/builder/service.py +632 -440
- rasa/builder/shared/tracker_context.py +212 -0
- rasa/builder/validation_service.py +4 -4
- rasa/cli/data.py +8 -3
- rasa/cli/project_templates/basic/actions/action_api.py +15 -0
- rasa/cli/project_templates/basic/actions/action_human_handoff.py +44 -0
- rasa/cli/project_templates/basic/config.yml +23 -0
- rasa/cli/project_templates/{plain → basic}/credentials.yml +8 -7
- rasa/cli/project_templates/basic/data/general/feedback.yml +20 -0
- rasa/cli/project_templates/basic/data/general/goodbye.yml +6 -0
- rasa/cli/project_templates/basic/data/general/hello.yml +7 -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/welcome.yml +9 -0
- rasa/cli/project_templates/{finance/data/patterns → basic/data/system}/pattern_completed.yml +2 -1
- rasa/cli/project_templates/basic/data/system/pattern_correction.yml +7 -0
- rasa/cli/project_templates/basic/data/system/pattern_search.yml +8 -0
- rasa/cli/project_templates/basic/data/system/pattern_session_start.yml +8 -0
- rasa/cli/project_templates/basic/docs/rasa_assistant_qa.txt +65 -0
- rasa/cli/project_templates/basic/docs/template.txt +7 -0
- rasa/cli/project_templates/basic/domain/general/assistant_details.yml +12 -0
- rasa/cli/project_templates/basic/domain/general/bot_identity.yml +5 -0
- rasa/cli/project_templates/basic/domain/general/cannot_handle.yml +5 -0
- rasa/cli/project_templates/basic/domain/general/feedback.yml +28 -0
- rasa/cli/project_templates/basic/domain/general/goodbye.yml +7 -0
- rasa/cli/project_templates/basic/domain/general/help.yml +5 -0
- rasa/cli/project_templates/basic/domain/general/human_handoff_domain.yml +35 -0
- rasa/cli/project_templates/{finance/domain/default_actions.yml → basic/domain/general/utils.yml} +0 -3
- rasa/cli/project_templates/basic/domain/general/welcome.yml +7 -0
- rasa/cli/project_templates/{plain → basic}/endpoints.yml +42 -27
- rasa/cli/project_templates/basic/prompts/rephraser_demo_personality_prompt.jinja2 +19 -0
- rasa/cli/project_templates/defaults.py +25 -3
- rasa/cli/project_templates/finance/actions/__init__.py +46 -0
- rasa/cli/project_templates/finance/actions/accounts/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/{action_ask_account.py → accounts/action_ask_account.py} +6 -9
- rasa/cli/project_templates/finance/actions/{action_check_balance.py → accounts/action_check_balance.py} +4 -4
- rasa/cli/project_templates/finance/actions/action_session_start.py +11 -6
- rasa/cli/project_templates/finance/actions/cards/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/{action_ask_card.py → cards/action_ask_card.py} +4 -3
- rasa/cli/project_templates/finance/actions/{action_check_card_existence.py → cards/action_check_card_existence.py} +4 -3
- rasa/cli/project_templates/finance/actions/{action_update_card_status.py → cards/action_update_card_status.py} +18 -9
- rasa/cli/project_templates/finance/actions/database.py +1 -0
- rasa/cli/project_templates/finance/actions/transfers/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/{action_add_payee.py → transfers/action_add_payee.py} +8 -3
- rasa/cli/project_templates/finance/actions/{action_ask_account_from.py → transfers/action_ask_account_from.py} +5 -4
- rasa/cli/project_templates/finance/actions/{action_check_payee_existence.py → transfers/action_check_payee_existence.py} +3 -3
- rasa/cli/project_templates/finance/actions/{action_check_sufficient_funds.py → transfers/action_check_sufficient_funds.py} +3 -4
- rasa/cli/project_templates/finance/actions/{action_list_payees.py → transfers/action_list_payees.py} +4 -3
- rasa/cli/project_templates/finance/actions/{action_remove_payee.py → transfers/action_remove_payee.py} +4 -4
- rasa/cli/project_templates/finance/config.yml +8 -19
- rasa/cli/project_templates/finance/credentials.yml +6 -7
- rasa/cli/project_templates/finance/csvs/cards.csv +10 -10
- rasa/cli/project_templates/finance/csvs/payees.csv +10 -9
- rasa/cli/project_templates/finance/data/{flows → accounts}/check_balance.yml +2 -1
- rasa/cli/project_templates/finance/data/general/bot_identity.yml +6 -0
- rasa/cli/project_templates/finance/data/general/feedback.yml +20 -0
- rasa/cli/project_templates/finance/data/general/goodbye.yml +6 -0
- rasa/cli/project_templates/finance/data/general/hello.yml +7 -0
- rasa/cli/project_templates/finance/data/{flows/welcome.yml → general/help.yml} +2 -7
- 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/{patterns → system/patterns}/pattern_chitchat.yml +0 -2
- 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/{patterns → system/patterns}/pattern_session_start.yml +0 -1
- rasa/cli/project_templates/finance/domain/{check_balance.yml → accounts/check_balance.yml} +2 -0
- rasa/cli/project_templates/finance/domain/general/assistant_details.yml +12 -0
- rasa/cli/project_templates/finance/domain/general/bot_identity.yml +5 -0
- rasa/cli/project_templates/finance/domain/general/cannot_handle.yml +5 -0
- rasa/cli/project_templates/finance/domain/general/defaults.yml +24 -0
- rasa/cli/project_templates/finance/domain/general/feedback.yml +28 -0
- rasa/cli/project_templates/finance/domain/general/goodbye.yml +7 -0
- rasa/cli/project_templates/finance/domain/general/help.yml +5 -0
- rasa/cli/project_templates/finance/domain/general/human_handoff.yml +30 -0
- rasa/cli/project_templates/finance/domain/general/utils.yml +13 -0
- rasa/cli/project_templates/finance/domain/general/welcome.yml +8 -0
- rasa/cli/project_templates/finance/endpoints.yml +1 -0
- rasa/cli/project_templates/finance/prompts/rephraser_demo_personality_prompt.jinja2 +3 -3
- rasa/cli/project_templates/telco/actions/actions_billing.py +24 -17
- rasa/cli/project_templates/telco/actions/actions_get_data_from_db.py +6 -1
- rasa/cli/project_templates/telco/actions/actions_run_diagnostics.py +6 -1
- rasa/cli/project_templates/telco/actions/actions_session_start.py +6 -1
- rasa/cli/project_templates/tutorial/config.yml +2 -1
- rasa/cli/scaffold.py +27 -2
- rasa/cli/train.py +8 -0
- rasa/cli/utils.py +31 -15
- rasa/core/actions/action.py +28 -41
- rasa/core/actions/action_run_slot_rejections.py +1 -1
- rasa/core/channels/development_inspector.py +47 -14
- rasa/core/channels/inspector/dist/assets/{arc-371401b1.js → arc-1ddec37b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-3f126156.js → blockDiagram-38ab4fdb-18af387c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-12f22eb7.js → c4Diagram-3d4e48cf-250127a3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/channel-59f6d54b.js +1 -0
- rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-03b1d386.js → classDiagram-70f12bd4-c3388b34.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-84f69d63.js → classDiagram-v2-f2320105-9c893a82.js} +1 -1
- rasa/core/channels/inspector/dist/assets/clone-26177ddb.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-ca47fd38.js → createText-2e5e7dd3-c111213b.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-f837ca8a.js → edges-e0da2a9e-812a729d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-8717ac54.js → erDiagram-9861fffd-fd5051bc.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-94f38b83.js → flowDb-956e92f1-3287ac02.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-b616f9fb.js → flowDiagram-66a62f08-692fb0b2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-29c03f5a.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-f5d24bb8.js → flowchart-elk-definition-4a651766-008376f1.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-b43ba8d9.js → ganttDiagram-c361ad54-df330a69.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-c3aafaa5.js → gitGraphDiagram-72cf32ee-e03676fb.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-0d0a2c10.js → graph-46fad2ba.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3862675e-58ea0305.js → index-3862675e-a484ac55.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-cce6f8a1.js → index-a003633f.js} +179 -179
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-b8f60461.js → infoDiagram-f8f76790-3f9e6ec2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-95be5545.js → journeyDiagram-49397b02-79f72383.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-da885b9b.js → layout-aad098e5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-f1c817d3.js → line-219ab7ae.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-d42801e6.js → linear-2cddbe62.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-a38923a6.js → mindmap-definition-fc14e90a-1d41ed99.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-ca6e71e9.js → pieDiagram-8a3498a8-cc496ee8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-b290dae9.js → quadrantDiagram-120e2f19-84d32884.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-03f02ceb.js → requirementDiagram-deff3bca-c0deb984.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-c49eee40.js → sankeyDiagram-04a897e0-b9d7fd62.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-b2cd6a3d.js → sequenceDiagram-704730f1-7d517565.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-e53a2028.js → stateDiagram-587899a1-98ef9b27.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-e1982a03.js → stateDiagram-v2-d93cdb3a-cee70748.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-d0226ca5.js → styles-6aaf32cf-3f9d1c96.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-0e21dc00.js → styles-9a916d00-67471923.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-9588494e.js → styles-c10674c1-bd093fb7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-be478d4f.js → svgDrawCommon-08f97a94-675794e8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-74631749.js → timeline-definition-85554ec2-0ac67617.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-a043552f.js → xychartDiagram-e933f94c-c018dc37.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +2 -2
- rasa/core/channels/inspector/index.html +1 -1
- rasa/core/channels/inspector/package.json +4 -3
- rasa/core/channels/inspector/src/App.tsx +53 -7
- rasa/core/channels/inspector/src/components/Chat.tsx +3 -2
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +1 -1
- rasa/core/channels/inspector/src/components/LatencyDisplay.tsx +268 -0
- rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +6 -2
- rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +8 -3
- rasa/core/channels/inspector/src/types.ts +8 -0
- rasa/core/channels/inspector/yarn.lock +12 -12
- rasa/core/channels/studio_chat.py +119 -34
- rasa/core/channels/voice_ready/twilio_voice.py +1 -1
- rasa/core/channels/voice_stream/asr/asr_engine.py +5 -1
- rasa/core/channels/voice_stream/asr/deepgram.py +5 -0
- rasa/core/channels/voice_stream/audiocodes.py +16 -8
- rasa/core/channels/voice_stream/browser_audio.py +39 -4
- rasa/core/channels/voice_stream/call_state.py +13 -2
- rasa/core/channels/voice_stream/genesys.py +16 -13
- rasa/core/channels/voice_stream/jambonz.py +14 -12
- rasa/core/channels/voice_stream/twilio_media_streams.py +14 -13
- rasa/core/channels/voice_stream/util.py +11 -1
- rasa/core/channels/voice_stream/voice_channel.py +108 -29
- rasa/core/nlg/callback.py +1 -1
- rasa/core/nlg/contextual_response_rephraser.py +19 -9
- rasa/core/nlg/generator.py +21 -5
- rasa/core/nlg/response.py +43 -6
- rasa/core/nlg/translate.py +8 -0
- rasa/core/policies/enterprise_search_policy.py +16 -21
- rasa/dialogue_understanding/commands/correct_slots_command.py +38 -10
- rasa/dialogue_understanding/generator/command_generator.py +5 -5
- rasa/dialogue_understanding/generator/command_parser.py +9 -13
- rasa/dialogue_understanding/processor/command_processor.py +149 -55
- rasa/dialogue_understanding/stack/utils.py +13 -3
- rasa/dialogue_understanding_test/du_test_schema.yml +3 -3
- rasa/dialogue_understanding_test/validation.py +9 -10
- rasa/e2e_test/e2e_config.py +18 -11
- rasa/e2e_test/e2e_test_schema.yml +3 -3
- rasa/e2e_test/utils/validation.py +17 -19
- rasa/engine/validation.py +86 -91
- rasa/exceptions.py +26 -1
- rasa/model_manager/model_api.py +2 -2
- rasa/model_manager/socket_bridge.py +8 -2
- rasa/shared/providers/_configs/default_litellm_client_config.py +3 -7
- rasa/shared/utils/cli.py +2 -0
- rasa/shared/utils/common.py +2 -1
- rasa/shared/utils/health_check/health_check.py +10 -14
- rasa/studio/upload.py +6 -2
- rasa/studio/utils.py +33 -22
- rasa/telemetry.py +95 -22
- rasa/utils/licensing.py +21 -10
- rasa/utils/log_utils.py +1 -1
- rasa/utils/tensorflow/transformer.py +3 -3
- rasa/validator.py +7 -5
- rasa/version.py +1 -1
- {rasa_pro-3.13.1a19.dist-info → rasa_pro-3.13.1a20.dist-info}/METADATA +7 -7
- {rasa_pro-3.13.1a19.dist-info → rasa_pro-3.13.1a20.dist-info}/RECORD +242 -205
- rasa/builder/constants.py +0 -4
- rasa/builder/copilot-llm-structured-output-response-schema.json +0 -69
- rasa/builder/copilot.py +0 -233
- rasa/builder/copilot_system_prompt.jinja2 +0 -245
- rasa/builder/create_openai_vector_store.py +0 -228
- rasa/builder/llm_context.py +0 -81
- rasa/cli/project_templates/finance/data/nlu.yml +0 -29
- rasa/cli/project_templates/finance/data/patterns/pattern_search.yml +0 -5
- rasa/cli/project_templates/finance/domain/default_flows.yml +0 -33
- rasa/cli/project_templates/finance/prompts/command-generator.jinja2 +0 -57
- rasa/cli/project_templates/finance/tests/conversation_repair/cancellations.yml +0 -12
- rasa/cli/project_templates/finance/tests/conversation_repair/cannot_handle.yml +0 -7
- rasa/cli/project_templates/finance/tests/conversation_repair/chitchat.yml +0 -7
- rasa/cli/project_templates/finance/tests/conversation_repair/clarification.yml +0 -9
- rasa/cli/project_templates/finance/tests/conversation_repair/completion.yml +0 -18
- rasa/cli/project_templates/finance/tests/conversation_repair/corrections.yml +0 -17
- rasa/cli/project_templates/finance/tests/conversation_repair/digressions.yml +0 -32
- rasa/cli/project_templates/finance/tests/conversation_repair/human_handoff.yml +0 -21
- rasa/cli/project_templates/finance/tests/conversation_repair/skipping_collect_steps.yml +0 -16
- rasa/cli/project_templates/finance/tests/demo_scripts/main.yml +0 -16
- rasa/cli/project_templates/finance/tests/happy_paths/balance_verification.yml +0 -15
- rasa/cli/project_templates/finance/tests/happy_paths/banking_questions.yml +0 -12
- rasa/cli/project_templates/finance/tests/happy_paths/card_blocking.yml +0 -52
- rasa/cli/project_templates/finance/tests/happy_paths/money_transfer.yml +0 -136
- rasa/cli/project_templates/finance/tests/happy_paths/payee_management.yml +0 -27
- rasa/cli/project_templates/finance/tests/happy_paths/user_greeted.yml +0 -5
- rasa/cli/project_templates/plain/config.yml +0 -17
- rasa/cli/project_templates/plain/data/patterns/pattern_session_start.yml +0 -7
- rasa/cli/project_templates/plain/domain.yml +0 -5
- rasa/core/channels/inspector/dist/assets/channel-f1efda17.js +0 -1
- rasa/core/channels/inspector/dist/assets/clone-fdf164e2.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-7d7a1629.js +0 -1
- rasa/shared/importers/static.py +0 -63
- /rasa/{cli/project_templates/plain/actions → builder/copilot}/__init__.py +0 -0
- /rasa/builder/{inkeep-rag-response-schema.json → document_retrieval/inkeep-rag-response-schema.json} +0 -0
- /rasa/cli/project_templates/finance/actions/{action_process_immediate_payment.py → transfers/action_process_immediate_payment.py} +0 -0
- /rasa/cli/project_templates/finance/actions/{action_schedule_payment.py → transfers/action_schedule_payment.py} +0 -0
- /rasa/cli/project_templates/finance/actions/{action_validate_payment_date.py → transfers/action_validate_payment_date.py} +0 -0
- /rasa/cli/project_templates/finance/data/{flows → cards}/block_card.yml +0 -0
- /rasa/cli/project_templates/finance/data/{flows → cards}/select_card.yml +0 -0
- /rasa/cli/project_templates/finance/data/{source → system/source}/accounts.json +0 -0
- /rasa/cli/project_templates/finance/data/{source → system/source}/advisors.json +0 -0
- /rasa/cli/project_templates/finance/data/{source → system/source}/appointments.json +0 -0
- /rasa/cli/project_templates/finance/data/{source → system/source}/branches.json +0 -0
- /rasa/cli/project_templates/finance/data/{source → system/source}/cards.json +0 -0
- /rasa/cli/project_templates/finance/data/{source → system/source}/payees.json +0 -0
- /rasa/cli/project_templates/finance/data/{source → system/source}/transactions.json +0 -0
- /rasa/cli/project_templates/finance/data/{source → system/source}/users.json +0 -0
- /rasa/cli/project_templates/finance/data/{flows → transfers}/add_payee.yml +0 -0
- /rasa/cli/project_templates/finance/data/{flows → transfers}/list_payees.yml +0 -0
- /rasa/cli/project_templates/finance/data/{flows → transfers}/remove_payee.yml +0 -0
- /rasa/cli/project_templates/finance/data/{flows → transfers}/transfer_money.yml +0 -0
- /rasa/cli/project_templates/finance/domain/{block_card.yml → cards/block_card.yml} +0 -0
- /rasa/cli/project_templates/finance/domain/{select_card.yml → cards/select_card.yml} +0 -0
- /rasa/cli/project_templates/finance/domain/{add_payee.yml → transfers/add_payee.yml} +0 -0
- /rasa/cli/project_templates/finance/domain/{list_payees.yml → transfers/list_payees.yml} +0 -0
- /rasa/cli/project_templates/finance/domain/{remove_payee.yml → transfers/remove_payee.yml} +0 -0
- /rasa/cli/project_templates/finance/domain/{transfer_money.yml → transfers/transfer_money.yml} +0 -0
- {rasa_pro-3.13.1a19.dist-info → rasa_pro-3.13.1a20.dist-info}/NOTICE +0 -0
- {rasa_pro-3.13.1a19.dist-info → rasa_pro-3.13.1a20.dist-info}/WHEEL +0 -0
- {rasa_pro-3.13.1a19.dist-info → rasa_pro-3.13.1a20.dist-info}/entry_points.txt +0 -0
rasa/builder/models.py
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"""Pydantic models for request/response validation."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
-
from
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from typing import Any, Dict, List, Literal, Optional
|
|
5
6
|
|
|
6
7
|
import structlog
|
|
7
|
-
from pydantic import BaseModel, Field,
|
|
8
|
+
from pydantic import BaseModel, Field, validator
|
|
8
9
|
|
|
9
10
|
from rasa.cli.scaffold import ProjectTemplateName
|
|
10
|
-
from rasa.shared.core.trackers import DialogueStateTracker
|
|
11
11
|
|
|
12
12
|
structlogger = structlog.get_logger()
|
|
13
13
|
|
|
@@ -45,150 +45,6 @@ class TemplateRequest(BaseModel):
|
|
|
45
45
|
return v
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
class BaseContent(BaseModel):
|
|
49
|
-
type: str
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
class TextContent(BaseContent):
|
|
53
|
-
type: Literal["text"]
|
|
54
|
-
text: str
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
class LinkContent(BaseContent):
|
|
58
|
-
type: Literal["link"]
|
|
59
|
-
text: str # This holds the URL
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
class CodeContent(BaseContent):
|
|
63
|
-
type: Literal["code"]
|
|
64
|
-
text: str
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
class FileContent(BaseContent):
|
|
68
|
-
type: Literal["file"]
|
|
69
|
-
file_path: str
|
|
70
|
-
file_content: str
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
class EventContent(BaseModel):
|
|
74
|
-
type: Literal["event"]
|
|
75
|
-
event: str = Field(..., description="The event's type_name")
|
|
76
|
-
|
|
77
|
-
event_data: Dict[str, Any] = Field(
|
|
78
|
-
default_factory=dict,
|
|
79
|
-
description="Contains event-specific data fields."
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
@model_validator(mode="before")
|
|
83
|
-
@classmethod
|
|
84
|
-
def _collect_event_data(cls, data: Dict[str, Any]) -> Dict[str, Any]:
|
|
85
|
-
generic = {"type", "event"}
|
|
86
|
-
data["event_data"] = {
|
|
87
|
-
key: data.pop(key) for key in list(data.keys()) if key not in generic
|
|
88
|
-
}
|
|
89
|
-
return data
|
|
90
|
-
|
|
91
|
-
class Config:
|
|
92
|
-
extra = "forbid"
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
class CopilotChatMessage(BaseModel):
|
|
96
|
-
"""Model for a single chat messages between the user and the copilot."""
|
|
97
|
-
|
|
98
|
-
role: str = Field(..., pattern="^(user|copilot)$")
|
|
99
|
-
content: List[
|
|
100
|
-
Union[TextContent, LinkContent, CodeContent, FileContent, EventContent]
|
|
101
|
-
] = Field(
|
|
102
|
-
...,
|
|
103
|
-
description=(
|
|
104
|
-
"The content of the message. "
|
|
105
|
-
"The content is expected to be a list of content blocks. "
|
|
106
|
-
"The content blocks are expected to be one of the following types: "
|
|
107
|
-
"text, link, code, or file."
|
|
108
|
-
),
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
@classmethod
|
|
112
|
-
def from_llm_response(cls, llm_response: Dict[str, Any]) -> "CopilotChatMessage":
|
|
113
|
-
"""Create a CopilotChatMessage from an LLM response (role: copilot)."""
|
|
114
|
-
parsed_content = []
|
|
115
|
-
block_type_to_content_class = {
|
|
116
|
-
"text": TextContent,
|
|
117
|
-
"link": LinkContent,
|
|
118
|
-
"code": CodeContent,
|
|
119
|
-
"file": FileContent,
|
|
120
|
-
"event": EventContent,
|
|
121
|
-
}
|
|
122
|
-
for block in llm_response.get("content_blocks", []):
|
|
123
|
-
block_type = block.get("type")
|
|
124
|
-
if block_type in block_type_to_content_class.keys():
|
|
125
|
-
parsed_content.append(block_type_to_content_class[block_type](**block))
|
|
126
|
-
else:
|
|
127
|
-
structlogger.error(
|
|
128
|
-
"copilot_chat_message.from_llm_response.unknown_content_block_type",
|
|
129
|
-
event_info=f"Unknown content block type: `{block_type}`",
|
|
130
|
-
block_type=block_type,
|
|
131
|
-
block=block,
|
|
132
|
-
llm_response=llm_response,
|
|
133
|
-
)
|
|
134
|
-
continue
|
|
135
|
-
|
|
136
|
-
return cls(role="copilot", content=parsed_content)
|
|
137
|
-
|
|
138
|
-
def get_text_content(self) -> str:
|
|
139
|
-
"""Concatenate all 'text' content blocks into a single string."""
|
|
140
|
-
return "\n".join(
|
|
141
|
-
content_block.text
|
|
142
|
-
for content_block in self.content
|
|
143
|
-
if isinstance(content_block, TextContent)
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
def to_openai_format(self) -> Dict[str, Any]:
|
|
147
|
-
"""Convert to OpenAI message format for API calls."""
|
|
148
|
-
role = "user" if self.role == "user" else "assistant"
|
|
149
|
-
|
|
150
|
-
if self.role == "user":
|
|
151
|
-
content = self.get_text_content()
|
|
152
|
-
else:
|
|
153
|
-
content = [block.model_dump() for block in self.content]
|
|
154
|
-
content = json.dumps(content)
|
|
155
|
-
|
|
156
|
-
return {"role": role, "content": content}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
class CopilotRequest(BaseModel):
|
|
160
|
-
"""Request model for the copilot endpoint."""
|
|
161
|
-
|
|
162
|
-
copilot_chat_history: List[CopilotChatMessage] = Field(
|
|
163
|
-
...,
|
|
164
|
-
description=(
|
|
165
|
-
"The chat history between the user and the copilot. "
|
|
166
|
-
"Used to generate a new response based on the previous conversation."
|
|
167
|
-
),
|
|
168
|
-
)
|
|
169
|
-
session_id: str = Field(
|
|
170
|
-
...,
|
|
171
|
-
description=(
|
|
172
|
-
"The session ID of chat session with the assistant. "
|
|
173
|
-
"Used to fetch the conversation from the tracker."
|
|
174
|
-
),
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
class CopilotContext(BaseModel):
|
|
179
|
-
"""Model containing the context used by the copilot to generate a response."""
|
|
180
|
-
|
|
181
|
-
tracker: Optional[DialogueStateTracker] = Field(None)
|
|
182
|
-
assistant_logs: str = Field("")
|
|
183
|
-
assistant_files: Dict[str, str] = Field({})
|
|
184
|
-
copilot_chat_history: List[CopilotChatMessage] = Field([])
|
|
185
|
-
|
|
186
|
-
class Config:
|
|
187
|
-
"""Config for LLMBuilderContext."""
|
|
188
|
-
|
|
189
|
-
arbitrary_types_allowed = True
|
|
190
|
-
|
|
191
|
-
|
|
192
48
|
class BotDataUpdateRequest(BaseModel):
|
|
193
49
|
"""Request model for bot data updates."""
|
|
194
50
|
|
|
@@ -202,67 +58,101 @@ class BotDataUpdateRequest(BaseModel):
|
|
|
202
58
|
allow_population_by_field_name = True
|
|
203
59
|
|
|
204
60
|
|
|
205
|
-
class
|
|
206
|
-
"""
|
|
61
|
+
class BotData(BaseModel):
|
|
62
|
+
"""Data of a running assistant."""
|
|
207
63
|
|
|
208
|
-
|
|
64
|
+
domain: Dict[str, Any] = Field(..., description="The domain of the assistant.")
|
|
65
|
+
flows: Dict[str, Any] = Field(..., description="The flows of the assistant.")
|
|
209
66
|
|
|
210
67
|
|
|
211
|
-
class
|
|
212
|
-
"""
|
|
68
|
+
class AssistantInfo(BaseModel):
|
|
69
|
+
"""Basic information about the loaded assistant."""
|
|
213
70
|
|
|
214
|
-
|
|
215
|
-
|
|
71
|
+
assistant_id: Optional[str] = Field(
|
|
72
|
+
None,
|
|
73
|
+
description=(
|
|
74
|
+
"Assistant identifier coming from `assistant_id` in the model "
|
|
75
|
+
"metadata (config.yml)."
|
|
76
|
+
),
|
|
77
|
+
)
|
|
216
78
|
|
|
217
79
|
|
|
218
|
-
class
|
|
219
|
-
"""
|
|
80
|
+
class ApiErrorResponse(BaseModel):
|
|
81
|
+
"""API error response model."""
|
|
220
82
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
83
|
+
status: Literal["error"] = "error"
|
|
84
|
+
error: str = Field(...)
|
|
85
|
+
details: Optional[Dict[str, Any]] = Field(None)
|
|
224
86
|
|
|
225
87
|
|
|
226
|
-
class
|
|
227
|
-
|
|
88
|
+
class ServerSentEventType(str, Enum):
|
|
89
|
+
progress = "progress"
|
|
90
|
+
error = "error"
|
|
91
|
+
_EOF = "_EOF"
|
|
228
92
|
|
|
229
|
-
type: Literal["file"] = "file"
|
|
230
|
-
file: str = Field(...)
|
|
231
|
-
content: str = Field(...)
|
|
232
93
|
|
|
94
|
+
class ServerSentEvent(BaseModel):
|
|
95
|
+
"""Generic Server-Sent Event payload."""
|
|
233
96
|
|
|
234
|
-
|
|
235
|
-
|
|
97
|
+
event: str = Field(..., description="SSE event name / type")
|
|
98
|
+
data: Dict[str, Any] = Field(
|
|
99
|
+
default_factory=dict,
|
|
100
|
+
description="Arbitrary JSON-serializable payload",
|
|
101
|
+
)
|
|
236
102
|
|
|
237
|
-
|
|
238
|
-
|
|
103
|
+
@classmethod
|
|
104
|
+
def build(cls, event: str, data: Any) -> "ServerSentEvent":
|
|
105
|
+
"""General-purpose constructor.
|
|
239
106
|
|
|
107
|
+
Args:
|
|
108
|
+
event: The event name (e.g. "progress", "error").
|
|
109
|
+
data: Arbitrary key-value pairs to include in the payload.
|
|
240
110
|
|
|
241
|
-
|
|
242
|
-
|
|
111
|
+
Returns:
|
|
112
|
+
A ServerSentEvent instance with the specified event and data.
|
|
113
|
+
"""
|
|
114
|
+
return cls(event=event, data=data)
|
|
243
115
|
|
|
244
|
-
|
|
116
|
+
@classmethod
|
|
117
|
+
def eof(cls) -> "ServerSentEvent":
|
|
118
|
+
"""Helper that returns the special end-of-stream marker."""
|
|
119
|
+
return cls(event=ServerSentEventType._EOF.value, data={})
|
|
245
120
|
|
|
121
|
+
def format(self) -> str:
|
|
122
|
+
"""Return the text representation used by SSE protocols."""
|
|
123
|
+
return (
|
|
124
|
+
f"event: {self.event}\n"
|
|
125
|
+
f"data: {json.dumps(self.data, separators=(', ', ': '))}\n\n"
|
|
126
|
+
)
|
|
246
127
|
|
|
247
|
-
class ApiErrorResponse(BaseModel):
|
|
248
|
-
"""API error response model."""
|
|
249
128
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
details: Optional[Dict[str, Any]] = Field(None)
|
|
129
|
+
class JobStatusEvent(ServerSentEvent):
|
|
130
|
+
"""Job status event with special handling for progress and error states."""
|
|
253
131
|
|
|
132
|
+
@classmethod
|
|
133
|
+
def from_status(
|
|
134
|
+
cls,
|
|
135
|
+
status: str,
|
|
136
|
+
message: Optional[str] = None,
|
|
137
|
+
) -> "JobStatusEvent":
|
|
138
|
+
"""Factory for job-status events.
|
|
254
139
|
|
|
255
|
-
|
|
256
|
-
|
|
140
|
+
Args:
|
|
141
|
+
status: The job status (e.g. "training", "train_success").
|
|
142
|
+
message: Optional error message for error events.
|
|
257
143
|
|
|
258
|
-
|
|
259
|
-
|
|
144
|
+
Returns:
|
|
145
|
+
A JobStatusEvent instance with the appropriate event type and data.
|
|
146
|
+
"""
|
|
147
|
+
event_type = (
|
|
148
|
+
ServerSentEventType.error if message else ServerSentEventType.progress
|
|
149
|
+
)
|
|
260
150
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
151
|
+
payload: Dict[str, Any] = {"status": status}
|
|
152
|
+
if message:
|
|
153
|
+
payload["message"] = message
|
|
264
154
|
|
|
265
|
-
return
|
|
155
|
+
return cls(event=event_type.value, data=payload)
|
|
266
156
|
|
|
267
157
|
|
|
268
158
|
class ValidationResult(BaseModel):
|
|
@@ -284,57 +174,24 @@ class TrainingResult(BaseModel):
|
|
|
284
174
|
BotFiles = Dict[str, Optional[str]]
|
|
285
175
|
|
|
286
176
|
|
|
287
|
-
class
|
|
288
|
-
|
|
177
|
+
class JobStatus(str, Enum):
|
|
178
|
+
received = "received"
|
|
179
|
+
done = "done"
|
|
180
|
+
error = "error"
|
|
289
181
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
metadata: Optional[Dict[str, Any]] = Field(None)
|
|
182
|
+
generating = "generating"
|
|
183
|
+
generation_success = "generation_success"
|
|
184
|
+
generation_error = "generation_error"
|
|
294
185
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
186
|
+
training = "training"
|
|
187
|
+
train_success = "train_success"
|
|
188
|
+
train_error = "train_error"
|
|
298
189
|
|
|
299
|
-
|
|
300
|
-
|
|
190
|
+
validating = "validating"
|
|
191
|
+
validation_success = "validation_success"
|
|
192
|
+
validation_error = "validation_error"
|
|
301
193
|
|
|
302
|
-
Returns:
|
|
303
|
-
Document object with extracted content and metadata
|
|
304
|
-
"""
|
|
305
|
-
source = rag_item.get("source", {})
|
|
306
|
-
text_content = cls._extract_text_from_source(source)
|
|
307
|
-
|
|
308
|
-
return cls(
|
|
309
|
-
content=text_content.strip() if text_content else "",
|
|
310
|
-
url=rag_item.get("url"),
|
|
311
|
-
title=rag_item.get("title"),
|
|
312
|
-
metadata={
|
|
313
|
-
"type": rag_item.get("type"),
|
|
314
|
-
"record_type": rag_item.get("record_type"),
|
|
315
|
-
"context": rag_item.get("context"),
|
|
316
|
-
"media_type": source.get("media_type"),
|
|
317
|
-
},
|
|
318
|
-
)
|
|
319
194
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
Args:
|
|
325
|
-
source: Source object from InKeep RAG response
|
|
326
|
-
|
|
327
|
-
Returns:
|
|
328
|
-
Extracted text content
|
|
329
|
-
"""
|
|
330
|
-
# Try to extract from content array first
|
|
331
|
-
if "content" in source:
|
|
332
|
-
text_parts = []
|
|
333
|
-
for content_item in source["content"]:
|
|
334
|
-
if content_item.get("type") == "text" and content_item.get("text"):
|
|
335
|
-
text_parts.append(content_item["text"])
|
|
336
|
-
if text_parts:
|
|
337
|
-
return "\n".join(text_parts)
|
|
338
|
-
|
|
339
|
-
# Fallback to source data
|
|
340
|
-
return source.get("data", "")
|
|
195
|
+
class JobCreateResponse(BaseModel):
|
|
196
|
+
job_id: str = Field(...)
|
|
197
|
+
status: JobStatus = JobStatus.received
|
|
@@ -3,15 +3,21 @@
|
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
5
|
import shutil
|
|
6
|
+
import tarfile
|
|
7
|
+
import tempfile
|
|
6
8
|
from pathlib import Path
|
|
7
9
|
from textwrap import dedent
|
|
8
10
|
from typing import Any, Dict, List, Optional
|
|
9
11
|
|
|
12
|
+
import aiofiles
|
|
13
|
+
import aiohttp
|
|
10
14
|
import structlog
|
|
11
15
|
|
|
16
|
+
import rasa.version
|
|
12
17
|
from rasa.builder import config
|
|
13
18
|
from rasa.builder.exceptions import ProjectGenerationError, ValidationError
|
|
14
19
|
from rasa.builder.llm_service import get_skill_generation_messages, llm_service
|
|
20
|
+
from rasa.builder.logging_utils import capture_exception_with_context
|
|
15
21
|
from rasa.builder.models import BotFiles
|
|
16
22
|
from rasa.builder.validation_service import validate_project
|
|
17
23
|
from rasa.cli.scaffold import ProjectTemplateName, create_initial_project
|
|
@@ -35,10 +41,11 @@ class ProjectGenerator:
|
|
|
35
41
|
self.project_folder = Path(project_folder)
|
|
36
42
|
self.project_folder.mkdir(parents=True, exist_ok=True)
|
|
37
43
|
|
|
38
|
-
def init_from_template(self, template: ProjectTemplateName) -> None:
|
|
44
|
+
async def init_from_template(self, template: ProjectTemplateName) -> None:
|
|
39
45
|
"""Create the initial project files."""
|
|
40
46
|
self.cleanup()
|
|
41
47
|
create_initial_project(self.project_folder.as_posix(), template)
|
|
48
|
+
await download_cache_for_template(template, self.project_folder.as_posix())
|
|
42
49
|
|
|
43
50
|
async def generate_project_with_retries(
|
|
44
51
|
self,
|
|
@@ -63,7 +70,7 @@ class ProjectGenerator:
|
|
|
63
70
|
if max_retries is None:
|
|
64
71
|
max_retries = config.MAX_RETRIES
|
|
65
72
|
|
|
66
|
-
self.init_from_template(template)
|
|
73
|
+
await self.init_from_template(template)
|
|
67
74
|
|
|
68
75
|
project_data = self._get_bot_data_for_llm()
|
|
69
76
|
|
|
@@ -168,11 +175,9 @@ class ProjectGenerator:
|
|
|
168
175
|
domain_path = self.project_folder / "domain"
|
|
169
176
|
|
|
170
177
|
return TrainingDataImporter.load_from_config(
|
|
171
|
-
config_path=self.project_folder / "config.yml",
|
|
172
|
-
domain_path=domain_path,
|
|
173
|
-
training_data_paths=[
|
|
174
|
-
self.project_folder / "data",
|
|
175
|
-
],
|
|
178
|
+
config_path=str(self.project_folder / "config.yml"),
|
|
179
|
+
domain_path=str(domain_path),
|
|
180
|
+
training_data_paths=[str(self.project_folder / "data")],
|
|
176
181
|
args={},
|
|
177
182
|
)
|
|
178
183
|
|
|
@@ -280,3 +285,82 @@ class ProjectGenerator:
|
|
|
280
285
|
error=str(e),
|
|
281
286
|
file_path=file_path,
|
|
282
287
|
)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
CACHE_BUCKET_URL = "https://trained-templates.s3.us-east-1.amazonaws.com"
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
async def download_cache_for_template(
|
|
294
|
+
template: ProjectTemplateName, project_folder: str
|
|
295
|
+
) -> None:
|
|
296
|
+
# get a temp path for the cache file download
|
|
297
|
+
temporary_cache_file = tempfile.NamedTemporaryFile(suffix=".tar.gz", delete=False)
|
|
298
|
+
|
|
299
|
+
try:
|
|
300
|
+
url = f"{CACHE_BUCKET_URL}/{rasa.version.__version__}-{template.value}.tar.gz"
|
|
301
|
+
async with aiohttp.ClientSession() as session:
|
|
302
|
+
async with session.get(url) as response:
|
|
303
|
+
response.raise_for_status()
|
|
304
|
+
async with aiofiles.open(temporary_cache_file.name, "wb") as f:
|
|
305
|
+
async for chunk in response.content.iter_chunked(1024 * 1024):
|
|
306
|
+
await f.write(chunk)
|
|
307
|
+
|
|
308
|
+
# extract the cache to the project folder
|
|
309
|
+
with tarfile.open(temporary_cache_file.name, "r:gz") as tar:
|
|
310
|
+
tar.extractall(path=project_folder)
|
|
311
|
+
|
|
312
|
+
structlogger.info(
|
|
313
|
+
"project_generator.download_cache_for_template.success",
|
|
314
|
+
template=template,
|
|
315
|
+
event_info=(
|
|
316
|
+
f"Downloaded cache for template, extracted to {project_folder}."
|
|
317
|
+
),
|
|
318
|
+
)
|
|
319
|
+
except aiohttp.ClientResponseError as e:
|
|
320
|
+
if e.status == 403:
|
|
321
|
+
structlogger.debug(
|
|
322
|
+
"project_generator.download_cache_for_template.no_cache_found",
|
|
323
|
+
template=template,
|
|
324
|
+
event_info=("No cache found for template, continuing without it."),
|
|
325
|
+
)
|
|
326
|
+
else:
|
|
327
|
+
structlogger.debug(
|
|
328
|
+
"project_generator.download_cache_for_template.response_error",
|
|
329
|
+
error=str(e),
|
|
330
|
+
status=e.status,
|
|
331
|
+
template=template,
|
|
332
|
+
event_info=(
|
|
333
|
+
"Failed to download cache for template, continuing without it."
|
|
334
|
+
),
|
|
335
|
+
)
|
|
336
|
+
capture_exception_with_context(
|
|
337
|
+
e,
|
|
338
|
+
"project_generator.download_cache_for_template.response_error",
|
|
339
|
+
tags={"template": template.value, "status": str(e.status)},
|
|
340
|
+
)
|
|
341
|
+
except Exception as exc:
|
|
342
|
+
structlogger.debug(
|
|
343
|
+
"project_generator.download_cache_for_template.unexpected_error",
|
|
344
|
+
error=str(exc),
|
|
345
|
+
template=template,
|
|
346
|
+
event_info=(
|
|
347
|
+
"Unexpected error when downloading cache for template, "
|
|
348
|
+
"continuing without it."
|
|
349
|
+
),
|
|
350
|
+
)
|
|
351
|
+
capture_exception_with_context(
|
|
352
|
+
exc,
|
|
353
|
+
"project_generator.download_cache_for_template.unexpected_error",
|
|
354
|
+
tags={"template": template.value},
|
|
355
|
+
)
|
|
356
|
+
finally:
|
|
357
|
+
# Clean up the temporary file
|
|
358
|
+
try:
|
|
359
|
+
Path(temporary_cache_file.name).unlink(missing_ok=True)
|
|
360
|
+
except Exception as exc:
|
|
361
|
+
structlogger.debug(
|
|
362
|
+
"project_generator.download_cache_for_template.cleanup_error",
|
|
363
|
+
error=str(exc),
|
|
364
|
+
template=template,
|
|
365
|
+
event_info=("Failed to cleanup cache for template, ignoring."),
|
|
366
|
+
)
|
rasa/builder/scrape_rasa_docs.py
CHANGED