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
rasa/telemetry.py
ADDED
|
@@ -0,0 +1,1876 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import contextlib
|
|
3
|
+
import hashlib
|
|
4
|
+
import inspect
|
|
5
|
+
import json
|
|
6
|
+
import logging
|
|
7
|
+
import multiprocessing
|
|
8
|
+
import os
|
|
9
|
+
import platform
|
|
10
|
+
import sys
|
|
11
|
+
import textwrap
|
|
12
|
+
import typing
|
|
13
|
+
import uuid
|
|
14
|
+
from collections import defaultdict
|
|
15
|
+
from datetime import datetime
|
|
16
|
+
from functools import wraps
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import Any, Callable, Dict, List, Optional, Text
|
|
19
|
+
|
|
20
|
+
import importlib_resources
|
|
21
|
+
import requests
|
|
22
|
+
from terminaltables import SingleTable
|
|
23
|
+
|
|
24
|
+
import rasa
|
|
25
|
+
import rasa.anonymization.utils
|
|
26
|
+
import rasa.shared.utils.io
|
|
27
|
+
import rasa.utils.io
|
|
28
|
+
from rasa import model
|
|
29
|
+
from rasa.constants import (
|
|
30
|
+
CONFIG_FILE_TELEMETRY_KEY,
|
|
31
|
+
CONFIG_TELEMETRY_DATE,
|
|
32
|
+
CONFIG_TELEMETRY_ENABLED,
|
|
33
|
+
CONFIG_TELEMETRY_ID,
|
|
34
|
+
)
|
|
35
|
+
from rasa.engine.storage.local_model_storage import LocalModelStorage
|
|
36
|
+
from rasa.shared.constants import (
|
|
37
|
+
CONFIG_LANGUAGE_KEY,
|
|
38
|
+
CONFIG_PIPELINE_KEY,
|
|
39
|
+
CONFIG_POLICIES_KEY,
|
|
40
|
+
CONFIG_PREDICT_SCHEMA,
|
|
41
|
+
CONFIG_RECIPE_KEY,
|
|
42
|
+
CONFIG_TRAIN_SCHEMA,
|
|
43
|
+
DOCS_URL_TELEMETRY,
|
|
44
|
+
LLM_API_HEALTH_CHECK_DEFAULT_VALUE,
|
|
45
|
+
LLM_API_HEALTH_CHECK_ENV_VAR,
|
|
46
|
+
MODEL_GROUP_CONFIG_KEY,
|
|
47
|
+
PROMPT_CONFIG_KEY,
|
|
48
|
+
PROMPT_TEMPLATE_CONFIG_KEY,
|
|
49
|
+
UTTER_ASK_PREFIX,
|
|
50
|
+
)
|
|
51
|
+
from rasa.shared.core.flows import Flow
|
|
52
|
+
from rasa.shared.core.flows.steps import (
|
|
53
|
+
CallFlowStep,
|
|
54
|
+
CollectInformationFlowStep,
|
|
55
|
+
LinkFlowStep,
|
|
56
|
+
SetSlotsFlowStep,
|
|
57
|
+
)
|
|
58
|
+
from rasa.shared.exceptions import RasaException
|
|
59
|
+
from rasa.utils import common as rasa_utils
|
|
60
|
+
|
|
61
|
+
if typing.TYPE_CHECKING:
|
|
62
|
+
from rasa.core.agent import Agent
|
|
63
|
+
from rasa.core.brokers.broker import EventBroker
|
|
64
|
+
from rasa.core.channels.channel import InputChannel
|
|
65
|
+
from rasa.core.tracker_store import TrackerStore
|
|
66
|
+
from rasa.core.utils import AvailableEndpoints
|
|
67
|
+
from rasa.e2e_test.e2e_test_case import Fixture, Metadata, TestCase
|
|
68
|
+
from rasa.shared.importers.importer import TrainingDataImporter
|
|
69
|
+
from rasa.shared.nlu.training_data.training_data import TrainingData
|
|
70
|
+
|
|
71
|
+
logger = logging.getLogger(__name__)
|
|
72
|
+
|
|
73
|
+
SEGMENT_TRACK_ENDPOINT = "https://api.segment.io/v1/track"
|
|
74
|
+
SEGMENT_IDENTIFY_ENDPOINT = "https://api.segment.io/v1/identify"
|
|
75
|
+
SEGMENT_REQUEST_TIMEOUT = 5 # seconds
|
|
76
|
+
|
|
77
|
+
TELEMETRY_ENABLED_ENVIRONMENT_VARIABLE = "RASA_TELEMETRY_ENABLED"
|
|
78
|
+
TELEMETRY_DEBUG_ENVIRONMENT_VARIABLE = "RASA_TELEMETRY_DEBUG"
|
|
79
|
+
RASA_PRO_CONFIG_FILE_TELEMETRY_KEY = "traits"
|
|
80
|
+
|
|
81
|
+
# the environment variable can be used for local development to set a test key
|
|
82
|
+
# e.g. `RASA_TELEMETRY_WRITE_KEY=12354 rasa train`
|
|
83
|
+
TELEMETRY_WRITE_KEY_ENVIRONMENT_VARIABLE = "RASA_TELEMETRY_WRITE_KEY"
|
|
84
|
+
EXCEPTION_WRITE_KEY_ENVIRONMENT_VARIABLE = "RASA_EXCEPTION_WRITE_KEY"
|
|
85
|
+
|
|
86
|
+
TELEMETRY_ID = "metrics_id"
|
|
87
|
+
TELEMETRY_ENABLED_BY_DEFAULT = True
|
|
88
|
+
|
|
89
|
+
# if one of these environment variables is set, we assume to be running in CI env
|
|
90
|
+
CI_ENVIRONMENT_TELL = [
|
|
91
|
+
"bamboo.buildKey",
|
|
92
|
+
"BUILD_ID",
|
|
93
|
+
"BUILD_NUMBER",
|
|
94
|
+
"BUILDKITE",
|
|
95
|
+
"CI",
|
|
96
|
+
"CIRCLECI",
|
|
97
|
+
"CONTINUOUS_INTEGRATION",
|
|
98
|
+
"GITHUB_ACTIONS",
|
|
99
|
+
"HUDSON_URL",
|
|
100
|
+
"JENKINS_URL",
|
|
101
|
+
"TEAMCITY_VERSION",
|
|
102
|
+
"TRAVIS",
|
|
103
|
+
"CODEBUILD_BUILD_ARN",
|
|
104
|
+
"CODEBUILD_BUILD_ID",
|
|
105
|
+
"CODEBUILD_BATCH_BUILD_IDENTIFIER",
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
# If updating or creating a new event, remember to update
|
|
109
|
+
# https://rasa.com/docs/rasa-pro/telemetry/telemetry OR
|
|
110
|
+
# https://rasa.com/docs/rasa-pro/telemetry/reference
|
|
111
|
+
TRAINING_STARTED_EVENT = "Training Started"
|
|
112
|
+
TRAINING_COMPLETED_EVENT = "Training Completed"
|
|
113
|
+
TELEMETRY_DISABLED_EVENT = "Telemetry Disabled"
|
|
114
|
+
TELEMETRY_DATA_SPLIT_EVENT = "Training Data Split"
|
|
115
|
+
TELEMETRY_DATA_VALIDATED_EVENT = "Training Data Validated"
|
|
116
|
+
TELEMETRY_DATA_CONVERTED_EVENT = "Training Data Converted"
|
|
117
|
+
TELEMETRY_TRACKER_EXPORTED_EVENT = "Tracker Exported"
|
|
118
|
+
TELEMETRY_INTERACTIVE_LEARNING_STARTED_EVENT = "Interactive Learning Started"
|
|
119
|
+
TELEMETRY_SERVER_STARTED_EVENT = "Server Started"
|
|
120
|
+
TELEMETRY_PROJECT_CREATED_EVENT = "Project Created"
|
|
121
|
+
TELEMETRY_SHELL_STARTED_EVENT = "Shell Started"
|
|
122
|
+
TELEMETRY_INSPECT_STARTED_EVENT = "Inspect Started"
|
|
123
|
+
TELEMETRY_VISUALIZATION_STARTED_EVENT = "Story Visualization Started"
|
|
124
|
+
TELEMETRY_TEST_CORE_EVENT = "Model Core Tested"
|
|
125
|
+
TELEMETRY_TEST_NLU_EVENT = "Model NLU Tested"
|
|
126
|
+
TELEMETRY_MARKERS_EXTRACTION_INITIATED_EVENT = "Markers Extraction Initiated"
|
|
127
|
+
TELEMETRY_MARKERS_EXTRACTED_EVENT = "Markers Extracted"
|
|
128
|
+
TELEMETRY_MARKERS_STATS_COMPUTED_EVENT = "Markers Statistics Computed"
|
|
129
|
+
TELEMETRY_MARKERS_PARSED_COUNT = "Markers Parsed"
|
|
130
|
+
|
|
131
|
+
TELEMETRY_RESPONSE_REPHRASED_EVENT = "Response Rephrased"
|
|
132
|
+
TELEMETRY_INTENTLESS_POLICY_TRAINING_STARTED_EVENT = (
|
|
133
|
+
"Intentless Policy Training Started"
|
|
134
|
+
)
|
|
135
|
+
TELEMETRY_INTENTLESS_POLICY_TRAINING_COMPLETED_EVENT = (
|
|
136
|
+
"Intentless Policy Training Completed"
|
|
137
|
+
)
|
|
138
|
+
TELEMETRY_INTENTLESS_POLICY_PREDICT_EVENT = "Intentless Policy Predicted"
|
|
139
|
+
TELEMETRY_E2E_TEST_RUN_STARTED_EVENT = "E2E Test Run Started"
|
|
140
|
+
TELEMETRY_ENTERPRISE_SEARCH_POLICY_TRAINING_STARTED_EVENT = (
|
|
141
|
+
"Enterprise Search Policy Training Started"
|
|
142
|
+
)
|
|
143
|
+
TELEMETRY_ENTERPRISE_SEARCH_POLICY_TRAINING_COMPLETED_EVENT = (
|
|
144
|
+
"Enterprise Search Policy Training Completed"
|
|
145
|
+
)
|
|
146
|
+
TELEMETRY_ENTERPRISE_SEARCH_POLICY_PREDICT_EVENT = "Enterprise Search Policy Predicted"
|
|
147
|
+
|
|
148
|
+
# licensing events
|
|
149
|
+
TELEMETRY_CONVERSATION_COUNT = "Conversation Count"
|
|
150
|
+
TELEMETRY_CONVERSATION_SOFT_LIMIT_REACHED = "Conversation Soft Limit Reached"
|
|
151
|
+
TELEMETRY_CONVERSATION_HARD_LIMIT_REACHED = "Conversation Hard Limit Reached"
|
|
152
|
+
|
|
153
|
+
# used to calculate the context on the first call and cache it afterwards
|
|
154
|
+
TELEMETRY_CONTEXT = None
|
|
155
|
+
|
|
156
|
+
# constants used for the training started events
|
|
157
|
+
NUM_FLOWS = "num_flows"
|
|
158
|
+
NUM_FLOWS_WITH_NLU_TRIGGER = "num_flows_with_nlu_trigger"
|
|
159
|
+
NUM_FLOWS_WITH_FLOW_GUARDS = "num_flows_with_flow_guards"
|
|
160
|
+
NUM_FLOWS_ALWAYS_INCLUDED_IN_PROMPT = "num_flows_always_included_in_prompt"
|
|
161
|
+
NUM_FLOWS_WITH_NOT_STARTABLE_FLOW_GUARDS = "num_flows_with_not_startable_flow_guards"
|
|
162
|
+
NUM_COLLECT_STEPS = "num_collect_steps"
|
|
163
|
+
NUM_COLLECT_STEPS_WITH_SEPARATE_UTTER = "num_collect_steps_with_separate_utter"
|
|
164
|
+
NUM_COLLECT_STEPS_WITH_REJECTIONS = "num_collect_steps_with_rejections"
|
|
165
|
+
NUM_COLLECT_STEPS_WITH_NOT_RESET_AFTER_FLOW_ENDS = (
|
|
166
|
+
"num_collect_steps_with_not_reset_after_flow_ends"
|
|
167
|
+
)
|
|
168
|
+
NUM_SET_SLOT_STEPS = "num_set_slot_steps"
|
|
169
|
+
MAX_DEPTH_OF_IF_CONSTRUCT = "max_depth_of_if_construct"
|
|
170
|
+
NUM_LINK_STEPS = "num_link_steps"
|
|
171
|
+
NUM_CALL_STEPS = "num_call_steps"
|
|
172
|
+
NUM_SHARED_SLOTS_BETWEEN_FLOWS = "num_shared_slots_between_flows"
|
|
173
|
+
LLM_COMMAND_GENERATOR_MODEL_NAME = "llm_command_generator_model_name"
|
|
174
|
+
LLM_COMMAND_GENERATOR_MODEL_GROUP_ID = "llm_command_generator_model_group_id"
|
|
175
|
+
LLM_COMMAND_GENERATOR_CUSTOM_PROMPT_USED = "llm_command_generator_custom_prompt_used"
|
|
176
|
+
MULTI_STEP_LLM_COMMAND_GENERATOR_HANDLE_FLOWS_PROMPT_USED = (
|
|
177
|
+
"multi_step_llm_command_generator_custom_handle_flows_prompt_used"
|
|
178
|
+
)
|
|
179
|
+
MULTI_STEP_LLM_COMMAND_GENERATOR_FILL_SLOTS_PROMPT_USED = (
|
|
180
|
+
"multi_step_llm_command_generator_custom_fill_slots_prompt_used"
|
|
181
|
+
)
|
|
182
|
+
FLOW_RETRIEVAL_ENABLED = "flow_retrieval_enabled"
|
|
183
|
+
FLOW_RETRIEVAL_EMBEDDING_MODEL_NAME = "flow_retrieval_embedding_model_name"
|
|
184
|
+
FLOW_RETRIEVAL_EMBEDDING_MODEL_GROUP_ID = "flow_retrieval_embedding_model_group_id"
|
|
185
|
+
TRACING_BACKEND = "tracing_backend"
|
|
186
|
+
METRICS_BACKEND = "metrics_backend"
|
|
187
|
+
VERSION = "version"
|
|
188
|
+
|
|
189
|
+
# E2E test conversion
|
|
190
|
+
TELEMETRY_E2E_TEST_CONVERSION_EVENT = "E2E Test Conversion Completed"
|
|
191
|
+
E2E_TEST_CONVERSION_FILE_TYPE = "file_type"
|
|
192
|
+
E2E_TEST_CONVERSION_TEST_CASE_COUNT = "test_case_count"
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def print_telemetry_reporting_info() -> None:
|
|
196
|
+
"""Print telemetry information to std out."""
|
|
197
|
+
message = textwrap.dedent(
|
|
198
|
+
f"""
|
|
199
|
+
Rasa Pro reports anonymous usage telemetry to help improve the product
|
|
200
|
+
for all its users.
|
|
201
|
+
|
|
202
|
+
If you'd like to opt-out, you can use `rasa telemetry disable`.
|
|
203
|
+
To learn more, check out {DOCS_URL_TELEMETRY}."""
|
|
204
|
+
).strip()
|
|
205
|
+
|
|
206
|
+
table = SingleTable([[message]])
|
|
207
|
+
print(table.table)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _default_telemetry_configuration(is_enabled: bool) -> Dict[Text, Any]:
|
|
211
|
+
return {
|
|
212
|
+
CONFIG_TELEMETRY_ENABLED: is_enabled,
|
|
213
|
+
CONFIG_TELEMETRY_ID: uuid.uuid4().hex,
|
|
214
|
+
CONFIG_TELEMETRY_DATE: datetime.now(),
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _write_default_telemetry_configuration(
|
|
219
|
+
is_enabled: bool = TELEMETRY_ENABLED_BY_DEFAULT,
|
|
220
|
+
) -> bool:
|
|
221
|
+
new_config = _default_telemetry_configuration(is_enabled)
|
|
222
|
+
|
|
223
|
+
keys = [CONFIG_FILE_TELEMETRY_KEY, RASA_PRO_CONFIG_FILE_TELEMETRY_KEY]
|
|
224
|
+
|
|
225
|
+
success = all(
|
|
226
|
+
[rasa_utils.write_global_config_value(key, new_config) for key in keys]
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
# Do not show info if user has enabled/disabled telemetry via env var
|
|
230
|
+
telemetry_environ = os.environ.get(TELEMETRY_ENABLED_ENVIRONMENT_VARIABLE)
|
|
231
|
+
if is_enabled and success and telemetry_environ is None:
|
|
232
|
+
print_telemetry_reporting_info()
|
|
233
|
+
|
|
234
|
+
return success
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def _is_telemetry_enabled_in_configuration() -> bool:
|
|
238
|
+
"""Read telemetry configuration from the user's Rasa config file in $HOME.
|
|
239
|
+
|
|
240
|
+
Creates a default configuration if no configuration exists.
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
`True`, if telemetry is enabled, `False` otherwise.
|
|
244
|
+
"""
|
|
245
|
+
try:
|
|
246
|
+
stored_config = rasa_utils.read_global_config_value(
|
|
247
|
+
CONFIG_FILE_TELEMETRY_KEY, unavailable_ok=False
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
return stored_config[CONFIG_TELEMETRY_ENABLED]
|
|
251
|
+
except ValueError as e:
|
|
252
|
+
logger.debug(f"Could not read telemetry settings from configuration file: {e}")
|
|
253
|
+
|
|
254
|
+
# seems like there is no config, we'll create one and enable telemetry
|
|
255
|
+
success = _write_default_telemetry_configuration()
|
|
256
|
+
# if writing the configuration failed, telemetry will be disabled
|
|
257
|
+
return TELEMETRY_ENABLED_BY_DEFAULT and success
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def is_telemetry_enabled() -> bool:
|
|
261
|
+
"""Check if telemetry is enabled either in configuration or environment.
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
`True`, if telemetry is enabled, `False` otherwise.
|
|
265
|
+
"""
|
|
266
|
+
from rasa.utils import licensing
|
|
267
|
+
|
|
268
|
+
if licensing.is_champion_server_license():
|
|
269
|
+
logger.debug("Telemetry is enabled for developer licenses.")
|
|
270
|
+
return True
|
|
271
|
+
|
|
272
|
+
telemetry_environ = os.environ.get(TELEMETRY_ENABLED_ENVIRONMENT_VARIABLE)
|
|
273
|
+
|
|
274
|
+
if telemetry_environ is not None:
|
|
275
|
+
return telemetry_environ.lower() == "true"
|
|
276
|
+
|
|
277
|
+
try:
|
|
278
|
+
return rasa_utils.read_global_config_value(
|
|
279
|
+
CONFIG_FILE_TELEMETRY_KEY, unavailable_ok=False
|
|
280
|
+
)[CONFIG_TELEMETRY_ENABLED]
|
|
281
|
+
except ValueError:
|
|
282
|
+
return False
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def initialize_telemetry() -> bool:
|
|
286
|
+
"""Read telemetry configuration from the user's Rasa config file in $HOME.
|
|
287
|
+
|
|
288
|
+
Creates a default configuration if no configuration exists.
|
|
289
|
+
|
|
290
|
+
Returns:
|
|
291
|
+
`True`, if telemetry is enabled, `False` otherwise.
|
|
292
|
+
"""
|
|
293
|
+
try:
|
|
294
|
+
# calling this even if the environment variable is set makes sure the
|
|
295
|
+
# configuration is created and there is a telemetry ID
|
|
296
|
+
is_enabled_in_configuration = _is_telemetry_enabled_in_configuration()
|
|
297
|
+
|
|
298
|
+
telemetry_environ = os.environ.get(TELEMETRY_ENABLED_ENVIRONMENT_VARIABLE)
|
|
299
|
+
|
|
300
|
+
if telemetry_environ is None:
|
|
301
|
+
return is_enabled_in_configuration
|
|
302
|
+
|
|
303
|
+
return telemetry_environ.lower() == "true"
|
|
304
|
+
except Exception as e: # skipcq:PYL-W0703
|
|
305
|
+
logger.exception(
|
|
306
|
+
f"Failed to initialize telemetry reporting: {e}."
|
|
307
|
+
f"Telemetry reporting will be disabled."
|
|
308
|
+
)
|
|
309
|
+
return False
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def ensure_telemetry_enabled(f: Callable[..., Any]) -> Callable[..., Any]:
|
|
313
|
+
"""Function decorator for telemetry functions that ensures telemetry is enabled.
|
|
314
|
+
|
|
315
|
+
WARNING: does not work as a decorator for async generators.
|
|
316
|
+
|
|
317
|
+
Args:
|
|
318
|
+
f: function to call if telemetry is enabled
|
|
319
|
+
Returns:
|
|
320
|
+
Return wrapped function
|
|
321
|
+
"""
|
|
322
|
+
# allows us to use the decorator for async generator functions
|
|
323
|
+
if inspect.isasyncgenfunction(f):
|
|
324
|
+
|
|
325
|
+
@wraps(f)
|
|
326
|
+
async def decorated_async_gen(*args: Any, **kwargs: Any) -> Any:
|
|
327
|
+
if is_telemetry_enabled():
|
|
328
|
+
yield f(*args, **kwargs)
|
|
329
|
+
|
|
330
|
+
return decorated_async_gen
|
|
331
|
+
|
|
332
|
+
# allows us to use the decorator for async and non async functions
|
|
333
|
+
if asyncio.iscoroutinefunction(f):
|
|
334
|
+
|
|
335
|
+
@wraps(f)
|
|
336
|
+
async def decorated_coroutine(*args: Any, **kwargs: Any) -> Any:
|
|
337
|
+
if is_telemetry_enabled():
|
|
338
|
+
return await f(*args, **kwargs)
|
|
339
|
+
return None
|
|
340
|
+
|
|
341
|
+
return decorated_coroutine
|
|
342
|
+
|
|
343
|
+
@wraps(f)
|
|
344
|
+
def decorated(*args: Any, **kwargs: Any) -> Any:
|
|
345
|
+
if is_telemetry_enabled():
|
|
346
|
+
return f(*args, **kwargs)
|
|
347
|
+
return None
|
|
348
|
+
|
|
349
|
+
return decorated
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def _fetch_write_key(tool: Text, environment_variable: Text) -> Optional[Text]:
|
|
353
|
+
"""Read the write key from a tool from our set of keys.
|
|
354
|
+
|
|
355
|
+
Args:
|
|
356
|
+
tool: name of the tool we want to fetch a key for
|
|
357
|
+
environment_variable: name of the environment variable to set the key
|
|
358
|
+
Returns:
|
|
359
|
+
write key, if a key was present.
|
|
360
|
+
"""
|
|
361
|
+
import importlib_resources
|
|
362
|
+
|
|
363
|
+
from rasa import __name__ as name
|
|
364
|
+
|
|
365
|
+
if os.environ.get(environment_variable):
|
|
366
|
+
# a write key set using the environment variable will always
|
|
367
|
+
# overwrite any key provided as part of the package (`keys` file)
|
|
368
|
+
return os.environ.get(environment_variable)
|
|
369
|
+
|
|
370
|
+
write_key_path = str(importlib_resources.files(name).joinpath("keys"))
|
|
371
|
+
|
|
372
|
+
# noinspection PyBroadException
|
|
373
|
+
try:
|
|
374
|
+
with open(write_key_path) as f:
|
|
375
|
+
return json.load(f).get(tool)
|
|
376
|
+
except Exception: # skipcq:PYL-W0703
|
|
377
|
+
return None
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def telemetry_write_key() -> Optional[Text]:
|
|
381
|
+
"""Read the Segment write key from the segment key text file.
|
|
382
|
+
|
|
383
|
+
The segment key text file should by present only in wheel/sdist packaged
|
|
384
|
+
versions of Rasa Pro. This avoids running telemetry locally when
|
|
385
|
+
developing on Rasa or when running CI builds.
|
|
386
|
+
|
|
387
|
+
In local development, this should always return `None` to avoid logging telemetry.
|
|
388
|
+
|
|
389
|
+
Returns:
|
|
390
|
+
Segment write key, if the key file was present.
|
|
391
|
+
"""
|
|
392
|
+
return _fetch_write_key("segment", TELEMETRY_WRITE_KEY_ENVIRONMENT_VARIABLE)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def sentry_write_key() -> Optional[Text]:
|
|
396
|
+
"""Read the sentry write key from the sentry key text file.
|
|
397
|
+
|
|
398
|
+
Returns:
|
|
399
|
+
Sentry write key, if the key file was present.
|
|
400
|
+
"""
|
|
401
|
+
return _fetch_write_key("sentry", EXCEPTION_WRITE_KEY_ENVIRONMENT_VARIABLE)
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
def _encode_base64(original: Text, encoding: Text = "utf-8") -> Text:
|
|
405
|
+
"""Encodes a string as a base64 string.
|
|
406
|
+
|
|
407
|
+
Args:
|
|
408
|
+
original: Text to be encoded.
|
|
409
|
+
encoding: Encoding used to convert text to binary.
|
|
410
|
+
|
|
411
|
+
Returns:
|
|
412
|
+
Encoded text.
|
|
413
|
+
"""
|
|
414
|
+
import base64
|
|
415
|
+
|
|
416
|
+
return base64.b64encode(original.encode(encoding)).decode(encoding)
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
def segment_request_header(write_key: Text) -> Dict[Text, Any]:
|
|
420
|
+
"""Use a segment write key to create authentication headers for the segment API.
|
|
421
|
+
|
|
422
|
+
Args:
|
|
423
|
+
write_key: Authentication key for segment.
|
|
424
|
+
|
|
425
|
+
Returns:
|
|
426
|
+
Authentication headers for segment.
|
|
427
|
+
"""
|
|
428
|
+
return {
|
|
429
|
+
"Authorization": "Basic {}".format(_encode_base64(write_key + ":")),
|
|
430
|
+
"Content-Type": "application/json",
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
def segment_request_payload(
|
|
435
|
+
distinct_id: Text,
|
|
436
|
+
event_name: Text,
|
|
437
|
+
properties: Dict[Text, Any],
|
|
438
|
+
context: Dict[Text, Any],
|
|
439
|
+
) -> Dict[Text, Any]:
|
|
440
|
+
"""Compose a valid payload for the segment API.
|
|
441
|
+
|
|
442
|
+
Args:
|
|
443
|
+
distinct_id: Unique telemetry ID.
|
|
444
|
+
event_name: Name of the event.
|
|
445
|
+
properties: Values to report along the event.
|
|
446
|
+
context: Context information about the event.
|
|
447
|
+
|
|
448
|
+
Returns:
|
|
449
|
+
Valid segment payload.
|
|
450
|
+
"""
|
|
451
|
+
return {
|
|
452
|
+
"userId": distinct_id,
|
|
453
|
+
"event": event_name,
|
|
454
|
+
"properties": properties,
|
|
455
|
+
"context": context,
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
def in_continuous_integration() -> bool:
|
|
460
|
+
"""Returns `True` if currently running inside a continuous integration context."""
|
|
461
|
+
return any(env in os.environ for env in CI_ENVIRONMENT_TELL)
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def _is_telemetry_debug_enabled() -> bool:
|
|
465
|
+
"""Check if telemetry debug mode is enabled."""
|
|
466
|
+
return (
|
|
467
|
+
os.environ.get(TELEMETRY_DEBUG_ENVIRONMENT_VARIABLE, "false").lower() == "true"
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
def print_telemetry_payload(payload: Dict[Text, Any]) -> None:
|
|
472
|
+
"""Print a telemetry payload to the commandline.
|
|
473
|
+
|
|
474
|
+
Args:
|
|
475
|
+
payload: payload to be delivered to segment.
|
|
476
|
+
"""
|
|
477
|
+
payload_json = json.dumps(payload, indent=2)
|
|
478
|
+
logger.debug(f"Telemetry payload: {payload_json}")
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
def _get_telemetry_write_key() -> Optional[Text]:
|
|
482
|
+
if os.environ.get(TELEMETRY_WRITE_KEY_ENVIRONMENT_VARIABLE):
|
|
483
|
+
return os.environ.get(TELEMETRY_WRITE_KEY_ENVIRONMENT_VARIABLE)
|
|
484
|
+
|
|
485
|
+
write_key_path = str(importlib_resources.files(rasa.__name__).joinpath("keys"))
|
|
486
|
+
|
|
487
|
+
try:
|
|
488
|
+
with open(write_key_path) as f:
|
|
489
|
+
return json.load(f).get("segment")
|
|
490
|
+
except Exception:
|
|
491
|
+
return None
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def _send_event(
|
|
495
|
+
distinct_id: Text,
|
|
496
|
+
event_name: Text,
|
|
497
|
+
properties: Dict[Text, Any],
|
|
498
|
+
context: Dict[Text, Any],
|
|
499
|
+
) -> None:
|
|
500
|
+
"""Report the contents segmentof an event to the /track Segment endpoint.
|
|
501
|
+
|
|
502
|
+
Documentation: https://.com/docs/sources/server/http/
|
|
503
|
+
|
|
504
|
+
Do not call this function from outside telemetry.py! This function does not
|
|
505
|
+
check if telemetry is enabled or not.
|
|
506
|
+
|
|
507
|
+
Args:
|
|
508
|
+
distinct_id: Unique telemetry ID.
|
|
509
|
+
event_name: Name of the event.
|
|
510
|
+
properties: Values to report along the event.
|
|
511
|
+
context: Context information about the event.
|
|
512
|
+
"""
|
|
513
|
+
payload = segment_request_payload(distinct_id, event_name, properties, context)
|
|
514
|
+
|
|
515
|
+
_send_request(SEGMENT_TRACK_ENDPOINT, payload)
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
def _send_request(url: Text, payload: Dict[Text, Any]) -> None:
|
|
519
|
+
"""Send a request to the Segment API.
|
|
520
|
+
|
|
521
|
+
Args:
|
|
522
|
+
url: URL of the Segment API endpoint
|
|
523
|
+
payload: payload to send to the Segment API
|
|
524
|
+
"""
|
|
525
|
+
if _is_telemetry_debug_enabled():
|
|
526
|
+
print_telemetry_payload(payload)
|
|
527
|
+
return
|
|
528
|
+
|
|
529
|
+
write_key = _get_telemetry_write_key()
|
|
530
|
+
if not write_key:
|
|
531
|
+
# If RASA_TELEMETRY_WRITE_KEY is empty or `None`, telemetry has not
|
|
532
|
+
# been enabled for this build (e.g. because it is running from source)
|
|
533
|
+
logger.debug("Skipping request to external service: telemetry key not set.")
|
|
534
|
+
return
|
|
535
|
+
|
|
536
|
+
headers = rasa.telemetry.segment_request_header(write_key)
|
|
537
|
+
|
|
538
|
+
resp = requests.post(
|
|
539
|
+
url=url,
|
|
540
|
+
headers=headers,
|
|
541
|
+
json=payload,
|
|
542
|
+
timeout=SEGMENT_REQUEST_TIMEOUT,
|
|
543
|
+
)
|
|
544
|
+
# handle different failure cases
|
|
545
|
+
if resp.status_code != 200:
|
|
546
|
+
logger.debug(
|
|
547
|
+
f"Segment telemetry request returned a {resp.status_code} response. "
|
|
548
|
+
f"Body: {resp.text}"
|
|
549
|
+
)
|
|
550
|
+
else:
|
|
551
|
+
data = resp.json()
|
|
552
|
+
if not data.get("success"):
|
|
553
|
+
logger.debug(
|
|
554
|
+
f"Segment telemetry request returned a failure. Response: {data}"
|
|
555
|
+
)
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
def _hash_directory_path(path: Text) -> Optional[Text]:
|
|
559
|
+
"""Create a hash for the directory.
|
|
560
|
+
|
|
561
|
+
Returns:
|
|
562
|
+
hash of the directories path
|
|
563
|
+
"""
|
|
564
|
+
full_path = Path(path).absolute()
|
|
565
|
+
return hashlib.sha256(str(full_path).encode("utf-8")).hexdigest()
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
# noinspection PyBroadException
|
|
569
|
+
def _is_docker() -> bool:
|
|
570
|
+
"""Guess if we are running in docker environment.
|
|
571
|
+
|
|
572
|
+
Returns:
|
|
573
|
+
`True` if we are running inside docker, `False` otherwise.
|
|
574
|
+
"""
|
|
575
|
+
# first we try to use the env
|
|
576
|
+
try:
|
|
577
|
+
os.stat("/.dockerenv")
|
|
578
|
+
return True
|
|
579
|
+
except Exception: # skipcq:PYL-W0703
|
|
580
|
+
pass
|
|
581
|
+
|
|
582
|
+
# if that didn't work, try to use proc information
|
|
583
|
+
try:
|
|
584
|
+
return "docker" in rasa.shared.utils.io.read_file("/proc/self/cgroup", "utf8")
|
|
585
|
+
except Exception: # skipcq:PYL-W0703
|
|
586
|
+
return False
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
def with_default_context_fields(
|
|
590
|
+
context: Optional[Dict[Text, Any]] = None,
|
|
591
|
+
) -> Dict[Text, Any]:
|
|
592
|
+
"""Return a new context dictionary with default and provided field values merged.
|
|
593
|
+
|
|
594
|
+
The default fields contain only the OS information for now.
|
|
595
|
+
|
|
596
|
+
Args:
|
|
597
|
+
context: Context information about the event.
|
|
598
|
+
|
|
599
|
+
Return:
|
|
600
|
+
A new context.
|
|
601
|
+
"""
|
|
602
|
+
context = context or {}
|
|
603
|
+
|
|
604
|
+
return {**_default_context_fields(), **context}
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
def _default_context_fields() -> Dict[Text, Any]:
|
|
608
|
+
"""Return a dictionary that contains the default context values.
|
|
609
|
+
|
|
610
|
+
Return:
|
|
611
|
+
A new context containing information about the runtime environment.
|
|
612
|
+
"""
|
|
613
|
+
from rasa.utils.licensing import get_license_hash, property_of_active_license
|
|
614
|
+
|
|
615
|
+
global TELEMETRY_CONTEXT
|
|
616
|
+
|
|
617
|
+
if not TELEMETRY_CONTEXT:
|
|
618
|
+
# Make sure to update the example in docs/docs/telemetry/telemetry.mdx
|
|
619
|
+
# if you change / add context
|
|
620
|
+
TELEMETRY_CONTEXT = {
|
|
621
|
+
"os": {"name": platform.system(), "version": platform.release()},
|
|
622
|
+
"ci": in_continuous_integration(),
|
|
623
|
+
"project": model.project_fingerprint(),
|
|
624
|
+
"directory": _hash_directory_path(os.getcwd()),
|
|
625
|
+
"python": sys.version.split(" ")[0],
|
|
626
|
+
"rasa_pro": rasa.__version__,
|
|
627
|
+
"cpu": multiprocessing.cpu_count(),
|
|
628
|
+
"docker": _is_docker(),
|
|
629
|
+
"license_hash": get_license_hash(),
|
|
630
|
+
"company": property_of_active_license(
|
|
631
|
+
lambda active_license: active_license.company
|
|
632
|
+
),
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
# avoid returning the cached dict --> caller could modify the dictionary...
|
|
636
|
+
# usually we would use `lru_cache`, but that doesn't return a dict copy and
|
|
637
|
+
# doesn't work on inner functions, so we need to roll our own caching...
|
|
638
|
+
return TELEMETRY_CONTEXT.copy()
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
def _track(
|
|
642
|
+
event_name: Text,
|
|
643
|
+
properties: Optional[Dict[Text, Any]] = None,
|
|
644
|
+
context: Optional[Dict[Text, Any]] = None,
|
|
645
|
+
) -> None:
|
|
646
|
+
"""Tracks a telemetry event.
|
|
647
|
+
|
|
648
|
+
It is OK to use this function from outside telemetry.py, but note that it
|
|
649
|
+
is recommended to create a new track_xyz() function for complex telemetry
|
|
650
|
+
events, or events that are generated from many parts of the Rasa Pro code.
|
|
651
|
+
|
|
652
|
+
Args:
|
|
653
|
+
event_name: Name of the event.
|
|
654
|
+
properties: Dictionary containing the event's properties.
|
|
655
|
+
context: Dictionary containing some context for this event.
|
|
656
|
+
"""
|
|
657
|
+
try:
|
|
658
|
+
telemetry_id = get_telemetry_id()
|
|
659
|
+
|
|
660
|
+
if not telemetry_id:
|
|
661
|
+
logger.debug("Will not report telemetry events as no ID was found.")
|
|
662
|
+
return
|
|
663
|
+
|
|
664
|
+
if not properties:
|
|
665
|
+
properties = {}
|
|
666
|
+
|
|
667
|
+
properties[TELEMETRY_ID] = telemetry_id
|
|
668
|
+
|
|
669
|
+
# this is an additional check in case _track() is called
|
|
670
|
+
# from a function that is not decorated with @ensure_telemetry_enabled
|
|
671
|
+
if is_telemetry_enabled():
|
|
672
|
+
_send_event(
|
|
673
|
+
telemetry_id,
|
|
674
|
+
event_name,
|
|
675
|
+
properties,
|
|
676
|
+
with_default_context_fields(context),
|
|
677
|
+
)
|
|
678
|
+
except Exception as e: # skipcq:PYL-W0703
|
|
679
|
+
logger.debug(f"Skipping telemetry reporting: {e}")
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
def _identify(
|
|
683
|
+
traits: Optional[Dict[Text, Any]] = None,
|
|
684
|
+
context: Optional[Dict[Text, Any]] = None,
|
|
685
|
+
) -> None:
|
|
686
|
+
"""Tracks telemetry traits.
|
|
687
|
+
|
|
688
|
+
It is OK to use this function from outside telemetry.py, but note that it
|
|
689
|
+
is recommended to create a new track_xyz() function for complex telemetry
|
|
690
|
+
traits, or traits that are generated from many parts of the Rasa Pro code.
|
|
691
|
+
|
|
692
|
+
Args:
|
|
693
|
+
traits: Dictionary containing the tracked traits.
|
|
694
|
+
context: Dictionary containing some context for the traits.
|
|
695
|
+
"""
|
|
696
|
+
try:
|
|
697
|
+
telemetry_id = get_telemetry_id()
|
|
698
|
+
|
|
699
|
+
if not telemetry_id:
|
|
700
|
+
logger.debug("Will not report telemetry events as no ID was found.")
|
|
701
|
+
return
|
|
702
|
+
|
|
703
|
+
if not traits:
|
|
704
|
+
traits = {}
|
|
705
|
+
|
|
706
|
+
_send_traits(telemetry_id, traits, with_default_context_fields(context))
|
|
707
|
+
except Exception as e:
|
|
708
|
+
logger.debug(f"Skipping telemetry reporting: {e}")
|
|
709
|
+
|
|
710
|
+
|
|
711
|
+
def _send_traits(
|
|
712
|
+
distinct_id: Text,
|
|
713
|
+
traits: Dict[Text, Any],
|
|
714
|
+
context: Dict[Text, Any],
|
|
715
|
+
) -> None:
|
|
716
|
+
"""Report the contents of telemetry traits to the /identify Segment endpoint.
|
|
717
|
+
|
|
718
|
+
Do not call this function from outside telemetry.py! This function does not
|
|
719
|
+
check if telemetry is enabled or not.
|
|
720
|
+
|
|
721
|
+
Args:
|
|
722
|
+
distinct_id: Unique telemetry ID.
|
|
723
|
+
traits: Pieces of information to be recorded about
|
|
724
|
+
rasa_plus interface implementations.
|
|
725
|
+
context: Context information to be sent along with traits.
|
|
726
|
+
"""
|
|
727
|
+
payload = segment_identify_request_payload(distinct_id, traits, context)
|
|
728
|
+
|
|
729
|
+
_send_request(SEGMENT_IDENTIFY_ENDPOINT, payload)
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
def segment_identify_request_payload(
|
|
733
|
+
distinct_id: Text,
|
|
734
|
+
traits: Dict[Text, Any],
|
|
735
|
+
context: Dict[Text, Any],
|
|
736
|
+
) -> Dict[Text, Any]:
|
|
737
|
+
"""Compose a valid payload for the segment API.
|
|
738
|
+
|
|
739
|
+
Args:
|
|
740
|
+
distinct_id: Unique telemetry ID.
|
|
741
|
+
traits: Pieces of information to be recorded about
|
|
742
|
+
rasa_plus interface implementations.
|
|
743
|
+
context: Context information to be sent along with traits.
|
|
744
|
+
|
|
745
|
+
Returns:
|
|
746
|
+
Valid segment payload.
|
|
747
|
+
"""
|
|
748
|
+
return {
|
|
749
|
+
"userId": distinct_id,
|
|
750
|
+
"traits": traits,
|
|
751
|
+
"context": context,
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
def get_telemetry_id() -> Optional[Text]:
|
|
756
|
+
"""Return the unique telemetry identifier for this Rasa Pro install.
|
|
757
|
+
|
|
758
|
+
The identifier can be based on the license.
|
|
759
|
+
Otherwise, it can be any string, but it should be a UUID.
|
|
760
|
+
|
|
761
|
+
Returns:
|
|
762
|
+
The identifier, if it is configured correctly.
|
|
763
|
+
"""
|
|
764
|
+
from rasa.utils.licensing import property_of_active_license
|
|
765
|
+
|
|
766
|
+
return property_of_active_license(lambda active_license: active_license.jti)
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
def toggle_telemetry_reporting(is_enabled: bool) -> None:
|
|
770
|
+
"""Write to the configuration if telemetry tracking should be enabled or disabled.
|
|
771
|
+
|
|
772
|
+
Args:
|
|
773
|
+
is_enabled: `True` if the telemetry reporting should be enabled,
|
|
774
|
+
`False` otherwise.
|
|
775
|
+
"""
|
|
776
|
+
configuration = rasa_utils.read_global_config_value(CONFIG_FILE_TELEMETRY_KEY)
|
|
777
|
+
|
|
778
|
+
if configuration:
|
|
779
|
+
configuration[CONFIG_TELEMETRY_ENABLED] = is_enabled
|
|
780
|
+
else:
|
|
781
|
+
configuration = _default_telemetry_configuration(is_enabled)
|
|
782
|
+
|
|
783
|
+
rasa_utils.write_global_config_value(CONFIG_FILE_TELEMETRY_KEY, configuration)
|
|
784
|
+
rasa_utils.write_global_config_value(
|
|
785
|
+
RASA_PRO_CONFIG_FILE_TELEMETRY_KEY, configuration
|
|
786
|
+
)
|
|
787
|
+
|
|
788
|
+
|
|
789
|
+
def filter_errors(
|
|
790
|
+
event: Optional[Dict[Text, Any]], hint: Optional[Dict[Text, Any]] = None
|
|
791
|
+
) -> Optional[Dict[Text, Any]]:
|
|
792
|
+
"""Filter errors.
|
|
793
|
+
|
|
794
|
+
Args:
|
|
795
|
+
event: event to be logged to sentry
|
|
796
|
+
hint: some hinting information sent alongside of the event
|
|
797
|
+
|
|
798
|
+
Returns:
|
|
799
|
+
the event without any sensitive / PII data or `None` if the event constitutes
|
|
800
|
+
an `ImportError` which should be discarded.
|
|
801
|
+
"""
|
|
802
|
+
if hint and "exc_info" in hint:
|
|
803
|
+
exc_type, exc_value, tb = hint["exc_info"]
|
|
804
|
+
if isinstance(exc_value, ImportError):
|
|
805
|
+
return None
|
|
806
|
+
return event
|
|
807
|
+
|
|
808
|
+
|
|
809
|
+
def before_send(
|
|
810
|
+
event: Dict[Text, Any], _unused_hint: Optional[Dict[Text, Any]] = None
|
|
811
|
+
) -> Optional[Dict[Text, Any]]:
|
|
812
|
+
"""Strips the sensitive data and filters errors before sending to sentry.
|
|
813
|
+
|
|
814
|
+
Args:
|
|
815
|
+
event: event to be logged to sentry
|
|
816
|
+
_unused_hint: some hinting information sent alongside of the event
|
|
817
|
+
|
|
818
|
+
Returns:
|
|
819
|
+
the event without any sensitive / PII data or `None` if the event should
|
|
820
|
+
be discarded.
|
|
821
|
+
"""
|
|
822
|
+
cleaned_event = strip_sensitive_data_from_sentry_event(event, _unused_hint)
|
|
823
|
+
return filter_errors(cleaned_event, _unused_hint)
|
|
824
|
+
|
|
825
|
+
|
|
826
|
+
def strip_sensitive_data_from_sentry_event(
|
|
827
|
+
event: Dict[Text, Any], _unused_hint: Optional[Dict[Text, Any]] = None
|
|
828
|
+
) -> Optional[Dict[Text, Any]]:
|
|
829
|
+
"""Remove any sensitive data from the event (e.g. path names).
|
|
830
|
+
|
|
831
|
+
Args:
|
|
832
|
+
event: event to be logged to sentry
|
|
833
|
+
_unused_hint: some hinting information sent alongside of the event
|
|
834
|
+
|
|
835
|
+
Returns:
|
|
836
|
+
the event without any sensitive / PII data or `None` if the event should
|
|
837
|
+
be discarded.
|
|
838
|
+
"""
|
|
839
|
+
# removes any paths from stack traces (avoids e.g. sending
|
|
840
|
+
# a users home directory name if package is installed there)
|
|
841
|
+
for value in event.get("exception", {}).get("values", []):
|
|
842
|
+
for frame in value.get("stacktrace", {}).get("frames", []):
|
|
843
|
+
frame["abs_path"] = ""
|
|
844
|
+
|
|
845
|
+
if f"rasa_sdk{os.path.sep}executor.py" in frame["filename"]:
|
|
846
|
+
# this looks a lot like an exception in the SDK and hence custom code
|
|
847
|
+
# no need for us to deal with that
|
|
848
|
+
return None
|
|
849
|
+
elif "site-packages" in frame["filename"]:
|
|
850
|
+
# drop site-packages and following slash / backslash
|
|
851
|
+
relative_name = frame["filename"].split("site-packages")[-1][1:]
|
|
852
|
+
frame["filename"] = os.path.join("site-packages", relative_name)
|
|
853
|
+
elif "dist-packages" in frame["filename"]:
|
|
854
|
+
# drop dist-packages and following slash / backslash
|
|
855
|
+
relative_name = frame["filename"].split("dist-packages")[-1][1:]
|
|
856
|
+
frame["filename"] = os.path.join("dist-packages", relative_name)
|
|
857
|
+
elif os.path.isabs(frame["filename"]):
|
|
858
|
+
# if the file path is absolute, we'll drop the whole event as this is
|
|
859
|
+
# very likely custom code. needs to happen after cleaning as
|
|
860
|
+
# site-packages / dist-packages paths are also absolute, but fine.
|
|
861
|
+
return None
|
|
862
|
+
return event
|
|
863
|
+
|
|
864
|
+
|
|
865
|
+
@ensure_telemetry_enabled
|
|
866
|
+
def initialize_error_reporting() -> None:
|
|
867
|
+
"""Sets up automated error reporting.
|
|
868
|
+
|
|
869
|
+
Exceptions are reported to sentry. We avoid sending any metadata (local
|
|
870
|
+
variables, paths, ...) to make sure we don't compromise any data. Only the
|
|
871
|
+
exception and its stacktrace is logged and only if the exception origins
|
|
872
|
+
from the `rasa` package.
|
|
873
|
+
"""
|
|
874
|
+
import sentry_sdk
|
|
875
|
+
from sentry_sdk import configure_scope
|
|
876
|
+
from sentry_sdk.integrations.atexit import AtexitIntegration
|
|
877
|
+
from sentry_sdk.integrations.dedupe import DedupeIntegration
|
|
878
|
+
from sentry_sdk.integrations.excepthook import ExcepthookIntegration
|
|
879
|
+
|
|
880
|
+
# key for local testing can be found at
|
|
881
|
+
# https://sentry.io/settings/rasahq/projects/rasa-open-source/install/python/
|
|
882
|
+
# for local testing, set the key using `RASA_EXCEPTION_WRITE_KEY=key rasa <command>`
|
|
883
|
+
key = sentry_write_key()
|
|
884
|
+
|
|
885
|
+
if not key:
|
|
886
|
+
return
|
|
887
|
+
|
|
888
|
+
telemetry_id = get_telemetry_id()
|
|
889
|
+
|
|
890
|
+
# this is a very defensive configuration, avoiding as many integrations as
|
|
891
|
+
# possible. it also submits very little data (exception with error message
|
|
892
|
+
# and line numbers).
|
|
893
|
+
sentry_sdk.init(
|
|
894
|
+
f"https://{key}.ingest.sentry.io/2801673",
|
|
895
|
+
before_send=before_send,
|
|
896
|
+
integrations=[
|
|
897
|
+
ExcepthookIntegration(),
|
|
898
|
+
DedupeIntegration(),
|
|
899
|
+
AtexitIntegration(lambda _, __: None),
|
|
900
|
+
],
|
|
901
|
+
send_default_pii=False, # activate PII filter
|
|
902
|
+
server_name=telemetry_id or "UNKNOWN",
|
|
903
|
+
ignore_errors=[
|
|
904
|
+
# std lib errors
|
|
905
|
+
KeyboardInterrupt, # user hit the interrupt key (Ctrl+C)
|
|
906
|
+
MemoryError, # machine is running out of memory
|
|
907
|
+
NotImplementedError, # user is using a feature that is not implemented
|
|
908
|
+
asyncio.CancelledError, # an async operation has been cancelled by the user
|
|
909
|
+
# expected Rasa errors
|
|
910
|
+
RasaException,
|
|
911
|
+
OSError,
|
|
912
|
+
],
|
|
913
|
+
in_app_include=["rasa"], # only submit errors in this package
|
|
914
|
+
with_locals=False, # don't submit local variables
|
|
915
|
+
release=f"rasa-{rasa.__version__}",
|
|
916
|
+
default_integrations=False,
|
|
917
|
+
environment="development" if in_continuous_integration() else "production",
|
|
918
|
+
)
|
|
919
|
+
|
|
920
|
+
if not telemetry_id:
|
|
921
|
+
return
|
|
922
|
+
|
|
923
|
+
with configure_scope() as scope:
|
|
924
|
+
# sentry added these more recently, just a protection in a case where a
|
|
925
|
+
# user has installed an older version of sentry
|
|
926
|
+
if hasattr(scope, "set_user"):
|
|
927
|
+
scope.set_user({"id": telemetry_id})
|
|
928
|
+
|
|
929
|
+
default_context = _default_context_fields()
|
|
930
|
+
if hasattr(scope, "set_context"):
|
|
931
|
+
if "os" in default_context:
|
|
932
|
+
# os is a nested dict, hence we report it separately
|
|
933
|
+
scope.set_context("Operating System", default_context.pop("os"))
|
|
934
|
+
scope.set_context("Environment", default_context)
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
@contextlib.contextmanager
|
|
938
|
+
def track_model_training(
|
|
939
|
+
training_data: "TrainingDataImporter", model_type: Text, is_finetuning: bool = False
|
|
940
|
+
) -> typing.Generator[None, None, None]:
|
|
941
|
+
"""Track a model training started.
|
|
942
|
+
|
|
943
|
+
WARNING: since this is a generator, it can't use the ensure telemetry
|
|
944
|
+
decorator. We need to manually add these checks here. This can be
|
|
945
|
+
fixed as soon as we drop python 3.6 support.
|
|
946
|
+
|
|
947
|
+
Args:
|
|
948
|
+
training_data: Training data used for the training.
|
|
949
|
+
model_type: Specifies the type of training, should be either "rasa", "core"
|
|
950
|
+
or "nlu".
|
|
951
|
+
is_finetuning: `True` if the model is trained by finetuning another model.
|
|
952
|
+
"""
|
|
953
|
+
if not initialize_telemetry():
|
|
954
|
+
# telemetry reporting is disabled. we won't do any reporting
|
|
955
|
+
yield # runs the training
|
|
956
|
+
return
|
|
957
|
+
|
|
958
|
+
config = training_data.get_config()
|
|
959
|
+
stories = training_data.get_stories()
|
|
960
|
+
nlu_data = training_data.get_nlu_data()
|
|
961
|
+
domain = training_data.get_domain()
|
|
962
|
+
flows = training_data.get_flows()
|
|
963
|
+
count_conditional_responses = domain.count_conditional_response_variations()
|
|
964
|
+
(
|
|
965
|
+
count_total_mappings,
|
|
966
|
+
count_custom_mappings,
|
|
967
|
+
count_conditional_mappings,
|
|
968
|
+
) = domain.count_slot_mapping_statistics()
|
|
969
|
+
|
|
970
|
+
training_id = uuid.uuid4().hex
|
|
971
|
+
|
|
972
|
+
tracking_data = {
|
|
973
|
+
"language": config.get(CONFIG_LANGUAGE_KEY),
|
|
974
|
+
"training_id": training_id,
|
|
975
|
+
"type": model_type,
|
|
976
|
+
"pipeline": config.get(CONFIG_PIPELINE_KEY),
|
|
977
|
+
"policies": config.get(CONFIG_POLICIES_KEY),
|
|
978
|
+
"train_schema": config.get(CONFIG_TRAIN_SCHEMA),
|
|
979
|
+
"predict_schema": config.get(CONFIG_PREDICT_SCHEMA),
|
|
980
|
+
"model_groups": rasa.core.utils.AvailableEndpoints.get_instance().model_groups,
|
|
981
|
+
"api_health_check_enabled": (
|
|
982
|
+
os.getenv(
|
|
983
|
+
LLM_API_HEALTH_CHECK_ENV_VAR, LLM_API_HEALTH_CHECK_DEFAULT_VALUE
|
|
984
|
+
).lower()
|
|
985
|
+
== "true"
|
|
986
|
+
),
|
|
987
|
+
"num_intent_examples": len(nlu_data.intent_examples),
|
|
988
|
+
"num_entity_examples": len(nlu_data.entity_examples),
|
|
989
|
+
"num_actions": len(domain.action_names_or_texts),
|
|
990
|
+
# Old nomenclature from when 'responses' were still called
|
|
991
|
+
# 'templates' in the domain
|
|
992
|
+
"num_templates": len(domain.responses),
|
|
993
|
+
"num_conditional_response_variations": count_conditional_responses,
|
|
994
|
+
"num_slot_mappings": count_total_mappings,
|
|
995
|
+
"num_custom_slot_mappings": count_custom_mappings,
|
|
996
|
+
"num_conditional_slot_mappings": count_conditional_mappings,
|
|
997
|
+
"num_slots": len(domain.slots),
|
|
998
|
+
"num_forms": len(domain.forms),
|
|
999
|
+
"num_intents": len(domain.intents),
|
|
1000
|
+
"num_entities": len(domain.entities),
|
|
1001
|
+
"num_story_steps": len(stories.story_steps),
|
|
1002
|
+
"num_lookup_tables": len(nlu_data.lookup_tables),
|
|
1003
|
+
"num_synonyms": len(nlu_data.entity_synonyms),
|
|
1004
|
+
"num_regexes": len(nlu_data.regex_features),
|
|
1005
|
+
"is_finetuning": is_finetuning,
|
|
1006
|
+
"recipe": config.get(CONFIG_RECIPE_KEY),
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
flow_statistics = _collect_flow_statistics(flows.underlying_flows)
|
|
1010
|
+
tracking_data.update(flow_statistics)
|
|
1011
|
+
command_generator_settings = _get_llm_command_generator_config(config)
|
|
1012
|
+
tracking_data.update(command_generator_settings)
|
|
1013
|
+
|
|
1014
|
+
# Make sure to update the example in docs/docs/telemetry/telemetry.mdx
|
|
1015
|
+
# if you change / add any properties
|
|
1016
|
+
_track(
|
|
1017
|
+
TRAINING_STARTED_EVENT,
|
|
1018
|
+
tracking_data,
|
|
1019
|
+
)
|
|
1020
|
+
start = datetime.now()
|
|
1021
|
+
yield
|
|
1022
|
+
runtime = datetime.now() - start
|
|
1023
|
+
|
|
1024
|
+
_track(
|
|
1025
|
+
TRAINING_COMPLETED_EVENT,
|
|
1026
|
+
{
|
|
1027
|
+
"training_id": training_id,
|
|
1028
|
+
"type": model_type,
|
|
1029
|
+
"runtime": int(runtime.total_seconds()),
|
|
1030
|
+
},
|
|
1031
|
+
)
|
|
1032
|
+
|
|
1033
|
+
|
|
1034
|
+
def _collect_flow_statistics(flows: List[Flow]) -> Dict[str, Any]:
|
|
1035
|
+
"""Collects some statistics about the flows, such as number of specific steps."""
|
|
1036
|
+
data = {
|
|
1037
|
+
NUM_FLOWS: len(flows),
|
|
1038
|
+
NUM_FLOWS_WITH_NLU_TRIGGER: 0,
|
|
1039
|
+
NUM_FLOWS_WITH_FLOW_GUARDS: 0,
|
|
1040
|
+
NUM_FLOWS_ALWAYS_INCLUDED_IN_PROMPT: 0,
|
|
1041
|
+
NUM_FLOWS_WITH_NOT_STARTABLE_FLOW_GUARDS: 0,
|
|
1042
|
+
NUM_COLLECT_STEPS: 0,
|
|
1043
|
+
NUM_COLLECT_STEPS_WITH_SEPARATE_UTTER: 0,
|
|
1044
|
+
NUM_COLLECT_STEPS_WITH_REJECTIONS: 0,
|
|
1045
|
+
NUM_COLLECT_STEPS_WITH_NOT_RESET_AFTER_FLOW_ENDS: 0,
|
|
1046
|
+
NUM_SET_SLOT_STEPS: 0,
|
|
1047
|
+
MAX_DEPTH_OF_IF_CONSTRUCT: 0,
|
|
1048
|
+
NUM_LINK_STEPS: 0,
|
|
1049
|
+
NUM_CALL_STEPS: 0,
|
|
1050
|
+
NUM_SHARED_SLOTS_BETWEEN_FLOWS: 0,
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
slots_used_in_different_flows = defaultdict(set)
|
|
1054
|
+
|
|
1055
|
+
for flow in flows:
|
|
1056
|
+
if flow.guard_condition:
|
|
1057
|
+
data[NUM_FLOWS_WITH_FLOW_GUARDS] += 1
|
|
1058
|
+
if flow.guard_condition.lower() == "false":
|
|
1059
|
+
data[NUM_FLOWS_WITH_NOT_STARTABLE_FLOW_GUARDS] += 1
|
|
1060
|
+
|
|
1061
|
+
if flow.always_include_in_prompt:
|
|
1062
|
+
data[NUM_FLOWS_ALWAYS_INCLUDED_IN_PROMPT] += 1
|
|
1063
|
+
|
|
1064
|
+
if flow.nlu_triggers:
|
|
1065
|
+
data[NUM_FLOWS_WITH_NLU_TRIGGER] += 1
|
|
1066
|
+
|
|
1067
|
+
for step in flow.steps_with_calls_resolved:
|
|
1068
|
+
if isinstance(step, CollectInformationFlowStep):
|
|
1069
|
+
slots_used_in_different_flows[step.collect].add(flow.id)
|
|
1070
|
+
data[NUM_COLLECT_STEPS] += 1
|
|
1071
|
+
if len(step.rejections) > 0:
|
|
1072
|
+
data[NUM_COLLECT_STEPS_WITH_REJECTIONS] += 1
|
|
1073
|
+
if not step.reset_after_flow_ends:
|
|
1074
|
+
data[NUM_COLLECT_STEPS_WITH_NOT_RESET_AFTER_FLOW_ENDS] += 1
|
|
1075
|
+
if step.utter != f"{UTTER_ASK_PREFIX}{step.collect}":
|
|
1076
|
+
data[NUM_COLLECT_STEPS_WITH_SEPARATE_UTTER] += 1
|
|
1077
|
+
|
|
1078
|
+
if isinstance(step, SetSlotsFlowStep):
|
|
1079
|
+
for slot in step.slots:
|
|
1080
|
+
slots_used_in_different_flows[slot["key"]].add(flow.id)
|
|
1081
|
+
data[NUM_SET_SLOT_STEPS] += 1
|
|
1082
|
+
|
|
1083
|
+
if isinstance(step, LinkFlowStep):
|
|
1084
|
+
data[NUM_LINK_STEPS] += 1
|
|
1085
|
+
|
|
1086
|
+
if isinstance(step, CallFlowStep):
|
|
1087
|
+
data[NUM_CALL_STEPS] += 1
|
|
1088
|
+
|
|
1089
|
+
if step.next:
|
|
1090
|
+
depth = step.next.depth_in_tree()
|
|
1091
|
+
if depth > data[MAX_DEPTH_OF_IF_CONSTRUCT]:
|
|
1092
|
+
data[MAX_DEPTH_OF_IF_CONSTRUCT] = depth
|
|
1093
|
+
|
|
1094
|
+
for flows_with_slot in slots_used_in_different_flows.values():
|
|
1095
|
+
if len(flows_with_slot) > 1:
|
|
1096
|
+
data[NUM_SHARED_SLOTS_BETWEEN_FLOWS] += 1
|
|
1097
|
+
|
|
1098
|
+
return data
|
|
1099
|
+
|
|
1100
|
+
|
|
1101
|
+
def _get_llm_command_generator_config(config: Dict[str, Any]) -> Optional[Dict]:
|
|
1102
|
+
"""Returns the configuration for the LLMCommandGenerator.
|
|
1103
|
+
|
|
1104
|
+
Includes the model name, whether a custom prompt is used, whether flow
|
|
1105
|
+
retrieval is enabled, and flow retrieval embedding model.
|
|
1106
|
+
"""
|
|
1107
|
+
from rasa.dialogue_understanding.generator import (
|
|
1108
|
+
LLMCommandGenerator,
|
|
1109
|
+
MultiStepLLMCommandGenerator,
|
|
1110
|
+
SingleStepLLMCommandGenerator,
|
|
1111
|
+
)
|
|
1112
|
+
from rasa.dialogue_understanding.generator.constants import (
|
|
1113
|
+
DEFAULT_LLM_CONFIG,
|
|
1114
|
+
FLOW_RETRIEVAL_KEY,
|
|
1115
|
+
LLM_CONFIG_KEY,
|
|
1116
|
+
)
|
|
1117
|
+
from rasa.dialogue_understanding.generator.flow_retrieval import (
|
|
1118
|
+
DEFAULT_EMBEDDINGS_CONFIG,
|
|
1119
|
+
)
|
|
1120
|
+
from rasa.dialogue_understanding.generator.multi_step.multi_step_llm_command_generator import ( # noqa: E501
|
|
1121
|
+
FILL_SLOTS_KEY,
|
|
1122
|
+
HANDLE_FLOWS_KEY,
|
|
1123
|
+
)
|
|
1124
|
+
from rasa.shared.constants import (
|
|
1125
|
+
EMBEDDINGS_CONFIG_KEY,
|
|
1126
|
+
MODEL_CONFIG_KEY,
|
|
1127
|
+
MODEL_NAME_CONFIG_KEY,
|
|
1128
|
+
)
|
|
1129
|
+
|
|
1130
|
+
def find_command_generator_component(pipeline: List) -> Optional[Dict]:
|
|
1131
|
+
"""Finds the LLMCommandGenerator component in the pipeline."""
|
|
1132
|
+
for component in pipeline:
|
|
1133
|
+
if component["name"] in [
|
|
1134
|
+
LLMCommandGenerator.__name__,
|
|
1135
|
+
SingleStepLLMCommandGenerator.__name__,
|
|
1136
|
+
MultiStepLLMCommandGenerator.__name__,
|
|
1137
|
+
]:
|
|
1138
|
+
return component
|
|
1139
|
+
return None
|
|
1140
|
+
|
|
1141
|
+
def extract_llm_command_generator_llm_client_settings(component: Dict) -> Dict:
|
|
1142
|
+
"""Extracts settings related to LLM command generator."""
|
|
1143
|
+
llm_config = component.get(LLM_CONFIG_KEY, {})
|
|
1144
|
+
# Config at this stage is not yet resolved, so read from `model_group`
|
|
1145
|
+
llm_model_group_id = llm_config.get(MODEL_GROUP_CONFIG_KEY)
|
|
1146
|
+
llm_model_name = llm_config.get(MODEL_CONFIG_KEY) or llm_config.get(
|
|
1147
|
+
MODEL_NAME_CONFIG_KEY
|
|
1148
|
+
)
|
|
1149
|
+
if llm_model_group_id is None and llm_model_name is None:
|
|
1150
|
+
llm_model_name = DEFAULT_LLM_CONFIG[MODEL_CONFIG_KEY]
|
|
1151
|
+
|
|
1152
|
+
custom_prompt_used = (
|
|
1153
|
+
PROMPT_CONFIG_KEY in component or PROMPT_TEMPLATE_CONFIG_KEY in component
|
|
1154
|
+
)
|
|
1155
|
+
return {
|
|
1156
|
+
LLM_COMMAND_GENERATOR_MODEL_NAME: llm_model_name,
|
|
1157
|
+
LLM_COMMAND_GENERATOR_MODEL_GROUP_ID: llm_model_group_id,
|
|
1158
|
+
LLM_COMMAND_GENERATOR_CUSTOM_PROMPT_USED: custom_prompt_used,
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
def extract_multistep_command_generator_prompt_settings(component: Dict) -> Dict:
|
|
1162
|
+
"""Extracts settings related to multistep command generator."""
|
|
1163
|
+
prompt_templates = component.get("prompt_templates", {})
|
|
1164
|
+
handle_flows_prompt_used = HANDLE_FLOWS_KEY in prompt_templates
|
|
1165
|
+
fill_slots_prompt_used = FILL_SLOTS_KEY in prompt_templates
|
|
1166
|
+
return {
|
|
1167
|
+
MULTI_STEP_LLM_COMMAND_GENERATOR_HANDLE_FLOWS_PROMPT_USED: handle_flows_prompt_used, # noqa: E501
|
|
1168
|
+
MULTI_STEP_LLM_COMMAND_GENERATOR_FILL_SLOTS_PROMPT_USED: fill_slots_prompt_used, # noqa: E501
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
def extract_flow_retrieval_settings(component: Dict) -> Dict:
|
|
1172
|
+
"""Extracts settings related to flow retrieval."""
|
|
1173
|
+
flow_retrieval_config = component.get(FLOW_RETRIEVAL_KEY, {})
|
|
1174
|
+
flow_retrieval_enabled = flow_retrieval_config.get("active", True)
|
|
1175
|
+
embeddings_config = flow_retrieval_config.get(
|
|
1176
|
+
EMBEDDINGS_CONFIG_KEY, DEFAULT_EMBEDDINGS_CONFIG
|
|
1177
|
+
)
|
|
1178
|
+
flow_retrieval_embedding_model_name = (
|
|
1179
|
+
(
|
|
1180
|
+
embeddings_config.get(MODEL_NAME_CONFIG_KEY)
|
|
1181
|
+
or embeddings_config.get(MODEL_CONFIG_KEY)
|
|
1182
|
+
)
|
|
1183
|
+
if flow_retrieval_enabled
|
|
1184
|
+
else None
|
|
1185
|
+
)
|
|
1186
|
+
# Config at this stage is not yet resolved, so read from `model_group`
|
|
1187
|
+
flow_retrieval_embedding_model_group_id = embeddings_config.get(
|
|
1188
|
+
MODEL_GROUP_CONFIG_KEY
|
|
1189
|
+
)
|
|
1190
|
+
return {
|
|
1191
|
+
FLOW_RETRIEVAL_ENABLED: flow_retrieval_enabled,
|
|
1192
|
+
FLOW_RETRIEVAL_EMBEDDING_MODEL_NAME: flow_retrieval_embedding_model_name,
|
|
1193
|
+
FLOW_RETRIEVAL_EMBEDDING_MODEL_GROUP_ID: flow_retrieval_embedding_model_group_id, # noqa: E501
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
def extract_settings(component: Dict) -> Dict:
|
|
1197
|
+
"""Extracts the settings from the command generator component."""
|
|
1198
|
+
settings = {}
|
|
1199
|
+
settings.update(extract_llm_command_generator_llm_client_settings(component))
|
|
1200
|
+
settings.update(extract_multistep_command_generator_prompt_settings(component))
|
|
1201
|
+
settings.update(extract_flow_retrieval_settings(component))
|
|
1202
|
+
return settings
|
|
1203
|
+
|
|
1204
|
+
command_generator_config = {
|
|
1205
|
+
LLM_COMMAND_GENERATOR_MODEL_NAME: None,
|
|
1206
|
+
LLM_COMMAND_GENERATOR_MODEL_GROUP_ID: None,
|
|
1207
|
+
LLM_COMMAND_GENERATOR_CUSTOM_PROMPT_USED: None,
|
|
1208
|
+
MULTI_STEP_LLM_COMMAND_GENERATOR_HANDLE_FLOWS_PROMPT_USED: None,
|
|
1209
|
+
MULTI_STEP_LLM_COMMAND_GENERATOR_FILL_SLOTS_PROMPT_USED: None,
|
|
1210
|
+
FLOW_RETRIEVAL_ENABLED: None,
|
|
1211
|
+
FLOW_RETRIEVAL_EMBEDDING_MODEL_NAME: None,
|
|
1212
|
+
FLOW_RETRIEVAL_EMBEDDING_MODEL_GROUP_ID: None,
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
pipeline = config.get(CONFIG_PIPELINE_KEY, [])
|
|
1216
|
+
if not isinstance(pipeline, list):
|
|
1217
|
+
return command_generator_config
|
|
1218
|
+
|
|
1219
|
+
command_generator_component = find_command_generator_component(pipeline)
|
|
1220
|
+
if command_generator_component is not None:
|
|
1221
|
+
extracted_settings = extract_settings(command_generator_component)
|
|
1222
|
+
command_generator_config.update(extracted_settings)
|
|
1223
|
+
|
|
1224
|
+
return command_generator_config
|
|
1225
|
+
|
|
1226
|
+
|
|
1227
|
+
@ensure_telemetry_enabled
|
|
1228
|
+
def track_telemetry_disabled() -> None:
|
|
1229
|
+
"""Track when a user disables telemetry."""
|
|
1230
|
+
_track(TELEMETRY_DISABLED_EVENT)
|
|
1231
|
+
|
|
1232
|
+
|
|
1233
|
+
@ensure_telemetry_enabled
|
|
1234
|
+
def track_data_split(fraction: float, data_type: Text) -> None:
|
|
1235
|
+
"""Track when a user splits data.
|
|
1236
|
+
|
|
1237
|
+
Args:
|
|
1238
|
+
fraction: How much data goes into train and how much goes into test
|
|
1239
|
+
data_type: Is this core, nlu or nlg data
|
|
1240
|
+
"""
|
|
1241
|
+
_track(TELEMETRY_DATA_SPLIT_EVENT, {"fraction": fraction, "type": data_type})
|
|
1242
|
+
|
|
1243
|
+
|
|
1244
|
+
@ensure_telemetry_enabled
|
|
1245
|
+
def track_validate_files(validation_success: bool) -> None:
|
|
1246
|
+
"""Track when a user validates data files.
|
|
1247
|
+
|
|
1248
|
+
Args:
|
|
1249
|
+
validation_success: Whether the validation was successful
|
|
1250
|
+
"""
|
|
1251
|
+
_track(TELEMETRY_DATA_VALIDATED_EVENT, {"validation_success": validation_success})
|
|
1252
|
+
|
|
1253
|
+
|
|
1254
|
+
@ensure_telemetry_enabled
|
|
1255
|
+
def track_data_convert(output_format: Text, data_type: Text) -> None:
|
|
1256
|
+
"""Track when a user converts data.
|
|
1257
|
+
|
|
1258
|
+
Args:
|
|
1259
|
+
output_format: Target format for the converter
|
|
1260
|
+
data_type: Is this core, nlu or nlg data
|
|
1261
|
+
"""
|
|
1262
|
+
_track(
|
|
1263
|
+
TELEMETRY_DATA_CONVERTED_EVENT,
|
|
1264
|
+
{"output_format": output_format, "type": data_type},
|
|
1265
|
+
)
|
|
1266
|
+
|
|
1267
|
+
|
|
1268
|
+
@ensure_telemetry_enabled
|
|
1269
|
+
def track_tracker_export(
|
|
1270
|
+
number_of_exported_events: int,
|
|
1271
|
+
tracker_store: "TrackerStore",
|
|
1272
|
+
event_broker: "EventBroker",
|
|
1273
|
+
) -> None:
|
|
1274
|
+
"""Track when a user exports trackers.
|
|
1275
|
+
|
|
1276
|
+
Args:
|
|
1277
|
+
number_of_exported_events: Number of events that got exported
|
|
1278
|
+
tracker_store: Store used to retrieve the events from
|
|
1279
|
+
event_broker: Broker the events are getting published towards
|
|
1280
|
+
"""
|
|
1281
|
+
_track(
|
|
1282
|
+
TELEMETRY_TRACKER_EXPORTED_EVENT,
|
|
1283
|
+
{
|
|
1284
|
+
"number_of_exported_events": number_of_exported_events,
|
|
1285
|
+
"tracker_store": type(tracker_store).__name__,
|
|
1286
|
+
"event_broker": type(event_broker).__name__,
|
|
1287
|
+
},
|
|
1288
|
+
)
|
|
1289
|
+
|
|
1290
|
+
|
|
1291
|
+
@ensure_telemetry_enabled
|
|
1292
|
+
def track_interactive_learning_start(
|
|
1293
|
+
skip_visualization: bool, save_in_e2e: bool
|
|
1294
|
+
) -> None:
|
|
1295
|
+
"""Track when a user starts an interactive learning session.
|
|
1296
|
+
|
|
1297
|
+
Args:
|
|
1298
|
+
skip_visualization: Is visualization skipped in this session
|
|
1299
|
+
save_in_e2e: Is e2e used in this session
|
|
1300
|
+
"""
|
|
1301
|
+
_track(
|
|
1302
|
+
TELEMETRY_INTERACTIVE_LEARNING_STARTED_EVENT,
|
|
1303
|
+
{"skip_visualization": skip_visualization, "save_in_e2e": save_in_e2e},
|
|
1304
|
+
)
|
|
1305
|
+
|
|
1306
|
+
|
|
1307
|
+
@ensure_telemetry_enabled
|
|
1308
|
+
def track_server_start(
|
|
1309
|
+
input_channels: List["InputChannel"],
|
|
1310
|
+
endpoints: Optional["AvailableEndpoints"],
|
|
1311
|
+
model_directory: Optional[Text],
|
|
1312
|
+
number_of_workers: int,
|
|
1313
|
+
is_api_enabled: bool,
|
|
1314
|
+
) -> None:
|
|
1315
|
+
"""Tracks when a user starts a rasa server.
|
|
1316
|
+
|
|
1317
|
+
Args:
|
|
1318
|
+
input_channels: Used input channels
|
|
1319
|
+
endpoints: Endpoint configuration for the server
|
|
1320
|
+
model_directory: directory of the running model
|
|
1321
|
+
number_of_workers: number of used Sanic workers
|
|
1322
|
+
is_api_enabled: whether the rasa API server is enabled
|
|
1323
|
+
"""
|
|
1324
|
+
from rasa.core.utils import AvailableEndpoints
|
|
1325
|
+
|
|
1326
|
+
def project_fingerprint_from_model(
|
|
1327
|
+
_model_directory: Optional[Text],
|
|
1328
|
+
) -> Optional[Text]:
|
|
1329
|
+
"""Gets project fingerprint from an app's loaded model."""
|
|
1330
|
+
if not model_directory:
|
|
1331
|
+
return None
|
|
1332
|
+
|
|
1333
|
+
try:
|
|
1334
|
+
model_archive = model.get_local_model(_model_directory)
|
|
1335
|
+
metadata = LocalModelStorage.metadata_from_archive(model_archive)
|
|
1336
|
+
|
|
1337
|
+
return metadata.project_fingerprint
|
|
1338
|
+
except Exception:
|
|
1339
|
+
return None
|
|
1340
|
+
|
|
1341
|
+
if not endpoints:
|
|
1342
|
+
endpoints = AvailableEndpoints()
|
|
1343
|
+
|
|
1344
|
+
_track(
|
|
1345
|
+
TELEMETRY_SERVER_STARTED_EVENT,
|
|
1346
|
+
{
|
|
1347
|
+
"input_channels": [i.name() for i in input_channels],
|
|
1348
|
+
"api_enabled": is_api_enabled,
|
|
1349
|
+
"number_of_workers": number_of_workers,
|
|
1350
|
+
"endpoints_nlg": endpoints.nlg.type if endpoints.nlg else None,
|
|
1351
|
+
"endpoints_nlu": endpoints.nlu.type if endpoints.nlu else None,
|
|
1352
|
+
"endpoints_action_server": endpoints.action.type
|
|
1353
|
+
if endpoints.action
|
|
1354
|
+
else None,
|
|
1355
|
+
"endpoints_model_server": endpoints.model.type if endpoints.model else None,
|
|
1356
|
+
"endpoints_tracker_store": endpoints.tracker_store.type
|
|
1357
|
+
if endpoints.tracker_store
|
|
1358
|
+
else None,
|
|
1359
|
+
"endpoints_lock_store": endpoints.lock_store.type
|
|
1360
|
+
if endpoints.lock_store
|
|
1361
|
+
else None,
|
|
1362
|
+
"endpoints_event_broker": endpoints.event_broker.type
|
|
1363
|
+
if endpoints.event_broker
|
|
1364
|
+
else None,
|
|
1365
|
+
"project": project_fingerprint_from_model(model_directory),
|
|
1366
|
+
},
|
|
1367
|
+
)
|
|
1368
|
+
|
|
1369
|
+
|
|
1370
|
+
@ensure_telemetry_enabled
|
|
1371
|
+
def track_project_init(path: Text) -> None:
|
|
1372
|
+
"""Track when a user creates a project using rasa init.
|
|
1373
|
+
|
|
1374
|
+
Args:
|
|
1375
|
+
path: Location of the project
|
|
1376
|
+
"""
|
|
1377
|
+
_track(
|
|
1378
|
+
TELEMETRY_PROJECT_CREATED_EVENT, {"init_directory": _hash_directory_path(path)}
|
|
1379
|
+
)
|
|
1380
|
+
|
|
1381
|
+
|
|
1382
|
+
@ensure_telemetry_enabled
|
|
1383
|
+
def track_shell_started(model_type: Text) -> None:
|
|
1384
|
+
"""Track when a user starts a bot using rasa shell.
|
|
1385
|
+
|
|
1386
|
+
Args:
|
|
1387
|
+
model_type: Type of the model, core / nlu or rasa.
|
|
1388
|
+
"""
|
|
1389
|
+
_track(TELEMETRY_SHELL_STARTED_EVENT, {"type": model_type})
|
|
1390
|
+
|
|
1391
|
+
|
|
1392
|
+
@ensure_telemetry_enabled
|
|
1393
|
+
def track_inspect_started(model_type: Text) -> None:
|
|
1394
|
+
"""Track when a user starts a bot using rasa inspect.
|
|
1395
|
+
|
|
1396
|
+
Args:
|
|
1397
|
+
model_type: Type of the model, core / nlu or rasa.
|
|
1398
|
+
"""
|
|
1399
|
+
_track(TELEMETRY_INSPECT_STARTED_EVENT, {"type": model_type})
|
|
1400
|
+
|
|
1401
|
+
|
|
1402
|
+
@ensure_telemetry_enabled
|
|
1403
|
+
def track_visualization() -> None:
|
|
1404
|
+
"""Track when a user runs the visualization."""
|
|
1405
|
+
_track(TELEMETRY_VISUALIZATION_STARTED_EVENT)
|
|
1406
|
+
|
|
1407
|
+
|
|
1408
|
+
@ensure_telemetry_enabled
|
|
1409
|
+
def track_core_model_test(num_story_steps: int, e2e: bool, agent: "Agent") -> None:
|
|
1410
|
+
"""Track when a user tests a core model.
|
|
1411
|
+
|
|
1412
|
+
Args:
|
|
1413
|
+
num_story_steps: Number of test stories used for the comparison
|
|
1414
|
+
e2e: indicator if tests running in end to end mode
|
|
1415
|
+
agent: Agent of the model getting tested
|
|
1416
|
+
"""
|
|
1417
|
+
if agent.processor is None:
|
|
1418
|
+
project_fingerprint = ""
|
|
1419
|
+
else:
|
|
1420
|
+
project_fingerprint = agent.processor.model_metadata.project_fingerprint
|
|
1421
|
+
|
|
1422
|
+
_track(
|
|
1423
|
+
TELEMETRY_TEST_CORE_EVENT,
|
|
1424
|
+
{
|
|
1425
|
+
"project": project_fingerprint,
|
|
1426
|
+
"end_to_end": e2e,
|
|
1427
|
+
"num_story_steps": num_story_steps,
|
|
1428
|
+
},
|
|
1429
|
+
)
|
|
1430
|
+
|
|
1431
|
+
|
|
1432
|
+
@ensure_telemetry_enabled
|
|
1433
|
+
def track_nlu_model_test(test_data: "TrainingData") -> None:
|
|
1434
|
+
"""Track when a user tests an nlu model.
|
|
1435
|
+
|
|
1436
|
+
Args:
|
|
1437
|
+
test_data: Data used for testing
|
|
1438
|
+
"""
|
|
1439
|
+
_track(
|
|
1440
|
+
TELEMETRY_TEST_NLU_EVENT,
|
|
1441
|
+
{
|
|
1442
|
+
"num_intent_examples": len(test_data.intent_examples),
|
|
1443
|
+
"num_entity_examples": len(test_data.entity_examples),
|
|
1444
|
+
"num_lookup_tables": len(test_data.lookup_tables),
|
|
1445
|
+
"num_synonyms": len(test_data.entity_synonyms),
|
|
1446
|
+
"num_regexes": len(test_data.regex_features),
|
|
1447
|
+
},
|
|
1448
|
+
)
|
|
1449
|
+
|
|
1450
|
+
|
|
1451
|
+
@ensure_telemetry_enabled
|
|
1452
|
+
def track_markers_extraction_initiated(
|
|
1453
|
+
strategy: Text, only_extract: bool, seed: bool, count: Optional[int]
|
|
1454
|
+
) -> None:
|
|
1455
|
+
"""Track when a user tries to extract success markers.
|
|
1456
|
+
|
|
1457
|
+
Args:
|
|
1458
|
+
strategy: The strategy the user is using for tracker selection
|
|
1459
|
+
only_extract: Indicates if the user is only extracting markers or also
|
|
1460
|
+
producing stats
|
|
1461
|
+
seed: Indicates if the user used a seed for this attempt
|
|
1462
|
+
count: (Optional) The number of trackers the user is trying to select.
|
|
1463
|
+
"""
|
|
1464
|
+
_track(
|
|
1465
|
+
TELEMETRY_MARKERS_EXTRACTION_INITIATED_EVENT,
|
|
1466
|
+
{
|
|
1467
|
+
"strategy": strategy,
|
|
1468
|
+
"only_extract": only_extract,
|
|
1469
|
+
"seed": seed,
|
|
1470
|
+
"count": count,
|
|
1471
|
+
},
|
|
1472
|
+
)
|
|
1473
|
+
|
|
1474
|
+
|
|
1475
|
+
@ensure_telemetry_enabled
|
|
1476
|
+
def track_markers_extracted(trackers_count: int) -> None:
|
|
1477
|
+
"""Track when markers have been extracted by a user.
|
|
1478
|
+
|
|
1479
|
+
Args:
|
|
1480
|
+
trackers_count: The actual number of trackers processed
|
|
1481
|
+
"""
|
|
1482
|
+
_track(TELEMETRY_MARKERS_EXTRACTED_EVENT, {"trackers_count": trackers_count})
|
|
1483
|
+
|
|
1484
|
+
|
|
1485
|
+
@ensure_telemetry_enabled
|
|
1486
|
+
def track_markers_stats_computed(trackers_count: int) -> None:
|
|
1487
|
+
"""Track when stats over markers have been computed by a user.
|
|
1488
|
+
|
|
1489
|
+
Args:
|
|
1490
|
+
trackers_count: The actual number of trackers processed
|
|
1491
|
+
"""
|
|
1492
|
+
_track(TELEMETRY_MARKERS_STATS_COMPUTED_EVENT, {"trackers_count": trackers_count})
|
|
1493
|
+
|
|
1494
|
+
|
|
1495
|
+
@ensure_telemetry_enabled
|
|
1496
|
+
def track_markers_parsed_count(
|
|
1497
|
+
marker_count: int, max_depth: int, branching_factor: int
|
|
1498
|
+
) -> None:
|
|
1499
|
+
"""Track when markers have been successfully parsed from config.
|
|
1500
|
+
|
|
1501
|
+
Args:
|
|
1502
|
+
marker_count: The number of markers found in the config
|
|
1503
|
+
max_depth: The maximum depth of any marker in the config
|
|
1504
|
+
branching_factor: The maximum number of children of any marker in the config.
|
|
1505
|
+
"""
|
|
1506
|
+
_track(
|
|
1507
|
+
TELEMETRY_MARKERS_PARSED_COUNT,
|
|
1508
|
+
{
|
|
1509
|
+
"marker_count": marker_count,
|
|
1510
|
+
"max_depth": max_depth,
|
|
1511
|
+
"branching_factor": branching_factor,
|
|
1512
|
+
},
|
|
1513
|
+
)
|
|
1514
|
+
|
|
1515
|
+
|
|
1516
|
+
def extract_assertion_type_counts(
|
|
1517
|
+
input_test_cases: List["TestCase"],
|
|
1518
|
+
) -> typing.Tuple[bool, Dict[str, Any]]:
|
|
1519
|
+
"""Extracts the total count of different assertion types from the test cases."""
|
|
1520
|
+
from rasa.e2e_test.assertions import AssertionType
|
|
1521
|
+
|
|
1522
|
+
uses_assertions = False
|
|
1523
|
+
|
|
1524
|
+
flow_started_count = 0
|
|
1525
|
+
flow_completed_count = 0
|
|
1526
|
+
flow_cancelled_count = 0
|
|
1527
|
+
pattern_clarification_contains_count = 0
|
|
1528
|
+
action_executed_count = 0
|
|
1529
|
+
slot_was_set_count = 0
|
|
1530
|
+
slot_was_not_set_count = 0
|
|
1531
|
+
bot_uttered_count = 0
|
|
1532
|
+
generative_response_is_relevant_count = 0
|
|
1533
|
+
generative_response_is_grounded_count = 0
|
|
1534
|
+
|
|
1535
|
+
for test_case in input_test_cases:
|
|
1536
|
+
for step in test_case.steps:
|
|
1537
|
+
assertions = step.assertions if step.assertions else []
|
|
1538
|
+
for assertion in assertions:
|
|
1539
|
+
if assertion.type == AssertionType.ACTION_EXECUTED.value:
|
|
1540
|
+
action_executed_count += 1
|
|
1541
|
+
elif assertion.type == AssertionType.SLOT_WAS_SET.value:
|
|
1542
|
+
slot_was_set_count += 1
|
|
1543
|
+
elif assertion.type == AssertionType.SLOT_WAS_NOT_SET.value:
|
|
1544
|
+
slot_was_not_set_count += 1
|
|
1545
|
+
elif assertion.type == AssertionType.BOT_UTTERED.value:
|
|
1546
|
+
bot_uttered_count += 1
|
|
1547
|
+
elif (
|
|
1548
|
+
assertion.type
|
|
1549
|
+
== AssertionType.GENERATIVE_RESPONSE_IS_RELEVANT.value
|
|
1550
|
+
):
|
|
1551
|
+
generative_response_is_relevant_count += 1
|
|
1552
|
+
elif (
|
|
1553
|
+
assertion.type
|
|
1554
|
+
== AssertionType.GENERATIVE_RESPONSE_IS_GROUNDED.value
|
|
1555
|
+
):
|
|
1556
|
+
generative_response_is_grounded_count += 1
|
|
1557
|
+
elif assertion.type == AssertionType.FLOW_STARTED.value:
|
|
1558
|
+
flow_started_count += 1
|
|
1559
|
+
elif assertion.type == AssertionType.FLOW_COMPLETED.value:
|
|
1560
|
+
flow_completed_count += 1
|
|
1561
|
+
elif assertion.type == AssertionType.FLOW_CANCELLED.value:
|
|
1562
|
+
flow_cancelled_count += 1
|
|
1563
|
+
elif (
|
|
1564
|
+
assertion.type == AssertionType.PATTERN_CLARIFICATION_CONTAINS.value
|
|
1565
|
+
):
|
|
1566
|
+
pattern_clarification_contains_count += 1
|
|
1567
|
+
|
|
1568
|
+
uses_assertions = True
|
|
1569
|
+
|
|
1570
|
+
result = {
|
|
1571
|
+
"flow_started_count": flow_started_count,
|
|
1572
|
+
"flow_completed_count": flow_completed_count,
|
|
1573
|
+
"flow_cancelled_count": flow_cancelled_count,
|
|
1574
|
+
"pattern_clarification_contains_count": pattern_clarification_contains_count,
|
|
1575
|
+
"action_executed_count": action_executed_count,
|
|
1576
|
+
"slot_was_set_count": slot_was_set_count,
|
|
1577
|
+
"slot_was_not_set_count": slot_was_not_set_count,
|
|
1578
|
+
"bot_uttered_count": bot_uttered_count,
|
|
1579
|
+
"generative_response_is_relevant_count": generative_response_is_relevant_count,
|
|
1580
|
+
"generative_response_is_grounded_count": generative_response_is_grounded_count,
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
return uses_assertions, result
|
|
1584
|
+
|
|
1585
|
+
|
|
1586
|
+
@ensure_telemetry_enabled
|
|
1587
|
+
def track_e2e_test_run(
|
|
1588
|
+
input_test_cases: List["TestCase"],
|
|
1589
|
+
input_fixtures: List["Fixture"],
|
|
1590
|
+
input_metadata: List["Metadata"],
|
|
1591
|
+
) -> None:
|
|
1592
|
+
"""Track an end-to-end test run."""
|
|
1593
|
+
properties = {
|
|
1594
|
+
"number_of_test_cases": len(input_test_cases),
|
|
1595
|
+
"number_of_fixtures": len(input_fixtures),
|
|
1596
|
+
"uses_fixtures": len(input_fixtures) > 0,
|
|
1597
|
+
"uses_metadata": len(input_metadata) > 0,
|
|
1598
|
+
"number_of_metadata": len(input_metadata),
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
uses_assertions, assertion_type_counts = extract_assertion_type_counts(
|
|
1602
|
+
input_test_cases
|
|
1603
|
+
)
|
|
1604
|
+
|
|
1605
|
+
properties.update({"uses_assertions": uses_assertions})
|
|
1606
|
+
|
|
1607
|
+
if uses_assertions:
|
|
1608
|
+
properties.update(assertion_type_counts)
|
|
1609
|
+
|
|
1610
|
+
_track(
|
|
1611
|
+
TELEMETRY_E2E_TEST_RUN_STARTED_EVENT,
|
|
1612
|
+
properties,
|
|
1613
|
+
)
|
|
1614
|
+
|
|
1615
|
+
|
|
1616
|
+
@ensure_telemetry_enabled
|
|
1617
|
+
def track_response_rephrase(
|
|
1618
|
+
rephrase_all: bool,
|
|
1619
|
+
custom_prompt_template: Optional[str],
|
|
1620
|
+
llm_type: Optional[str],
|
|
1621
|
+
llm_model: Optional[str],
|
|
1622
|
+
llm_model_group_id: Optional[str],
|
|
1623
|
+
) -> None:
|
|
1624
|
+
"""Track when a user rephrases a response."""
|
|
1625
|
+
_track(
|
|
1626
|
+
TELEMETRY_RESPONSE_REPHRASED_EVENT,
|
|
1627
|
+
{
|
|
1628
|
+
"rephrase_all": rephrase_all,
|
|
1629
|
+
"custom_prompt_template": custom_prompt_template,
|
|
1630
|
+
"llm_type": llm_type,
|
|
1631
|
+
"llm_model": llm_model,
|
|
1632
|
+
"llm_model_group_id": llm_model_group_id,
|
|
1633
|
+
},
|
|
1634
|
+
)
|
|
1635
|
+
|
|
1636
|
+
|
|
1637
|
+
@ensure_telemetry_enabled
|
|
1638
|
+
def track_intentless_policy_train() -> None:
|
|
1639
|
+
"""Track when a user trains a policy."""
|
|
1640
|
+
_track(TELEMETRY_INTENTLESS_POLICY_TRAINING_STARTED_EVENT)
|
|
1641
|
+
|
|
1642
|
+
|
|
1643
|
+
@ensure_telemetry_enabled
|
|
1644
|
+
def track_intentless_policy_train_completed(
|
|
1645
|
+
embeddings_type: Optional[str],
|
|
1646
|
+
embeddings_model: Optional[str],
|
|
1647
|
+
embeddings_model_group_id: Optional[str],
|
|
1648
|
+
llm_type: Optional[str],
|
|
1649
|
+
llm_model: Optional[str],
|
|
1650
|
+
llm_model_group_id: Optional[str],
|
|
1651
|
+
) -> None:
|
|
1652
|
+
"""Track when a user trains a policy."""
|
|
1653
|
+
_track(
|
|
1654
|
+
TELEMETRY_INTENTLESS_POLICY_TRAINING_COMPLETED_EVENT,
|
|
1655
|
+
{
|
|
1656
|
+
"embeddings_type": embeddings_type,
|
|
1657
|
+
"embeddings_model": embeddings_model,
|
|
1658
|
+
"embeddings_model_group_id": embeddings_model_group_id,
|
|
1659
|
+
"llm_type": llm_type,
|
|
1660
|
+
"llm_model": llm_model,
|
|
1661
|
+
"llm_model_group_id": llm_model_group_id,
|
|
1662
|
+
},
|
|
1663
|
+
)
|
|
1664
|
+
|
|
1665
|
+
|
|
1666
|
+
@ensure_telemetry_enabled
|
|
1667
|
+
def track_intentless_policy_predict(
|
|
1668
|
+
embeddings_type: Optional[str],
|
|
1669
|
+
embeddings_model: Optional[str],
|
|
1670
|
+
embeddings_model_group_id: Optional[str],
|
|
1671
|
+
llm_type: Optional[str],
|
|
1672
|
+
llm_model: Optional[str],
|
|
1673
|
+
llm_model_group_id: Optional[str],
|
|
1674
|
+
score: float,
|
|
1675
|
+
) -> None:
|
|
1676
|
+
"""Track when a user trains a policy."""
|
|
1677
|
+
_track(
|
|
1678
|
+
TELEMETRY_INTENTLESS_POLICY_PREDICT_EVENT,
|
|
1679
|
+
{
|
|
1680
|
+
"embeddings_type": embeddings_type,
|
|
1681
|
+
"embeddings_model": embeddings_model,
|
|
1682
|
+
"embeddings_model_group_id": embeddings_model_group_id,
|
|
1683
|
+
"llm_type": llm_type,
|
|
1684
|
+
"llm_model": llm_model,
|
|
1685
|
+
"llm_model_group_id": llm_model_group_id,
|
|
1686
|
+
"score": score,
|
|
1687
|
+
},
|
|
1688
|
+
)
|
|
1689
|
+
|
|
1690
|
+
|
|
1691
|
+
@ensure_telemetry_enabled
|
|
1692
|
+
def identify_endpoint_config_traits(
|
|
1693
|
+
endpoints_file: Optional[Text],
|
|
1694
|
+
context: Optional[Dict[Text, Any]] = None,
|
|
1695
|
+
) -> None:
|
|
1696
|
+
"""Collect traits if enabled.
|
|
1697
|
+
|
|
1698
|
+
Otherwise, sets traits to None.
|
|
1699
|
+
"""
|
|
1700
|
+
traits: Dict[str, Any] = {}
|
|
1701
|
+
|
|
1702
|
+
traits = append_tracing_trait(traits, endpoints_file)
|
|
1703
|
+
traits = append_metrics_trait(traits, endpoints_file)
|
|
1704
|
+
traits = append_anonymization_trait(traits, endpoints_file)
|
|
1705
|
+
|
|
1706
|
+
_identify(traits, context)
|
|
1707
|
+
|
|
1708
|
+
|
|
1709
|
+
def append_tracing_trait(
|
|
1710
|
+
traits: Dict[str, Any], endpoints_file: Optional[str]
|
|
1711
|
+
) -> Dict[str, Any]:
|
|
1712
|
+
"""Append the tracing trait to the traits dictionary."""
|
|
1713
|
+
import rasa.utils.endpoints
|
|
1714
|
+
from rasa.tracing.constants import ENDPOINTS_TRACING_KEY
|
|
1715
|
+
|
|
1716
|
+
tracing_config = rasa.utils.endpoints.read_endpoint_config(
|
|
1717
|
+
endpoints_file, ENDPOINTS_TRACING_KEY
|
|
1718
|
+
)
|
|
1719
|
+
traits[TRACING_BACKEND] = (
|
|
1720
|
+
tracing_config.type if tracing_config is not None else None
|
|
1721
|
+
)
|
|
1722
|
+
|
|
1723
|
+
return traits
|
|
1724
|
+
|
|
1725
|
+
|
|
1726
|
+
def append_metrics_trait(
|
|
1727
|
+
traits: Dict[str, Any], endpoints_file: Optional[str]
|
|
1728
|
+
) -> Dict[str, Any]:
|
|
1729
|
+
"""Append the metrics trait to the traits dictionary."""
|
|
1730
|
+
import rasa.utils.endpoints
|
|
1731
|
+
from rasa.tracing.constants import ENDPOINTS_METRICS_KEY
|
|
1732
|
+
|
|
1733
|
+
metrics_config = rasa.utils.endpoints.read_endpoint_config(
|
|
1734
|
+
endpoints_file, ENDPOINTS_METRICS_KEY
|
|
1735
|
+
)
|
|
1736
|
+
traits[METRICS_BACKEND] = (
|
|
1737
|
+
metrics_config.type if metrics_config is not None else None
|
|
1738
|
+
)
|
|
1739
|
+
|
|
1740
|
+
return traits
|
|
1741
|
+
|
|
1742
|
+
|
|
1743
|
+
def append_anonymization_trait(
|
|
1744
|
+
traits: Dict[str, Any], endpoints_file: Optional[str]
|
|
1745
|
+
) -> Dict[str, Any]:
|
|
1746
|
+
"""Append the anonymization trait to the traits dictionary."""
|
|
1747
|
+
from rasa.anonymization.anonymisation_rule_yaml_reader import (
|
|
1748
|
+
KEY_ANONYMIZATION_RULES,
|
|
1749
|
+
)
|
|
1750
|
+
|
|
1751
|
+
anonymization_config = rasa.anonymization.utils.read_endpoint_config(
|
|
1752
|
+
endpoints_file, KEY_ANONYMIZATION_RULES
|
|
1753
|
+
)
|
|
1754
|
+
|
|
1755
|
+
traits[KEY_ANONYMIZATION_RULES] = (
|
|
1756
|
+
rasa.anonymization.utils.extract_anonymization_traits(
|
|
1757
|
+
anonymization_config, KEY_ANONYMIZATION_RULES
|
|
1758
|
+
)
|
|
1759
|
+
)
|
|
1760
|
+
|
|
1761
|
+
return traits
|
|
1762
|
+
|
|
1763
|
+
|
|
1764
|
+
@ensure_telemetry_enabled
|
|
1765
|
+
def track_enterprise_search_policy_train_started() -> None:
|
|
1766
|
+
"""Track when a user starts training Enterprise Search policy."""
|
|
1767
|
+
_track(TELEMETRY_ENTERPRISE_SEARCH_POLICY_TRAINING_STARTED_EVENT)
|
|
1768
|
+
|
|
1769
|
+
|
|
1770
|
+
@ensure_telemetry_enabled
|
|
1771
|
+
def track_enterprise_search_policy_train_completed(
|
|
1772
|
+
vector_store_type: Optional[str],
|
|
1773
|
+
embeddings_type: Optional[str],
|
|
1774
|
+
embeddings_model: Optional[str],
|
|
1775
|
+
embeddings_model_group_id: Optional[str],
|
|
1776
|
+
llm_type: Optional[str],
|
|
1777
|
+
llm_model: Optional[str],
|
|
1778
|
+
llm_model_group_id: Optional[str],
|
|
1779
|
+
citation_enabled: Optional[bool],
|
|
1780
|
+
) -> None:
|
|
1781
|
+
"""Track when a user completes training Enterprise Search policy."""
|
|
1782
|
+
_track(
|
|
1783
|
+
TELEMETRY_ENTERPRISE_SEARCH_POLICY_TRAINING_COMPLETED_EVENT,
|
|
1784
|
+
{
|
|
1785
|
+
"vector_store_type": vector_store_type,
|
|
1786
|
+
"embeddings_type": embeddings_type,
|
|
1787
|
+
"embeddings_model": embeddings_model,
|
|
1788
|
+
"embeddings_model_group_id": embeddings_model_group_id,
|
|
1789
|
+
"llm_type": llm_type,
|
|
1790
|
+
"llm_model": llm_model,
|
|
1791
|
+
"llm_model_group_id": llm_model_group_id,
|
|
1792
|
+
"citation_enabled": citation_enabled,
|
|
1793
|
+
},
|
|
1794
|
+
)
|
|
1795
|
+
|
|
1796
|
+
|
|
1797
|
+
@ensure_telemetry_enabled
|
|
1798
|
+
def track_enterprise_search_policy_predict(
|
|
1799
|
+
vector_store_type: Optional[str],
|
|
1800
|
+
embeddings_type: Optional[str],
|
|
1801
|
+
embeddings_model: Optional[str],
|
|
1802
|
+
embeddings_model_group_id: Optional[str],
|
|
1803
|
+
llm_type: Optional[str],
|
|
1804
|
+
llm_model: Optional[str],
|
|
1805
|
+
llm_model_group_id: Optional[str],
|
|
1806
|
+
citation_enabled: Optional[bool],
|
|
1807
|
+
) -> None:
|
|
1808
|
+
"""Track when a user predicts the next action using Enterprise Search policy."""
|
|
1809
|
+
_track(
|
|
1810
|
+
TELEMETRY_ENTERPRISE_SEARCH_POLICY_PREDICT_EVENT,
|
|
1811
|
+
{
|
|
1812
|
+
"vector_store_type": vector_store_type,
|
|
1813
|
+
"embeddings_type": embeddings_type,
|
|
1814
|
+
"embeddings_model": embeddings_model,
|
|
1815
|
+
"embeddings_model_group_id": embeddings_model_group_id,
|
|
1816
|
+
"llm_type": llm_type,
|
|
1817
|
+
"llm_model": llm_model,
|
|
1818
|
+
"llm_model_group_id": llm_model_group_id,
|
|
1819
|
+
"citation_enabled": citation_enabled,
|
|
1820
|
+
},
|
|
1821
|
+
)
|
|
1822
|
+
|
|
1823
|
+
|
|
1824
|
+
@ensure_telemetry_enabled
|
|
1825
|
+
def track_conversation_count_hard_limit(
|
|
1826
|
+
conversation_count: int, tracked_month: datetime
|
|
1827
|
+
) -> None:
|
|
1828
|
+
"""Track when the number of conversations reaches the hard limit."""
|
|
1829
|
+
_track(
|
|
1830
|
+
TELEMETRY_CONVERSATION_HARD_LIMIT_REACHED,
|
|
1831
|
+
{
|
|
1832
|
+
"conversation_count": conversation_count,
|
|
1833
|
+
"year": tracked_month.year,
|
|
1834
|
+
"month": tracked_month.month,
|
|
1835
|
+
},
|
|
1836
|
+
)
|
|
1837
|
+
|
|
1838
|
+
|
|
1839
|
+
@ensure_telemetry_enabled
|
|
1840
|
+
def track_conversation_count_soft_limit(
|
|
1841
|
+
conversation_count: int, tracked_month: datetime
|
|
1842
|
+
) -> None:
|
|
1843
|
+
"""Track when the number of conversations reaches the soft limit."""
|
|
1844
|
+
_track(
|
|
1845
|
+
TELEMETRY_CONVERSATION_SOFT_LIMIT_REACHED,
|
|
1846
|
+
{
|
|
1847
|
+
"conversation_count": conversation_count,
|
|
1848
|
+
"year": tracked_month.year,
|
|
1849
|
+
"month": tracked_month.month,
|
|
1850
|
+
},
|
|
1851
|
+
)
|
|
1852
|
+
|
|
1853
|
+
|
|
1854
|
+
@ensure_telemetry_enabled
|
|
1855
|
+
def track_conversation_count(conversation_count: int, tracked_month: datetime) -> None:
|
|
1856
|
+
"""Track the number of conversations."""
|
|
1857
|
+
_track(
|
|
1858
|
+
TELEMETRY_CONVERSATION_COUNT,
|
|
1859
|
+
{
|
|
1860
|
+
"conversation_count": conversation_count,
|
|
1861
|
+
"year": tracked_month.year,
|
|
1862
|
+
"month": tracked_month.month,
|
|
1863
|
+
},
|
|
1864
|
+
)
|
|
1865
|
+
|
|
1866
|
+
|
|
1867
|
+
@ensure_telemetry_enabled
|
|
1868
|
+
def track_e2e_test_conversion_completed(file_type: str, test_case_count: int) -> None:
|
|
1869
|
+
"""Track the used input file type for E2E test conversion."""
|
|
1870
|
+
_track(
|
|
1871
|
+
TELEMETRY_E2E_TEST_CONVERSION_EVENT,
|
|
1872
|
+
{
|
|
1873
|
+
E2E_TEST_CONVERSION_FILE_TYPE: file_type,
|
|
1874
|
+
E2E_TEST_CONVERSION_TEST_CASE_COUNT: test_case_count,
|
|
1875
|
+
},
|
|
1876
|
+
)
|