rasa-pro 3.12.0.dev1__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.
- README.md +41 -0
- rasa/__init__.py +9 -0
- rasa/__main__.py +177 -0
- rasa/anonymization/__init__.py +2 -0
- rasa/anonymization/anonymisation_rule_yaml_reader.py +91 -0
- rasa/anonymization/anonymization_pipeline.py +286 -0
- rasa/anonymization/anonymization_rule_executor.py +260 -0
- rasa/anonymization/anonymization_rule_orchestrator.py +120 -0
- rasa/anonymization/schemas/config.yml +47 -0
- rasa/anonymization/utils.py +118 -0
- rasa/api.py +160 -0
- rasa/cli/__init__.py +5 -0
- rasa/cli/arguments/__init__.py +0 -0
- rasa/cli/arguments/data.py +106 -0
- rasa/cli/arguments/default_arguments.py +207 -0
- rasa/cli/arguments/evaluate.py +65 -0
- rasa/cli/arguments/export.py +51 -0
- rasa/cli/arguments/interactive.py +74 -0
- rasa/cli/arguments/run.py +219 -0
- rasa/cli/arguments/shell.py +17 -0
- rasa/cli/arguments/test.py +211 -0
- rasa/cli/arguments/train.py +279 -0
- rasa/cli/arguments/visualize.py +34 -0
- rasa/cli/arguments/x.py +30 -0
- rasa/cli/data.py +354 -0
- rasa/cli/dialogue_understanding_test.py +251 -0
- rasa/cli/e2e_test.py +259 -0
- rasa/cli/evaluate.py +222 -0
- rasa/cli/export.py +250 -0
- rasa/cli/inspect.py +75 -0
- rasa/cli/interactive.py +166 -0
- rasa/cli/license.py +65 -0
- rasa/cli/llm_fine_tuning.py +403 -0
- rasa/cli/markers.py +78 -0
- rasa/cli/project_templates/__init__.py +0 -0
- rasa/cli/project_templates/calm/actions/__init__.py +0 -0
- rasa/cli/project_templates/calm/actions/action_template.py +27 -0
- rasa/cli/project_templates/calm/actions/add_contact.py +30 -0
- rasa/cli/project_templates/calm/actions/db.py +57 -0
- rasa/cli/project_templates/calm/actions/list_contacts.py +22 -0
- rasa/cli/project_templates/calm/actions/remove_contact.py +35 -0
- rasa/cli/project_templates/calm/config.yml +10 -0
- rasa/cli/project_templates/calm/credentials.yml +33 -0
- rasa/cli/project_templates/calm/data/flows/add_contact.yml +31 -0
- rasa/cli/project_templates/calm/data/flows/list_contacts.yml +14 -0
- rasa/cli/project_templates/calm/data/flows/remove_contact.yml +29 -0
- rasa/cli/project_templates/calm/db/contacts.json +10 -0
- rasa/cli/project_templates/calm/domain/add_contact.yml +39 -0
- rasa/cli/project_templates/calm/domain/list_contacts.yml +17 -0
- rasa/cli/project_templates/calm/domain/remove_contact.yml +38 -0
- rasa/cli/project_templates/calm/domain/shared.yml +10 -0
- rasa/cli/project_templates/calm/e2e_tests/cancelations/user_cancels_during_a_correction.yml +16 -0
- rasa/cli/project_templates/calm/e2e_tests/cancelations/user_changes_mind_on_a_whim.yml +7 -0
- rasa/cli/project_templates/calm/e2e_tests/corrections/user_corrects_contact_handle.yml +20 -0
- rasa/cli/project_templates/calm/e2e_tests/corrections/user_corrects_contact_name.yml +19 -0
- rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_adds_contact_to_their_list.yml +15 -0
- rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_lists_contacts.yml +5 -0
- rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_removes_contact.yml +11 -0
- rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_removes_contact_from_list.yml +12 -0
- rasa/cli/project_templates/calm/endpoints.yml +58 -0
- rasa/cli/project_templates/default/actions/__init__.py +0 -0
- rasa/cli/project_templates/default/actions/actions.py +27 -0
- rasa/cli/project_templates/default/config.yml +44 -0
- rasa/cli/project_templates/default/credentials.yml +33 -0
- rasa/cli/project_templates/default/data/nlu.yml +91 -0
- rasa/cli/project_templates/default/data/rules.yml +13 -0
- rasa/cli/project_templates/default/data/stories.yml +30 -0
- rasa/cli/project_templates/default/domain.yml +34 -0
- rasa/cli/project_templates/default/endpoints.yml +42 -0
- rasa/cli/project_templates/default/tests/test_stories.yml +91 -0
- rasa/cli/project_templates/tutorial/actions/__init__.py +0 -0
- rasa/cli/project_templates/tutorial/actions/actions.py +22 -0
- rasa/cli/project_templates/tutorial/config.yml +12 -0
- rasa/cli/project_templates/tutorial/credentials.yml +33 -0
- rasa/cli/project_templates/tutorial/data/flows.yml +8 -0
- rasa/cli/project_templates/tutorial/data/patterns.yml +11 -0
- rasa/cli/project_templates/tutorial/domain.yml +35 -0
- rasa/cli/project_templates/tutorial/endpoints.yml +55 -0
- rasa/cli/run.py +143 -0
- rasa/cli/scaffold.py +273 -0
- rasa/cli/shell.py +141 -0
- rasa/cli/studio/__init__.py +0 -0
- rasa/cli/studio/download.py +62 -0
- rasa/cli/studio/studio.py +296 -0
- rasa/cli/studio/train.py +59 -0
- rasa/cli/studio/upload.py +62 -0
- rasa/cli/telemetry.py +102 -0
- rasa/cli/test.py +280 -0
- rasa/cli/train.py +278 -0
- rasa/cli/utils.py +484 -0
- rasa/cli/visualize.py +40 -0
- rasa/cli/x.py +206 -0
- rasa/constants.py +45 -0
- rasa/core/__init__.py +17 -0
- rasa/core/actions/__init__.py +0 -0
- rasa/core/actions/action.py +1318 -0
- rasa/core/actions/action_clean_stack.py +59 -0
- rasa/core/actions/action_exceptions.py +24 -0
- rasa/core/actions/action_hangup.py +29 -0
- rasa/core/actions/action_repeat_bot_messages.py +89 -0
- rasa/core/actions/action_run_slot_rejections.py +210 -0
- rasa/core/actions/action_trigger_chitchat.py +31 -0
- rasa/core/actions/action_trigger_flow.py +109 -0
- rasa/core/actions/action_trigger_search.py +31 -0
- rasa/core/actions/constants.py +5 -0
- rasa/core/actions/custom_action_executor.py +191 -0
- rasa/core/actions/direct_custom_actions_executor.py +109 -0
- rasa/core/actions/e2e_stub_custom_action_executor.py +72 -0
- rasa/core/actions/forms.py +741 -0
- rasa/core/actions/grpc_custom_action_executor.py +251 -0
- rasa/core/actions/http_custom_action_executor.py +145 -0
- rasa/core/actions/loops.py +114 -0
- rasa/core/actions/two_stage_fallback.py +186 -0
- rasa/core/agent.py +559 -0
- rasa/core/auth_retry_tracker_store.py +122 -0
- rasa/core/brokers/__init__.py +0 -0
- rasa/core/brokers/broker.py +126 -0
- rasa/core/brokers/file.py +58 -0
- rasa/core/brokers/kafka.py +324 -0
- rasa/core/brokers/pika.py +388 -0
- rasa/core/brokers/sql.py +86 -0
- rasa/core/channels/__init__.py +61 -0
- rasa/core/channels/botframework.py +338 -0
- rasa/core/channels/callback.py +84 -0
- rasa/core/channels/channel.py +456 -0
- rasa/core/channels/console.py +241 -0
- rasa/core/channels/development_inspector.py +197 -0
- rasa/core/channels/facebook.py +419 -0
- rasa/core/channels/hangouts.py +329 -0
- rasa/core/channels/inspector/.eslintrc.cjs +25 -0
- rasa/core/channels/inspector/.gitignore +23 -0
- rasa/core/channels/inspector/README.md +54 -0
- rasa/core/channels/inspector/assets/favicon.ico +0 -0
- rasa/core/channels/inspector/assets/rasa-chat.js +2 -0
- rasa/core/channels/inspector/custom.d.ts +3 -0
- rasa/core/channels/inspector/dist/assets/arc-861ddd57.js +1 -0
- rasa/core/channels/inspector/dist/assets/array-9f3ba611.js +1 -0
- rasa/core/channels/inspector/dist/assets/c4Diagram-d0fbc5ce-921f02db.js +10 -0
- rasa/core/channels/inspector/dist/assets/classDiagram-936ed81e-b436c4f8.js +2 -0
- rasa/core/channels/inspector/dist/assets/classDiagram-v2-c3cb15f1-511a23cb.js +2 -0
- rasa/core/channels/inspector/dist/assets/createText-62fc7601-ef476ecd.js +7 -0
- rasa/core/channels/inspector/dist/assets/edges-f2ad444c-f1878e0a.js +4 -0
- rasa/core/channels/inspector/dist/assets/erDiagram-9d236eb7-fac75185.js +51 -0
- rasa/core/channels/inspector/dist/assets/flowDb-1972c806-201c5bbc.js +6 -0
- rasa/core/channels/inspector/dist/assets/flowDiagram-7ea5b25a-f904ae41.js +4 -0
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-b080d6f2.js +1 -0
- rasa/core/channels/inspector/dist/assets/flowchart-elk-definition-abe16c3d-1813da66.js +139 -0
- rasa/core/channels/inspector/dist/assets/ganttDiagram-9b5ea136-872af172.js +266 -0
- rasa/core/channels/inspector/dist/assets/gitGraphDiagram-99d0ae7c-34a0af5a.js +70 -0
- rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-128cfa44.ttf +0 -0
- rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-21dbcb97.woff +0 -0
- rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-222b5e26.svg +329 -0
- rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-9ad89b2a.woff2 +0 -0
- rasa/core/channels/inspector/dist/assets/index-2c4b9a3b-42ba3e3d.js +1 -0
- rasa/core/channels/inspector/dist/assets/index-37817b51.js +1317 -0
- rasa/core/channels/inspector/dist/assets/index-3ee28881.css +1 -0
- rasa/core/channels/inspector/dist/assets/infoDiagram-736b4530-6b731386.js +7 -0
- rasa/core/channels/inspector/dist/assets/init-77b53fdd.js +1 -0
- rasa/core/channels/inspector/dist/assets/journeyDiagram-df861f2b-e8579ac6.js +139 -0
- rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-60c05ee4.woff +0 -0
- rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-8335d9b8.svg +438 -0
- rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-9cc39c75.ttf +0 -0
- rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-ead13ccf.woff2 +0 -0
- rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-16705655.woff2 +0 -0
- rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-5aeb07f9.woff +0 -0
- rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-9c459044.ttf +0 -0
- rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-9e2898a4.svg +435 -0
- rasa/core/channels/inspector/dist/assets/layout-89e6403a.js +1 -0
- rasa/core/channels/inspector/dist/assets/line-dc73d3fc.js +1 -0
- rasa/core/channels/inspector/dist/assets/linear-f5b1d2bc.js +1 -0
- rasa/core/channels/inspector/dist/assets/mindmap-definition-beec6740-82cb74fa.js +109 -0
- rasa/core/channels/inspector/dist/assets/ordinal-ba9b4969.js +1 -0
- rasa/core/channels/inspector/dist/assets/path-53f90ab3.js +1 -0
- rasa/core/channels/inspector/dist/assets/pieDiagram-dbbf0591-bdf5f29b.js +35 -0
- rasa/core/channels/inspector/dist/assets/quadrantDiagram-4d7f4fd6-c7a0cbe4.js +7 -0
- rasa/core/channels/inspector/dist/assets/requirementDiagram-6fc4c22a-7ec5410f.js +52 -0
- rasa/core/channels/inspector/dist/assets/sankeyDiagram-8f13d901-caee5554.js +8 -0
- rasa/core/channels/inspector/dist/assets/sequenceDiagram-b655622a-2935f8db.js +122 -0
- rasa/core/channels/inspector/dist/assets/stateDiagram-59f0c015-8f5d9693.js +1 -0
- rasa/core/channels/inspector/dist/assets/stateDiagram-v2-2b26beab-d565d1de.js +1 -0
- rasa/core/channels/inspector/dist/assets/styles-080da4f6-75ad421d.js +110 -0
- rasa/core/channels/inspector/dist/assets/styles-3dcbcfbf-7e764226.js +159 -0
- rasa/core/channels/inspector/dist/assets/styles-9c745c82-7a4e0e61.js +207 -0
- rasa/core/channels/inspector/dist/assets/svgDrawCommon-4835440b-4019d1bf.js +1 -0
- rasa/core/channels/inspector/dist/assets/timeline-definition-5b62e21b-01ea12df.js +61 -0
- rasa/core/channels/inspector/dist/assets/xychartDiagram-2b33534f-89407137.js +7 -0
- rasa/core/channels/inspector/dist/index.html +42 -0
- rasa/core/channels/inspector/index.html +40 -0
- rasa/core/channels/inspector/jest.config.ts +13 -0
- rasa/core/channels/inspector/package.json +52 -0
- rasa/core/channels/inspector/setupTests.ts +2 -0
- rasa/core/channels/inspector/src/App.tsx +220 -0
- rasa/core/channels/inspector/src/components/Chat.tsx +95 -0
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +108 -0
- rasa/core/channels/inspector/src/components/DialogueInformation.tsx +187 -0
- rasa/core/channels/inspector/src/components/DialogueStack.tsx +136 -0
- rasa/core/channels/inspector/src/components/ExpandIcon.tsx +16 -0
- rasa/core/channels/inspector/src/components/FullscreenButton.tsx +45 -0
- rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +22 -0
- rasa/core/channels/inspector/src/components/NoActiveFlow.tsx +21 -0
- rasa/core/channels/inspector/src/components/RasaLogo.tsx +32 -0
- rasa/core/channels/inspector/src/components/SaraDiagrams.tsx +39 -0
- rasa/core/channels/inspector/src/components/Slots.tsx +91 -0
- rasa/core/channels/inspector/src/components/Welcome.tsx +54 -0
- rasa/core/channels/inspector/src/helpers/audiostream.ts +191 -0
- rasa/core/channels/inspector/src/helpers/formatters.test.ts +392 -0
- rasa/core/channels/inspector/src/helpers/formatters.ts +306 -0
- rasa/core/channels/inspector/src/helpers/utils.ts +127 -0
- rasa/core/channels/inspector/src/main.tsx +13 -0
- rasa/core/channels/inspector/src/theme/Button/Button.ts +29 -0
- rasa/core/channels/inspector/src/theme/Heading/Heading.ts +31 -0
- rasa/core/channels/inspector/src/theme/Input/Input.ts +27 -0
- rasa/core/channels/inspector/src/theme/Link/Link.ts +10 -0
- rasa/core/channels/inspector/src/theme/Modal/Modal.ts +47 -0
- rasa/core/channels/inspector/src/theme/Table/Table.tsx +38 -0
- rasa/core/channels/inspector/src/theme/Tooltip/Tooltip.ts +12 -0
- rasa/core/channels/inspector/src/theme/base/breakpoints.ts +8 -0
- rasa/core/channels/inspector/src/theme/base/colors.ts +88 -0
- rasa/core/channels/inspector/src/theme/base/fonts/fontFaces.css +29 -0
- rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.eot +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.svg +329 -0
- rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.ttf +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.woff +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.woff2 +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.eot +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.svg +438 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.ttf +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.woff +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.woff2 +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.eot +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.svg +435 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.ttf +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.woff +0 -0
- rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.woff2 +0 -0
- rasa/core/channels/inspector/src/theme/base/radii.ts +9 -0
- rasa/core/channels/inspector/src/theme/base/shadows.ts +7 -0
- rasa/core/channels/inspector/src/theme/base/sizes.ts +7 -0
- rasa/core/channels/inspector/src/theme/base/space.ts +15 -0
- rasa/core/channels/inspector/src/theme/base/styles.ts +13 -0
- rasa/core/channels/inspector/src/theme/base/typography.ts +24 -0
- rasa/core/channels/inspector/src/theme/base/zIndices.ts +19 -0
- rasa/core/channels/inspector/src/theme/index.ts +101 -0
- rasa/core/channels/inspector/src/types.ts +84 -0
- rasa/core/channels/inspector/src/vite-env.d.ts +1 -0
- rasa/core/channels/inspector/tests/__mocks__/fileMock.ts +1 -0
- rasa/core/channels/inspector/tests/__mocks__/matchMedia.ts +16 -0
- rasa/core/channels/inspector/tests/__mocks__/styleMock.ts +1 -0
- rasa/core/channels/inspector/tests/renderWithProviders.tsx +14 -0
- rasa/core/channels/inspector/tsconfig.json +26 -0
- rasa/core/channels/inspector/tsconfig.node.json +10 -0
- rasa/core/channels/inspector/vite.config.ts +8 -0
- rasa/core/channels/inspector/yarn.lock +6249 -0
- rasa/core/channels/mattermost.py +229 -0
- rasa/core/channels/rasa_chat.py +126 -0
- rasa/core/channels/rest.py +230 -0
- rasa/core/channels/rocketchat.py +174 -0
- rasa/core/channels/slack.py +620 -0
- rasa/core/channels/socketio.py +302 -0
- rasa/core/channels/telegram.py +298 -0
- rasa/core/channels/twilio.py +169 -0
- rasa/core/channels/vier_cvg.py +374 -0
- rasa/core/channels/voice_ready/__init__.py +0 -0
- rasa/core/channels/voice_ready/audiocodes.py +501 -0
- rasa/core/channels/voice_ready/jambonz.py +121 -0
- rasa/core/channels/voice_ready/jambonz_protocol.py +396 -0
- rasa/core/channels/voice_ready/twilio_voice.py +403 -0
- rasa/core/channels/voice_ready/utils.py +37 -0
- rasa/core/channels/voice_stream/__init__.py +0 -0
- rasa/core/channels/voice_stream/asr/__init__.py +0 -0
- rasa/core/channels/voice_stream/asr/asr_engine.py +89 -0
- rasa/core/channels/voice_stream/asr/asr_event.py +18 -0
- rasa/core/channels/voice_stream/asr/azure.py +130 -0
- rasa/core/channels/voice_stream/asr/deepgram.py +90 -0
- rasa/core/channels/voice_stream/audio_bytes.py +8 -0
- rasa/core/channels/voice_stream/browser_audio.py +107 -0
- rasa/core/channels/voice_stream/call_state.py +23 -0
- rasa/core/channels/voice_stream/tts/__init__.py +0 -0
- rasa/core/channels/voice_stream/tts/azure.py +106 -0
- rasa/core/channels/voice_stream/tts/cartesia.py +118 -0
- rasa/core/channels/voice_stream/tts/tts_cache.py +27 -0
- rasa/core/channels/voice_stream/tts/tts_engine.py +58 -0
- rasa/core/channels/voice_stream/twilio_media_streams.py +173 -0
- rasa/core/channels/voice_stream/util.py +57 -0
- rasa/core/channels/voice_stream/voice_channel.py +427 -0
- rasa/core/channels/webexteams.py +134 -0
- rasa/core/concurrent_lock_store.py +210 -0
- rasa/core/constants.py +112 -0
- rasa/core/evaluation/__init__.py +0 -0
- rasa/core/evaluation/marker.py +267 -0
- rasa/core/evaluation/marker_base.py +923 -0
- rasa/core/evaluation/marker_stats.py +293 -0
- rasa/core/evaluation/marker_tracker_loader.py +103 -0
- rasa/core/exceptions.py +29 -0
- rasa/core/exporter.py +284 -0
- rasa/core/featurizers/__init__.py +0 -0
- rasa/core/featurizers/precomputation.py +410 -0
- rasa/core/featurizers/single_state_featurizer.py +421 -0
- rasa/core/featurizers/tracker_featurizers.py +1262 -0
- rasa/core/http_interpreter.py +89 -0
- rasa/core/information_retrieval/__init__.py +7 -0
- rasa/core/information_retrieval/faiss.py +124 -0
- rasa/core/information_retrieval/information_retrieval.py +137 -0
- rasa/core/information_retrieval/milvus.py +59 -0
- rasa/core/information_retrieval/qdrant.py +96 -0
- rasa/core/jobs.py +63 -0
- rasa/core/lock.py +139 -0
- rasa/core/lock_store.py +343 -0
- rasa/core/migrate.py +403 -0
- rasa/core/nlg/__init__.py +3 -0
- rasa/core/nlg/callback.py +146 -0
- rasa/core/nlg/contextual_response_rephraser.py +320 -0
- rasa/core/nlg/generator.py +230 -0
- rasa/core/nlg/interpolator.py +143 -0
- rasa/core/nlg/response.py +155 -0
- rasa/core/nlg/summarize.py +70 -0
- rasa/core/persistor.py +538 -0
- rasa/core/policies/__init__.py +0 -0
- rasa/core/policies/ensemble.py +329 -0
- rasa/core/policies/enterprise_search_policy.py +905 -0
- rasa/core/policies/enterprise_search_prompt_template.jinja2 +25 -0
- rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +60 -0
- rasa/core/policies/flow_policy.py +205 -0
- rasa/core/policies/flows/__init__.py +0 -0
- rasa/core/policies/flows/flow_exceptions.py +44 -0
- rasa/core/policies/flows/flow_executor.py +754 -0
- rasa/core/policies/flows/flow_step_result.py +43 -0
- rasa/core/policies/intentless_policy.py +1031 -0
- rasa/core/policies/intentless_prompt_template.jinja2 +22 -0
- rasa/core/policies/memoization.py +538 -0
- rasa/core/policies/policy.py +725 -0
- rasa/core/policies/rule_policy.py +1273 -0
- rasa/core/policies/ted_policy.py +2169 -0
- rasa/core/policies/unexpected_intent_policy.py +1022 -0
- rasa/core/processor.py +1465 -0
- rasa/core/run.py +342 -0
- rasa/core/secrets_manager/__init__.py +0 -0
- rasa/core/secrets_manager/constants.py +36 -0
- rasa/core/secrets_manager/endpoints.py +391 -0
- rasa/core/secrets_manager/factory.py +241 -0
- rasa/core/secrets_manager/secret_manager.py +262 -0
- rasa/core/secrets_manager/vault.py +584 -0
- rasa/core/test.py +1335 -0
- rasa/core/tracker_store.py +1703 -0
- rasa/core/train.py +105 -0
- rasa/core/training/__init__.py +89 -0
- rasa/core/training/converters/__init__.py +0 -0
- rasa/core/training/converters/responses_prefix_converter.py +119 -0
- rasa/core/training/interactive.py +1744 -0
- rasa/core/training/story_conflict.py +381 -0
- rasa/core/training/training.py +93 -0
- rasa/core/utils.py +366 -0
- rasa/core/visualize.py +70 -0
- rasa/dialogue_understanding/__init__.py +0 -0
- rasa/dialogue_understanding/coexistence/__init__.py +0 -0
- rasa/dialogue_understanding/coexistence/constants.py +4 -0
- rasa/dialogue_understanding/coexistence/intent_based_router.py +196 -0
- rasa/dialogue_understanding/coexistence/llm_based_router.py +327 -0
- rasa/dialogue_understanding/coexistence/router_template.jinja2 +12 -0
- rasa/dialogue_understanding/commands/__init__.py +61 -0
- rasa/dialogue_understanding/commands/can_not_handle_command.py +70 -0
- rasa/dialogue_understanding/commands/cancel_flow_command.py +125 -0
- rasa/dialogue_understanding/commands/change_flow_command.py +44 -0
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +57 -0
- rasa/dialogue_understanding/commands/clarify_command.py +86 -0
- rasa/dialogue_understanding/commands/command.py +85 -0
- rasa/dialogue_understanding/commands/correct_slots_command.py +297 -0
- rasa/dialogue_understanding/commands/error_command.py +79 -0
- rasa/dialogue_understanding/commands/free_form_answer_command.py +9 -0
- rasa/dialogue_understanding/commands/handle_code_change_command.py +73 -0
- rasa/dialogue_understanding/commands/human_handoff_command.py +66 -0
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +57 -0
- rasa/dialogue_understanding/commands/noop_command.py +54 -0
- rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +60 -0
- rasa/dialogue_understanding/commands/restart_command.py +58 -0
- rasa/dialogue_understanding/commands/session_end_command.py +61 -0
- rasa/dialogue_understanding/commands/session_start_command.py +59 -0
- rasa/dialogue_understanding/commands/set_slot_command.py +160 -0
- rasa/dialogue_understanding/commands/skip_question_command.py +75 -0
- rasa/dialogue_understanding/commands/start_flow_command.py +107 -0
- rasa/dialogue_understanding/commands/user_silence_command.py +59 -0
- rasa/dialogue_understanding/commands/utils.py +45 -0
- rasa/dialogue_understanding/generator/__init__.py +21 -0
- rasa/dialogue_understanding/generator/command_generator.py +464 -0
- rasa/dialogue_understanding/generator/constants.py +27 -0
- rasa/dialogue_understanding/generator/flow_document_template.jinja2 +4 -0
- rasa/dialogue_understanding/generator/flow_retrieval.py +466 -0
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +500 -0
- rasa/dialogue_understanding/generator/llm_command_generator.py +67 -0
- rasa/dialogue_understanding/generator/multi_step/__init__.py +0 -0
- rasa/dialogue_understanding/generator/multi_step/fill_slots_prompt.jinja2 +62 -0
- rasa/dialogue_understanding/generator/multi_step/handle_flows_prompt.jinja2 +38 -0
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +920 -0
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +261 -0
- rasa/dialogue_understanding/generator/single_step/__init__.py +0 -0
- rasa/dialogue_understanding/generator/single_step/command_prompt_template.jinja2 +60 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +486 -0
- rasa/dialogue_understanding/patterns/__init__.py +0 -0
- rasa/dialogue_understanding/patterns/cancel.py +111 -0
- rasa/dialogue_understanding/patterns/cannot_handle.py +43 -0
- rasa/dialogue_understanding/patterns/chitchat.py +37 -0
- rasa/dialogue_understanding/patterns/clarify.py +97 -0
- rasa/dialogue_understanding/patterns/code_change.py +41 -0
- rasa/dialogue_understanding/patterns/collect_information.py +90 -0
- rasa/dialogue_understanding/patterns/completed.py +40 -0
- rasa/dialogue_understanding/patterns/continue_interrupted.py +42 -0
- rasa/dialogue_understanding/patterns/correction.py +278 -0
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +301 -0
- rasa/dialogue_understanding/patterns/human_handoff.py +37 -0
- rasa/dialogue_understanding/patterns/internal_error.py +47 -0
- rasa/dialogue_understanding/patterns/repeat.py +37 -0
- rasa/dialogue_understanding/patterns/restart.py +37 -0
- rasa/dialogue_understanding/patterns/search.py +37 -0
- rasa/dialogue_understanding/patterns/session_start.py +37 -0
- rasa/dialogue_understanding/patterns/skip_question.py +38 -0
- rasa/dialogue_understanding/patterns/user_silence.py +37 -0
- rasa/dialogue_understanding/processor/__init__.py +0 -0
- rasa/dialogue_understanding/processor/command_processor.py +720 -0
- rasa/dialogue_understanding/processor/command_processor_component.py +43 -0
- rasa/dialogue_understanding/stack/__init__.py +0 -0
- rasa/dialogue_understanding/stack/dialogue_stack.py +178 -0
- rasa/dialogue_understanding/stack/frames/__init__.py +19 -0
- rasa/dialogue_understanding/stack/frames/chit_chat_frame.py +27 -0
- rasa/dialogue_understanding/stack/frames/dialogue_stack_frame.py +137 -0
- rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +157 -0
- rasa/dialogue_understanding/stack/frames/pattern_frame.py +10 -0
- rasa/dialogue_understanding/stack/frames/search_frame.py +27 -0
- rasa/dialogue_understanding/stack/utils.py +211 -0
- rasa/dialogue_understanding/utils.py +14 -0
- rasa/dialogue_understanding_test/__init__.py +0 -0
- rasa/dialogue_understanding_test/command_metric_calculation.py +12 -0
- rasa/dialogue_understanding_test/constants.py +17 -0
- rasa/dialogue_understanding_test/du_test_case.py +118 -0
- rasa/dialogue_understanding_test/du_test_result.py +11 -0
- rasa/dialogue_understanding_test/du_test_runner.py +93 -0
- rasa/dialogue_understanding_test/io.py +54 -0
- rasa/dialogue_understanding_test/validation.py +22 -0
- rasa/e2e_test/__init__.py +0 -0
- rasa/e2e_test/aggregate_test_stats_calculator.py +134 -0
- rasa/e2e_test/assertions.py +1345 -0
- rasa/e2e_test/assertions_schema.yml +129 -0
- rasa/e2e_test/constants.py +31 -0
- rasa/e2e_test/e2e_config.py +220 -0
- rasa/e2e_test/e2e_config_schema.yml +26 -0
- rasa/e2e_test/e2e_test_case.py +569 -0
- rasa/e2e_test/e2e_test_converter.py +363 -0
- rasa/e2e_test/e2e_test_converter_prompt.jinja2 +70 -0
- rasa/e2e_test/e2e_test_coverage_report.py +364 -0
- rasa/e2e_test/e2e_test_result.py +54 -0
- rasa/e2e_test/e2e_test_runner.py +1192 -0
- rasa/e2e_test/e2e_test_schema.yml +181 -0
- rasa/e2e_test/pykwalify_extensions.py +39 -0
- rasa/e2e_test/stub_custom_action.py +70 -0
- rasa/e2e_test/utils/__init__.py +0 -0
- rasa/e2e_test/utils/e2e_yaml_utils.py +55 -0
- rasa/e2e_test/utils/io.py +598 -0
- rasa/e2e_test/utils/validation.py +178 -0
- rasa/engine/__init__.py +0 -0
- rasa/engine/caching.py +463 -0
- rasa/engine/constants.py +17 -0
- rasa/engine/exceptions.py +14 -0
- rasa/engine/graph.py +642 -0
- rasa/engine/loader.py +48 -0
- rasa/engine/recipes/__init__.py +0 -0
- rasa/engine/recipes/config_files/default_config.yml +41 -0
- rasa/engine/recipes/default_components.py +97 -0
- rasa/engine/recipes/default_recipe.py +1272 -0
- rasa/engine/recipes/graph_recipe.py +79 -0
- rasa/engine/recipes/recipe.py +93 -0
- rasa/engine/runner/__init__.py +0 -0
- rasa/engine/runner/dask.py +250 -0
- rasa/engine/runner/interface.py +49 -0
- rasa/engine/storage/__init__.py +0 -0
- rasa/engine/storage/local_model_storage.py +244 -0
- rasa/engine/storage/resource.py +110 -0
- rasa/engine/storage/storage.py +199 -0
- rasa/engine/training/__init__.py +0 -0
- rasa/engine/training/components.py +176 -0
- rasa/engine/training/fingerprinting.py +64 -0
- rasa/engine/training/graph_trainer.py +256 -0
- rasa/engine/training/hooks.py +164 -0
- rasa/engine/validation.py +1451 -0
- rasa/env.py +14 -0
- rasa/exceptions.py +69 -0
- rasa/graph_components/__init__.py +0 -0
- rasa/graph_components/converters/__init__.py +0 -0
- rasa/graph_components/converters/nlu_message_converter.py +48 -0
- rasa/graph_components/providers/__init__.py +0 -0
- rasa/graph_components/providers/domain_for_core_training_provider.py +87 -0
- rasa/graph_components/providers/domain_provider.py +71 -0
- rasa/graph_components/providers/flows_provider.py +74 -0
- rasa/graph_components/providers/forms_provider.py +44 -0
- rasa/graph_components/providers/nlu_training_data_provider.py +56 -0
- rasa/graph_components/providers/responses_provider.py +44 -0
- rasa/graph_components/providers/rule_only_provider.py +49 -0
- rasa/graph_components/providers/story_graph_provider.py +96 -0
- rasa/graph_components/providers/training_tracker_provider.py +55 -0
- rasa/graph_components/validators/__init__.py +0 -0
- rasa/graph_components/validators/default_recipe_validator.py +550 -0
- rasa/graph_components/validators/finetuning_validator.py +302 -0
- rasa/hooks.py +111 -0
- rasa/jupyter.py +63 -0
- rasa/llm_fine_tuning/__init__.py +0 -0
- rasa/llm_fine_tuning/annotation_module.py +241 -0
- rasa/llm_fine_tuning/conversations.py +144 -0
- rasa/llm_fine_tuning/llm_data_preparation_module.py +178 -0
- rasa/llm_fine_tuning/paraphrasing/__init__.py +0 -0
- rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +281 -0
- rasa/llm_fine_tuning/paraphrasing/default_rephrase_prompt_template.jina2 +44 -0
- rasa/llm_fine_tuning/paraphrasing/rephrase_validator.py +121 -0
- rasa/llm_fine_tuning/paraphrasing/rephrased_user_message.py +10 -0
- rasa/llm_fine_tuning/paraphrasing_module.py +128 -0
- rasa/llm_fine_tuning/storage.py +174 -0
- rasa/llm_fine_tuning/train_test_split_module.py +441 -0
- rasa/markers/__init__.py +0 -0
- rasa/markers/marker.py +269 -0
- rasa/markers/marker_base.py +828 -0
- rasa/markers/upload.py +74 -0
- rasa/markers/validate.py +21 -0
- rasa/model.py +118 -0
- rasa/model_manager/__init__.py +0 -0
- rasa/model_manager/config.py +40 -0
- rasa/model_manager/model_api.py +559 -0
- rasa/model_manager/runner_service.py +286 -0
- rasa/model_manager/socket_bridge.py +146 -0
- rasa/model_manager/studio_jwt_auth.py +86 -0
- rasa/model_manager/trainer_service.py +325 -0
- rasa/model_manager/utils.py +87 -0
- rasa/model_manager/warm_rasa_process.py +187 -0
- rasa/model_service.py +112 -0
- rasa/model_testing.py +457 -0
- rasa/model_training.py +596 -0
- rasa/nlu/__init__.py +7 -0
- rasa/nlu/classifiers/__init__.py +3 -0
- rasa/nlu/classifiers/classifier.py +5 -0
- rasa/nlu/classifiers/diet_classifier.py +1881 -0
- rasa/nlu/classifiers/fallback_classifier.py +192 -0
- rasa/nlu/classifiers/keyword_intent_classifier.py +188 -0
- rasa/nlu/classifiers/logistic_regression_classifier.py +253 -0
- rasa/nlu/classifiers/mitie_intent_classifier.py +156 -0
- rasa/nlu/classifiers/regex_message_handler.py +56 -0
- rasa/nlu/classifiers/sklearn_intent_classifier.py +330 -0
- rasa/nlu/constants.py +77 -0
- rasa/nlu/convert.py +40 -0
- rasa/nlu/emulators/__init__.py +0 -0
- rasa/nlu/emulators/dialogflow.py +55 -0
- rasa/nlu/emulators/emulator.py +49 -0
- rasa/nlu/emulators/luis.py +86 -0
- rasa/nlu/emulators/no_emulator.py +10 -0
- rasa/nlu/emulators/wit.py +56 -0
- rasa/nlu/extractors/__init__.py +0 -0
- rasa/nlu/extractors/crf_entity_extractor.py +715 -0
- rasa/nlu/extractors/duckling_entity_extractor.py +206 -0
- rasa/nlu/extractors/entity_synonyms.py +178 -0
- rasa/nlu/extractors/extractor.py +470 -0
- rasa/nlu/extractors/mitie_entity_extractor.py +293 -0
- rasa/nlu/extractors/regex_entity_extractor.py +220 -0
- rasa/nlu/extractors/spacy_entity_extractor.py +95 -0
- rasa/nlu/featurizers/__init__.py +0 -0
- rasa/nlu/featurizers/dense_featurizer/__init__.py +0 -0
- rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +445 -0
- rasa/nlu/featurizers/dense_featurizer/dense_featurizer.py +57 -0
- rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +768 -0
- rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +170 -0
- rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +132 -0
- rasa/nlu/featurizers/featurizer.py +89 -0
- rasa/nlu/featurizers/sparse_featurizer/__init__.py +0 -0
- rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +867 -0
- rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +571 -0
- rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +271 -0
- rasa/nlu/featurizers/sparse_featurizer/sparse_featurizer.py +9 -0
- rasa/nlu/model.py +24 -0
- rasa/nlu/run.py +27 -0
- rasa/nlu/selectors/__init__.py +0 -0
- rasa/nlu/selectors/response_selector.py +987 -0
- rasa/nlu/test.py +1940 -0
- rasa/nlu/tokenizers/__init__.py +0 -0
- rasa/nlu/tokenizers/jieba_tokenizer.py +148 -0
- rasa/nlu/tokenizers/mitie_tokenizer.py +75 -0
- rasa/nlu/tokenizers/spacy_tokenizer.py +72 -0
- rasa/nlu/tokenizers/tokenizer.py +239 -0
- rasa/nlu/tokenizers/whitespace_tokenizer.py +95 -0
- rasa/nlu/utils/__init__.py +35 -0
- rasa/nlu/utils/bilou_utils.py +462 -0
- rasa/nlu/utils/hugging_face/__init__.py +0 -0
- rasa/nlu/utils/hugging_face/registry.py +108 -0
- rasa/nlu/utils/hugging_face/transformers_pre_post_processors.py +311 -0
- rasa/nlu/utils/mitie_utils.py +113 -0
- rasa/nlu/utils/pattern_utils.py +168 -0
- rasa/nlu/utils/spacy_utils.py +310 -0
- rasa/plugin.py +90 -0
- rasa/server.py +1588 -0
- rasa/shared/__init__.py +0 -0
- rasa/shared/constants.py +311 -0
- rasa/shared/core/__init__.py +0 -0
- rasa/shared/core/command_payload_reader.py +109 -0
- rasa/shared/core/constants.py +180 -0
- rasa/shared/core/conversation.py +46 -0
- rasa/shared/core/domain.py +2172 -0
- rasa/shared/core/events.py +2559 -0
- rasa/shared/core/flows/__init__.py +7 -0
- rasa/shared/core/flows/flow.py +562 -0
- rasa/shared/core/flows/flow_path.py +84 -0
- rasa/shared/core/flows/flow_step.py +146 -0
- rasa/shared/core/flows/flow_step_links.py +319 -0
- rasa/shared/core/flows/flow_step_sequence.py +70 -0
- rasa/shared/core/flows/flows_list.py +258 -0
- rasa/shared/core/flows/flows_yaml_schema.json +303 -0
- rasa/shared/core/flows/nlu_trigger.py +117 -0
- rasa/shared/core/flows/steps/__init__.py +24 -0
- rasa/shared/core/flows/steps/action.py +56 -0
- rasa/shared/core/flows/steps/call.py +64 -0
- rasa/shared/core/flows/steps/collect.py +112 -0
- rasa/shared/core/flows/steps/constants.py +5 -0
- rasa/shared/core/flows/steps/continuation.py +36 -0
- rasa/shared/core/flows/steps/end.py +22 -0
- rasa/shared/core/flows/steps/internal.py +44 -0
- rasa/shared/core/flows/steps/link.py +51 -0
- rasa/shared/core/flows/steps/no_operation.py +48 -0
- rasa/shared/core/flows/steps/set_slots.py +50 -0
- rasa/shared/core/flows/steps/start.py +30 -0
- rasa/shared/core/flows/utils.py +39 -0
- rasa/shared/core/flows/validation.py +735 -0
- rasa/shared/core/flows/yaml_flows_io.py +405 -0
- rasa/shared/core/generator.py +908 -0
- rasa/shared/core/slot_mappings.py +526 -0
- rasa/shared/core/slots.py +654 -0
- rasa/shared/core/trackers.py +1183 -0
- rasa/shared/core/training_data/__init__.py +0 -0
- rasa/shared/core/training_data/loading.py +89 -0
- rasa/shared/core/training_data/story_reader/__init__.py +0 -0
- rasa/shared/core/training_data/story_reader/story_reader.py +129 -0
- rasa/shared/core/training_data/story_reader/story_step_builder.py +168 -0
- rasa/shared/core/training_data/story_reader/yaml_story_reader.py +888 -0
- rasa/shared/core/training_data/story_writer/__init__.py +0 -0
- rasa/shared/core/training_data/story_writer/story_writer.py +76 -0
- rasa/shared/core/training_data/story_writer/yaml_story_writer.py +444 -0
- rasa/shared/core/training_data/structures.py +858 -0
- rasa/shared/core/training_data/visualization.html +146 -0
- rasa/shared/core/training_data/visualization.py +603 -0
- rasa/shared/data.py +249 -0
- rasa/shared/engine/__init__.py +0 -0
- rasa/shared/engine/caching.py +26 -0
- rasa/shared/exceptions.py +167 -0
- rasa/shared/importers/__init__.py +0 -0
- rasa/shared/importers/importer.py +770 -0
- rasa/shared/importers/multi_project.py +215 -0
- rasa/shared/importers/rasa.py +108 -0
- rasa/shared/importers/remote_importer.py +196 -0
- rasa/shared/importers/utils.py +36 -0
- rasa/shared/nlu/__init__.py +0 -0
- rasa/shared/nlu/constants.py +53 -0
- rasa/shared/nlu/interpreter.py +10 -0
- rasa/shared/nlu/training_data/__init__.py +0 -0
- rasa/shared/nlu/training_data/entities_parser.py +208 -0
- rasa/shared/nlu/training_data/features.py +492 -0
- rasa/shared/nlu/training_data/formats/__init__.py +10 -0
- rasa/shared/nlu/training_data/formats/dialogflow.py +163 -0
- rasa/shared/nlu/training_data/formats/luis.py +87 -0
- rasa/shared/nlu/training_data/formats/rasa.py +135 -0
- rasa/shared/nlu/training_data/formats/rasa_yaml.py +618 -0
- rasa/shared/nlu/training_data/formats/readerwriter.py +244 -0
- rasa/shared/nlu/training_data/formats/wit.py +52 -0
- rasa/shared/nlu/training_data/loading.py +137 -0
- rasa/shared/nlu/training_data/lookup_tables_parser.py +30 -0
- rasa/shared/nlu/training_data/message.py +490 -0
- rasa/shared/nlu/training_data/schemas/__init__.py +0 -0
- rasa/shared/nlu/training_data/schemas/data_schema.py +85 -0
- rasa/shared/nlu/training_data/schemas/nlu.yml +53 -0
- rasa/shared/nlu/training_data/schemas/responses.yml +70 -0
- rasa/shared/nlu/training_data/synonyms_parser.py +42 -0
- rasa/shared/nlu/training_data/training_data.py +729 -0
- rasa/shared/nlu/training_data/util.py +223 -0
- rasa/shared/providers/__init__.py +0 -0
- rasa/shared/providers/_configs/__init__.py +0 -0
- rasa/shared/providers/_configs/azure_openai_client_config.py +677 -0
- rasa/shared/providers/_configs/client_config.py +59 -0
- rasa/shared/providers/_configs/default_litellm_client_config.py +132 -0
- rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +236 -0
- rasa/shared/providers/_configs/litellm_router_client_config.py +222 -0
- rasa/shared/providers/_configs/model_group_config.py +173 -0
- rasa/shared/providers/_configs/openai_client_config.py +177 -0
- rasa/shared/providers/_configs/rasa_llm_client_config.py +75 -0
- rasa/shared/providers/_configs/self_hosted_llm_client_config.py +178 -0
- rasa/shared/providers/_configs/utils.py +117 -0
- rasa/shared/providers/_ssl_verification_utils.py +124 -0
- rasa/shared/providers/_utils.py +79 -0
- rasa/shared/providers/constants.py +7 -0
- rasa/shared/providers/embedding/__init__.py +0 -0
- rasa/shared/providers/embedding/_base_litellm_embedding_client.py +243 -0
- rasa/shared/providers/embedding/_langchain_embedding_client_adapter.py +74 -0
- rasa/shared/providers/embedding/azure_openai_embedding_client.py +335 -0
- rasa/shared/providers/embedding/default_litellm_embedding_client.py +126 -0
- rasa/shared/providers/embedding/embedding_client.py +90 -0
- rasa/shared/providers/embedding/embedding_response.py +41 -0
- rasa/shared/providers/embedding/huggingface_local_embedding_client.py +191 -0
- rasa/shared/providers/embedding/litellm_router_embedding_client.py +138 -0
- rasa/shared/providers/embedding/openai_embedding_client.py +172 -0
- rasa/shared/providers/llm/__init__.py +0 -0
- rasa/shared/providers/llm/_base_litellm_client.py +265 -0
- rasa/shared/providers/llm/azure_openai_llm_client.py +415 -0
- rasa/shared/providers/llm/default_litellm_llm_client.py +110 -0
- rasa/shared/providers/llm/litellm_router_llm_client.py +202 -0
- rasa/shared/providers/llm/llm_client.py +78 -0
- rasa/shared/providers/llm/llm_response.py +50 -0
- rasa/shared/providers/llm/openai_llm_client.py +161 -0
- rasa/shared/providers/llm/rasa_llm_client.py +120 -0
- rasa/shared/providers/llm/self_hosted_llm_client.py +276 -0
- rasa/shared/providers/mappings.py +94 -0
- rasa/shared/providers/router/__init__.py +0 -0
- rasa/shared/providers/router/_base_litellm_router_client.py +185 -0
- rasa/shared/providers/router/router_client.py +75 -0
- rasa/shared/utils/__init__.py +0 -0
- rasa/shared/utils/cli.py +102 -0
- rasa/shared/utils/common.py +324 -0
- rasa/shared/utils/constants.py +4 -0
- rasa/shared/utils/health_check/__init__.py +0 -0
- rasa/shared/utils/health_check/embeddings_health_check_mixin.py +31 -0
- rasa/shared/utils/health_check/health_check.py +258 -0
- rasa/shared/utils/health_check/llm_health_check_mixin.py +31 -0
- rasa/shared/utils/io.py +499 -0
- rasa/shared/utils/llm.py +764 -0
- rasa/shared/utils/pykwalify_extensions.py +27 -0
- rasa/shared/utils/schemas/__init__.py +0 -0
- rasa/shared/utils/schemas/config.yml +2 -0
- rasa/shared/utils/schemas/domain.yml +145 -0
- rasa/shared/utils/schemas/events.py +214 -0
- rasa/shared/utils/schemas/model_config.yml +36 -0
- rasa/shared/utils/schemas/stories.yml +173 -0
- rasa/shared/utils/yaml.py +1068 -0
- rasa/studio/__init__.py +0 -0
- rasa/studio/auth.py +270 -0
- rasa/studio/config.py +136 -0
- rasa/studio/constants.py +19 -0
- rasa/studio/data_handler.py +368 -0
- rasa/studio/download.py +489 -0
- rasa/studio/results_logger.py +137 -0
- rasa/studio/train.py +134 -0
- rasa/studio/upload.py +563 -0
- rasa/telemetry.py +1876 -0
- rasa/tracing/__init__.py +0 -0
- rasa/tracing/config.py +355 -0
- rasa/tracing/constants.py +62 -0
- rasa/tracing/instrumentation/__init__.py +0 -0
- rasa/tracing/instrumentation/attribute_extractors.py +765 -0
- rasa/tracing/instrumentation/instrumentation.py +1306 -0
- rasa/tracing/instrumentation/intentless_policy_instrumentation.py +144 -0
- rasa/tracing/instrumentation/metrics.py +294 -0
- rasa/tracing/metric_instrument_provider.py +205 -0
- rasa/utils/__init__.py +0 -0
- rasa/utils/beta.py +83 -0
- rasa/utils/cli.py +28 -0
- rasa/utils/common.py +639 -0
- rasa/utils/converter.py +53 -0
- rasa/utils/endpoints.py +331 -0
- rasa/utils/io.py +252 -0
- rasa/utils/json_utils.py +60 -0
- rasa/utils/licensing.py +542 -0
- rasa/utils/log_utils.py +181 -0
- rasa/utils/mapper.py +210 -0
- rasa/utils/ml_utils.py +147 -0
- rasa/utils/plotting.py +362 -0
- rasa/utils/sanic_error_handler.py +32 -0
- rasa/utils/singleton.py +23 -0
- rasa/utils/tensorflow/__init__.py +0 -0
- rasa/utils/tensorflow/callback.py +112 -0
- rasa/utils/tensorflow/constants.py +116 -0
- rasa/utils/tensorflow/crf.py +492 -0
- rasa/utils/tensorflow/data_generator.py +440 -0
- rasa/utils/tensorflow/environment.py +161 -0
- rasa/utils/tensorflow/exceptions.py +5 -0
- rasa/utils/tensorflow/feature_array.py +366 -0
- rasa/utils/tensorflow/layers.py +1565 -0
- rasa/utils/tensorflow/layers_utils.py +113 -0
- rasa/utils/tensorflow/metrics.py +281 -0
- rasa/utils/tensorflow/model_data.py +798 -0
- rasa/utils/tensorflow/model_data_utils.py +499 -0
- rasa/utils/tensorflow/models.py +935 -0
- rasa/utils/tensorflow/rasa_layers.py +1094 -0
- rasa/utils/tensorflow/transformer.py +640 -0
- rasa/utils/tensorflow/types.py +6 -0
- rasa/utils/train_utils.py +572 -0
- rasa/utils/url_tools.py +53 -0
- rasa/utils/yaml.py +54 -0
- rasa/validator.py +1644 -0
- rasa/version.py +3 -0
- rasa_pro-3.12.0.dev1.dist-info/METADATA +199 -0
- rasa_pro-3.12.0.dev1.dist-info/NOTICE +5 -0
- rasa_pro-3.12.0.dev1.dist-info/RECORD +790 -0
- rasa_pro-3.12.0.dev1.dist-info/WHEEL +4 -0
- rasa_pro-3.12.0.dev1.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,620 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import hashlib
|
|
3
|
+
import hmac
|
|
4
|
+
from http import HTTPStatus
|
|
5
|
+
import json
|
|
6
|
+
import logging
|
|
7
|
+
import re
|
|
8
|
+
import time
|
|
9
|
+
from typing import Any, Awaitable, Callable, Dict, List, Optional, Set, Text
|
|
10
|
+
|
|
11
|
+
from rasa.core.channels.channel import InputChannel, OutputChannel, UserMessage
|
|
12
|
+
from rasa.shared.constants import DOCS_URL_CONNECTORS_SLACK
|
|
13
|
+
from rasa.shared.exceptions import InvalidConfigException
|
|
14
|
+
import rasa.shared.utils.io
|
|
15
|
+
from sanic import Blueprint, response
|
|
16
|
+
from sanic.request import Request
|
|
17
|
+
from sanic.response import HTTPResponse
|
|
18
|
+
from slack_sdk.web.async_client import AsyncWebClient
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class SlackBot(OutputChannel):
|
|
24
|
+
"""A Slack communication channel."""
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
def name(cls) -> Text:
|
|
28
|
+
return "slack"
|
|
29
|
+
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
token: Text,
|
|
33
|
+
slack_channel: Optional[Text] = None,
|
|
34
|
+
thread_id: Optional[Text] = None,
|
|
35
|
+
proxy: Optional[Text] = None,
|
|
36
|
+
) -> None:
|
|
37
|
+
self.slack_channel = slack_channel
|
|
38
|
+
self.thread_id = thread_id
|
|
39
|
+
self.proxy = proxy
|
|
40
|
+
self.client = AsyncWebClient(token, proxy=proxy)
|
|
41
|
+
super().__init__()
|
|
42
|
+
|
|
43
|
+
async def _post_message(self, channel: Text, **kwargs: Any) -> None:
|
|
44
|
+
# type issues below are ignored because the `run_async` paramenter
|
|
45
|
+
# above ensures chat_postMessage is await-able. mypy complains
|
|
46
|
+
# because the type annotations are not precise enough in Slack
|
|
47
|
+
if self.thread_id:
|
|
48
|
+
await self.client.chat_postMessage(
|
|
49
|
+
channel=channel, **kwargs, thread_ts=self.thread_id
|
|
50
|
+
)
|
|
51
|
+
else:
|
|
52
|
+
await self.client.chat_postMessage(channel=channel, **kwargs)
|
|
53
|
+
|
|
54
|
+
async def send_text_message(
|
|
55
|
+
self, recipient_id: Text, text: Text, **kwargs: Any
|
|
56
|
+
) -> None:
|
|
57
|
+
"""Send text message to Slack API."""
|
|
58
|
+
recipient = self.slack_channel or recipient_id
|
|
59
|
+
for message_part in text.strip().split("\n\n"):
|
|
60
|
+
await self._post_message(
|
|
61
|
+
channel=recipient, as_user=True, text=message_part, type="mrkdwn"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
async def send_image_url(
|
|
65
|
+
self, recipient_id: Text, image: Text, **kwargs: Any
|
|
66
|
+
) -> None:
|
|
67
|
+
recipient = self.slack_channel or recipient_id
|
|
68
|
+
image_block = {"type": "image", "image_url": image, "alt_text": image}
|
|
69
|
+
|
|
70
|
+
await self._post_message(
|
|
71
|
+
channel=recipient, as_user=True, text=image, blocks=[image_block]
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
async def send_attachment( # type: ignore[override]
|
|
75
|
+
self, recipient_id: Text, attachment: Dict[Text, Any], **kwargs: Any
|
|
76
|
+
) -> None:
|
|
77
|
+
"""Sends message with attachment."""
|
|
78
|
+
recipient = self.slack_channel or recipient_id
|
|
79
|
+
await self._post_message(
|
|
80
|
+
channel=recipient, as_user=True, attachments=[attachment], **kwargs
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
async def send_text_with_buttons(
|
|
84
|
+
self,
|
|
85
|
+
recipient_id: Text,
|
|
86
|
+
text: Text,
|
|
87
|
+
buttons: List[Dict[Text, Any]],
|
|
88
|
+
**kwargs: Any,
|
|
89
|
+
) -> None:
|
|
90
|
+
recipient = self.slack_channel or recipient_id
|
|
91
|
+
|
|
92
|
+
text_block = {"type": "section", "text": {"type": "plain_text", "text": text}}
|
|
93
|
+
|
|
94
|
+
if len(buttons) > 5:
|
|
95
|
+
rasa.shared.utils.io.raise_warning(
|
|
96
|
+
"Slack API currently allows only up to 5 buttons. "
|
|
97
|
+
"Since you added more than 5, slack will ignore all of them."
|
|
98
|
+
)
|
|
99
|
+
return await self.send_text_message(recipient, text, **kwargs)
|
|
100
|
+
|
|
101
|
+
button_block = {
|
|
102
|
+
"type": "actions",
|
|
103
|
+
"elements": [
|
|
104
|
+
{
|
|
105
|
+
"type": "button",
|
|
106
|
+
"text": {"type": "plain_text", "text": button["title"]},
|
|
107
|
+
"value": button["payload"],
|
|
108
|
+
}
|
|
109
|
+
for button in buttons
|
|
110
|
+
],
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
await self._post_message(
|
|
114
|
+
channel=recipient,
|
|
115
|
+
as_user=True,
|
|
116
|
+
text=text,
|
|
117
|
+
blocks=[text_block, button_block],
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
async def send_custom_json(
|
|
121
|
+
self, recipient_id: Text, json_message: Dict[Text, Any], **kwargs: Any
|
|
122
|
+
) -> None:
|
|
123
|
+
channel = json_message.get("channel", self.slack_channel or recipient_id)
|
|
124
|
+
json_message.setdefault("as_user", True)
|
|
125
|
+
await self._post_message(channel=channel, **json_message)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class SlackInput(InputChannel):
|
|
129
|
+
"""Slack input channel implementation. Based on the HTTPInputChannel."""
|
|
130
|
+
|
|
131
|
+
@classmethod
|
|
132
|
+
def name(cls) -> Text:
|
|
133
|
+
return "slack"
|
|
134
|
+
|
|
135
|
+
@classmethod
|
|
136
|
+
def from_credentials(cls, credentials: Optional[Dict[Text, Any]]) -> InputChannel:
|
|
137
|
+
if not credentials:
|
|
138
|
+
cls.raise_missing_credentials_exception()
|
|
139
|
+
|
|
140
|
+
return cls(
|
|
141
|
+
credentials.get("slack_token"),
|
|
142
|
+
credentials.get("slack_channel"),
|
|
143
|
+
credentials.get("proxy"),
|
|
144
|
+
credentials.get("slack_retry_reason_header", "x-slack-retry-reason"),
|
|
145
|
+
credentials.get("slack_retry_number_header", "x-slack-retry-num"),
|
|
146
|
+
credentials.get("errors_ignore_retry", None),
|
|
147
|
+
credentials.get("use_threads", False),
|
|
148
|
+
credentials.get("slack_signing_secret", ""),
|
|
149
|
+
credentials.get("conversation_granularity", "sender"),
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
def __init__(
|
|
153
|
+
self,
|
|
154
|
+
slack_token: Text,
|
|
155
|
+
slack_channel: Optional[Text] = None,
|
|
156
|
+
proxy: Optional[Text] = None,
|
|
157
|
+
slack_retry_reason_header: Optional[Text] = None,
|
|
158
|
+
slack_retry_number_header: Optional[Text] = None,
|
|
159
|
+
errors_ignore_retry: Optional[List[Text]] = None,
|
|
160
|
+
use_threads: Optional[bool] = False,
|
|
161
|
+
slack_signing_secret: Text = "",
|
|
162
|
+
conversation_granularity: Optional[Text] = "sender",
|
|
163
|
+
) -> None:
|
|
164
|
+
"""Create a Slack input channel.
|
|
165
|
+
|
|
166
|
+
Needs a couple of settings to properly authenticate and validate
|
|
167
|
+
messages. Details to setup:
|
|
168
|
+
|
|
169
|
+
https://github.com/slackapi/python-slackclient
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
slack_token: Your Slack Authentication token. You can create a
|
|
173
|
+
Slack app and get your Bot User OAuth Access Token
|
|
174
|
+
`here <https://api.slack.com/slack-apps>`_.
|
|
175
|
+
slack_channel: the string identifier for a channel to which
|
|
176
|
+
the bot posts, or channel name (e.g. '#bot-test')
|
|
177
|
+
If not set, messages will be sent back
|
|
178
|
+
to the "App" DM channel of your bot's name.
|
|
179
|
+
proxy: A Proxy Server to route your traffic through
|
|
180
|
+
slack_retry_reason_header: Slack HTTP header name indicating reason
|
|
181
|
+
that slack send retry request.
|
|
182
|
+
slack_retry_number_header: Slack HTTP header name indicating
|
|
183
|
+
the attempt number.
|
|
184
|
+
errors_ignore_retry: Any error codes given by Slack
|
|
185
|
+
included in this list will be ignored.
|
|
186
|
+
Error codes are listed
|
|
187
|
+
`here <https://api.slack.com/events-api#errors>`_.
|
|
188
|
+
use_threads: If set to `True`, your bot will send responses in Slack as
|
|
189
|
+
a threaded message. Responses will appear as a normal Slack message
|
|
190
|
+
if set to `False`.
|
|
191
|
+
slack_signing_secret: Slack creates a unique string for your app and
|
|
192
|
+
shares it with you. This allows us to verify requests from Slack
|
|
193
|
+
with confidence by verifying signatures using your signing secret.
|
|
194
|
+
conversation_granularity: conversation granularity for slack conversations.
|
|
195
|
+
sender allows 1 conversation per user (across channels)
|
|
196
|
+
channel allows 1 conversation per user per channel
|
|
197
|
+
thread allows 1 conversation per user per thread
|
|
198
|
+
"""
|
|
199
|
+
self.slack_token = slack_token
|
|
200
|
+
self.slack_channel = slack_channel
|
|
201
|
+
self.proxy = proxy
|
|
202
|
+
self.errors_ignore_retry = errors_ignore_retry or ("http_timeout",)
|
|
203
|
+
self.retry_reason_header = slack_retry_reason_header
|
|
204
|
+
self.retry_num_header = slack_retry_number_header
|
|
205
|
+
self.use_threads = use_threads
|
|
206
|
+
self.slack_signing_secret = slack_signing_secret
|
|
207
|
+
self.conversation_granularity = conversation_granularity
|
|
208
|
+
self._background_tasks: Set[asyncio.Task] = set()
|
|
209
|
+
|
|
210
|
+
self._validate_credentials()
|
|
211
|
+
|
|
212
|
+
def _validate_credentials(self) -> None:
|
|
213
|
+
"""Raises exceptions if the connector is not properly configured."""
|
|
214
|
+
if not self.slack_signing_secret:
|
|
215
|
+
raise InvalidConfigException(
|
|
216
|
+
f"Your slack bot is missing a configured signing secret. Running a "
|
|
217
|
+
f"bot without a signing secret is insecure and was removed. "
|
|
218
|
+
f"You need to add a `slack_signing_secret` parameter to your channel "
|
|
219
|
+
f"configuration. "
|
|
220
|
+
f"More info at {DOCS_URL_CONNECTORS_SLACK} ."
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
@staticmethod
|
|
224
|
+
def _is_app_mention(slack_event: Dict) -> bool:
|
|
225
|
+
try:
|
|
226
|
+
return slack_event["event"]["type"] == "app_mention"
|
|
227
|
+
except KeyError:
|
|
228
|
+
return False
|
|
229
|
+
|
|
230
|
+
@staticmethod
|
|
231
|
+
def _is_direct_message(slack_event: Dict) -> bool:
|
|
232
|
+
try:
|
|
233
|
+
return slack_event["event"]["channel_type"] == "im"
|
|
234
|
+
except KeyError:
|
|
235
|
+
return False
|
|
236
|
+
|
|
237
|
+
@staticmethod
|
|
238
|
+
def _is_user_message(slack_event: Dict[Text, Any]) -> bool:
|
|
239
|
+
return (
|
|
240
|
+
slack_event.get("event") is not None
|
|
241
|
+
and (
|
|
242
|
+
slack_event.get("event", {}).get("type") == "message"
|
|
243
|
+
or slack_event.get("event", {}).get("type") == "app_mention"
|
|
244
|
+
)
|
|
245
|
+
and slack_event.get("event", {}).get("text")
|
|
246
|
+
and not slack_event.get("event", {}).get("bot_id")
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
@staticmethod
|
|
250
|
+
def _sanitize_user_message(
|
|
251
|
+
text: Text, uids_to_remove: Optional[List[Text]]
|
|
252
|
+
) -> Text:
|
|
253
|
+
"""Remove superfluous/wrong/problematic tokens from a message.
|
|
254
|
+
|
|
255
|
+
Probably a good starting point for pre-formatting of user-provided text
|
|
256
|
+
to make NLU's life easier in case they go funky to the power of extreme
|
|
257
|
+
|
|
258
|
+
In the current state will just drop self-mentions of bot itself
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
text: raw message as sent from slack
|
|
262
|
+
uids_to_remove: a list of user ids to remove from the content
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
str: parsed and cleaned version of the input text
|
|
266
|
+
"""
|
|
267
|
+
uids_to_remove = uids_to_remove or []
|
|
268
|
+
|
|
269
|
+
for uid_to_remove in uids_to_remove:
|
|
270
|
+
escaped_uid = re.escape(str(uid_to_remove))
|
|
271
|
+
|
|
272
|
+
# heuristic to format majority cases OK
|
|
273
|
+
# can be adjusted to taste later if needed,
|
|
274
|
+
# but is a good first approximation
|
|
275
|
+
for regex, replacement in [
|
|
276
|
+
(rf"<@{escaped_uid}>\s", ""),
|
|
277
|
+
(rf"\s<@{escaped_uid}>", ""), # a bit arbitrary but probably OK
|
|
278
|
+
(rf"<@{escaped_uid}>", " "),
|
|
279
|
+
]:
|
|
280
|
+
text = re.sub(regex, replacement, text)
|
|
281
|
+
|
|
282
|
+
# Find multiple mailto or http links like
|
|
283
|
+
# <mailto:xyz@rasa.com|xyz@rasa.com> or
|
|
284
|
+
# <http://url.com|url.com> in text and substitute
|
|
285
|
+
# it with original content
|
|
286
|
+
pattern = r"(\<(?:mailto|https?):\/\/.*?\|.*?\>)"
|
|
287
|
+
match = re.findall(pattern, text)
|
|
288
|
+
|
|
289
|
+
if match:
|
|
290
|
+
for remove in match:
|
|
291
|
+
replacement = remove.split("|")[1]
|
|
292
|
+
replacement = replacement.replace(">", "")
|
|
293
|
+
text = text.replace(remove, replacement)
|
|
294
|
+
return text.strip()
|
|
295
|
+
|
|
296
|
+
@staticmethod
|
|
297
|
+
def _is_interactive_message(payload: Dict) -> bool:
|
|
298
|
+
"""Check wheter the input is a supported interactive input type."""
|
|
299
|
+
supported = [
|
|
300
|
+
"button",
|
|
301
|
+
"select",
|
|
302
|
+
"static_select",
|
|
303
|
+
"external_select",
|
|
304
|
+
"conversations_select",
|
|
305
|
+
"users_select",
|
|
306
|
+
"channels_select",
|
|
307
|
+
"overflow",
|
|
308
|
+
"datepicker",
|
|
309
|
+
]
|
|
310
|
+
if payload.get("actions"):
|
|
311
|
+
action_type = payload["actions"][0].get("type")
|
|
312
|
+
if action_type in supported:
|
|
313
|
+
return True
|
|
314
|
+
elif action_type:
|
|
315
|
+
logger.warning(
|
|
316
|
+
f"Received input from a Slack interactive component of type "
|
|
317
|
+
f"'{payload['actions'][0]['type']}', "
|
|
318
|
+
f"for which payload parsing is not yet supported."
|
|
319
|
+
)
|
|
320
|
+
return False
|
|
321
|
+
|
|
322
|
+
@staticmethod
|
|
323
|
+
def _get_interactive_response(action: Dict) -> Optional[Text]:
|
|
324
|
+
"""Parse the payload for the response value."""
|
|
325
|
+
if action["type"] == "button":
|
|
326
|
+
return action.get("value")
|
|
327
|
+
elif action["type"] == "select":
|
|
328
|
+
return action.get("selected_options", [{}])[0].get("value")
|
|
329
|
+
elif action["type"] == "static_select":
|
|
330
|
+
return action.get("selected_option", {}).get("value")
|
|
331
|
+
elif action["type"] == "external_select":
|
|
332
|
+
return action.get("selected_option", {}).get("value")
|
|
333
|
+
elif action["type"] == "conversations_select":
|
|
334
|
+
return action.get("selected_conversation")
|
|
335
|
+
elif action["type"] == "users_select":
|
|
336
|
+
return action.get("selected_user")
|
|
337
|
+
elif action["type"] == "channels_select":
|
|
338
|
+
return action.get("selected_channel")
|
|
339
|
+
elif action["type"] == "overflow":
|
|
340
|
+
return action.get("selected_option", {}).get("value")
|
|
341
|
+
elif action["type"] == "datepicker":
|
|
342
|
+
return action.get("selected_date")
|
|
343
|
+
|
|
344
|
+
return None
|
|
345
|
+
|
|
346
|
+
async def process_message(
|
|
347
|
+
self,
|
|
348
|
+
request: Request,
|
|
349
|
+
on_new_message: Callable[[UserMessage], Awaitable[Any]],
|
|
350
|
+
text: Text,
|
|
351
|
+
sender_id: Optional[Text],
|
|
352
|
+
metadata: Optional[Dict],
|
|
353
|
+
) -> Any:
|
|
354
|
+
"""Slack retries to post messages up to 3 times based on
|
|
355
|
+
failure conditions defined here:
|
|
356
|
+
https://api.slack.com/events-api#failure_conditions.
|
|
357
|
+
"""
|
|
358
|
+
retry_reason = request.headers.get(self.retry_reason_header)
|
|
359
|
+
retry_count = request.headers.get(self.retry_num_header)
|
|
360
|
+
if retry_count and retry_reason in self.errors_ignore_retry:
|
|
361
|
+
logger.warning(
|
|
362
|
+
f"Received retry #{retry_count} request from slack"
|
|
363
|
+
f" due to {retry_reason}."
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
return response.text(
|
|
367
|
+
"", status=HTTPStatus.CREATED, headers={"X-Slack-No-Retry": "1"}
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
if metadata is not None:
|
|
371
|
+
output_channel = metadata.get("out_channel")
|
|
372
|
+
if self.use_threads:
|
|
373
|
+
thread_id = metadata.get("thread_id")
|
|
374
|
+
else:
|
|
375
|
+
thread_id = None
|
|
376
|
+
else:
|
|
377
|
+
output_channel = None
|
|
378
|
+
thread_id = None
|
|
379
|
+
|
|
380
|
+
try:
|
|
381
|
+
user_msg = UserMessage(
|
|
382
|
+
text,
|
|
383
|
+
self.get_output_channel(output_channel, thread_id),
|
|
384
|
+
sender_id,
|
|
385
|
+
input_channel=self.name(),
|
|
386
|
+
metadata=metadata,
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
# We need to save a reference to this background task to
|
|
390
|
+
# make sure it doesn't disappear. See:
|
|
391
|
+
# https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task
|
|
392
|
+
task: asyncio.Task = asyncio.create_task(on_new_message(user_msg))
|
|
393
|
+
self._background_tasks.add(task)
|
|
394
|
+
task.add_done_callback(self._background_tasks.discard)
|
|
395
|
+
except Exception as e:
|
|
396
|
+
logger.error(f"Exception when trying to handle message.{e}")
|
|
397
|
+
logger.error(str(e), exc_info=True)
|
|
398
|
+
|
|
399
|
+
return response.text("")
|
|
400
|
+
|
|
401
|
+
def get_metadata(self, request: Request) -> Dict[Text, Any]:
|
|
402
|
+
"""Extracts the metadata from a slack API event.
|
|
403
|
+
|
|
404
|
+
Slack Documentation: https://api.slack.com/types/event
|
|
405
|
+
|
|
406
|
+
Args:
|
|
407
|
+
request: A `Request` object that contains a slack API event in the body.
|
|
408
|
+
|
|
409
|
+
Returns:
|
|
410
|
+
Metadata extracted from the sent event payload. This includes the output
|
|
411
|
+
channel for the response, and users that have installed the bot.
|
|
412
|
+
"""
|
|
413
|
+
content_type = request.headers.get("content-type")
|
|
414
|
+
|
|
415
|
+
# Slack API sends either a JSON-encoded or a URL-encoded body depending on the
|
|
416
|
+
# content
|
|
417
|
+
if content_type == "application/json":
|
|
418
|
+
# if JSON-encoded message is received
|
|
419
|
+
slack_event = request.json
|
|
420
|
+
event = slack_event.get("event", {})
|
|
421
|
+
thread_id = event.get("thread_ts", event.get("ts"))
|
|
422
|
+
|
|
423
|
+
users = []
|
|
424
|
+
if "authed_users" in slack_event:
|
|
425
|
+
users = slack_event.get("authed_users")
|
|
426
|
+
elif (
|
|
427
|
+
"authorizations" in slack_event
|
|
428
|
+
and len(slack_event.get("authorizations")) > 0
|
|
429
|
+
):
|
|
430
|
+
users.append(slack_event.get("authorizations")[0].get("user_id"))
|
|
431
|
+
|
|
432
|
+
return {
|
|
433
|
+
"out_channel": event.get("channel"),
|
|
434
|
+
"thread_id": thread_id,
|
|
435
|
+
"users": users,
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
if content_type == "application/x-www-form-urlencoded":
|
|
439
|
+
# if URL-encoded message is received
|
|
440
|
+
output = request.form
|
|
441
|
+
payload = json.loads(output["payload"][0])
|
|
442
|
+
message = payload.get("message", {})
|
|
443
|
+
thread_id = message.get("thread_ts", message.get("ts"))
|
|
444
|
+
|
|
445
|
+
users = []
|
|
446
|
+
if payload.get("user", {}).get("id"):
|
|
447
|
+
users.append(payload.get("user", {}).get("id"))
|
|
448
|
+
|
|
449
|
+
return {
|
|
450
|
+
"out_channel": payload.get("channel", {}).get("id"),
|
|
451
|
+
"thread_id": thread_id,
|
|
452
|
+
"users": users,
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
return {}
|
|
456
|
+
|
|
457
|
+
def is_request_from_slack_authentic(self, request: Request) -> bool:
|
|
458
|
+
"""Validate a request from Slack for its authenticity.
|
|
459
|
+
|
|
460
|
+
Checks if the signature matches the one we expect from Slack. Ensures
|
|
461
|
+
we don't process request from a third-party disguising as slack.
|
|
462
|
+
|
|
463
|
+
Args:
|
|
464
|
+
request: incoming request to be checked
|
|
465
|
+
|
|
466
|
+
Returns:
|
|
467
|
+
`True` if the request came from Slack.
|
|
468
|
+
"""
|
|
469
|
+
try:
|
|
470
|
+
slack_signing_secret = bytes(self.slack_signing_secret, "utf-8")
|
|
471
|
+
|
|
472
|
+
slack_signature = request.headers.get("X-Slack-Signature", "")
|
|
473
|
+
slack_request_timestamp = request.headers.get(
|
|
474
|
+
"X-Slack-Request-Timestamp", "0"
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
if abs(time.time() - int(slack_request_timestamp)) > 60 * 5:
|
|
478
|
+
# The request timestamp is more than five minutes from local time.
|
|
479
|
+
# It could be a replay attack, so let's ignore it.
|
|
480
|
+
return False
|
|
481
|
+
|
|
482
|
+
prefix = f"v0:{slack_request_timestamp}:".encode("utf-8")
|
|
483
|
+
basestring = prefix + request.body
|
|
484
|
+
digest = hmac.new(
|
|
485
|
+
slack_signing_secret, basestring, hashlib.sha256
|
|
486
|
+
).hexdigest()
|
|
487
|
+
computed_signature = f"v0={digest}"
|
|
488
|
+
|
|
489
|
+
return hmac.compare_digest(computed_signature, slack_signature)
|
|
490
|
+
except Exception as e:
|
|
491
|
+
logger.error(
|
|
492
|
+
f"Failed to validate slack request authenticity. "
|
|
493
|
+
f"Assuming invalid request. Error: {e}"
|
|
494
|
+
)
|
|
495
|
+
return False
|
|
496
|
+
|
|
497
|
+
def blueprint(
|
|
498
|
+
self, on_new_message: Callable[[UserMessage], Awaitable[Any]]
|
|
499
|
+
) -> Blueprint:
|
|
500
|
+
slack_webhook = Blueprint("slack_webhook", __name__)
|
|
501
|
+
|
|
502
|
+
@slack_webhook.route("/", methods=["GET"])
|
|
503
|
+
async def health(_: Request) -> HTTPResponse:
|
|
504
|
+
return response.json({"status": "ok"})
|
|
505
|
+
|
|
506
|
+
@slack_webhook.route("/webhook", methods=["GET", "POST"])
|
|
507
|
+
async def webhook(request: Request) -> HTTPResponse:
|
|
508
|
+
content_type = request.headers.get("content-type")
|
|
509
|
+
|
|
510
|
+
if not self.is_request_from_slack_authentic(request):
|
|
511
|
+
return response.text(
|
|
512
|
+
"Message is not properly signed with a valid "
|
|
513
|
+
"X-Slack-Signature header",
|
|
514
|
+
status=HTTPStatus.BAD_REQUEST,
|
|
515
|
+
)
|
|
516
|
+
|
|
517
|
+
# Slack API sends either a JSON-encoded or a URL-encoded body
|
|
518
|
+
# depending on the content
|
|
519
|
+
|
|
520
|
+
if content_type == "application/json":
|
|
521
|
+
# if JSON-encoded message is received
|
|
522
|
+
output = request.json
|
|
523
|
+
event = output.get("event", {})
|
|
524
|
+
user_message = event.get("text", "")
|
|
525
|
+
sender_id = event.get("user", "")
|
|
526
|
+
metadata = self.get_metadata(request)
|
|
527
|
+
channel_id = metadata.get("out_channel")
|
|
528
|
+
thread_id = metadata.get("thread_id")
|
|
529
|
+
conversation_id = self._get_conversation_id(
|
|
530
|
+
sender_id, channel_id, thread_id
|
|
531
|
+
)
|
|
532
|
+
|
|
533
|
+
if "challenge" in output:
|
|
534
|
+
return response.json(output.get("challenge"))
|
|
535
|
+
|
|
536
|
+
if not self._is_user_message(output):
|
|
537
|
+
logger.debug(
|
|
538
|
+
"Received message from Slack which doesn't look like "
|
|
539
|
+
"a user message. Skipping message."
|
|
540
|
+
)
|
|
541
|
+
return response.text("Bot message delivered.")
|
|
542
|
+
|
|
543
|
+
if not self._is_supported_channel(output, metadata):
|
|
544
|
+
logger.warning(
|
|
545
|
+
f"Received message on unsupported "
|
|
546
|
+
f"channel: {metadata['out_channel']}"
|
|
547
|
+
)
|
|
548
|
+
return response.text("channel not supported.")
|
|
549
|
+
|
|
550
|
+
return await self.process_message(
|
|
551
|
+
request,
|
|
552
|
+
on_new_message,
|
|
553
|
+
text=self._sanitize_user_message(user_message, metadata["users"]),
|
|
554
|
+
sender_id=conversation_id,
|
|
555
|
+
metadata=metadata,
|
|
556
|
+
)
|
|
557
|
+
elif content_type == "application/x-www-form-urlencoded":
|
|
558
|
+
# if URL-encoded message is received
|
|
559
|
+
output = request.form
|
|
560
|
+
payload = json.loads(output["payload"][0])
|
|
561
|
+
|
|
562
|
+
if self._is_interactive_message(payload):
|
|
563
|
+
sender_id = payload["user"]["id"]
|
|
564
|
+
text = self._get_interactive_response(payload["actions"][0])
|
|
565
|
+
if text is not None:
|
|
566
|
+
metadata = self.get_metadata(request)
|
|
567
|
+
channel_id = metadata.get("out_channel")
|
|
568
|
+
thread_id = metadata.get("thread_id")
|
|
569
|
+
conversation_id = self._get_conversation_id(
|
|
570
|
+
sender_id, channel_id, thread_id
|
|
571
|
+
)
|
|
572
|
+
return await self.process_message(
|
|
573
|
+
request, on_new_message, text, conversation_id, metadata
|
|
574
|
+
)
|
|
575
|
+
if payload["actions"][0]["type"] == "button":
|
|
576
|
+
# link buttons don't have "value", don't send their clicks to
|
|
577
|
+
# bot
|
|
578
|
+
return response.text("User clicked link button")
|
|
579
|
+
return response.text(
|
|
580
|
+
"The input message could not be processed.",
|
|
581
|
+
status=HTTPStatus.INTERNAL_SERVER_ERROR,
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
return response.text("Bot message delivered.")
|
|
585
|
+
|
|
586
|
+
return slack_webhook
|
|
587
|
+
|
|
588
|
+
def _get_conversation_id(
|
|
589
|
+
self,
|
|
590
|
+
sender_id: Optional[Text],
|
|
591
|
+
channel_id: Optional[Text],
|
|
592
|
+
thread_id: Optional[Text],
|
|
593
|
+
) -> Optional[Text]:
|
|
594
|
+
conversation_id = sender_id
|
|
595
|
+
if self.conversation_granularity == "channel" and sender_id and channel_id:
|
|
596
|
+
conversation_id = sender_id + "_" + channel_id
|
|
597
|
+
if (
|
|
598
|
+
self.conversation_granularity == "thread"
|
|
599
|
+
and sender_id
|
|
600
|
+
and channel_id
|
|
601
|
+
and thread_id
|
|
602
|
+
):
|
|
603
|
+
conversation_id = sender_id + "_" + channel_id + "_" + thread_id
|
|
604
|
+
return conversation_id
|
|
605
|
+
|
|
606
|
+
def _is_supported_channel(self, slack_event: Dict, metadata: Dict) -> bool:
|
|
607
|
+
return (
|
|
608
|
+
self._is_direct_message(slack_event)
|
|
609
|
+
or self._is_app_mention(slack_event)
|
|
610
|
+
or metadata["out_channel"] == self.slack_channel
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
def get_output_channel(
|
|
614
|
+
self, channel: Optional[Text] = None, thread_id: Optional[Text] = None
|
|
615
|
+
) -> OutputChannel:
|
|
616
|
+
channel = channel or self.slack_channel
|
|
617
|
+
return SlackBot(self.slack_token, channel, thread_id, self.proxy)
|
|
618
|
+
|
|
619
|
+
def set_output_channel(self, channel: Text) -> None:
|
|
620
|
+
self.slack_channel = channel
|